docs(superpowers): 5 design specs from PR-E + sipher#262 follow-up list#276
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Amendment added (commit
|
Adds compile-time exhaustiveness checks for the two discriminated-union switches that translate streaming events between layers — AgentCore.streamMessage and chunkToSSE in adapters/web.ts. Motivated by the cross-file plumbing drop caught at PR-E holistic review (sipher#262 commit f62b308): adding a new ResponseChunk variant requires coordinated edits across three files, and today's switches silently skip unhandled cases at runtime instead of failing at build time. Spec covers: assertNever helper at packages/agent/src/core/assert-never.ts, declared ChatStreamEvent union for the Pi event side, two patterns (narrowed-discriminant vs full-variant), test plan including type-only expectTypeOf assertions, and follow-ups (ResponseChunk → tagged union, codebase-wide switch audit, lint rule).
Proposes a proactive expiry SSE event so SignTxCards grey out when the
promise-gate TTL hits. Today the 5-minute timeout rejects the pending
signing promise but never notifies the SSE client — cards stay in
"pending sign" state indefinitely, late signs hit 404 confirm routes,
and the chat thread shows a confusing assistant turn next to an
unmarked clickable card.
Spec covers: event shape ({type, flagId, reason}), server emission via
the existing externalQueue mechanism (same path sentinel_pause uses),
onExpire callback wired into createPendingSigning, client-side message
expiry state with greyed-out SignTxCard rendering, test plan (server +
client + integration). Depends on the assertNever spec landing first
to catch the three-switch fanout at typecheck.
Today's POST /api/tool-signing/:flagId/confirm blindly trusts the client-supplied signature string. A compromised browser, buggy client, or replay attack can submit syntactically-valid garbage and Torque attribution fires for non-existent transactions. Spec adds RPC-based verification before resolvePendingSigning runs. Spec covers: three-tier verification (existence via getSignatureStatuses, sender-binding via getTransaction fee-payer check, instruction-match deferred), SIPHER_SIG_VERIFY=strict|advisory|off env flag mirroring the SENTINEL_MODE precedent, advisory-mode soak-test rollout path, latency budget (~250-1000ms acceptable), failure posture (closed-by-default with operator override), and risks including RPC quota burn, replay attack residual surface, and webhook-alternative tradeoffs.
Today's executeClaim is a Phase 1 stub — returns serializedTx: null and a placeholder "Stealth key derived" message without performing actual ECDH or building the on-chain claim_transfer instruction. Yet the Torque growth-hook fires sipher_private_claim_completed with the input deposit-tx signature as the emission key, polluting attribution. Spec covers: ECDH stealth-private-key recovery from announcement + viewing/spending keys, announcement parser, claim_tx builder (signs server-side with ephemeral stealth keypair, leaves fee-payer signature to the client via existing tool-signing wrapper), growth-hook adjustment to emit claim-tx signature instead of deposit-tx signature, viewing-key exposure surface analysis (sensitive — server-side ECDH delegation is a real trust step), test plan (announcement parsing, ECDH round-trip, end-to-end devnet flow), and follow-ups (SPL token path, client-side ECDH variant, in-flight claim dedupe).
…+ delegation) The crank (COURIER) ticks every 60s and picks up scheduled_ops rows, but executeTool routes through the tool-signing wrapper that requires real-time user signing — so scheduled ops "fail" silently after the 5-min promise-gate TTL. Spec defines per-tool execution strategies across three families. Spec covers: - Immediate batch (splitSend, consolidate): user signs N txs in one session via wallet.signAllTransactions; minutes horizon - Pre-signed durable nonce (scheduleSend, drip): user pre-signs N txs each anchored to a single-use durable nonce account at create time; server broadcasts at scheduled times; hours-to-weeks horizon - Wallet delegation (sweep, recurring): scope-limited authority via Squads Smart Account (Phase A) or custom sipher_delegation program (Phase B, future); indefinite horizon Plus: per-tool classification table, on-chain trust analysis for each family, COURIER hardening (backoff, single-flight, observability, atomic status CAS), test plan per family, risks (operator-key compromise, signed-tx blob leakage, privacy regression with Squads, recipient meta-address rotation), and a 3-PR rollout (PR-A durable nonce, PR-B Squads delegation, PR-C COURIER hardening).
The original Spec 4 (claim Phase 2) assumed the server would build
claim_transfer from scratch — own announcement parser, own ECDH
derivation, own partial-sign + serialize for client-side fee-payer
signing via the tool-signing wrapper.
Discovered during implementation scoping that @sip-protocol/sdk@^0.7.4
already exposes the complete primitive surface:
parseAnnouncement(memo) → SolanaAnnouncement | null
scanForPayments(params) → SolanaScanResult[]
claimStealthPayment(params) → { txSignature, destinationAddress, ... }
deriveStealthPrivateKey + deriveSolanaStealthKeys
claimStealthPayment is the kicker — it accepts the user's viewing+spending
private keys and internally derives the stealth privkey, builds
claim_transfer, signs with the stealth keypair, and BROADCASTS. The
SignTxCard / tool-signing wrapper flow from the original spec doesn't fit:
no client-side signing is needed because the SDK handles everything
server-side with delegated keys.
Amendment adds:
- "SDK reality check (2026-05-15)" section to the spec
- Path A: SDK-driven claim (recommended; ~3-4 hour scope; one-shot
server call; no SignTxCard; honest Torque attribution from day one)
- Path B: Fork SDK to separate build + broadcast (original spec's UX;
4-6 day scope; flagged as "security theater" since the keys are
already server-side regardless)
- Revised Implementation steps (5 steps, Path A)
- Revised test plan (5-6 tests instead of 15+)
- Revised migration / rollout (frontend changes none required)
- Path A-specific risks (stealth address resolution, SDK version drift)
The original Implementation / Test plan sections stay intact in the
document as the Path B reference if the consent-ceremony UX is later
prioritized.
Recommendation: ship Path A. Phase 1 stub is shipping incorrect Torque
attribution today (deposit-tx-sig instead of claim-tx-sig); Path A fixes
that in a small, focused PR. Path B can be a follow-up if RECTOR decides
the SignTxCard ceremony is worth the build cost.
331c302 to
9ec524c
Compare
Summary
Five design specs bundled as follow-ups to PR-E (#269 canonical Torque ingest) and PR #271 (sipher#262 signing callback). All proposed in spec form — none are implementation; each is sized 1 PR (or 3 PRs for the largest) and can be picked off independently. Ordered smallest → largest below.
Specs
2026-05-15-assert-never-exhaustiveness-design.md— Compile-time exhaustiveness guards on theAgentCore.streamMessage+chunkToSSEswitches. Closes the silent-drop trap caught at PR-E holistic review (sipher#262f62b308). Small (~0.5 day). Foundation for the other specs.2026-05-15-tool-signing-expired-sse-design.md—tool_signing_expiredSSE event soSignTxCardgreys out when the 5-min promise-gate TTL hits. Removes the "ghost card" UX. Small-medium (1-1.5 days).2026-05-15-server-side-sig-verification-design.md— Three-tiergetSignatureStatuses+getTransactionverification beforeresolvePendingSigningruns. AddsSIPHER_SIG_VERIFY=strict|advisory|offenv flag mirroring theSENTINEL_MODEprecedent. Medium (2-3 days).2026-05-15-claim-phase-2-design.md— Replace the Phase 1 claim stub with real ECDH derivation +claim_transferinstruction building. Surfaces the viewing-key-shared-with-server trust step that today's stub already implicitly accepts. Medium-large (4-6 days).2026-05-15-scheduled-op-broadcasts-design.md— Per-tool execution strategy fordrip/splitSend/sweep/consolidate/recurring/scheduleSend. Three families: immediate batch, pre-signed durable nonce, wallet delegation (Squads Smart Account → custom program). Largest (3 PRs across 2-3 weeks).Why a single bundled docs PR
The specs cross-reference each other (
[[name]]Wiki-link syntax). Most of them are coupled to the same surface —pending-signing.ts,ResponseChunk,chunkToSSE, the growth-hook emission table. Reviewing together surfaces the shared concerns; merging together prevents the cross-refs from being broken Wikilink dead-ends.If individual PRs are preferred for execution, splitting later is trivial — each spec is self-contained.
Status of each spec
All five are Proposed — awaiting RECTOR review. Nothing here ships behavior; each can be approved/revised/discarded independently.
Cross-references
Common dependencies, captured for review:
Test plan
docs/superpowers/specs/[[name]]) resolve to actual filenames in this PR