Auctions → Applesauce: NDK→applesauce Migration Plan for Plebeian Market
- Auctions → Applesauce: NDK→applesauce Migration Plan for Plebeian Market
- Why this exists
- Survey findings (verified against the live repo, 2026-09-08)
- Plan: P0–P5
- P0 — Sync + seam baseline (prerequisite, parallel-safe)
- P1 — Wave-B sweep + read flips (mechanical, parallelizable)
- P2 — Private-claim read/unwrap (A1 pattern, signer-gated)
- P3 — Publish lanes (signer-gated — the real critical path)
- P4 — nip60 quarantine (last, independent)
- P5 — Conflict-zone + capstone
- Already done (found in prior work)
- Explicitly out of scope
- Controlling external dependency
- Verification gates (every wave)
- Related
Auctions → Applesauce: NDK→applesauce Migration Plan for Plebeian Market
Author: Felix
Date: 2026-09-08
Repo: PlebeianApp/market — auctions branch
Related: ADR-0002 (NDK→applesauce strangler-fig), epic #1005, ADR-0011 (#1269)
Why this exists
ADR-0002 governs migrating Plebeian Market’s runtime Nostr I/O from @nostr-dev-kit (NDK) to applesauce, using a library-agnostic seam (src/lib/nostr/io.ts) with a temporary NDK bridge and an applesauce destination adapter. Master has done Wave 0 + Wave A1b read flips. The auctions feature branch — where all auction code lives — was built in parallel, directly on NDK, and never routed through the seam.
This post documents the survey of auctions-side NDK usage and the migration plan that follows ADR-0002. It is intended to be linked from the PRs that implement the plan, so reviewers have the full picture in one place.
Survey findings (verified against the live repo, 2026-09-08)
Ground truth
- Auctions is NOT behind master’s merged migration. The auctions branch already contains all master NDK→applesauce commits (Wave 0 #1075, Wave A1b #1121, seam + guard) —
io.ts/io-applesauce.ts/io-ndk.tsare byte-identical to master. Merging master will not reduce the NDK surplus. - The +30 NDK files are auctions-native. 30 source files exist only on the auctions branch and import NDK directly. Zero auction files import the seam. The branch raised its own footprint baseline (127→161, commit
40fc5dec) instead of routing new code through the seam; actual usage is now ~157. - Applesauce version skew is the hidden landmine: master merged the applesauce 5.2→6.2 upgrade plus adapter fixes (
6a241604and friends) — all missing from auctions, which still pinsapplesauce-* ^5.2.0. Flipping any auction module to the applesauce adapter on 5.2 would inherit the exact bugs master already fixed (5.2 virtual-EOSE backstop, unbounded reconnect, first-relay-EOSE group kill). - Pleasant surprise: the auction validator server + contextvm are already applesauce-native (via
@contextvm/sdk,startAuctionValidator({ signer, relayPool })) with zero NDK imports. Pure auction libs (src/lib/auction/*,auctionSettlement.ts,settlementDescriptor.ts) are NDK-free. These are not migration targets. - Two NDK singletons on auctions: the client store (
src/lib/stores/ndk.ts, +235L auctions watchdog divergence,relay-policy.ts) and a server issuer singleton (src/server/ndk.ts,NDKPrivateKeySignerfor lightning invoices — Wave E territory).
The real migration surface (26 auction files with NDK refs)
| Bucket | Files | What |
|---|---|---|
| Read paths | src/queries/auctions.tsx (1139L, 14 fetchers + live bid subscription), src/queries/liveChat.tsx |
ndkActions.fetchEventsWithTimeout → seam fetchEvents; raw ndk.subscribe → seam subscribe |
| Publish paths | src/publish/auctions.tsx (1650L, 6 sign+publish lanes: create/delete/bid/path-release/settlement/claim), src/publish/liveChat.tsx |
new NDKEvent + event.sign(signer) + ndkActions.publishEvent → seam publish/sign (signer-gated) |
| NIP-17/59 private claim | publishAuctionClaimOrder gift-wrap path, privateAuctionClaimMessage.ts |
A1-pilot pattern already proven on the branch by queries/orders.tsx |
| Wallet / escrow | src/lib/stores/nip60.ts (2518L!) |
Bid-escrow engine grafted on @nostr-dev-kit/wallet (NDKCashuWallet/NDKZapper). Not a seam flip — a quarantine. Someone else owns migrating the wallet to coco; do not touch. |
| Type-only (Wave B) | ~21 files: AuctionBidder, AuctionCard, AuctionBidsContainer, AuctionCountdown, AuctionTimelineChart, dashboard routes, auctionBidderStatus.ts, utils/auctions.ts, + 9 test files |
import type { NDKEvent } → raw NostrEvent / seam re-exports. Mechanical. |
| Shared conflict-zone | src/publish/orders.tsx, src/publish/featured.tsx, dashboard index |
Master’s Wave C owns these; auctions inherits. |
Plan: P0–P5
P0 — Sync + seam baseline (prerequisite, parallel-safe)
- Merge master into auctions (gets applesauce 6.2 upgrade + adapter fixes + e2e stability sweep).
- Land missing seam helpers on the branch:
FetchOptionsonfetchNdkEventSet, newest-winsfetchNdkEvent,onEoseboundary on subscribe (cherry-pick from #1262 head with attribution, or land directly). - Re-baseline the stale guard (
scripts/ndk-baseline.txt, currently 161 vs actual ~157) to the guard-printed number so the ratchet becomes meaningful.
- Gate:
test:unit,tsc,format:check, footprint guard, e2e smoke. Nothing touches auction logic.
P1 — Wave-B sweep + read flips (mechanical, parallelizable)
- Swap type-only NDK imports → seam re-exports across the ~21 type-only auction files + 9 test files.
- Flip
queries/auctions.tsx: 14 fetchers →fetchNdkEventSet/fetchNdkEvent(preserve per-fetchtimeoutMs: 8000, blacklist filter, deterministic version-collapse), live bid subscription → seamsubscribewithonEose. - Flip
queries/liveChat.tsx. getUser()deep treatment onAuctionCard/auctions.$auctionId.
- Gate per batch: focused tests + full unit + tsc + format; ratchet baseline per batch.
P2 — Private-claim read/unwrap (A1 pattern, signer-gated)
fetchPrivateAuctionClaimForMarker + privateAuctionClaimMessage.ts, reusing the orders.tsx seam-rewrite pattern. Starts when the ADR-0008 signer seam (#1252) is available on the branch.
P3 — Publish lanes (signer-gated — the real critical path)
Split publish/auctions.tsx by mutation group, one commit each: (1) create/edit/delete auction, (2) publishAuctionBid (preserve lock-then-sign-then-publish ordering against nip60), (3) settlement + path-release, (4) claim order (gift-wrap → private relays with relay-targeting semantics). Money lanes get integration coverage on the local relay. All money-moving publish lanes are blocked on the signer seam (#1252) — flipping consumers before the signer chain lands would break bunker-buyer auction claims.
P4 — nip60 quarantine (last, independent)
Wallet stays NDK — coco wallet migration owned elsewhere. Pure reclaim/locktime logic already exported → extract to src/lib/auction/ TDD surface so money logic is seam-independent. Document the Wave-D carve-out.
P5 — Conflict-zone + capstone
Inherit master Wave C files (orders.tsx, featured.tsx, dashboard), then auction-side Wave-D-equivalent: delete the auction NDK singleton + io-ndk.ts except the wallet runtime and src/server/ndk.ts (Wave E).
Already done (found in prior work)
A worktree/branch chore/auctions-seam-flips on the felixfelix-bot fork already contains the P0 seam-helper prereqs and the P1 read flips for queries/auctions.tsx + queries/liveChat.tsx (commits bf4aec67…0cd21501, baseline ratcheted to 151). That work predates the current upstream/auctions head (ADR-0011 era) and needs a rebase onto current auctions + the 6.2 upgrade before it can land. The plan builds on it rather than restarting.
Explicitly out of scope
- Auction validator server +
contextvm/(already applesauce-native via@contextvm/sdk) - Pure auction libs (
src/lib/auction/*,auctionSettlement.ts) — zero NDK src/lib/stores/nip60.tswallet runtime (coco migration owned separately)src/server/ndk.ts(Wave E)
Controlling external dependency
P2/P3 (every money-moving publish) are blocked on the signer seam living on unmerged PR #1252 (adr/022-signer-migration, ADR-0008). P0 + P1 run fully in parallel with #1252/#1262 review. While waiting, publish-lane logic can be pre-refactored into pure event builders (mostly already true via tagBuilders.ts / settlementDescriptor.ts) so the eventual flip is a thin sign+publish swap.
Verification gates (every wave)
bun run test:unitbun run format:check- NDK-footprint guard ratchet (
scripts/check-ndk-footprint.sh) - Root-cause waves: relevant e2e specs, assertions unchanged
Related
- ADR-0002:
docs/adr/ADR-0002-nostr-io-migration-ndk-to-applesauce.md - Epic: PlebeianApp/market#1005
- ADR-0008 signer migration: PR #1252
- Seam read-path precedent: PR #1262 (
chore/wave1-queries)
- Reference: https://github.com/PlebeianApp/market
Write a comment