Skip to content

feat/issues-68-69-78-79 - #181

Merged
Darkvader-ship-it merged 2 commits into
PHASE-STELLAR:mainfrom
CeceOs92:feat/issues-68-69-78-79
Aug 31, 2026
Merged

feat/issues-68-69-78-79#181
Darkvader-ship-it merged 2 commits into
PHASE-STELLAR:mainfrom
CeceOs92:feat/issues-68-69-78-79

Conversation

@CeceOs92

Copy link
Copy Markdown
Contributor

Summary

Implements four phase-NNN delivery units, each a flag-gated isolated domain
module with zod schema validation, a typed error class, route error boundaries,
and a npx tsx unit-test suite. Every feature is a no-op with zero regression
when its flag is unset.

Closes #68
Closes #69
Closes #78
Closes #79

#68 — Quarantine malformed x402 invoices in a dead-letter review queue (Module #44, phase-144)

Malformed x402 / trustline payloads previously failed with a bare 400 and were
dropped — no audit trail.

  • lib/x402-dead-letter.tsX402InvoiceSchema; pure classifyInvoice();
    quarantineInvoice() persists the rejected payload with a redaction pass over
    secret-looking keys and a fingerprint for duplicate detection;
    listDeadLetterQueue() / getDeadLetterEntry() / resolveDeadLetterEntry() /
    getDeadLetterStats() operator surface. Type-only re-export from
    lib/classic-liq.ts (keeps node:fs out of the client bundle).
  • app/api/classic-liq/trustline/route.ts — schema failure now quarantines
    the payload and returns 422 { code: "QUARANTINED", deadLetterId } instead of
    dropping it; the phase-119 CID verification block is wrapped in an error
    boundary that normalizes unexpected throws to a 409; GET ?view=dead-letter
    exposes the review queue + stats.
  • components/trustline-button.tsx — surfaces the QUARANTINED response
    with a review-queue reference (es/en).
  • tests/x402-dead-letter.test.ts — 14 tests: schema, redaction,
    fingerprinting, quarantine, dedupe, resolve/stats, flag-off no-op.

#69 — Sybil-resistance checks via on-chain history scoring (Module #45, phase-145)

Bots farm rewards with freshly created wallets; there was no shared notion of
"how established is this account on chain".

  • lib/sybil-resistance.tsSybilScoreInputSchema; pure
    scoreWalletHistory() → 0–100 trust score + trusted | caution | suspect
    band + contributing-signal list (account age, tx depth, counterparty
    diversity, balance, config effort, sponsored-dormant penalty);
    isSybilSuspect(); fetchAccountHistoryFeatures() (best-effort Horizon
    reader); flag-gated assessWalletSybilRisk().
  • app/api/og/profile/route.tsx / app/api/og/chamber/route.tsx — emit
    X-Phase-Sybil-Band / X-Phase-Sybil-Score observability headers for the
    resolved wallet (chamber via ?wallet=). Best-effort; does not change pixels.
  • tests/sybil-resistance.test.ts — 12 tests: schema defaults, band
    boundaries, penalty, clamping, custom threshold, typed error, flag gate.

#78 — Faucet deny-list with on-chain governance veto (Module #56, phase-156)

Abusive wallets could not be cleanly excluded, and there was no governed way to
add or remove an exclusion.

  • lib/faucet-deny-list.tsAddDenyRequestSchema / GovernanceVetoSchema;
    proposeDenyListEntry() (deny-first: active immediately);
    castGovernanceVeto() — once a quorum of distinct governance signers
    (PHASE_GOVERNANCE_SIGNERS env) veto, the entry flips to vetoed and the
    wallet is no longer denied; isWalletDenied(), liftDenyListEntry(),
    listDenyList(). Full re-export from lib/signal-store.ts.
  • app/api/signals/[id]/replies/route.ts — denied wallets get
    403 { code: "WALLET_DENIED", reason }; wrapped so a store read failure never
    500s the reply path.
  • app/signals/[id]/page.tsx — shows an "author on deny-list" banner.
  • tests/faucet-deny-list.test.ts — 12 tests: schema, governance signer
    set, quorum derivation, propose/duplicate/validation, veto quorum lift,
    non-signer/duplicate/not-found rejections, manual lift, flag-off.

#79 — Virtualize the Chamber NFT grid for 10k+ tokens (Module #57, phase-157)

Rendering all owned tokens freezes low-end devices.

  • lib/nft-grid-virtualization.ts — dependency-free windowing math:
    computeGridWindow() (visible index range + overscan + spacer offset + total
    scroll height), computeColumnCount() (responsive auto-fill), clampScrollTop(),
    sliceVisible(), nftGridOverscanPx(). Importable from server and client.
    Re-exported from lib/profile-store.ts.
  • components/wallet-avatar.tsx — IntersectionObserver rootMargin now
    nftGridOverscanPx() (240px when enabled, 50px legacy) so avatars in a large
    scrolling grid mount just ahead of view.
  • app/api/profile/avatar/route.ts?wallets=G...,G... batch mode
    (getAvatarsForWallets, max 50) so a grid avoids N round-trips;
    X-Phase157 header on the single-avatar path.
  • tests/nft-grid-virtualization.test.ts — 10 tests: column count, scroll
    clamping, empty grid, large-grid windowing, scrolled offset, bottom clamp,
    row gap, typed error, slice, overscan flag gate.

Verification

  • New suites: x402-dead-letter 14 · sybil-resistance 12 · faucet-deny-list
    12 · nft-grid-virtualization 10 — all pass via npx tsx tests/<name>.test.ts.
  • Full existing suite (18 files) still passes; og-integration (which inspects
    the touched OG routes) green.
  • npx tsc --noEmit: net-zero new errors (55 pre-existing, 55 after).

Rollback

Unset the relevant NEXT_PUBLIC_FEATURE_PHASE_144 / 145 / 156 / 157 (and
FEATURE_PHASE_*) env var and restart. JSON sidecars (x402-dead-letter.json,
faucet-deny-list.json) can be deleted; nothing else references them. No data
migration to revert.

Notes

  • New feature flags registered in lib/feature-flags.ts (union, env map,
    getEnabledFeatureFlags).
  • New sidecar keys x402DeadLetter / faucetDenyList added to
    lib/server-data-paths.ts.
  • #78 needs PHASE_GOVERNANCE_SIGNERS (comma-separated G... addresses) set
    for vetoes to be accepted.
  • Per PROJECT_ARCHITECTURE.md / docs/TECHNICAL.md: these are additive
    flag-gated modules with no architectural change, so no doc updates were
    required — flag descriptions live in lib/feature-flags.ts.

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@CeceOs92 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Darkvader-ship-it
Darkvader-ship-it merged commit 62e336f into PHASE-STELLAR:main Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment