From d4a5513d712462fab2e4a707ad300066121510ba Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:11:29 +0800 Subject: [PATCH 001/144] Add Tier 1/Tier 2 simplification macro plan --- .planning/macro-plan/AGENT-HANDOFF.md | 162 +++++ .planning/macro-plan/DECISIONS.md | 109 +++ .planning/macro-plan/EVIDENCE-PLAN.md | 143 ++++ .planning/macro-plan/EXECUTION-SLICES.md | 679 ++++++++++++++++++ .planning/macro-plan/MACRO-PLAN.md | 201 ++++++ .../macro-plan/PROTECTED-ACTION-GATES.md | 135 ++++ .planning/macro-plan/README.md | 47 ++ .planning/macro-plan/REVIEW-GATES.md | 76 ++ .planning/macro-plan/RISKS.md | 101 +++ .planning/macro-plan/RUNTIME-GATES.md | 88 +++ .planning/macro-plan/TASKS.jsonl | 10 + .../audits/evidence.md | 342 +++++++++ .../audits/product-devex-design.md | 212 ++++++ .../audits/protected-action.md | 144 ++++ .../audits/runtime-agent.md | 210 ++++++ .../audits/slices.md | 182 +++++ .../blocked-checks.md | 34 + .../input.md | 88 +++ .../source-snapshot.md | 42 ++ .../validation.md | 31 + 20 files changed, 3036 insertions(+) create mode 100644 .planning/macro-plan/AGENT-HANDOFF.md create mode 100644 .planning/macro-plan/DECISIONS.md create mode 100644 .planning/macro-plan/EVIDENCE-PLAN.md create mode 100644 .planning/macro-plan/EXECUTION-SLICES.md create mode 100644 .planning/macro-plan/MACRO-PLAN.md create mode 100644 .planning/macro-plan/PROTECTED-ACTION-GATES.md create mode 100644 .planning/macro-plan/README.md create mode 100644 .planning/macro-plan/REVIEW-GATES.md create mode 100644 .planning/macro-plan/RISKS.md create mode 100644 .planning/macro-plan/RUNTIME-GATES.md create mode 100644 .planning/macro-plan/TASKS.jsonl create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/evidence.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/product-devex-design.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/protected-action.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/runtime-agent.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/slices.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md diff --git a/.planning/macro-plan/AGENT-HANDOFF.md b/.planning/macro-plan/AGENT-HANDOFF.md new file mode 100644 index 0000000..0dcf99c --- /dev/null +++ b/.planning/macro-plan/AGENT-HANDOFF.md @@ -0,0 +1,162 @@ +# Agent Handoff + +## Objective + +Implement the Tier 1/Tier 2 Handshake product simplification program in order, starting with the non-authority service workflow story and surface contract. The user wants the macro plan completed first, then implementation. The first executable slice is deliberately small in code footprint but strict in proof: create the simplified product surface without creating authority. + +## Source Boundary + +Read these first, in this order: + +1. `AGENTS.md` +2. `README.md` +3. `QUALITY.md` +4. `STRUCTURE.md` +5. `docs/internal/decisions.md` +6. `docs/internal/protocol-notes.md` +7. `docs/internal/protocol-layman.md` +8. `.planning/macro-plan/MACRO-PLAN.md` +9. `.planning/macro-plan/EXECUTION-SLICES.md` +10. `.planning/macro-plan/PROTECTED-ACTION-GATES.md` +11. `.planning/macro-plan/RUNTIME-GATES.md` +12. `.planning/macro-plan/TASKS.jsonl` + +`.planning/` is scratch except for this active execution handoff. Use it as planning evidence, not repo-facing product truth. + +## Runtime Profile + +Primary runtime is Codex in a workspace-write checkout with restricted network. Use `apply_patch` for edits. Use `rg` for discovery. Use focused tests before broad gates. Preserve dirty worktree state as user-owned. + +Multi-host posture is evidence-only: Codex, Claude Code, Hermes, OpenClaw, MCP, browser, A2A, OpenAPI, auth.md, and x402 do not share one runtime model. Do not claim native containment for any host from this plan. + +## Instruction Sources + +- `AGENTS.md`: invariant and doctrine. +- `QUALITY.md`: naming, quality, and boundary gates. +- `STRUCTURE.md`: source ownership. +- `docs/internal/*`: current product/protocol canon. +- `src/*/LANE.md`: lane ownership before source edits. +- `.planning/macro-plan/*`: execution program and stop conditions. + +## Context Bundle + +Core product move: + +```text +Passport -> evidence package the agent presents +ServiceWorkflowAdmission -> service-side accepted/refused/stale/proof-gap mapping +ServiceWorkflowHandle -> carried non-authority workflow context +Action Request -> fresh CandidateAction / ActionContract +Clearance -> PolicyDecision + one-use Greenlight/Refusal + GatewayCheck +Outcome -> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` + +Non-authority IDs: + +```text +passportPackageDigest +passportPresentationId +admissionId +serviceWorkflowHandleId +serviceWorkflowHandleDigest +``` + +All are correlation/reconstruction refs only. + +## Ignored Context + +Ignore older `.planning/macro/runs/20260525T141206-service-gateway-principal-agent-link/final/*` as a governing source. Treat historical Tier 3 plans as boundary reminders only. Do not use `.planning/` labels in repo-facing source, package scripts, public exports, or canonical docs. + +## Tool Contract + +Allowed: + +- read source, docs, tests, and planning artifacts; +- edit tracked docs, `src/surfaces`, architecture/product tests, examples, and narrowly related exports when required by the active slice; +- execute focused quality gates; +- use up to five subagents only when the user explicitly asks for delegation or sidecar work. + +Forbidden: + +- direct protected mutations outside user-authorized shell commands; +- broad network research unless requested or required for current unstable facts; +- rewriting protocol kernel state unless a slice proves a distinct enforceable transition; +- treating CLI, MCP, SDK, runtime ingress, docs, review screens, examples, certificates, passport IDs, or workflow handles as authority. + +## Subagent Topology + +Use sidecars only for non-overlapping review or implementation scopes: + +- product/docs; +- surface/schema; +- architecture tests; +- runtime/agent negative tests; +- evidence/release gate. + +No sidecar owns final authority claims, final plan status, or Tier 3 promotion. + +## Protected-Action Boundary + +Admission and handle stop before policy. Every protected action still requires: + +```text +CandidateAction +ActionContract +PolicyDecision +one-use Greenlight or Refusal +GatewayCheckAttempt +Receipt / Refusal / ProofGap +``` + +If a gateway cannot enforce before consequence, this is advisory, not Handshake. + +## Checkpoints + +- After macro-plan validation: git checkpoint. +- After Tier 1 story/schema/tests pass focused gates: git checkpoint. +- After docs convergence passes claims/format checks: git checkpoint. +- After Tier 2 example/runtime gates pass: git checkpoint. +- Before any Tier 3 work: stop and report proof state. + +## Stop Conditions + +Stop immediately if: + +- a Passport, Admission, Badge, or Handle object creates authority; +- `ServiceWorkflowHandle` is accepted as policy/gateway/signer/mutation evidence; +- raw credential, token, private key, `PaymentPayload`, or `PAYMENT-SIGNATURE` appears in passport/admission/handle records; +- a rendered review or docs summary is treated as permission; +- x402/auth.md fixture work precedes non-authority surface tests; +- Tier 3 work starts before Tier 1/Tier 2 proof gates close. + +## Evaluation Path + +Start narrow: + +```bash +npm run quality:claims +npm run quality:architecture +``` + +Then run focused slices: + +```bash +npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts +``` + +Use `npm run check:repo` before claiming implementation closeout. + +## Proof Gaps + +- No source-owned service workflow admission schema exists yet. +- No negative tests yet prove the five non-authority IDs cannot create authority. +- No local service workflow example exists yet. +- No live provider custody, settlement, hosted operation, or native host containment is proven. + +## Non-Claims + +This handoff does not authorize Tier 3, hosted operation, provider custody, settlement finality, marketplace trust, cross-org trust, broad x402 compatibility, aggregate spend enforcement, broad runtime interception, or native host containment. + +## Next Agent Step + +Implement Slice T1-01 and T1-02 together only far enough to make the boundary testable: add `docs/internal/service-workflow-story.md`, add `src/surfaces/service-workflow-admission.ts`, then add or update architecture tests so the new surface is provably non-authority. diff --git a/.planning/macro-plan/DECISIONS.md b/.planning/macro-plan/DECISIONS.md new file mode 100644 index 0000000..3da3f24 --- /dev/null +++ b/.planning/macro-plan/DECISIONS.md @@ -0,0 +1,109 @@ +# Decisions + +## DEC-001 + +- ID: DEC-001 +- Status: Accepted +- Decision: Proceed from the decision-gated macro map into a full Tier 1/Tier 2 macro plan. +- Rationale: The user explicitly authorized the full plan and implementation sequence after reviewing the goal. +- Source: User instruction and `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md`. +- Revisit Trigger: If sidecar review finds an authority violation that cannot be converted into a concrete gate. + +## DEC-002 + +- ID: DEC-002 +- Status: Accepted +- Decision: Keep Passport as a docs/story input noun only. +- Rationale: Passport helps users understand presented standing evidence but is too authority-shaped for protocol or API authority. +- Source: `.planning/macro-map/MACRO-MAP.md`, `views/DESIGN.md`, `views/AUTHORITY.md`. +- Revisit Trigger: If user comprehension evidence shows Passport consistently implies identity or permission even with cut lines. + +## DEC-003 + +- ID: DEC-003 +- Status: Accepted +- Decision: Use `ServiceWorkflowAdmission` as the source/API surface output. +- Rationale: It is narrower than standalone Admission and makes the service-side mapping explicit. +- Source: `.planning/macro-map/MECHANISM-MAP.md`, `views/ENG.md`, `.planning/codebase/CONCERNS.md`. +- Revisit Trigger: If implementation reveals a clearer non-authority noun with stronger tests. + +## DEC-004 + +- ID: DEC-004 +- Status: Accepted +- Decision: Use `ServiceWorkflowHandle` as the carried workflow context object. +- Rationale: It is less authority-loaded than Badge and can carry context/digest refs with explicit false authority flags. +- Source: `views/DESIGN.md`, `views/DEVEX.md`, `views/AGENT.md`, `views/RUNTIME.md`. +- Revisit Trigger: If developers still treat handle as reusable permission in tests or review. + +## DEC-005 + +- ID: DEC-005 +- Status: Accepted +- Decision: Keep Badge as optional narrative shorthand only. +- Rationale: Badge is memorable but reads like bearer auth. It must not become schema, route, export, or protocol object. +- Source: `.planning/macro-map/FACET-MAP.md`, `views/CEO.md`, `views/DESIGN.md`. +- Revisit Trigger: If product copy requires removing Badge entirely to preserve the boundary. + +## DEC-006 + +- ID: DEC-006 +- Status: Accepted +- Decision: Split passport/admission/workflow IDs into five non-authority refs. +- Rationale: Correlation and reconstruction need stable refs, but no ref may create authority. +- Source: User-provided invariant and current macro-plan input. +- Revisit Trigger: If source implementation requires additional digests for canonicalization or redaction. + +## DEC-007 + +- ID: DEC-007 +- Status: Accepted +- Decision: First implementation home is docs plus `src/surfaces`, not `src/protocol/areas`. +- Rationale: No new enforceable transition exists; current protocol primitives already represent evidence, attempt bounds, exact contracts, policy, gateway, and readback. +- Source: `.planning/codebase/ARCHITECTURE.md`, `.planning/codebase/STRUCTURE.md`, `STRUCTURE.md`. +- Revisit Trigger: Only if a future source design identifies a distinct terminal or state-transition event. + +## DEC-008 + +- ID: DEC-008 +- Status: Accepted +- Decision: Tier 2 examples and runtime convergence wait for Tier 1 schema and boundary tests. +- Rationale: Demo-first would overclaim the product story before authority boundaries are source-enforced. +- Source: `.planning/macro-map/EXECUTION-MAP.md`, `.planning/macro-map/PROTECTED-ACTION-MAP.md`. +- Revisit Trigger: If a non-source prototype is requested separately and clearly marked throwaway. + +## DEC-009 + +- ID: DEC-009 +- Status: Accepted +- Decision: Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit. +- Rationale: Hosted operation must consume proven local/source-owned surfaces, not expand the kernel or package surface prematurely. +- Source: `docs/internal/decisions.md`, macro-plan objective, prior Tier 3 boundary guidance. +- Revisit Trigger: If the user starts a separate hosted workspace with explicit Tier 3 scope. + +## DEC-010 + +- ID: DEC-010 +- Status: Rejected +- Decision: Do not make Passport a protocol primitive. +- Rationale: It would duplicate evidence and authority-adjacent records without adding a gateway-enforced transition. +- Source: `.planning/codebase/CONCERNS.md`, `.planning/macro-map/MECHANISM-MAP.md`. +- Revisit Trigger: A future protocol decision proves a distinct enforceable state. + +## DEC-011 + +- ID: DEC-011 +- Status: Rejected +- Decision: Do not sell passport validation as the bought authority unit. +- Rationale: The economic unit remains protected-event terminalization and reconstructable evidence. +- Source: `views/CEO.md`, `docs/internal/decisions.md`. +- Revisit Trigger: Paid pilot evidence proves a separate validation product without weakening authority claims. + +## DEC-012 + +- ID: DEC-012 +- Status: Deferred +- Decision: Defer live x402/auth.md composite service gateway demo. +- Rationale: The surface and non-authority tests must land before composite external rails. +- Source: `.planning/macro-map/PROTECTED-ACTION-MAP.md`, `.planning/codebase/INTEGRATIONS.md`. +- Revisit Trigger: T2-04 starts after Tier 1 and early Tier 2 gates pass. diff --git a/.planning/macro-plan/EVIDENCE-PLAN.md b/.planning/macro-plan/EVIDENCE-PLAN.md new file mode 100644 index 0000000..fe1d0ff --- /dev/null +++ b/.planning/macro-plan/EVIDENCE-PLAN.md @@ -0,0 +1,143 @@ +# Evidence Plan + +## Current Evidence + +The plan is grounded in canonical docs, the current macro map, and current codebase maps. Canon proves the authority chain and product-surface boundary. The macro map proves lens convergence around non-authority product simplification. The codebase maps identify source placement, tests, and proof gaps. Source implementation is still required for the new service workflow surface. + +Current structural validation result: + +```text +Macro plan output is valid. +``` + +Sidecar review result: all five assigned audit reports exist under `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/`. The reports recommend preserving protected-action, runtime, product, and evidence gates. The chair reconciliation narrows implementation readiness to the first Tier 1 story/schema/test slice and keeps protected-action fixtures, host containment claims, external rails, public-surface convergence, and Tier 3 blocked until source proof exists. + +## Verification Commands + +Macro-plan validation: + +```bash +/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +``` + +Observed output: + +```text +Macro plan output is valid. +``` + +Tier 1 documentation and surface verification: + +```bash +npm run quality:claims +npm run quality:architecture +npm run check:types +git diff --check +``` + +Protocol simplification focused verification: + +```bash +npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts +``` + +Tier 2 example and integration verification will use a new focused product test plus existing x402/auth.md gateway tests when those surfaces are touched. + +Full closeout: + +```bash +npm run format:check +npm run check:repo +``` + +## Replay And Refusal Cases + +Required cases: + +- handle reused after refusal; +- handle reused after proof gap; +- handle reused after consumed greenlight replay; +- changed payment amount or endpoint after admission; +- dynamic tool construction from handle; +- raw x402 payload supplied through admission; +- raw bearer/API token supplied through handle; +- gateway policy drift between admission and action request; +- credential-ref or authority-ref isolation before protected action; +- stale passport evidence or expired admission. + +Each case must stop before signer use, mutation, receipt export, or certificate minting unless a fresh exact contract clears through policy and gateway. + +## Review Prompts + +Use these review prompts before promoting implementation: + +- Does any simplified noun imply permission? +- Can the user approve admission while the later action contract differs? +- Can an agent pass the handle directly into a protected tool? +- Can generated code mutate through a sibling route after admission? +- Does the readback distinguish admission, policy, gateway, downstream, receipt, refusal, replay, and proof gap? +- Does every public claim match the current source proof ledger? +- Does Tier 3 remain blocked? + +## Fixtures Or Examples + +Planned fixture sequence: + +1. Local service workflow admission fixture emits JSON and Markdown. +2. Negative fixture attempts to use handle as authority and is refused. +3. Later x402 fixture uses handle as context to create one fresh `x402_payment.exact` action request. +4. Output separates admission readback from protected-action terminal evidence. + +Existing examples to mirror: + +- `examples/self-hosted-activation/` +- `examples/x402-protected-spend/` +- `examples/external-adapter-sdk/` +- `examples/x402-protected-tool-profiles/` +- `examples/mcp-reference-transcript/` + +## Readback And Redaction Checks + +Readback must omit: + +- raw credentials; +- provider secret paths; +- private keys; +- bearer/API tokens; +- raw x402 `PaymentPayload`; +- `PAYMENT-SIGNATURE`; +- raw internal protocol records unless route admission explicitly allows a safe internal read; +- mutation commands hidden inside handle fields. + +Readback must include: + +- explicit non-authority flags; +- accepted/refused/stale/proof-gap claim rows; +- digest/ref fields for reconstruction; +- fresh action contract requirement; +- proof gaps and next safe recovery moves. + +## Browser Or Visual Evidence + +No browser or visual evidence is required for the first Tier 1 implementation because this is source/docs/schema/test work. If a review renderer or UI is introduced later, visual QA must verify that admission, handle, clearance, receipt, refusal, and proof-gap states are visibly separate and not summarized as one approval badge. + +## Runtime Proof Artifacts + +Runtime artifacts to collect during Tier 2: + +- runtime ingress negative cases; +- MCP proposal/readback output; +- host profile posture rows; +- raw sibling bypass inventory; +- generated-execution graph evidence for loop/retry/dynamic-tool cases; +- proof-gap readback for unverified hosts. + +## Evidence Not Yet Available + +- user comprehension evidence for Passport/Admission/Badge naming; +- live external x402 provider/facilitator behavior; +- provider-grade auth.md credential custody; +- browser/A2A/OpenAPI gateway-owned protected path evidence; +- native containment for non-Codex hosts; +- hosted operation, provider custody, retention, org auth, or Tier 3 cloud evidence; +- market willingness to pay for passport validation as a standalone product. diff --git a/.planning/macro-plan/EXECUTION-SLICES.md b/.planning/macro-plan/EXECUTION-SLICES.md new file mode 100644 index 0000000..ff942ec --- /dev/null +++ b/.planning/macro-plan/EXECUTION-SLICES.md @@ -0,0 +1,679 @@ +# Execution Slices + +## Slice T0-00 - Macro Package And Review Reconciliation + +### ID + +T0-00 + +### Invariant Or Risk + +The plan itself can launder unresolved blockers into an executable-looking artifact. The chair must preserve source boundary, sidecar disagreement, non-proofs, and implementation gates. + +### Objective + +Produce a validated macro-plan package with source snapshot, sidecar reviews, evidence plan, runtime gates, protected-action gates, task records, and implementation entry. + +### Source Evidence + +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-map/FACET-MAP.md` +- `.planning/codebase/*` +- `README.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `gsd-macro-plan` references and validator + +### Inputs + +Run input, source snapshot, sidecar audit reports, macro-map package, codebase maps, canonical docs. + +### Outputs + +`.planning/macro-plan/*`, `TASKS.jsonl`, validation output, git checkpoint. + +### Dependencies + +User authorization to continue from the decision-gated macro map. + +### Owner + +Chair. + +### Stop Conditions + +- The plan claims authority, hosted operation, provider custody, native host containment, settlement, or Tier 3 readiness. +- Sidecar reports are missing and no fallback is recorded. +- Validator fails and the package is not revised. + +### Proof Gates + +- Validator reports the macro plan output is valid. +- Sidecar reports exist or missing reports are explicitly recorded. +- `git status --short` is inspected before committing. + +### Verification Commands Or Checks + +```bash +/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +git status --short +``` + +### Rollback Or Abandonment Criteria + +Abandon the executable status if a sidecar finds a live authority or runtime blocker that cannot be turned into a concrete implementation gate. + +### Agent Handoff Needs + +Fresh agent reads `AGENT-HANDOFF.md`, this file, `TASKS.jsonl`, `PROTECTED-ACTION-GATES.md`, and `RUNTIME-GATES.md`. + +## Slice T1-01 - Service Workflow Story + +### ID + +T1-01 + +### Invariant Or Risk + +Users need a simple story, but the story cannot imply permission. If a story says the agent is "admitted" without separating clearance, this is advisory, not Handshake. + +### Objective + +Create `docs/internal/service-workflow-story.md` that teaches the simplified flow and maps each noun to existing protocol/evidence objects. + +### Source Evidence + +- `.planning/macro-map/EXPERIENCE-MAP.md` +- `.planning/macro-map/views/DESIGN.md` +- `.planning/macro-map/views/DEVEX.md` +- `docs/internal/protocol-layman.md` +- `README.md` +- `docs/internal/protocol-notes.md` + +### Inputs + +Noun set: Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, Outcome. Five non-authority IDs. Canonical protocol chain. + +### Outputs + +`docs/internal/service-workflow-story.md` + +### Dependencies + +T0-00. + +### Owner + +Product/docs implementer. + +### Stop Conditions + +- The doc says Passport, Admission, Badge, Handle, Certificate, or review creates permission. +- The doc collapses admission and clearance. +- The doc lacks refusal, proof-gap, replay, or isolation recovery states. + +### Proof Gates + +- Story states Passport is evidence package only. +- Story states Admission is service-side accepted/refused/stale/proof-gap mapping only. +- Story states Handle is workflow context only and requires fresh action contracts. +- Story states Clearance is exact policy plus one-use greenlight/refusal plus gateway check. +- Story states Outcome is receipt/refusal/replay refusal/proof gap/certificate evidence, not downstream success. + +### Verification Commands Or Checks + +```bash +npm run quality:claims +git diff --check +``` + +### Rollback Or Abandonment Criteria + +Revert the doc slice if claim-boundary tests reject the language or if the doc needs a new authority primitive to make the story coherent. + +### Agent Handoff Needs + +Read `docs/internal/protocol-layman.md` and keep the new story shorter than a protocol spec but strict about non-authority. + +## Slice T1-02 - Surface Contract And Non-Authority IDs + +### ID + +T1-02 + +### Invariant Or Risk + +A product surface can create implied authority through fields and exports even when text says otherwise. + +### Objective + +Create `src/surfaces/service-workflow-admission.ts` defining `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, authority boundary fields, claim rows, and the five non-authority IDs. + +### Source Evidence + +- `.planning/macro-map/MECHANISM-MAP.md` +- `.planning/macro-map/views/ENG.md` +- `.planning/macro-map/views/AUTHORITY.md` +- `.planning/codebase/STRUCTURE.md` +- `.planning/codebase/CONVENTIONS.md` +- `src/surfaces/outcome.ts` +- `src/surfaces/boundary-manifest.ts` + +### Inputs + +Existing surface non-authority field conventions, Zod schema style, strict TypeScript settings. + +### Outputs + +- `src/surfaces/service-workflow-admission.ts` +- possibly `src/surfaces/index.ts` export if package posture allows, guarded by tests + +### Dependencies + +T1-01. + +### Owner + +Surface/schema implementer. + +### Stop Conditions + +- The file imports protocol internals that create policy, greenlight, gateway, receipt, certificate, store, or adapter authority. +- The schema carries raw token, key, `PaymentPayload`, `PAYMENT-SIGNATURE`, signer, credential material, receipt export, or certificate material. +- The schema can widen resources, actions, spend, gateway, or policy bounds. + +### Proof Gates + +- `createsAuthority: false` +- `createsPolicyDecision: false` +- `createsGreenlight: false` +- `performsGatewayCheck: false` +- `permitsMutation: false` +- `exportsReceipt: false` +- `mintsTerminalCertificate: false` +- `freshActionContractRequired: true` +- IDs defined: `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, `serviceWorkflowHandleDigest` + +### Verification Commands Or Checks + +```bash +npm run quality:architecture +npm run check:types +``` + +### Rollback Or Abandonment Criteria + +Abandon source surface if a distinct enforceable protocol transition is truly required; return to macro planning before adding protocol state. + +### Agent Handoff Needs + +Study existing `src/surfaces/outcome.ts` and `src/surfaces/boundary-manifest.ts`; follow their non-authority style. + +## Slice T1-03 - Naming, Claim, And Surface Boundary Guards + +### ID + +T1-03 + +### Invariant Or Risk + +Friendly nouns can drift into protocol areas, runtime dispatch, gateway execution, root exports, or public claims. + +### Objective + +Add architecture and claim-boundary tests for Passport, Admission, Badge, `ServiceWorkflowAdmission`, and `ServiceWorkflowHandle`. + +### Source Evidence + +- `.planning/codebase/TESTING.md` +- `.planning/codebase/CONCERNS.md` +- `test/architecture/naming-posture.test.ts` +- `test/architecture/claim-boundary.test.ts` +- `test/architecture/surface-boundary-posture.test.ts` +- `test/architecture/root-exports.test.ts` + +### Inputs + +Existing architecture tests and package export posture. + +### Outputs + +- `test/architecture/workflow-admission-boundary.test.ts` or extensions to existing architecture tests +- claim-boundary vocabulary updates where needed + +### Dependencies + +T1-02. + +### Owner + +Architecture-test implementer. + +### Stop Conditions + +- Tests rely only on prose while source exports can still imply authority. +- Tests allow `Badge` as API/schema/protocol noun. +- Tests allow handle fields to satisfy policy, gateway, signer, mutation, receipt, or certificate material. + +### Proof Gates + +- Surface object stays out of `src/protocol/areas/*`. +- Surface object stays out of gateway adapter execution paths. +- Root exports remain curated. +- Forbidden raw credential/payment/material fields are rejected. +- Non-authority booleans are required. + +### Verification Commands Or Checks + +```bash +npm run quality:claims +npm run quality:architecture +``` + +### Rollback Or Abandonment Criteria + +If guards become too string-scanny to prove boundary, add schema-level tests and import-boundary checks before continuing. + +### Agent Handoff Needs + +Do not weaken existing architecture tests to admit the new surface. + +## Slice T1-04 - Canonical Docs Convergence + +### ID + +T1-04 + +### Invariant Or Risk + +Docs can diverge: README may teach x402 mechanics while internal docs teach Passport/Admission, producing two product models. + +### Objective + +Converge canonical docs on the simplified flow while preserving the current product kernel and proof ledger. + +### Source Evidence + +- `README.md` +- `QUALITY.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/protocol-layman.md` +- `docs/internal/service-workflow-story.md` + +### Inputs + +Completed story and surface schema. + +### Outputs + +Tightly scoped documentation patches, not a broad rewrite. + +### Dependencies + +T1-01, T1-02, T1-03. + +### Owner + +Docs implementer. + +### Stop Conditions + +- Docs imply public package availability, MCP Registry, certificate, passport, or handle creates authority. +- Docs claim Tier 3 hosted operation or external provider custody. +- Docs remove proof gaps to sound simpler. + +### Proof Gates + +- `quality:claims` passes. +- Docs mention the simplified flow and exact protected-action chain together. +- Tier 3 remains blocked by explicit source gate. + +### Verification Commands Or Checks + +```bash +npm run quality:claims +npm run format:check +``` + +### Rollback Or Abandonment Criteria + +Revert doc convergence if it creates a second inconsistent product story. + +### Agent Handoff Needs + +Patch canonical docs only after source schema and tests exist. + +## Slice T2-01 - SDK / CLI / MCP Surface Alignment + +### ID + +T2-01 + +### Invariant Or Risk + +Developer surfaces can make admission feel executable if they expose a handle before explaining clearance. + +### Objective + +Align SDK role-client guidance, CLI readback language, and MCP metadata/resource descriptions with the simplified product model without adding execution authority. + +### Source Evidence + +- `README.md` +- `src/cli/command-manifest.ts` +- `src/mcp/catalog.ts` +- `src/mcp/resources.ts` +- `src/sdk/surface-clients/index.ts` +- `.planning/codebase/STACK.md` +- `.planning/codebase/CONVENTIONS.md` + +### Inputs + +Tier 1 schema and docs. + +### Outputs + +Surface language updates, readback helper shapes, or docs-only references depending on source fit. + +### Dependencies + +T1-04. + +### Owner + +Surface integration implementer. + +### Stop Conditions + +- CLI gains mutation-shaped commands for admission. +- MCP tool exposure expands beyond proposal/evidence. +- SDK clients infer authority from admission readback. + +### Proof Gates + +- CLI command posture remains evidence/readiness/readback only. +- MCP remains proposal/evidence only. +- SDK role clients remain role-scoped and do not accept handle as permission. + +### Verification Commands Or Checks + +```bash +npm run quality:architecture +npm run test -- test/architecture/cli-command-posture.test.ts test/architecture/mcp-surface-posture.test.ts test/sdk/role-clients.test.ts +``` + +### Rollback Or Abandonment Criteria + +If alignment needs new public exports, pause for export posture review before continuing. + +### Agent Handoff Needs + +Keep changes sparse; do not redesign CLI/MCP. + +## Slice T2-02 - Local Service Workflow Example + +### ID + +T2-02 + +### Invariant Or Risk + +A demo can accidentally become a product claim if it hides proof gaps or implies live provider execution. + +### Objective + +Create a local example that emits JSON and Markdown showing Passport presentation, service admission, workflow handle, fresh x402 action request, and separated readback states. + +### Source Evidence + +- `examples/self-hosted-activation/` +- `examples/x402-protected-spend/` +- `examples/external-adapter-sdk/` +- `test/product/*` +- `.planning/macro-map/EXPERIENCE-MAP.md` +- `.planning/macro-map/PROTECTED-ACTION-MAP.md` + +### Inputs + +Tier 1 schema and tests. + +### Outputs + +- `examples/service-workflow-admission/` +- product test for example output +- generated output contract in JSON and Markdown + +### Dependencies + +T2-01. + +### Owner + +Example implementer. + +### Stop Conditions + +- Example claims live provider custody, hosted operation, settlement, broad x402 compatibility, or host containment. +- Example skips fresh `ActionContract`. +- Example treats handle readback as receipt evidence. + +### Proof Gates + +- Output includes false authority flags. +- Output distinguishes admission evidence from protected-action receipt/refusal/proof-gap. +- Product test asserts the example’s non-claims. + +### Verification Commands Or Checks + +```bash +npm run demo:service-workflow-admission +npm run test -- test/product/service-workflow-admission.test.ts +``` + +### Rollback Or Abandonment Criteria + +Defer the example if it requires a new live external rail to look convincing. + +### Agent Handoff Needs + +Use existing examples as style references; emit stable Prettier-friendly JSON and Markdown. + +## Slice T2-03 - Runtime And Generated-Agent Misuse Tests + +### ID + +T2-03 + +### Invariant Or Risk + +Generated agents will reuse a handle in loops, retries, dynamic tool calls, stale review flows, browser/network paths, or raw sibling calls unless negative cases make that impossible to miss. + +### Objective + +Add runtime/product tests proving handle/admission cannot authorize protected actions and must recraft fresh action requests after drift, refusal, replay, proof gap, or isolation. + +### Source Evidence + +- `.planning/macro-map/AGENT-RUNTIME-MAP.md` +- `.planning/macro-map/views/AGENT.md` +- `.planning/macro-map/views/RUNTIME.md` +- `src/runtime/ingress/index.ts` +- `src/runtime/ingress/schemas.ts` +- `test/runtime/runtime-ingress.test.ts` + +### Inputs + +Tier 1 schema, local example, runtime ingress tests. + +### Outputs + +Focused negative tests and updated evidence plan. + +### Dependencies + +T2-02. + +### Owner + +Runtime test implementer. + +### Stop Conditions + +- Tests require native host containment to pass. +- Tests treat runtime ingress as enforcement. +- Tests rely on a rendered review screen as permission. + +### Proof Gates + +- Loops and retries require fresh action contracts. +- Dynamic tool construction is refused or proof-gapped. +- Raw sibling bypass posture is visible. +- Stale rendered review cannot authorize changed parameters. + +### Verification Commands Or Checks + +```bash +npm run test -- test/runtime/runtime-ingress.test.ts +npm run quality:architecture +``` + +### Rollback Or Abandonment Criteria + +If runtime tests expose a source bug in current ingress posture, stop implementation and fix the source bug before continuing product polish. + +### Agent Handoff Needs + +Do not claim browser, A2A, OpenAPI, Hermes, OpenClaw, Claude Code, or generic MCP containment from local tests. + +## Slice T2-04 - x402 / auth.md Protected-Action Fixture Gate + +### ID + +T2-04 + +### Invariant Or Risk + +The first fixture that connects service workflow admission to a protected action can imply that admission cleared spend. + +### Objective + +Connect one admitted workflow context to one fresh buyer-side `x402_payment.exact` action request, preserving auth.md as provenance if included and x402 as one exact per-call protected action. + +### Source Evidence + +- `src/adapters/x402-payment/*` +- `src/adapters/auth-md/*` +- `examples/x402-protected-spend/` +- `test/adapters/x402-wallet-gateway.test.ts` +- `test/integration/x402-d1-http.test.ts` +- `.planning/macro-map/PROTECTED-ACTION-MAP.md` + +### Inputs + +Tier 1/Tier 2 admission example and runtime misuse tests. + +### Outputs + +Fixture or product test proving fresh contract, policy, gateway check, replay refusal, and proof-gap separation. + +### Dependencies + +T2-03. + +### Owner + +Protected-action fixture implementer. + +### Stop Conditions + +- `PaymentPayload` or `PAYMENT-SIGNATURE` enters passport/admission/handle. +- Signer invocation occurs before verified gateway evidence. +- Fixture claims live provider custody, settlement, facilitator operation, seller middleware, or aggregate spend. + +### Proof Gates + +- Fresh `ActionContract` is created for the protected action. +- Policy and gateway evidence remain separate. +- Replay refusal and downstream proof gap are recorded distinctly. +- Handle is context only. + +### Verification Commands Or Checks + +```bash +npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts +npm run quality:claims +``` + +### Rollback Or Abandonment Criteria + +Defer auth.md composite behavior unless credential holder, gateway holder, refusal boundary, and raw credential redaction are source-proven. + +### Agent Handoff Needs + +Treat x402/auth.md as evidence rails until exact clearance; do not merge them into a composite authority artifact. + +## Slice T2-05 - Tier 3 Lock And Release Gate + +### ID + +T2-05 + +### Invariant Or Risk + +Hosted Tier 3 pressure can pull unfinished product simplification into hosted claims and package creep. + +### Objective + +Add a release/admission gate stating Tier 3 cannot consume or extend the simplified surface until Tier 1 and Tier 2 gates are verified or proof-gapped. + +### Source Evidence + +- `docs/internal/decisions.md` +- `.planning/macro-map/MACRO-HANDOFF.md` +- Memory-derived prior Tier 3 boundary guidance +- `README.md` + +### Inputs + +Completed Tier 1/Tier 2 gates. + +### Outputs + +Decision entry or internal gate doc update, plus final repo gate evidence. + +### Dependencies + +T2-04. + +### Owner + +Release gate owner. + +### Stop Conditions + +- Tier 3 hosted operation starts from unverified local surface behavior. +- Protocol kernel exports expand for hosted needs without separate Tier 1/Tier 2 proof. +- Product language claims clearing-house, marketplace, certification, settlement, or cross-org trust. + +### Proof Gates + +- `npm run check:repo` passes. +- Tier 3 proof gaps are explicit. +- Any required hosted workspace boundary is recorded separately. + +### Verification Commands Or Checks + +```bash +npm run check:repo +git status --short +``` + +### Rollback Or Abandonment Criteria + +If Tier 3 needs a kernel change, split it back into Tier 1/Tier 2 before hosted work continues. + +### Agent Handoff Needs + +Do not implement hosted operation in this checkout as part of simplification unless the user explicitly opens a separate Tier 3 workspace. diff --git a/.planning/macro-plan/MACRO-PLAN.md b/.planning/macro-plan/MACRO-PLAN.md new file mode 100644 index 0000000..23ed099 --- /dev/null +++ b/.planning/macro-plan/MACRO-PLAN.md @@ -0,0 +1,201 @@ +# Macro Plan + +## Invariant At Stake + +Tier 1 and Tier 2 product simplification may hide protocol complexity from users, but it must not hide authority. A user can see a clean flow, an agent can carry a workflow handle, and a service can accept standing evidence, but no Passport, Admission, Badge, Handle, Certificate, review screen, or ID can become identity, permission, reusable auth, policy approval, gateway acceptance, signer permission, receipt export, terminal certification, or mutation authority. + +The protected-action invariant remains exact: + +```text +standing evidence +-> service-side admission/readback +-> bounded workflow context +-> fresh protected-action request +-> exact ActionContract +-> PolicyDecision +-> one-use Greenlight or Refusal +-> GatewayCheck before mutation +-> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` + +## Source Boundary + +| Source | Role | Status | +| --- | --- | --- | +| `.planning/macro-map/MACRO-HANDOFF.md` | Handoff from Passport / Admission / Badge macro map | Decision-gated, now user-authorized for full planning | +| `.planning/macro-map/MACRO-MAP.md` | Selected macro move and non-proofs | Derived planning evidence | +| `.planning/macro-map/FACET-MAP.md`, `views/*.md` | CEO, ENG, DESIGN, DEVEX, AGENT, RUNTIME, AUTHORITY pressure | Independent lens evidence | +| `.planning/macro-map/MECHANISM-MAP.md`, `EXECUTION-MAP.md`, `EXPERIENCE-MAP.md`, `AGENT-RUNTIME-MAP.md`, `PROTECTED-ACTION-MAP.md` | Mechanism, sequencing, experience, runtime, and authority maps | Required plan inputs | +| `.planning/codebase/ARCHITECTURE.md`, `STRUCTURE.md`, `CONVENTIONS.md`, `TESTING.md`, `CONCERNS.md`, `INTEGRATIONS.md`, `STACK.md` | Placement, testing, conventions, proof gaps, integrations, and package posture | Derived evidence; source-check during implementation | +| `README.md`, `QUALITY.md`, `STRUCTURE.md` | Package posture, quality language, source ownership | Canon | +| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Product kernel, proof ledger, expansion admission, current protocol notes | Canon | +| `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md` | Definition, architecture, and plain-language translation | Canon | +| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/*` | Input packet, source snapshot, blocked checks, sidecar audits, validation | Current run evidence | + +## Current Evidence + +The current kernel already has the protected-action authority spine: exact contracts, policy decisions, one-use greenlights/refusals, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. Canonical docs make product surfaces non-authority by definition. Runtime ingress is proposal-only. MCP is proposal/evidence-only. CLI and SDK surfaces are role-scoped but do not infer authority from evidence reads. Gateway adapters mutate only after verified gateway evidence. + +The macro map converges on the same architectural conclusion: do not add a Passport protocol primitive; do not make Admission a policy decision; do not make Badge reusable auth. The right product simplification is a surface/readback layer that translates standing evidence into service workflow admission, then forces every protected action into fresh clearance. + +The codebase map points to `src/surfaces` as the first implementation home. It also names the verification lanes: claim-boundary tests, naming-posture tests, surface-boundary posture tests, protocol compilation/policy/gateway tests, runtime-ingress tests, and product/demo tests when examples change. + +## Non-Proofs + +This plan does not prove live x402 provider custody, settlement finality, seller middleware, facilitator operation, broad x402 compatibility, hosted operation, external registry lookup, marketplace trust, cross-org passport trust, native host containment, browser-side control, aggregate spend enforcement, provider-grade auth.md credential lifecycle, or Tier 3 hosted product readiness. + +It also does not prove that users will interpret Badge correctly. The plan resolves that by using `ServiceWorkflowHandle` as the source/API noun and treating Badge as optional narrative copy only. User-facing simplicity must come from state separation and explicit non-authority fields, not from a magical noun. + +## Selected Macro Move + +Build a two-tier simplification program: + +```text +Tier 1: Source-owned non-authority surface contract + -> service workflow story + -> ServiceWorkflowAdmission / ServiceWorkflowHandle schema + -> non-authority ID fields + -> architecture and claim-boundary guards + -> docs and plain-language convergence + +Tier 2: Activation and readback convergence + -> SDK/CLI/MCP/example surfaces use the same model + -> generated-agent and runtime misuse gates + -> local fixture connects admitted workflow context to one fresh x402 exact action request + -> receipt/refusal/proof-gap readback remains event-specific + -> Tier 3 remains blocked until proof gates pass or proof gaps are explicit +``` + +The five non-authority ID fields are part of the surface contract only: + +```text +passportPackageDigest +passportPresentationId +admissionId +serviceWorkflowHandleId +serviceWorkflowHandleDigest +``` + +Each field must carry `createsAuthority: false` at the surface-object level and must not satisfy policy, gateway, signer, mutation, receipt, or certificate requirements. + +## Plan Status + +`READY_FOR_AGENT_EXECUTION` + +The executable claim is narrow: a bounded agent can start the first implementation slice from `AGENT-HANDOFF.md` without chat-only context. This status does not mean all Tier 1/Tier 2 work is implemented, and it does not mean Tier 3 can start. Former decision-gated concerns are resolved into implementation gates: the user accepted a full plan plus implementation sequence, while non-authority, runtime, protected-action, evidence, and review checks remain required stop conditions. + +## Execution Thesis + +The simplification succeeds by changing the user’s first model, not by changing the authority spine. + +The user should see: + +```text +Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome +``` + +The implementation must still preserve: + +```text +Evidence refs -> CandidateAction -> ActionContract -> PolicyDecision -> one-use Greenlight/Refusal -> GatewayCheck -> Receipt/Refusal/ProofGap +``` + +Tier 1 creates the non-authority model and proves it cannot create authority. Tier 2 connects that model to activation, runtime, and example surfaces so developers do not meet raw protocol internals first. Tier 3 stays locked until the local/source-owned simplification path is coherent. + +## Non-Goals + +- Do not add `Passport`, `Admission`, `Badge`, or `ServiceWorkflowHandle` as protocol primitives. +- Do not widen `OperatingEnvelope.allowedResources` from a passport or handle. +- Do not let a handle become a bearer token, greenlight, gateway pass, credential ref, signer input, payment payload, receipt, certificate, or mutation command. +- Do not claim hosted operation, provider custody, settlement, marketplace trust, cross-org trust, native host containment, aggregate spend enforcement, live provider verification, or Tier 3 readiness. +- Do not turn `.planning/` artifacts into repo-facing source names, package scripts, public exports, or canonical docs. +- Do not build a full x402/auth.md live demo before surface non-authority gates exist. + +## Target State + +Tier 1 target state: + +- `docs/internal/service-workflow-story.md` explains Passport, Service Admission, Workflow Handle, Action Request, Clearance, and Outcome in plain language. +- `src/surfaces/service-workflow-admission.ts` defines `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` as non-authority product-surface records. +- Tests prove the new surface cannot create or satisfy policy, greenlight, gateway check, mutation, receipt, certificate, signer use, payment material, raw credentials, or resource widening. +- Canonical docs use the simplified flow without overclaiming. + +Tier 2 target state: + +- README first-use, protocol-layman docs, SDK role-client guidance, CLI/MCP descriptions, and examples converge on the same simplified flow. +- A local example emits JSON and Markdown for service workflow admission and a fresh x402 action request path. +- Runtime and generated-agent negative cases cover loops, retries, branches, dynamic tool construction, stale review, changed observed parameters, raw sibling bypass, replay, proof gaps, and isolation. +- Product tests prove admission/readback and protected-action outcome evidence remain separate. + +## Decisions + +- Accept `Passport` as a docs/story input noun only. +- Accept `ServiceWorkflowAdmission` as the source/API surface output noun. +- Accept `ServiceWorkflowHandle` as the carried workflow context noun. +- Treat `Badge` as optional narrative shorthand only; do not make it a schema, protocol, export, or route noun. +- Split non-authority IDs into `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, and `serviceWorkflowHandleDigest`. +- Keep the first implementation in docs, `src/surfaces`, architecture tests, and product tests before any x402/auth.md fixture expansion. +- Keep Tier 3 blocked until Tier 1/Tier 2 gates are verified or explicitly recorded as proof gaps. + +## Blocking Concerns + +The plan carries strict implementation gates: + +- Non-authority flags are mandatory on admission and handle objects. +- The handle must not be accepted as policy, gateway, signer, mutation, receipt, or certificate evidence. +- Multi-host runtime posture must stay host-specific and proof-gap aware. +- Source placement must remain outside protocol areas unless a future source-owned transition proves a new enforceable state. +- Product docs must include exact fields, failure states, and proof gates; metaphor-only docs are insufficient. +- Protected-event terminalization remains the economic unit; passport validation is adoption plumbing, not the bought authority claim. + +## Runtime And Protected-Action Summary + +Runtime posture: + +| Target | Evidence | Posture | +| --- | --- | --- | +| Codex | Existing local profile/readiness and MCP proposal evidence | Strongest local profile; no host-wide containment claim | +| Claude Code | Managed/profile parity artifacts in current x402 protected-tool lane | Profile evidence only | +| Hermes | Tool-packet/profile artifact | Profile evidence only | +| OpenClaw | Tool-packet/profile artifact | Profile evidence only | +| MCP | Local proposal/evidence server and read-only resources | Proposal/readback only | +| x402 | One buyer-side exact per-call local proof lane | Protected-action family; no live provider/settlement claim | +| auth.md | Provenance and credential-custody evidence profile | Evidence and future protected API call family | +| Browser, A2A, OpenAPI | Operation, route, and side-channel evidence contexts | Proof-gap surfaces until gateway-owned path exists | + +Protected-action posture: the first Tier 2 fixture may connect an admitted workflow handle to one `x402_payment.exact` action request, but only after the handle is proven non-authority. The handle may help populate context and evidence refs. It cannot skip candidate action, exact contract, policy, one-use greenlight/refusal, gateway check, or terminal readback. + +## Verification Gates + +- Execute `npm run quality:claims` after canonical docs or public language changes. +- Execute `npm run quality:architecture` after source surfaces, naming, exports, CLI, MCP, SDK, or adapter posture changes. +- Execute the focused protocol simplification slice when proposal/evidence/readback paths change: `npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts`. +- Execute product/demo tests after adding the service workflow example. +- Execute `npm run format:check` and `npm run check:repo` before claiming implementation closeout. +- Validate this macro-plan package with `/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan`. + +## Risks And Proof Gaps + +Primary risk: the friendly product layer becomes authority-shaped. The mitigation is schema-level non-authority flags, architecture gates, product tests, runtime negative cases, and refusal/proof-gap readback. + +Secondary risk: Tier 2 tries to prove too much too early. The mitigation is a local/source-owned fixture first, explicit non-claims, and no live-provider or hosted claim until a separate evidence packet proves it. + +Long-run risk: Tier 3 pressure causes kernel/package creep. The mitigation is a hard gate: Tier 3 may consume the simplified Tier 1/Tier 2 surface only after source gates pass; if Tier 3 needs kernel changes, those return as separate Tier 1/Tier 2 work. + +## Handoff To Phase Planning + +Detailed phase planning should start from `EXECUTION-SLICES.md`, not from chat memory. Slice T1-01 is the first implementation step: create the internal story doc and source-owned surface contract skeleton in a way that is immediately testable. Slice T1-02 and T1-03 add the strict schema and guard tests. Tier 2 slices begin only after Tier 1 gates pass. + +Fresh agents must read `AGENT-HANDOFF.md`, `PROTECTED-ACTION-GATES.md`, `RUNTIME-GATES.md`, and `TASKS.jsonl` before editing source. They must source-open named files before implementation and preserve user-owned dirty state. + +## Smallest Next Mechanism + +Implement the Tier 1 surface spine: + +```text +docs/internal/service-workflow-story.md +src/surfaces/service-workflow-admission.ts +test/architecture/workflow-admission-boundary.test.ts +``` + +The story and schema must define the five non-authority IDs, require fresh action contracts for protected events, and prove the surface cannot create authority. diff --git a/.planning/macro-plan/PROTECTED-ACTION-GATES.md b/.planning/macro-plan/PROTECTED-ACTION-GATES.md new file mode 100644 index 0000000..cb93019 --- /dev/null +++ b/.planning/macro-plan/PROTECTED-ACTION-GATES.md @@ -0,0 +1,135 @@ +# Protected-Action Gates + +## Source Boundary + +| Source | Protected-Action Role | Status | +| --- | --- | --- | +| `.planning/macro-map/PROTECTED-ACTION-MAP.md` | Authority, gateway, bypass, and readback map | Derived gate input | +| `.planning/macro-map/views/AUTHORITY.md` | Non-authority and field-boundary pressure | Lens evidence | +| `.planning/macro-map/views/RUNTIME.md` | x402/auth.md and host-profile proof gaps | Lens evidence | +| `.planning/codebase/ARCHITECTURE.md`, `CONCERNS.md`, `INTEGRATIONS.md` | Current authority placement and integration boundaries | Derived codebase evidence | +| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Canon product/protocol boundary | Canon | +| `src/adapters/x402-payment/wallet-gateway.ts` | Current signer boundary after verified gateway evidence | Source anchor for implementation phase | +| `src/adapters/auth-md/gateway.ts` | Current credentialed API fixture after verified gateway evidence | Source anchor for implementation phase | + +## Protected-Action Triggers + +Protected-action gates apply when an admitted workflow attempts: + +- `x402_payment.exact`; +- `auth_md_protected_api_call.exact`; +- credentialed service call; +- external API mutation; +- package install, repo write, preview deploy, cloud config, CI/release, or database/data-plane mutation; +- browser-side paid or consequential action; +- any generated tool call with side effects. + +## Candidate Actions + +The admission surface may help produce context for a fresh candidate action. It cannot be the candidate action. It cannot be an action contract. It cannot carry a policy result. It cannot carry a one-use greenlight. It cannot carry gateway check evidence. + +First admitted Tier 2 candidate: + +```text +serviceWorkflowHandle -> fresh x402_payment.exact action request -> ActionContract +``` + +The handle is context and evidence refs only. + +## Authority Boundary + +Authority begins at exact policy evaluation over an `ActionContract`, then proceeds to one-use greenlight/refusal and gateway check. Admission and handle surfaces must explicitly state: + +```text +createsAuthority: false +createsPolicyDecision: false +createsGreenlight: false +performsGatewayCheck: false +permitsMutation: false +exportsReceipt: false +mintsTerminalCertificate: false +freshActionContractRequired: true +``` + +## Gateway Or Enforcement Boundary + +The gateway check remains the final pre-mutation enforcement point. For x402, payment material and `PAYMENT-SIGNATURE` remain behind the gateway and only appear after verified gateway evidence. For auth.md, raw credential material remains outside protocol records and credential resolution occurs after gateway check. + +If a path cannot enforce at the gateway before mutation, this is advisory, not Handshake. + +## Raw Sibling Or Bypass Posture + +The plan must preserve raw sibling posture: + +- raw x402 payment payload input is forbidden; +- raw bearer/API tokens are forbidden; +- direct HTTP, MCP, browser, package manager, shell, network, cloud, deploy, or database paths are bypass/proof-gap surfaces unless wrapped by a gateway-owned protected path; +- dynamic endpoint/tool construction requires refusal or recrafting; +- stale metadata, changed observed parameters, consumed greenlight replay, idempotency mismatch, gateway policy drift, authority-ref isolation, and credential-ref isolation require refusal or a fresh exact contract. + +## Field-Level Acceptance Matrix + +| Field Or Surface | May Carry | Must Not Carry | Authority Posture | +| --- | --- | --- | --- | +| `passportPackageDigest` | digest of evidence bundle | identity trust, spend approval, signer material | evidence only | +| `passportPresentationId` | unique intake/presentation ref | policy decision, gateway admission | correlation only | +| `admissionId` | service-side accepted/refused/stale/proof-gap result ref | greenlight, receipt, certificate | readback only | +| `serviceWorkflowHandleId` | workflow context ref | bearer auth, tool permission, credential ref | context only | +| `serviceWorkflowHandleDigest` | digest of handle payload | resource widening, payment payload, signature | integrity only | +| `ServiceWorkflowAdmission` | claim rows, evidence refs, proof gaps, bounds digest | mutation permission, policy/gateway outputs | product surface | +| `ServiceWorkflowHandle` | context refs, expiry, next action requirements | raw secrets, receipts, certificates, signer refs | product surface | +| Action Request | candidate action input | reusable authority | proposal candidate | +| `ActionContract` | exact protected action commitment | execution proof | proposed commitment | +| `PolicyDecision` | allow/refuse/review/halt/quarantine decision | gateway check or mutation proof | policy authority | +| `Greenlight` | one exact gateway-bound use | reusable auth | one-use authority candidate | +| `GatewayCheckAttempt` | pre-mutation enforcement evidence | downstream business success | gateway authority | +| `Receipt` / `ProofGap` | terminal evidence/readback | future permission | terminal evidence | + +## Generated-Execution Stress Coverage + +Tests and fixtures must cover: + +- loops that reuse the handle; +- retries after refusal, proof gap, replay, or isolation; +- branches that change endpoint, amount, resource, payee, gateway, or credential refs; +- dynamic tool names and late-bound parameters; +- stale rendered review; +- parallel proposals from one handle; +- raw sibling MCP/x402/browser/network/package-manager paths; +- generated code that emits a safe-looking output while attempting unsafe work. + +## Evidence Readback Separation + +Admission readback is not protected-action receipt evidence. Readback must distinguish: + +- passport evidence; +- service admission result; +- workflow handle context; +- candidate action; +- action contract; +- policy decision; +- greenlight or refusal; +- gateway check; +- credential resolution after gateway check; +- mutation attempt; +- downstream observation; +- receipt; +- refusal; +- replay refusal; +- proof gap; +- optional terminal certificate. + +## Receipt Refusal Proof-Gap Evidence + +Receipts prove the Handshake chain, not downstream business success. Refusals are durable product outcomes, not noise. Proof gaps are explicit missing, stale, contradictory, or unavailable evidence. Replay refusal proves one-use authority was already consumed or duplicated. None of these outcomes grants retry permission without a fresh exact contract. + +## Non-Claims + +No Passport, Admission, Badge, Handle, Certificate, review surface, MCP tool, OpenAPI route, A2A task, x402 payment capability, auth.md credential issuance, runtime profile, host activation artifact, npm package, or registry listing creates authority. + +## Blocked Checks + +- Field-level negative tests do not exist yet. +- Workflow-handle-specific raw sibling inventory does not exist yet. +- Live external rails are unverified. +- Hosted operation and native host containment remain proof gaps. diff --git a/.planning/macro-plan/README.md b/.planning/macro-plan/README.md new file mode 100644 index 0000000..38e4d02 --- /dev/null +++ b/.planning/macro-plan/README.md @@ -0,0 +1,47 @@ +# Tier 1 / Tier 2 Product Simplification Macro Plan + +## Scope + +This package turns the current Passport / Admission / Badge macro map into a full Tier 1 and Tier 2 execution program. The goal is not a small story slice. The goal is to make Handshake simpler to use while preserving the exact contract, policy, one-use greenlight or refusal, gateway check, receipt, refusal, proof-gap, isolation, and reconstruction boundaries. + +Tier 3 progression is blocked until Tier 1 and Tier 2 product surfaces are sharp, source-backed, and verified or proof-gapped. + +## Source Map + +| Source | Role | Status | +| --- | --- | --- | +| `.planning/macro-map/*` | Current macro-map package and lens evidence | Derived planning input | +| `.planning/codebase/*` | Current codebase map for placement, tests, conventions, integrations, and concerns | Derived evidence; implementation must source-check | +| `README.md`, `QUALITY.md`, `STRUCTURE.md` | Current package posture, quality rules, source ownership | Canon | +| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Product kernel, proof ledger, protocol notes, expansion gates | Canon | +| `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md` | Protocol definition, architecture, and plain-language guide | Canon | +| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/*` | Run input, source snapshot, sidecar audits, validation evidence | This plan run | + +## Sidecar Review + +Five sidecar auditors completed bounded reports: + +- execution slices and full-program sequencing; +- protected-action posture and non-authority ID model; +- runtime and generated-agent posture; +- evidence, validation, and closeout gates; +- product, design, DevEx, and adoption. + +The chair owns sequencing, status, authority claims, and implementation entry. Sidecars pressure-test the plan; they do not promote proof gaps into authority. + +## Status + +This macro plan is validated as an implementation handoff for the first bounded Tier 1 story/schema/test slice and a full long-running program for the remaining Tier 1 and Tier 2 simplification work. It does not claim protected-action fixture readiness, runtime containment, Tier 3 readiness, hosted operation, external provider custody, settlement finality, marketplace trust, host-wide containment, or reusable passport authority. + +## Artifact Index + +- `MACRO-PLAN.md`: governing plan, scope, target state, and implementation entry. +- `EXECUTION-SLICES.md`: full Tier 1 and Tier 2 slices with proof gates and stop conditions. +- `AGENT-HANDOFF.md`: fresh-agent execution context and first implementation step. +- `RUNTIME-GATES.md`: host/runtime suitability and continuation gates. +- `PROTECTED-ACTION-GATES.md`: authority, gateway, field-level, bypass, readback, and proof-gap gates. +- `EVIDENCE-PLAN.md`: commands, examples, fixtures, review prompts, and unavailable evidence. +- `REVIEW-GATES.md`: sidecar and review gate reconciliation. +- `RISKS.md`: tracked risks with owners and mitigations. +- `DECISIONS.md`: accepted, rejected, deferred, and revisit-triggered decisions. +- `TASKS.jsonl`: assignable next mechanisms for planning and implementation. diff --git a/.planning/macro-plan/REVIEW-GATES.md b/.planning/macro-plan/REVIEW-GATES.md new file mode 100644 index 0000000..dae95a7 --- /dev/null +++ b/.planning/macro-plan/REVIEW-GATES.md @@ -0,0 +1,76 @@ +# Review Gates + +## Gate Summary + +| Gate | Evidence | Status | +| --- | --- | --- | +| CEO | Buyer story and economic unit reviewed in macro-map lens | Keep language, contain it | +| Engineering | Source placement and tests reviewed in macro-map lens | Surface first, no protocol primitive | +| Design | User mental model reviewed in macro-map lens | State separation required | +| DevEx | First-use path and docs/SDK/CLI/MCP reviewed in macro-map lens | Converge surfaces after schema | +| Agent | Generated-agent misuse reviewed in macro-map lens | Handle misuse tests required | +| Runtime | Multi-host posture reviewed in macro-map lens | Host-specific proof gaps required | +| Protected Action | Authority and gateway boundary reviewed in macro-map lens | Non-authority matrix required | +| Evidence | Macro-plan validation and proof gaps | Validator and sidecar reconciliation required | + +## Sidecar Review + +Sidecar audits are expected under `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/`: + +- `slices.md` +- `protected-action.md` +- `runtime-agent.md` +- `evidence.md` +- `product-devex-design.md` + +All five sidecar reports are present. The chair reconciled them by narrowing implementation readiness to the first Tier 1 story/schema/test slice. Protected-action fixture work, multi-host runtime claims, public-surface convergence, and Tier 3 remain gated until their source proof exists. Sidecar findings can add gates, risks, and task details; they cannot authorize weaker authority claims. + +| Report | Chair Reconciliation | +| --- | --- | +| `audits/slices.md` | Full-program slices are captured in `EXECUTION-SLICES.md`; implementation starts only after macro validation. | +| `audits/protected-action.md` | Field-level matrix and negative-test requirements are captured in `PROTECTED-ACTION-GATES.md`; protected-action fixtures stay gated. | +| `audits/runtime-agent.md` | Host-specific posture and generated-execution stress gates are captured in `RUNTIME-GATES.md`; no generic multi-host execution claim. | +| `audits/evidence.md` | Validator result and status reconciliation are recorded in `EVIDENCE-PLAN.md` and run-local `validation.md`. | +| `audits/product-devex-design.md` | 10-star product criteria and convergence plan are captured in execution slices and tasks; public ergonomics wait for source schema/tests. | + +## CEO Gate + +Pass condition: the buyer story centers on protected-event clearing and reconstruction, not passport validation as authority. Passport validation may be free/open adoption plumbing. Paid value remains protected-event terminalization, retention/readback/export, and gateway readiness. + +Fail condition: the product sells trusted agents, reusable badges, passport permissions, marketplace certification, settlement, cross-org trust, or hosted clearing before proof. + +## Engineering Gate + +Pass condition: first implementation lives in `docs/internal`, `src/surfaces`, and architecture/product tests. It does not add `src/protocol/areas/passport`, protocol object registry entries, gateway adapter authority, root authority exports, or store migrations. + +Fail condition: source placement makes a surface noun look like protocol state without a distinct enforceable transition. + +## Design Gate + +Pass condition: the user-facing model separates Passport evidence, Service Admission, Workflow Handle, Action Request, Clearance, Gateway Check, and Outcome. The review surface does not show one approval badge over mixed states. + +Fail condition: admission review is substituted for exact action-contract review. This is review theatre. + +## DevEx Gate + +Pass condition: README, protocol-layman docs, role-client guidance, CLI/MCP descriptions, and examples teach the simplified flow while preserving non-authority flags and proof gaps. + +Fail condition: developers receive a badge/handle API before learning that every protected action requires fresh clearance. + +## Agent Gate + +Pass condition: agent handoff and tests cover loops, retries, branches, dynamic tool construction, stale review, changed params, raw siblings, replay, proof gaps, and isolation. + +Fail condition: generated code can pass a handle into an unwrapped consequential tool. The generated code escaped the contract boundary. + +## Runtime Gate + +Pass condition: runtime posture is host-specific. Codex, Claude Code, Hermes, OpenClaw, MCP, browser, A2A, OpenAPI, auth.md, and x402 are not collapsed into one runtime claim. + +Fail condition: host profiles, MCP visibility, OpenAPI routes, or A2A metadata are treated as enforcement. + +## Protected-Action Gate + +Pass condition: the field-level matrix proves admission and handle cannot create authority, policy decisions, greenlights, gateway checks, signer use, payment material, mutation, receipts, certificates, or resource widening. x402/auth.md remain exact per-event rails. + +Fail condition: one admission or handle can authorize multiple mutations. This is ambient authority wearing a badge. diff --git a/.planning/macro-plan/RISKS.md b/.planning/macro-plan/RISKS.md new file mode 100644 index 0000000..730c813 --- /dev/null +++ b/.planning/macro-plan/RISKS.md @@ -0,0 +1,101 @@ +# Risks + +## RISK-001 + +- ID: RISK-001 +- Severity: Critical +- Risk: `ServiceWorkflowHandle` becomes reusable auth. +- Trigger: SDK, CLI, MCP, runtime, or example code accepts a handle as sufficient evidence for protected mutation. +- Mitigation: Literal false non-authority flags, surface-boundary tests, runtime misuse tests, and fresh action contract requirement. +- Owner: Surface/schema implementer and architecture-test implementer. +- Status: Active gate. + +## RISK-002 + +- ID: RISK-002 +- Severity: Critical +- Risk: Admission is mistaken for policy decision or gateway acceptance. +- Trigger: Docs or schema use Admission without showing accepted/refused/stale/proof-gap rows and separate clearance state. +- Mitigation: Use `ServiceWorkflowAdmission`, not standalone `Admission`; require action request and clearance sections in docs and readback. +- Owner: Product/docs implementer. +- Status: Active gate. + +## RISK-003 + +- ID: RISK-003 +- Severity: High +- Risk: Passport digest or presentation ID becomes identity, trust, or spend approval. +- Trigger: Passport fields are used in policy/gateway checks as sufficient proof rather than evidence refs. +- Mitigation: Define all passport/admission/handle IDs as correlation and reconstruction only; test they cannot create authority. +- Owner: Protected-action reviewer. +- Status: Active gate. + +## RISK-004 + +- ID: RISK-004 +- Severity: High +- Risk: Product simplification becomes metaphor-only documentation. +- Trigger: Story docs land without source schema, fields, tests, examples, and proof gates. +- Mitigation: Pair story with surface contract and architecture tests in Tier 1. +- Owner: Chair. +- Status: Active gate. + +## RISK-005 + +- ID: RISK-005 +- Severity: High +- Risk: Tier 2 fixture overclaims x402/auth.md external rails. +- Trigger: Example claims live provider custody, settlement, broad x402 compatibility, auth.md approval, or hosted operation. +- Mitigation: Local/source-owned fixture first; explicit non-claims; x402/auth.md adapter tests when touched. +- Owner: Protected-action fixture implementer. +- Status: Deferred until Tier 2. + +## RISK-006 + +- ID: RISK-006 +- Severity: High +- Risk: Multi-host runtime language becomes containment claim. +- Trigger: Codex-local evidence is generalized to Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, or OpenAPI. +- Mitigation: Runtime posture table and host-specific proof gaps; no native containment claim. +- Owner: Runtime test implementer. +- Status: Active gate. + +## RISK-007 + +- ID: RISK-007 +- Severity: Medium +- Risk: Architecture tests rely on string scans and miss semantic authority drift. +- Trigger: Dynamic imports, re-export indirection, or schema aliasing bypasses surface-boundary checks. +- Mitigation: Combine import-boundary tests, schema assertions, explicit non-authority fields, and product output tests. +- Owner: Architecture-test implementer. +- Status: Active gate. + +## RISK-008 + +- ID: RISK-008 +- Severity: Medium +- Risk: Canonical docs and README diverge into two first-use stories. +- Trigger: service workflow story lands but README still teaches only x402 install mechanics. +- Mitigation: Canonical docs convergence slice after source surface and tests. +- Owner: Docs implementer. +- Status: Planned. + +## RISK-009 + +- ID: RISK-009 +- Severity: High +- Risk: Tier 3 starts before Tier 1/Tier 2 proof gates close. +- Trigger: Hosted-workspace pressure turns local simplification into hosted operation or package-surface expansion. +- Mitigation: Tier 3 lock slice and final repo gate; feed any kernel need back into Tier 1/Tier 2. +- Owner: Release gate owner. +- Status: Active gate. + +## RISK-010 + +- ID: RISK-010 +- Severity: Medium +- Risk: The first implementation grows into broad SDK/CLI/MCP redesign. +- Trigger: Developer ergonomics work expands before surface contract proves the model. +- Mitigation: Implementation starts with story, surface schema, and boundary test only; Tier 2 convergence follows after gates. +- Owner: Chair. +- Status: Active gate. diff --git a/.planning/macro-plan/RUNTIME-GATES.md b/.planning/macro-plan/RUNTIME-GATES.md new file mode 100644 index 0000000..5ccf8e1 --- /dev/null +++ b/.planning/macro-plan/RUNTIME-GATES.md @@ -0,0 +1,88 @@ +# Runtime Gates + +## Source Boundary + +| Source | Runtime Role | Status | +| --- | --- | --- | +| `.planning/macro-map/AGENT-RUNTIME-MAP.md` | Runtime posture for Passport / Admission / Handle move | Derived gate input | +| `.planning/macro-map/views/AGENT.md` | Generated-agent handoff and misuse risks | Lens evidence | +| `.planning/macro-map/views/RUNTIME.md` | Multi-host and x402/auth.md posture | Lens evidence | +| `.planning/codebase/INTEGRATIONS.md` | Current external rail and host profile map | Derived codebase evidence | +| `src/runtime/ingress/index.ts`, `src/runtime/ingress/schemas.ts` | Proposal-only runtime ingress | Source proof for current runtime posture | +| `src/mcp/x402-proposal.ts`, `src/x402-protected-tool/LANE.md` | MCP proposal and x402 host-profile posture | Source proof for proposal/readback non-authority | +| `README.md`, `docs/internal/protocol-notes.md` | Canonical non-claims for MCP, host profiles, x402, and runtime evidence | Canon | + +## Runtime Targets + +| Target | Current Evidence | Suitability Posture | +| --- | --- | --- | +| Codex | Local profile and MCP proposal/readback evidence | Usable for first implementation and local verification; no host-wide containment claim | +| Claude Code | Managed profile artifact in x402 protected-tool lane | Surface parity target; verify before runtime-specific claims | +| Hermes | Tool-packet/profile artifact | Surface parity target; verify before runtime-specific claims | +| OpenClaw | Tool-packet/profile artifact | Surface parity target; verify before runtime-specific claims | +| MCP | Local stdio proposal/evidence server | Proposal/readback only; no policy/gateway/mutation | +| x402 | One buyer-side exact per-call local proof path | Protected-action rail; gateway/signer boundary still required | +| auth.md | Credential provenance and protected API profile | Evidence rail; not action approval | +| Browser | Potential side channel | Treat as bypass/proof-gap unless gateway-owned path exists | +| A2A | Task/metadata context | Evidence only | +| OpenAPI | Route/catalog context | Operation description only | + +## Suitability Postures + +The weakest host posture controls the claim. The plan may say "multi-host evidence posture" but not "multi-host containment." Codex is the active implementation runtime. Other hosts remain product-surface parity and future verification targets until their activation artifacts are source-checked and executed. + +## Instruction Sources + +Runtime agents must receive: + +- `AGENTS.md` invariant and cut lines; +- `AGENT-HANDOFF.md` context bundle; +- `PROTECTED-ACTION-GATES.md` authority boundary; +- source lane `LANE.md` files before edits; +- focused tests for runtime ingress, MCP posture, and surface boundary. + +## Tool Contract + +Allowed runtime actions: + +- inspect admission and handle evidence; +- propose fresh action requests; +- use runtime ingress as proposal evidence; +- read redacted evidence and proof gaps; +- recraft exact contracts after drift or refusal. + +Forbidden runtime actions: + +- treat handle as permission; +- invoke signer or payment payload generation from admission; +- mutate from Passport/Badge/Handle; +- retry proof gaps as permission; +- dynamically construct protected tools without classifier/refusal checks; +- route around gateway via browser, shell, network, package manager, raw MCP, raw x402, or direct HTTP sibling paths. + +## Approval Or Permission Behavior + +Human approval of a story, rendered review, or admission report is not permission. Runtime approval must bind to the exact protected-action contract and later gateway check. If the generated code can call an unwrapped consequential tool, the generated code escaped the contract boundary. + +## Subagent Behavior + +Subagents can review runtime posture, write isolated tests, or implement disjoint slices. They must not claim final runtime suitability. Promoting a host from profile evidence to native operation requires source-specific verification and a separate proof packet. + +## Continuation State + +Continuation must survive compaction and restart through: + +- `.planning/macro-plan/AGENT-HANDOFF.md`; +- `TASKS.jsonl`; +- source comments avoided unless necessary; +- git checkpoints after validated slices; +- test output captured in closeout notes or run validation files. + +## Blocked Runtime Checks + +These checks block broad claims, not the first Tier 1 implementation: + +- no browser/A2A/OpenAPI gateway-owned path exists for this workflow handle; +- no Claude Code, Hermes, OpenClaw, or generic MCP runtime smoke has been executed for service workflow admission; +- no native host containment proof exists; +- no raw sibling inventory specific to this new handle surface exists until runtime misuse tests are written. diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl new file mode 100644 index 0000000..2fd1cef --- /dev/null +++ b/.planning/macro-plan/TASKS.jsonl @@ -0,0 +1,10 @@ +{"id":"MPLAN-001","phase":"T0","slice":"T0-00","title":"Validate and checkpoint macro-plan package","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Implementation must start from a validated package, not chat-only planning.","acceptance":["Macro-plan validator reports valid output.","Sidecar audit files are present or missing reports are recorded.","Git status is inspected before checkpoint."],"non_goals":["Do not claim Tier 3 readiness from macro-plan validation."],"status":"open","proof_gate":"Macro-plan validator passes on .planning/macro-plan.","next_mechanism":"Run the macro-plan validator and record validation evidence."} +{"id":"MPLAN-002","phase":"T1","slice":"T1-01","title":"Create internal service workflow story","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-001"],"evidence":[".planning/macro-map/EXPERIENCE-MAP.md","docs/internal/protocol-layman.md","README.md"],"candidate_paths":["docs/internal/service-workflow-story.md"],"rationale":"The first user-facing simplification must teach the flow without implying authority.","acceptance":["Story maps Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, and Outcome to exact protocol/evidence boundaries.","Story includes forbidden interpretations for passport IDs, handle, certificate, review, and receipt.","Story includes refusal, replay, proof-gap, and isolation recovery language."],"non_goals":["Do not create public marketing claims or hosted-operation claims."],"status":"open","proof_gate":"quality:claims passes after the story doc is added.","next_mechanism":"Write docs/internal/service-workflow-story.md with noun mapping and non-authority cut lines."} +{"id":"MPLAN-003","phase":"T1","slice":"T1-02","title":"Implement non-authority service workflow surface schema","priority":"P0","owner":"surface-schema-implementer","runtime":"codex","depends_on":["MPLAN-002"],"evidence":[".planning/macro-map/MECHANISM-MAP.md",".planning/macro-map/views/ENG.md","src/surfaces/outcome.ts","src/surfaces/boundary-manifest.ts"],"candidate_paths":["src/surfaces/service-workflow-admission.ts","src/surfaces/index.ts"],"rationale":"The simplified product model needs a source-owned schema before demos or SDK/CLI/MCP surfaces use it.","acceptance":["Schema defines ServiceWorkflowAdmission and ServiceWorkflowHandle.","Schema includes passportPackageDigest, passportPresentationId, admissionId, serviceWorkflowHandleId, serviceWorkflowHandleDigest.","Schema sets createsAuthority, createsPolicyDecision, createsGreenlight, performsGatewayCheck, permitsMutation, exportsReceipt, and mintsTerminalCertificate to false and freshActionContractRequired to true."],"non_goals":["Do not add protocol primitive, gateway adapter, store migration, policy evaluator, or mutation runner."],"status":"open","proof_gate":"check:types passes and architecture gate accepts the surface posture.","next_mechanism":"Add src/surfaces/service-workflow-admission.ts following existing surface outcome conventions."} +{"id":"MPLAN-004","phase":"T1","slice":"T1-03","title":"Add workflow admission boundary tests","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["MPLAN-003"],"evidence":[".planning/codebase/TESTING.md","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"candidate_paths":["test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"The known failure mode is naming and surface drift into authority-bearing paths.","acceptance":["Tests fail if Passport, Badge, ServiceWorkflowAdmission, or ServiceWorkflowHandle appear as protocol primitives or authority exports.","Tests reject raw credential, token, PaymentPayload, PAYMENT-SIGNATURE, signer, receipt export, certificate, gateway check, policy, greenlight, and mutation fields on the surface.","Tests require the false non-authority flags."],"non_goals":["Do not weaken existing architecture tests to admit the new surface."],"status":"open","proof_gate":"quality:architecture and quality:claims pass.","next_mechanism":"Add focused architecture tests for workflow-admission boundary."} +{"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"open","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} +{"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"open","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} +{"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"open","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} +{"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} +{"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"open","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} +{"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"open","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/evidence.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/evidence.md new file mode 100644 index 0000000..1014183 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/evidence.md @@ -0,0 +1,342 @@ +## Audit Scope + +Focus: evidence plan, validation, proof gaps, and closeout commands for the Tier 1 / Tier 2 product-simplification macro-plan run. + +Verdict: fail for fresh-agent handoff as-is. The source boundary is strong enough for macro planning, and the macro-map validator passes, but the macro-plan package is not currently validated and cannot be treated as execution-ready evidence. The macro-plan validator fails, and the artifacts disagree about whether the user-owned noun/scope decision is resolved or still blocking. + +This audit does not select a macro move, synthesize the final plan, promote final status, or authorize implementation. + +## Source Boundary + +Authoritative source boundary for this audit: + +| Source | Role | Evidence Posture | +| --- | --- | --- | +| `AGENTS.md` user-provided instructions | Doctrine and invariant boundary | Governs this audit | +| `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` | Macro-plan workflow and success criteria | Required source | +| `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md` | Required artifacts and sections | Required source | +| `/Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` | Quality bar beyond validator | Required source | +| `/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py` | Structural validator behavior | Required source and executed command | +| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` | Run input, success criteria, anti-patterns, initial status | Required source | +| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md` | Run-local source snapshot and non-proofs | Required source | +| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md` | Run-local blocked checks | Additional run source | +| `.planning/macro-map/FACET-MAP.md` | Lens convergence and blocked checks | Required source | +| `.planning/macro-map/CONCERNS.md` | Open P0/P1 concerns | Required source | +| `.planning/codebase/TESTING.md` | Focused and repo verification gates | Required source | +| `README.md` | Current product/kernel orientation and command posture | Required source | +| `docs/internal/decisions.md` | Canon decisions, proof ledger, expansion gate | Required source | +| `docs/internal/protocol-notes.md` | Protocol primitive, evidence rules, proof lanes | Required source | +| `package.json` | Actual package scripts and command contract | Required source | +| `.planning/macro-plan/*.md`, `.planning/macro-plan/TASKS.jsonl` | Current macro-plan package under audit | Additional source needed to audit handoff | + +Non-sources: chat memory, future intent, sidecar expectations, and `.planning/` scratch not named above. `.planning/` is evidence for planning posture only; it is not repo-facing canon. + +## Files Read + +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md` +- `.planning/macro-map/FACET-MAP.md` +- `.planning/macro-map/CONCERNS.md` +- `.planning/codebase/TESTING.md` +- `README.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `package.json` +- `.planning/macro-plan/README.md` +- `.planning/macro-plan/MACRO-PLAN.md` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/RUNTIME-GATES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` +- `.planning/macro-plan/EVIDENCE-PLAN.md` +- `.planning/macro-plan/REVIEW-GATES.md` +- `.planning/macro-plan/RISKS.md` +- `.planning/macro-plan/DECISIONS.md` +- `.planning/macro-plan/TASKS.jsonl` + +## Invariant At Stake + +Product simplification may hide protocol complexity from users, but it must not hide or weaken authority, gateway, evidence, refusal, proof-gap, isolation, or reconstruction boundaries. + +For evidence closeout, the specific invariant is: a fresh agent must be able to reconstruct what is proven, what is only planning posture, what is explicitly blocked, and which commands must pass before implementation. If the plan claims readiness while validation fails or artifacts disagree about blockers, this is not auditable. + +## Pass Conditions + +Artifact completeness checklist: + +| Artifact | Required Evidence Condition | Current Posture | +| --- | --- | --- | +| `README.md` | Scope, source map, sidecar review, status, artifact index | Present, but sidecar path references a different run ID than this assigned audit run | +| `MACRO-PLAN.md` | Exactly one status token, current evidence, non-proofs, verification gates, smallest next mechanism | Present, but validator fails because multiple status tokens appear | +| `EXECUTION-SLICES.md` | Slices with source evidence, stop conditions, proof gates, rollback/abandonment, handoff needs | Present; S0 decision gate conflicts with claimed ready posture | +| `AGENT-HANDOFF.md` | Fresh-agent objective, source boundary, runtime profile, tool contract, checkpoints, stop conditions, proof gaps | Present, but says the macro plan is blocked until noun-set acceptance | +| `RUNTIME-GATES.md` | Per-runtime posture, approval behavior, subagent behavior, continuation, blocked checks | Present; correctly proof-gaps multi-host containment | +| `PROTECTED-ACTION-GATES.md` | Candidate actions, authority boundary, gateway boundary, bypass posture, readback separation, proof gaps | Present; correctly treats admission/handle as non-candidate evidence | +| `EVIDENCE-PLAN.md` | Current evidence, commands, replay/refusal cases, review prompts, fixtures/examples, redaction, runtime artifacts, unavailable evidence | Present; needs stronger exact command plan and current validation result | +| `REVIEW-GATES.md` | CEO, engineering, design, DevEx, agent, runtime, protected-action pass/block gates | Present, but says the plan is blocked and no sidecar auditors ran | +| `RISKS.md` | Each risk has ID, severity, trigger, mitigation, owner, status | Present | +| `DECISIONS.md` | Each decision has ID, status, decision, rationale, source, revisit trigger | Present, but `MPLAN-D001` says blocked macro plan while README/MACRO-PLAN say ready for phase planning | +| `TASKS.jsonl` | Valid JSONL task records with evidence, acceptance, non-goals, proof gate, next mechanism | Present, but `MPLAN-001` is still open and later tasks are blocked | + +Validation pass conditions before handoff: + +1. `python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan` exits 0. +2. Status posture is consistent across `README.md`, `MACRO-PLAN.md`, `AGENT-HANDOFF.md`, `REVIEW-GATES.md`, `DECISIONS.md`, and `TASKS.jsonl`. +3. The plan either records the user decision as accepted and closes `MPLAN-001`, or keeps implementation blocked and avoids ready phrasing. +4. `EVIDENCE-PLAN.md` records the exact current validator output, not only a future command. +5. `REVIEW-GATES.md` records this and other sidecar audits before any readiness claim. +6. `blocked-checks.md` is updated or reconciled so it no longer says the macro-plan package has not been written or validated after the package exists. +7. Implementation entry is limited to phase planning unless a detailed phase plan names source files, focused tests, proof gaps, and rollback gates. + +Implementation-entry conditions: + +- Fresh agent may begin detailed phase planning only after macro-plan validation passes and status contradictions are reconciled. +- Fresh agent may begin source implementation only after a detailed phase plan exists for S1-S3 with source-opened target files, exact focused tests, and explicit non-authority acceptance criteria. +- Fresh agent must not implement fixture/demo work until S1-S4 guardrail gates exist or are explicitly blocked with proof gaps. +- Fresh agent must checkpoint with `git status --short` before edits and after each slice. The current checkpoint observed by this audit is clean on branch `main`; no commit was made. + +## Failures + +1. Structural validator failure. + +Current command result: + +```bash +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +``` + +Current output: + +```text +ERROR: MACRO-PLAN.md must contain exactly one plan status +``` + +The immediate cause is that `MACRO-PLAN.md` contains more than one recognized status token. It includes `READY_FOR_PHASE_PLANNING` twice and also mentions `NEEDS_USER_DECISION`. + +2. Status contradiction across artifacts. + +- `README.md` and `MACRO-PLAN.md` say `READY_FOR_PHASE_PLANNING`. +- `AGENT-HANDOFF.md` says the macro plan is blocked until the user accepts the surface-first noun set. +- `REVIEW-GATES.md` says this macro plan is blocked because the macro map requires a user-owned noun/scope decision. +- `DECISIONS.md` says the accepted decision is to produce a blocked macro plan rather than an executable plan. +- `TASKS.jsonl` keeps `MPLAN-001` open and later tasks blocked. +- `blocked-checks.md` says the macro-plan package has not yet been written or validated, which is stale relative to the package now under audit. + +This is not a cosmetic inconsistency. A fresh agent could either start phase planning from `MACRO-PLAN.md` or stop at `AGENT-HANDOFF.md` and `REVIEW-GATES.md`. That means the handoff is not reconstructable. + +3. Evidence plan is command-shaped but not closeout-shaped. + +`EVIDENCE-PLAN.md` lists the right categories: current evidence, commands, replay/refusal cases, review prompts, fixtures/examples, readback/redaction checks, runtime proof artifacts, and unavailable evidence. It does not record the current macro-plan validator failure, the stale blocked-checks state, or the cross-artifact status conflict. + +4. Review gate state is not reconciled with this sidecar process. + +`REVIEW-GATES.md` says no sidecar auditors ran because normal macro planning is blocked. This audit exists and must be summarized by the chair before any status is promoted. This sidecar cannot promote status; it can only report that review evidence is currently incomplete. + +5. Handoff says "wait for user decision" while run input says the user explicitly authorized the full macro-plan pass. + +This may be resolvable by chair reconciliation, but as written it is a handoff hazard. If the user decision is accepted, the artifacts should record the decision and close or supersede S0. If not accepted, the ready status should be removed. + +## Proof Gaps + +Evidence gaps: + +- No current passing macro-plan validator output. +- No reconciliation record explaining whether the noun/scope decision is accepted, blocked, or superseded. +- No source schema for `ServiceWorkflowAdmission`. +- No source schema for `ServiceWorkflowHandle`. +- No negative tests proving admission/handle cannot create or satisfy `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `Receipt`, `AuthorityCertificate`, signer invocation, payment material, or mutation. +- No handle misuse tests for loops, retries, dynamic tool names, stale review surfaces, changed params, raw siblings, browser/network side channels, replay, or idempotency mismatch. +- No implemented readback artifact showing admission, handle, action request, clearance, receipt, refusal, and proof gap as separate states. +- No runtime proof artifacts for Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, or OpenAPI. +- No native host containment proof. +- No live external rail proof for ERC-8004, auth.md deployment corpus, live x402 provider custody, hosted custody, provider signer lifecycle, Agentic.Market listing, facilitator operation, settlement/finality, or MCP Registry lookup for this run. +- No evidence that public-facing docs or examples preserve `createsAuthority: false` for the proposed nouns because those docs/schemas do not exist yet. + +Non-proofs that must stay explicit: + +- Macro-map validation is not macro-plan validation. +- Passing the structural macro-plan validator would not prove source implementation, authority safety, runtime containment, or user comprehension. +- Codex-local or package-profile evidence does not prove other host containment. +- Admission/readback evidence does not prove policy, greenlight, gateway check, signer use, mutation, receipt export, or terminal certificate. +- Receipt evidence does not prove downstream business success or payment settlement. +- `.planning/codebase/*` routes implementation attention, but source files and tests must still be opened before edits. + +Validator risks: + +- The validator catches the current multiple-status failure, but its status scanner also treats negative mentions as status tokens. The chair should avoid writing status constants in explanatory prose inside `MACRO-PLAN.md`. +- The validator is structural. It does not detect cross-file contradictions like blocked handoff plus ready macro status. +- It does not verify that commands were run, that sidecar audits exist, that stale `blocked-checks.md` was reconciled, or that `TASKS.jsonl` statuses align with `MACRO-PLAN.md`. +- It does not prove the content-level quality bar: source-opened implementation paths, real negative tests, runtime proof artifacts, readback redaction, or refusal/replay fixtures. +- It can reject weak filler strings such as "run tests"; current artifacts mostly avoid that, but any repair should keep proof gates exact rather than generic. + +Replay/refusal cases that must remain in the plan and later fixtures: + +- consumed greenlight replay refuses before signer reuse; +- idempotency mismatch requires a new exact contract; +- stale metadata requires reload; +- changed observed parameters require recraft; +- raw sibling route requires stop, isolation, or proof gap; +- credential-ref or authority-ref isolation blocks policy/gateway; +- proof gap does not grant retry permission; +- handle presented as policy/gateway/signer/mutation input refuses; +- dynamic tool construction or late-bound endpoint/amount refuses or requires a new exact action contract. + +Readback/redaction gaps to close before implementation claims: + +- Admission readback must expose refs, digests, claim status, expiry, proof-gap reason, and non-authority flags only. +- It must not expose raw credentials, tokens, payment payloads, payment signatures, private keys, provider secrets, raw authorization headers, or signer material. +- Receipt readback must remain separate from admission readback. +- Runtime evidence, gateway-check evidence, mutation-attempt evidence, downstream observation, replay refusal, proof gap, and certificate must be separate in readback. + +## Required Changes + +1. Reconcile status before any handoff. + +Choose one evidence posture and make every artifact agree: + +- If the user decision is accepted: close or supersede `MPLAN-001`, update `AGENT-HANDOFF.md`, `REVIEW-GATES.md`, `DECISIONS.md`, and `blocked-checks.md`, and keep `READY_FOR_PHASE_PLANNING` only once in `MACRO-PLAN.md`. +- If the decision remains blocked: remove ready phrasing from `README.md` and `MACRO-PLAN.md`, keep tasks blocked, and set the plan posture to blocked without laundering it into phase planning. + +2. Fix structural validation. + +`MACRO-PLAN.md` must contain exactly one macro-plan status token. Avoid mentioning other status constants in prose. Then rerun: + +```bash +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +``` + +3. Update evidence closeout. + +`EVIDENCE-PLAN.md` should record: + +- macro-map validator result; +- macro-plan validator result; +- current git branch and status; +- whether sidecar audits exist and where; +- exact commands that must pass before phase planning versus implementation; +- explicit skipped commands and why; +- stale or unavailable evidence. + +4. Reconcile run-local `blocked-checks.md`. + +It currently says the package has not yet been written or validated. That statement is stale now that the package exists and macro-plan validation has been attempted. It should be updated by the chair, not this sidecar. + +5. Make review prompts operational. + +Review prompts should become pass/block questions tied to artifacts and commands: + +- CEO: does the plan avoid a standalone Passport identity/trust/certification claim? +- Engineering: do source paths stay outside protocol authority and carry hard non-authority flags? +- Design/DevEx: can users distinguish admission, action request, clearance, receipt, refusal, and proof gap? +- Agent/runtime: can generated code misuse the handle in loops, retries, branches, dynamic tools, stale review, raw siblings, or browser/network side channels? +- Protected-action: can any field create or satisfy policy, greenlight, gateway check, signer use, mutation, receipt, or certificate? + +6. Add an exact verification command plan. + +Minimum planning closeout: + +```bash +python3 /Users/joelchan/.codex/skills/gsd-plan-map/scripts/validate_plan_map_output.py .planning/macro-map +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +git status --short +``` + +Minimum first implementation-slice closeout after S1-S3 source changes: + +```bash +npm run quality:claims +npm run quality:architecture +npm run format:check +git diff --check +``` + +Protocol/readback implementation closeout when admission/handle schemas or projections exist: + +```bash +npm run test -- test/architecture/surface-boundary-posture.test.ts test/architecture/claim-boundary.test.ts test/architecture/naming-posture.test.ts +npm run test -- test/protocol/evidence-projections.test.ts test/protocol/representation-contract.test.ts test/runtime/runtime-ingress.test.ts +npm run quality:claims +npm run quality:architecture +``` + +Protected-action fixture closeout when x402/auth.md stitch work begins: + +```bash +npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/integration/auth-md-protected-call.test.ts test/integration/auth-md-receipt-reconstruction.test.ts +npm run test -- test/conformance/protected-mutation-adapter-conformance.test.ts +npm run check:repo +``` + +Full repo closeout before any claim that implementation is integrated: + +```bash +npm run check:repo +git status --short +``` + +Git checkpoint advice: + +- Do not commit from the audit sidecar. +- Before implementation starts, the chair or implementing agent should record `git status --short` and `git branch --show-current`. +- Create a checkpoint after macro-plan reconciliation and before source edits. +- After each slice, use `git status --short`, `git diff --stat`, and the slice-specific tests before proceeding. +- Do not mix macro-plan artifact repairs with source implementation in the same checkpoint. + +## Status Recommendation + +Do not promote final status from this sidecar. + +Evidence recommendation: block fresh-agent handoff until the macro-plan validator passes and the status contradictions are reconciled. After that, the package may be suitable for detailed phase planning, not source implementation. Source implementation should remain blocked until a detailed phase plan for the first slice names exact source paths, focused tests, proof gaps, rollback criteria, and non-authority acceptance conditions. + +Smallest next mechanism: reconcile the plan-status evidence by updating the macro-plan package so `MACRO-PLAN.md` has exactly one status token and every handoff/review/task artifact agrees on whether S0 is closed or still blocking, then rerun the macro-plan validator and record the result in `EVIDENCE-PLAN.md`. + +## Commands Or Tools Used + +Commands and tools used for this audit: + +```bash +rg -n "Tier 3 doctrine|x402 sandbox|tier1|Tier 1|macro-plan|protected-action|evidence|proof gap" /Users/joelchan/.codex/memories/MEMORY.md +sed -n '84,121p' /Users/joelchan/.codex/memories/MEMORY.md +sed -n '221,232p' /Users/joelchan/.codex/memories/MEMORY.md +sed -n '1,240p' /Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md +sed -n '1,260p' /Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md +sed -n '1,260p' /Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md +sed -n '1,520p' /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py +sed -n '1,260p' .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md +sed -n '1,320p' .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md +sed -n '1,240p' .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md +sed -n '1,340p' .planning/macro-map/FACET-MAP.md +sed -n '1,320p' .planning/macro-map/CONCERNS.md +sed -n '1,340p' .planning/codebase/TESTING.md +sed -n '1,360p' README.md +sed -n '1,360p' docs/internal/decisions.md +sed -n '1,720p' docs/internal/protocol-notes.md +sed -n '1,260p' package.json +rg --files .planning/macro-plan .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification +sed -n '1,420p' .planning/macro-plan/EXECUTION-SLICES.md +sed -n '1,360p' .planning/macro-plan/RUNTIME-GATES.md +sed -n '1,360p' .planning/macro-plan/PROTECTED-ACTION-GATES.md +sed -n '1,320p' .planning/macro-plan/RISKS.md +sed -n '1,260p' .planning/macro-plan/DECISIONS.md +sed -n '1,260p' .planning/macro-plan/README.md +sed -n '1,260p' .planning/macro-plan/TASKS.jsonl +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +python3 /Users/joelchan/.codex/skills/gsd-plan-map/scripts/validate_plan_map_output.py .planning/macro-map +git status --short +git branch --show-current +rg -n "READY_FOR|NEEDS_|BLOCKED|CUT|DEGRADED" .planning/macro-plan/MACRO-PLAN.md .planning/macro-plan/README.md .planning/macro-plan/AGENT-HANDOFF.md .planning/macro-plan/REVIEW-GATES.md .planning/macro-plan/TASKS.jsonl .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md +``` + +Observed command results: + +- Macro-map validator: `Plan map output is valid.` +- Macro-plan validator: `ERROR: MACRO-PLAN.md must contain exactly one plan status` +- Git branch: `main` +- Git status before report write: clean + +Only this file was written by this sidecar audit. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/product-devex-design.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/product-devex-design.md new file mode 100644 index 0000000..32e06dc --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/product-devex-design.md @@ -0,0 +1,212 @@ +## Audit Scope + +Focus: 10-star product design, DevEx, and adoption for Tier 1 / Tier 2 product simplification. + +Verdict: keep the simplification direction, but do not let it become executable macro-plan evidence until one source-owned product-surface readback contract, one first-use demo, and negative non-authority tests exist. "Simple" must mean the user sees fewer kernel nouns while the system preserves the exact boundary: + +```text +standing evidence +-> service admission/readback +-> non-authority workflow handle +-> fresh protected action request +-> exact policy decision +-> one-use greenlight or refusal +-> gateway check before mutation +-> receipt, refusal, replay refusal, proof gap, or terminal evidence +``` + +If Passport, Admission, Badge, Handle, Certificate, CLI, MCP, SDK, docs, or examples imply reusable permission, this is ambient authority wearing a badge. + +## Source Boundary + +Canonical repo truth wins over `.planning/` scratch. The current source boundary says: + +- `README.md`, `docs/internal/decisions.md`, and `docs/internal/protocol-notes.md` define Handshake as protected action infrastructure for automated decision making. +- Product surfaces are CLI, MCP, SDK, docs, demos, or service readback that expose proposal/evidence/readback without creating authority. +- The current first official wedge is one buyer-side `x402_payment.exact` per-call protected action. +- Public npm availability, MCP Registry metadata, host profiles, local demos, terminal certificates, and readback surfaces are evidence/distribution, not authority. +- `.planning/macro-map/*` and `.planning/codebase/*` are scratch/derived planning evidence, useful for this audit but not repo-facing canon. + +Memory was used only as context for known local Handshake boundary pitfalls. It is not source evidence for this audit. + +## Files Read + +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` +- `/Users/joelchan/.codex/memories/MEMORY.md` context only +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` +- `.planning/macro-map/EXPERIENCE-MAP.md` +- `.planning/macro-map/views/DESIGN.md` +- `.planning/macro-map/views/DEVEX.md` +- `.planning/macro-map/views/CEO.md` +- `.planning/codebase/STACK.md` +- `.planning/codebase/STRUCTURE.md` +- `.planning/codebase/CONVENTIONS.md` +- `.planning/codebase/TESTING.md` +- `README.md` +- `docs/internal/protocol-layman.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` + +## Invariant At Stake + +Product simplification may hide protocol complexity from users, but it must not hide or weaken authority, gateway, evidence, refusal, proof-gap, isolation, or reconstruction boundaries. + +The product-design invariant: + +```text +Every user-facing shortcut must map to a visible non-authority surface or to a source-owned protocol transition. No friendly noun may smuggle permission. +``` + +The DevEx invariant: + +```text +The fastest developer path must teach the protected-action chain by doing one local proof, including a negative authority attempt, without making CLI/MCP/SDK/example artifacts look like enforcement. +``` + +## Pass Conditions + +### 10-Star Criteria Refinements + +- The first screen / first doc / first command teaches the story as "service accepts evidence into a bounded workflow, then every protected event still needs fresh clearance." +- Every surfaced object has explicit false posture fields, at minimum: `createsAuthority: false`, `createsGreenlight: false`, `performsGatewayCheck: false`, `permitsMutation: false`, plus existing repo posture fields where applicable. +- The five non-authority correlation fields are preserved and documented: `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, and `serviceWorkflowHandleDigest`. +- The first-use path includes a negative attempt where a handle alone fails to call a protected API, pay an x402 challenge, mutate a service, satisfy a gateway, export a receipt, or mint a certificate. +- SDK, CLI, MCP, docs, and examples converge on one packet shape. They must not each invent a parallel metaphor. +- Role-scoped SDK clients are taught before the lower-level `HandshakeClient`. +- MCP remains proposal/evidence/readback only. New MCP resources may expose admission/readback, but no MCP tool may imply it can admit, approve, pay, sign, gateway-check, or mutate. +- CLI commands remain evidence/readiness/readback only and must be listed in `src/cli/command-manifest.ts` with explicit non-goals before docs teach them. +- Example output is the source-owned teaching artifact: JSON plus Markdown, product-tested, with no hosted/provider/settlement/marketplace/certification overclaim. +- Tier 3 progression remains blocked until Tier 1 / Tier 2 simplification either has passing proof gates or records explicit proof gaps. + +### First-Use Path + +The macro plan should require this first-use path: + +1. Read a short story section in `docs/internal/protocol-layman.md` that avoids `OperatingEnvelope`, `DelegatedAuthorityRef`, and `ActionContract` until after the user understands the flow. +2. Run a local source-owned fixture that emits a `ServiceWorkflowAdmission` or `ServiceWorkflowAdmissionReport`. +3. Inspect a `ServiceWorkflowHandle` with all non-authority flags and the five correlation fields. +4. Try to use the handle as authority and observe a refusal/proof-gap/readback result before any signer, gateway check, mutation, receipt export, or certificate. +5. Create one fresh `x402_payment.exact` protected action request using the existing readiness ladder. +6. Clear or refuse it through the role-scoped runtime, policy, and gateway clients. +7. Inspect receipt/refusal/replay-refusal/proof-gap readback and, only after terminal evidence exists, optional certificate verification. + +The current `README.md` x402 ladder is useful, but it starts with installation mechanics. The simplified path should wrap that ladder in the product story instead of replacing the authority sequence. + +### Naming Decisions + +- Use `ServiceWorkflowAdmission` or `ServiceWorkflowAdmissionReport` for the surface that records accepted/refused/stale/proof-gap standing evidence. +- Use `ServiceWorkflowHandle` for the carried workflow context object. +- Keep `Badge` out of exported SDK, CLI, MCP, source path, test, and package-surface names. It can appear only as carefully bounded explanatory copy, if at all. +- `AgentPassportPackage` is acceptable as a presented evidence bundle name only if every use says it is not identity, trust, permission, spend approval, gateway acceptance, signer permission, mutation permission, receipt export, terminal certification, or reusable auth. +- Avoid `Admission` as a verb in commands or tools. `admit`, `approve`, `authorize`, `certify`, `trust`, `login`, `verifyAgent`, and `grant` are too authority-loaded unless backed by a source-owned transition with the same authority. +- Keep `AuthorityCertificate` visibly terminal: receipt/refusal/proof-gap/replay evidence only, not a pass or badge. + +## Failures + +- No source-owned `ServiceWorkflowAdmission`, `ServiceWorkflowAdmissionReport`, or `ServiceWorkflowHandle` schema exists in the required sources. +- No current demo starts with an evidence/passport package, emits admission/readback, proves handle-as-authority failure, and then continues into one `x402_payment.exact` clearance. +- No rendered review/readback artifact was available to inspect for copy, layout, state separation, or hidden authority leakage. +- No negative tests currently prove the proposed fields cannot create policy decisions, greenlights, gateway checks, signer use, mutations, receipts, exports, or certificates. +- `Badge` remains the most dangerous simplification noun. Developers will naturally treat it as reusable auth unless the API name is `ServiceWorkflowHandle` and the false posture fields are mandatory. +- The README first-use ladder is mechanically strong but product-cognitively inverted: it teaches install/x402 mechanics before the larger protected-action story. +- SDK/CLI/MCP/docs/examples are not yet converged around one product packet. Without convergence, simplification becomes more vocabulary, not less complexity. + +### UX Anti-Patterns + +- Showing a single "approved", "verified", "admitted", or "cleared" badge without separate rows for evidence recognition, action request, policy decision, gateway check, mutation attempt, receipt/refusal/proof gap, and downstream uncertainty. +- Letting the handle appear in UI near buttons that say pay, execute, sign, deploy, approve, retry, or repair. +- Treating refusal, proof gap, replay refusal, or support-bundle generation as retry permission. +- Using certificate visuals before terminal evidence exists. +- Rendering a human summary that is not structurally bound to the exact action contract. +- Teaching `HandshakeClient` first and only later explaining role custody. +- Hiding raw/sibling bypass posture from the first-use proof. +- Copying hand-written JSON into docs instead of generating schema-shaped samples from source-owned demos. + +## Proof Gaps + +- User comprehension is unproven. The macro map has strong reasoning, but no evidence that new developers will distinguish Passport/Admission/Handle from auth. +- Product-surface source placement is unresolved. The safe default is `src/surfaces` plus example/readback tests, not `src/protocol/areas`, unless a new authority transition is intentionally created. +- CLI command shape is unresolved. A new command may be useful only if it is readback/evidence posture and manifest-tested. +- MCP readback shape is unresolved. A read-only resource is safer than a new tool. +- SDK surface shape is unresolved. Role-scoped clients should expose or consume the readback shape without acquiring all-role authority. +- Adoption value is unproven until a clean installed-artifact or local repo first-use path can be run by a fresh developer without chat memory. +- No source-owned packet yet proves docs, SDK, CLI, MCP, and examples all describe the same object with the same non-authority fields. + +## Required Changes + +### Docs / SDK / CLI / MCP / Example Convergence Plan + +1. Define one source-owned surface packet: + +```text +ServiceWorkflowAdmissionReport + passportPackageDigest + passportPresentationId + admissionId + acceptedStandingEvidenceRefs + refusedStandingEvidenceRefs + staleStandingEvidenceRefs + proofGapEvidenceRefs + serviceWorkflowHandleId + serviceWorkflowHandleDigest + boundedAttemptScope + nextActionRequestTemplateRef + createsAuthority: false + createsGreenlight: false + performsGatewayCheck: false + permitsMutation: false +``` + +2. Place it in a product-surface/readback lane first, not in a protocol primitive lane, unless the chair explicitly scopes a new authority transition. +3. Add a local example such as `examples/service-workflow-admission/` that emits stable JSON and Markdown output and includes a handle-as-authority refusal. +4. Update `docs/internal/protocol-layman.md` to teach this story, then map it to the exact protocol chain. +5. Update `README.md` first-use language so the existing x402 ladder is the protected-event continuation, not the whole product story. +6. SDK: expose or consume the packet through role-scoped clients only. Do not teach the all-role root client as the first activation path. +7. CLI: either reuse existing evidence/readback commands or add only a manifest-declared readback command. It must have explicit non-goals and must not use mutation-shaped names. +8. MCP: expose admission/readback as read-only resources if needed. Keep `handshake.actions.x402_payment.propose` as proposal-only and do not add an authority-sounding admission tool. +9. Examples: make generated demo output the source of docs snippets where possible. +10. Tests: add or extend `quality:claims`, `quality:architecture`, `surface-boundary-posture`, CLI/MCP posture, role-client, and product demo tests to lock the convergence. + +### Adoption Gates + +- Gate 1: a fresh developer can run the local example and see accepted/refused/stale/proof-gap evidence plus non-authority handle fields without reading kernel internals first. +- Gate 2: the negative handle-as-authority path refuses before policy, greenlight, gateway check, signer use, mutation, receipt export, or certificate. +- Gate 3: the same packet fields appear in docs, SDK typing, CLI/MCP readback, and example output. +- Gate 4: role-scoped SDK client docs remain the first taught SDK path. +- Gate 5: `npm run quality:claims` passes after language changes. +- Gate 6: `npm run quality:architecture` passes after surface, command, export, and naming changes. +- Gate 7: focused product/demo tests pass for the generated output packet. +- Gate 8: package/public-surface checks pass if any export or package README changes. +- Gate 9: `npm run check:repo` passes before the macro plan treats the simplification as implementation-ready. + +## Status Recommendation + +Sidecar recommendation: design/DevEx/adoption gate is not passable yet. The direction is strong enough to plan, but not strong enough to execute without a source-owned packet, a first-use demo, convergence across surfaces, and negative non-authority tests. + +Do not use this focus as evidence for `READY_FOR_AGENT_EXECUTION`. This sidecar does not select the macro-plan status; the chair must reconcile this with other audits and validation. + +## Commands Or Tools Used + +- `rg -n` over `/Users/joelchan/.codex/memories/MEMORY.md` for relevant Handshake context. +- `wc -l` for required source sizing. +- `sed -n` for required source reads. +- `ls -la` to inspect the assigned audit directory. +- `test -e` to confirm the assigned report did not already exist. +- `git status --short -- ` to check the assigned write path. +- `apply_patch` to write this one report. + +## Smallest Next Mechanism + +Build the non-authority readback contract before changing public story or SDK ergonomics: + +```text +ServiceWorkflowAdmissionReport + ServiceWorkflowHandle +-> explicit false authority fields +-> handle-as-authority refusal fixture +-> one x402 protected-event continuation +-> JSON/Markdown example output +-> claim, architecture, CLI/MCP, SDK, and product tests +``` + +That is the smallest mechanism that can make the product feel simple without making the system basic or advisory. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/protected-action.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/protected-action.md new file mode 100644 index 0000000..11c96e2 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/protected-action.md @@ -0,0 +1,144 @@ +## Audit Scope + +Verdict: accept the Passport / Admission / Handle ID model only as a non-authority product-surface or projection contract. Do not let it become a protocol primitive, gateway input, reusable workflow credential, signer permission, x402/auth.md clearance, receipt, or terminal certificate. + +Assigned focus: protected-action posture and authority boundaries for `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, and `serviceWorkflowHandleDigest`. + +Out of scope: selecting the macro move, synthesizing the final macro plan, promoting final plan status, editing source, running implementation gates, or proving runtime containment. + +## Source Boundary + +Canonical source truth for authority claims is `README.md`, `QUALITY.md`, `docs/internal/decisions.md`, and `docs/internal/protocol-notes.md`. These sources say product surfaces expose proposal/evidence/readback without creating authority; authority remains exact contract, policy decision, one-use greenlight, gateway check, and receipt/refusal/proof gap. + +Derived planning evidence is `.planning/macro-map/*` and `.planning/codebase/*`. It can pressure-test the plan, but it cannot promote Passport, Admission, Badge, or Handle fields into source truth. + +The run input explicitly requires all five ID fields to be correlation/reconstruction fields with `createsAuthority: false`. A read-only source search did not find those five field names in non-hidden source/docs; they are not source-owned implementation yet. + +Memory was used only for prior-boundary context and was not treated as authority. + +## Files Read + +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-protected-action-gates.md` +- `/Users/joelchan/.codex/memories/MEMORY.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` +- `.planning/macro-map/PROTECTED-ACTION-MAP.md` +- `.planning/macro-map/views/AUTHORITY.md` +- `.planning/macro-map/views/RUNTIME.md` +- `.planning/macro-map/CONCERNS.md` +- `.planning/codebase/ARCHITECTURE.md` +- `.planning/codebase/CONCERNS.md` +- `.planning/codebase/INTEGRATIONS.md` +- `README.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `QUALITY.md` + +## Invariant At Stake + +Passport, Admission, and Handle fields may help correlate a service workflow and reconstruct later protected-action evidence. They must not create permission, trust, policy, greenlight, gateway acceptance, signer access, payment material, mutation authority, receipt export, terminal certification, hosted operation, or reusable auth. + +Every protected event still needs a fresh `CandidateAction` or refusal, exact `ActionContract`, `PolicyDecision`, one-use `Greenlight` or `Refusal`, `GatewayCheckAttempt`, and terminal receipt/refusal/replay refusal/proof gap. If an admitted workflow or handle can execute without that chain, the compiler overreached the principal. + +## Pass Conditions + +### Field-Level Protected-Action Acceptance Matrix Additions + +| Field | Allowed Meaning | Required Flags | Forbidden Interpretation | Required Rejection | +| --- | --- | --- | --- | --- | +| `passportPackageDigest` | Content digest of the presented evidence bundle for reconstruction. | `createsAuthority: false`; `createsPolicyDecision: false`; `createsGreenlight: false`; `performsGatewayCheck: false`; `permitsMutation: false`; `containsSecretOrPaymentMaterial: false`. | Identity proof, trust proof, credential custody proof, policy input that bypasses fresh action evaluation. | Reject if used as `ActionContract` digest, delegated authority digest, credential-ref digest, gateway-readiness digest, or signer/payment material. | +| `passportPresentationId` | Unique per service intake or presentation event. | Same false authority flags. | Session token, bearer auth, reusable service admission, future-call permission. | Reject if reused to satisfy policy, gateway, SDK role-client auth, MCP tool auth, or OpenAPI security. | +| `admissionId` | Service-side workflow intake result reference: accepted, refused, or proof gap. | Same false authority flags plus `isProtectedActionClearance: false`. | `PolicyDecision`, `Greenlight`, gateway admission, route custody, mutation approval, receipt. | Reject if passed to policy/gateway APIs as sufficient evidence, or if an accepted admission skips `CandidateAction` creation/refusal. | +| `serviceWorkflowHandleId` | Carried workflow correlation reference for context and readback. | Same false authority flags plus `isReusableAuth: false`; `widensOperatingEnvelope: false`. | Badge, API key, capability token, x402 payment approval, auth.md credential, retry permission. | Reject if runtime, MCP, browser, shell, HTTP, x402, or auth.md code treats it as permission to call a protected surface. | +| `serviceWorkflowHandleDigest` | Digest of carried workflow handle context for drift detection and reconstruction. | Same false authority flags plus `isGatewayBinding: false`. | Contract digest, greenlight digest, gateway check digest, receipt digest, terminal certificate digest. | Reject if digest drift is smoothed over; require refusal or a new exact contract. | + +### Boundary Conditions + +- `CandidateAction`/refusal boundary: Admission may prepare context only. Each protected action must still create a fresh candidate or refusal with current assumptions, parameters, idempotency, delegated-authority status, credential posture, bypass posture, and evidence expectations. +- Gateway/enforcement boundary: Only the exact contract -> policy -> one-use greenlight -> gateway check chain may precede mutation. The five ID fields must never satisfy `VerifiedGatewayCheck`. +- Raw sibling bypass: Direct x402 payloads/signatures, bearer tokens, raw HTTP/MCP/browser/shell/package/network routes, dynamic tool names, changed parameters, stale metadata, and consumed greenlights must be refused or recorded as bypass/proof gap. If enforcement is not gateway-backed, This is advisory, not Handshake. +- x402 posture: current wedge stays one buyer-side `x402_payment.exact` per call. `PaymentPayload` and `PAYMENT-SIGNATURE` stay behind the wallet gateway after `VerifiedGatewayCheck`. +- auth.md posture: auth.md prose, PRM/AS metadata, registration, claims, scopes, revocation, and credentials are provenance/custody evidence only until a protected API call clears through exact contract, policy, one-use greenlight, gateway check, and post-gate credential resolution. +- Receipt/refusal/proof-gap separation: Admission/handle readback is not receipt evidence. Downstream finality unknown stays proof gap, not success. +- Tier 3 block: hosted operation, provider/customer gateway custody beyond local proof, marketplace/certification, cross-org trust, aggregate spend, seller/facilitator operation, and hosted mutation authority remain blocked until source evidence and gates prove them. + +### Non-Claims Required + +- Passport package does not prove identity authorization. +- Presentation ID does not prove principal understanding. +- Admission ID does not prove protected-action approval. +- Service workflow handle does not prove permission, settlement, signer access, credential access, gateway acceptance, or retry authority. +- Handle digest does not prove contract, greenlight, gateway, receipt, or certificate binding. +- MCP visibility, x402 capability, auth.md credential issuance, OpenAPI route shape, browser observation, host profile, or public npm/MCP Registry distribution does not create authority. + +## Failures + +- The macro map already records that no field-level acceptance matrix exists for `ServiceWorkflowAdmission`; this report supplies required additions, but source does not yet enforce them. +- No negative test proves `ServiceWorkflowHandle` cannot be passed into policy, gateway, runtime, SDK, MCP, x402, or auth.md APIs as permission. +- `Admission` is overloaded across route custody, hosted readiness, product admission packets, and receipt/export language. A standalone `Admission` object would blur route admission, workflow acceptance, policy decision, and gateway clearance. This is advisory, not Handshake. +- The five fields are not yet source-owned schema fields with hard false booleans; they currently live in planning intent. +- Raw sibling bypass posture is documented, but no Passport/Admission/Handle-specific probe proves generated code cannot route around the protected path. +- x402/auth.md composite execution remains an expansion candidate, not current execution authority. auth.md credential issuance plus x402 payment capability must not be marketed as a cleared composite call. +- Tier 3 hosted-operation language must remain blocked. The current sources explicitly leave hosted mutation authority, provider/customer gateway custody beyond local proof, settlement/finality, marketplace/certification, cross-org trust, aggregate spend enforcement, and host-wide containment as proof gaps or cut lines. + +## Proof Gaps + +- No source-owned `ServiceWorkflowAdmission` / `ServiceWorkflowHandle` schema was read. +- No source-owned matrix row proves all five fields have `createsAuthority: false`. +- No test gate was run for claim boundary, architecture boundary, protocol compilation, policy/gateway refusal, runtime ingress, x402, auth.md, or receipt projection. +- No host-specific smoke was run for browser, A2A, Claude Code, Hermes, OpenClaw, generic MCP, shell, package manager, or direct network bypass. +- No external x402 provider/facilitator finality, provider custody, settlement, or customer gateway custody proof exists in the audited sources. +- No provider-grade auth.md credential lifecycle or credential redaction fuzzing proof exists. +- No proof shows a handle cannot widen `OperatingEnvelope.allowedResources`, carry raw credential/payment material, or stand in for delegated authority. +- No receipt/export fixture proves admission readback cannot be mistaken for receipt, terminal certificate, downstream success, or retry permission. + +## Required Changes + +### Implementation Blockers + +- Block source implementation until the field-level acceptance matrix is source-owned and tested. +- Block docs, demos, SDK, CLI, MCP, and examples from saying Passport, Admission, Badge, or Handle creates authority. +- Block any kernel object, root export, protocol-area path, gateway-route name, or role-client method that makes the five fields look authority-bearing. +- Block x402/auth.md demo promotion until the non-authority surface is in place and the paid/credentialed call still routes through exact event clearance. +- Block Tier 3 progression until Tier 1/Tier 2 simplification has proof gates or explicit proof gaps recorded. + +### Negative Tests Required + +- Architecture/claim-boundary test: `Passport`, standalone `Admission`, `Badge`, `ServiceWorkflowAdmission`, and `ServiceWorkflowHandle` must not appear under `src/protocol/areas/*`, authority-bearing root exports, gateway execution paths, or policy/gateway route names unless a distinct enforceable transition is documented. +- Schema test: all five fields require `createsAuthority: false`; any `true`, omitted flag, raw secret, payment payload/signature, bearer token, signer ref, or resource-widening field fails. +- Policy/gateway test: `admissionId` and `serviceWorkflowHandleId` cannot satisfy `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `VerifiedGatewayCheck`, `Receipt`, or `AuthorityCertificate` inputs. +- Runtime stress test: loops, retries, branches, dynamic tool construction, stale review surfaces, late-bound parameters, and changed observed parameters produce refusal/new contract, not handle reuse. +- x402 test: handle/admission fields cannot create `PaymentPayload`, `PAYMENT-SIGNATURE`, signer invocation, live provider custody, or aggregate spend authority. +- auth.md test: handle/admission fields cannot resolve credentials, create Authorization headers, widen scopes, bypass revocation/isolation, or make `readyForCompositeExecution` true. +- Receipt/projection test: admission readback cannot be emitted as receipt, receipt export, terminal certificate, downstream success, or retry permission. +- Raw sibling bypass test: direct HTTP, MCP, browser, shell, package-manager, network, raw x402, and raw bearer paths remain prevented, refused, isolated, or proof-gapped per host posture. + +### Smallest Next Mechanism + +Add a source-owned product-surface contract outside `src/protocol/areas/*`: + +```text +ServiceWorkflowAdmission -> accepted | refused | proof_gap +ServiceWorkflowHandle -> correlation/readback context only +``` + +The schema must include the five ID fields, the hard false authority flags, host/runtime bypass posture refs, and redacted evidence refs. Pair it with the negative tests above before any product-language, SDK, CLI, MCP, demo, or Tier 3 work uses the model. + +## Status Recommendation + +Recommendation for this protected-action gate: `NEEDS_PROTECTED_ACTION_POSTURE`. + +Do not promote to `READY_FOR_AGENT_EXECUTION` on this focus until the field-level matrix, source-owned non-authority schema, and negative tests exist. Keep the move only as a non-authority product-surface simplification. The macro chair can still plan around it, but only with the blockers preserved as proof gates. + +## Commands Or Tools Used + +- `sed -n '1,220p' /Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `sed -n '1,260p' /Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-protected-action-gates.md` +- `rg -n "Tier 3|Passport|Admission|Handle|passportPackageDigest|passportPresentationId|admissionId|serviceWorkflowHandleId|serviceWorkflowHandleDigest|protected action|x402|authority|createsAuthority|greenlight|gateway|CandidateAction|refusal|proof gap|bypass" /Users/joelchan/.codex/memories/MEMORY.md` +- `wc -l` on required source files and the target report path. +- `sed -n` on the required macro-plan input, macro-map, codebase, README, decisions, protocol-notes, and QUALITY files. +- `rg -n "passportPackageDigest|passportPresentationId|admissionId|serviceWorkflowHandleId|serviceWorkflowHandleDigest|ServiceWorkflowAdmission|ServiceWorkflowHandle|createsAuthority" . README.md QUALITY.md docs/internal/decisions.md docs/internal/protocol-notes.md` +- `rg -n "CandidateAction|Refusal|Greenlight|GatewayCheck|VerifiedGatewayCheck|PaymentPayload|PAYMENT-SIGNATURE|auth\\.md|x402_payment\\.exact|proof gap|bypass|host-wide containment|Tier 3|hosted" ...` +- `git status --short -- .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/protected-action.md` +- `ls -la .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits` +- `apply_patch` to add this report only. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/runtime-agent.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/runtime-agent.md new file mode 100644 index 0000000..6e3a94d --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/runtime-agent.md @@ -0,0 +1,210 @@ +## Audit Scope + +Focus: runtime and generated-agent posture for the Tier 1 / Tier 2 product-simplification macro-plan run `20260525T095940Z-tier1-tier2-product-simplification`. + +Assigned sidecar focus: Codex, Claude Code, OpenClaw, Hermes, auth.md, x402, MCP, browser, A2A, OpenAPI, generated loops, retries, branches, dynamic tool names, stale review, raw sibling bypass, and handle misuse. + +Verdict: runtime-agent posture is not executable as a generic multi-host plan. The macro plan can proceed only as a runtime-gated planning package that preserves `NEEDS_RUNTIME_PROFILE` / `NEEDS_AGENT_REVIEW` blockers until the handle/admission surface has host-specific proof rows, generated-execution stop rules, raw sibling posture, and negative tests. This sidecar does not select the macro move and does not promote final status. + +## Source Boundary + +Canonical repo truth for runtime claims comes from `README.md`, `docs/internal/protocol-notes.md`, and source files under `src/`. `.planning/` files are scratch or derived evidence. They are valid for this macro-plan run but cannot become repo-facing authority without source and test promotion. + +The governing planning input says product simplification must not hide authority, gateway, evidence, refusal, proof-gap, isolation, or reconstruction boundaries. It also says Passport, Admission, Badge, Handle, Certificate, review surfaces, and IDs are evidence/correlation surfaces only unless a source-owned protocol transition proves otherwise. + +The runtime map explicitly names Codex, Claude Code, OpenClaw, Hermes, auth.md, x402, MCP, browser, A2A, and OpenAPI as distinct contexts. None can be collapsed into "agent admitted" or "host contained." + +Source confirms the same boundary: + +- Runtime ingress is proposal-only and records generated execution evidence, generated graph evidence, tool-call drafts, intent compilations, action contracts, or refusals. +- MCP is proposal/evidence transport only. +- x402 protected-tool profiles are readiness/profile artifacts only. +- auth.md is provenance plus gateway-custody evidence until exact protected API calls clear through policy and gateway. +- OpenAPI and HTTP admission describe route/caller custody only, not side-effect proof. +- Browser, A2A, shell, network, package-manager, and generic MCP interception remain proof gaps unless a specific gateway-owned protected path proves otherwise. + +## Files Read + +Required sources read: + +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-runtime-gates.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` +- `.planning/macro-map/AGENT-RUNTIME-MAP.md` +- `.planning/macro-map/views/AGENT.md` +- `.planning/macro-map/views/RUNTIME.md` +- `.planning/codebase/ARCHITECTURE.md` +- `.planning/codebase/INTEGRATIONS.md` +- `.planning/codebase/TESTING.md` +- `docs/internal/protocol-notes.md` +- `README.md` +- `src/runtime/ingress/index.ts` +- `src/runtime/ingress/schemas.ts` +- `src/mcp/x402-proposal.ts` +- `src/x402-protected-tool/LANE.md` + +Additional source anchors read for runtime/auth/browser/OpenAPI/A2A posture: + +- `src/runtime/ingress/families.ts` +- `src/adapters/auth-md/action-proposal.ts` +- `src/adapters/auth-md/gateway.ts` +- `src/adapters/auth-md/bypass-probes.ts` +- `src/adapters/x402-payment/protected-tool-facade/index.ts` +- `src/adapters/x402-payment/protected-tool-profile/index.ts` +- `src/http/admission/index.ts` +- `src/http/openapi/index.ts` +- `src/mcp/LANE.md` +- `.planning/codebase/CONCERNS.md` +- `.planning/macro-map/MACRO-MAP.md` +- `.planning/macro-map/TASKS.jsonl` + +## Invariant At Stake + +No generated or automated consequential action may execute outside declared bounds. Runtime/tool/catalog/profile/admission evidence can help form candidate contracts, but it cannot become authority. + +Specific invariant: a Passport, Admission, Badge, or `ServiceWorkflowHandle` may carry context for an admitted workflow attempt, but it must not satisfy policy, create a greenlight, pass a gateway check, invoke a signer, create payment material, resolve credentials, execute a mutation, export a receipt, mint a certificate, or authorize retries. Every protected event still needs a fresh exact action contract, policy decision, one-use greenlight or refusal, gateway check, and receipt/refusal/proof gap. + +If a handle lets generated code call a protected tool, raw signer, browser tool, MCP sibling, OpenAPI route, A2A task, or auth.md/x402 path as permission, this is ambient authority wearing a badge. + +## Pass Conditions + +### Runtime Suitability Rows + +| Runtime or rail | Suitability for this macro plan | Pass condition | Non-claim that must survive | +| --- | --- | --- | --- | +| Codex local | Conditionally operable for source-owned local x402 profile evidence only | Name `AGENTS.md`, skill/MCP discovery, sandbox/approval/file-edit posture, non-interactive failure behavior, local profile target, and raw sibling probes | Not host-wide containment, user host mutation proof, policy, gateway, signer, or receipt proof | +| Claude Code | Profile required / proof-gapped | Name `CLAUDE.md`, skills/plugins, `.claude/agents`, managed MCP target, permissions, foreground/background subagent behavior, and fresh-context delegation prompt requirements | Not native host certification or unmanaged MCP containment | +| Hermes | Tool-packet profile required / proof-gapped | Name `hermes.tool-packet.json`, command/args/config digest, host tool digest, tool-list digest, unmanaged-tool-packet posture, and native-host non-claims | Not native host certification, gateway authority, or signer custody | +| OpenClaw | Tool-packet profile required / proof-gapped | Name `openclaw.tool-packet.json`, command/args/config digest, host tool digest, tool-list digest, unmanaged-tool-packet posture, and native-host non-claims | Not native host certification, gateway authority, or signer custody | +| Generic MCP | Proposal/evidence transport only | Keep MCP resources/tools as proposal/readback surfaces and require trusted runtime-side readiness/policy binding before contract proposal | Not enforcement, authorization, recovery authority, process supervision, broad MCP protection, or raw sibling containment | +| x402 | Narrow local/reference exact per-call path only | Bind official exact payment requirement, delegated spend ref, gateway readiness, policy version, selected requirement digest, idempotency, and `VerifiedGatewayCheck` before gateway-held signer use | Not principal spend authority, aggregate spend ledger, settlement, provider custody, hosted payment operation, broad x402 compatibility, or marketplace certification | +| auth.md | Provenance plus protected API-call proposal/gateway fixture only | Keep auth.md metadata, scopes, registration, and credential issuance as evidence; exact protected API call must clear through action contract, policy, greenlight, gateway check, and post-gate credential resolution | Not OAuth provider, identity provider, service gateway, WorkOS replacement, or protected-action approval | +| Browser | Evidence/probe surface only | Any browser-side mutation must be represented as its own protected path with raw sibling posture and gateway-owned mutation credential | Not controlled by MCP, OpenAPI, A2A, or host profile by default | +| A2A | Operation/task catalog evidence only | Treat task/agent/service shape as source evidence for a future candidate action, not as side-effect proof | Not gateway admission or protected-action clearance | +| OpenAPI | Route/catalog evidence only | Keep route security schemes as caller-custody/admission evidence; protected side effects still require exact contract and gateway check | Not runtime enforcement or proof that a side effect occurred | +| Runtime ingress | Proposal-only for known dispatch families | Preserve wrapped, raw sibling, and ambiguous dispatch distinctions; keep loops/retries/branches/dynamic construction/late-bound params in evidence and refusals | Not host-wide interception or sandbox containment | +| ServiceWorkflowHandle / Badge | Not executable authority | Carry only refs/digests, expiry, workflow bounds, non-authority flags, and requirement for fresh action request | Not reusable auth, permission, gateway acceptance, signer use, receipt, or retry permission | + +Weakest host posture controls executable status. Parity artifacts are not certification. + +### Generated-Execution Stress Gates + +The macro plan passes runtime-agent review only if it records these gates as stop conditions or negative tests: + +| Stress case | Required behavior | +| --- | --- | +| Loop over protected calls | Each iteration needs its own exact action request or explicit refusal; handle reuse must not create authority. | +| Retry after refusal/proof gap/replay | Stop or create a new exact contract according to reason code; never retry from handle/admission alone. | +| Branch-dependent action | Branch ref must be carried into generated execution evidence and candidate binding; stale summaries are not authority. | +| Dynamic tool name or endpoint construction | Refuse or mark ambiguous before contract proposal unless the exact tool/action/gateway binding is reconstructed. | +| Late-bound parameters | Refuse or recraft before policy/gateway; stale review cannot authorize changed params. | +| Stale rendered review | Require fresh contract/review binding; rendered review is evidence only. | +| Raw sibling route detected | Stop and record bypass posture/proof gap; do not smooth into success. | +| Browser/network side channel | Treat as raw sibling or unobserved region until host-specific proof exists. | +| Direct MCP/OpenAPI/A2A route | Treat as proposal/catalog evidence only unless exact gateway path is proven. | +| auth.md raw bearer or token replay | Refuse before compilation/gateway; raw credential material must not enter handle, evidence, or receipt. | +| x402 raw payment payload/signature | Refuse before signer use; `PaymentPayload` / `PAYMENT-SIGNATURE` must stay gateway-held after verified gate. | + +### Continuation And Handoff Requirements + +A future agent handoff must include: + +- source priority: canonical docs/source first, `.planning/` scratch second; +- exact allowed files and forbidden authority paths; +- runtime-specific suitability rows for Codex, Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, OpenAPI, auth.md, and x402; +- explicit non-authority flags for Passport, Admission, Badge, and `ServiceWorkflowHandle`; +- raw sibling inventory for x402 signer/payment, auth.md bearer/API, MCP sibling, browser, network, shell, package manager, repo write, deploy, and database mutation routes; +- stop conditions for stale metadata, stale policy, stale readiness, changed observed params, replay, proof gap, isolation, revocation, unknown gateway posture, raw sibling reachability, and unobserved generated-code regions; +- eval path a named runtime can run after compaction, restart, or handoff. + +## Failures + +P0: A macro plan that treats `ServiceWorkflowHandle`, Badge, MCP tool visibility, OpenAPI security schemes, A2A task shape, x402 capability, or auth.md credential issuance as permission fails the runtime invariant. This is advisory, not Handshake. + +P0: A macro plan that says "multi-host protected action" without separate Codex, Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, and OpenAPI rows overclaims. Host profiles are not containment. + +P0: A plan that allows a handle to skip a fresh action request for each protected event creates reusable ambient authority. The compiler overreached the principal. + +P1: Current source has strong proposal-only runtime ingress, but the new Passport/Admission/Badge/Handle surface does not yet have source-owned runtime misuse tests. The plan must add those gates before fixture or demo work. + +P1: Runtime ingress models loops, retries, branches, dynamic construction, late-bound params, raw siblings, and ambiguous dispatches, but it remains caller-observed evidence. It cannot prove every raw sibling path in a host was intercepted. + +P1: x402 protected-tool profiles can prepare runtime dispatch only after trusted readiness, but they remain profile/readiness artifacts. They do not perform policy, gateway check, signer use, mutation, receipt export, settlement, provider custody, native host certification, or host-wide containment. + +P1: auth.md protects useful provenance and credential-custody paths, but provider-grade credential custody and composite auth.md + x402 execution remain proof gaps. Do not plan a composite service-gateway proof before the surface gates exist. + +P1: Browser, A2A, and OpenAPI currently lack live protected-path probes in the read boundary. They must be treated as operation/catalog/evidence rails only. + +## Proof Gaps + +### Runtime-Specific Proof Gaps + +| Runtime or rail | Proof gap | Required proof before executable claim | +| --- | --- | --- | +| Codex | Local host-origin evidence does not prove host-wide containment or user host mutation control | Codex-local activation/readback plus named raw sibling probes for the exact handle workflow | +| Claude Code | Managed/profile parity artifact only | `.mcp.json` or managed MCP packet, permissions, fresh-context subagent handoff, unmanaged sibling posture, and smoke evidence | +| Hermes | Tool-packet artifact only | `hermes.tool-packet.json` packet, command/args/config/tool-list digests, native-host non-claims, and raw sibling posture | +| OpenClaw | Tool-packet artifact only | `openclaw.tool-packet.json` packet, command/args/config/tool-list digests, native-host non-claims, and raw sibling posture | +| Generic MCP | Tool discovery and proposal transport are not enforcement | External host transcript plus refusal/readback behavior, with sibling MCP path posture | +| Browser | No browser-side mutation interception proof | Browser-specific protected path or explicit proof gap for browser tool/network side effects | +| A2A | No task/agent side-effect proof | A2A operation-to-action-contract mapping plus gateway-owned mutation boundary | +| OpenAPI | Route shape and bearer schemes are not gateway admission | Operation catalog evidence plus proof that mutation routes require exact contract and gateway check | +| x402 | Local exact per-call proof is not live provider custody, settlement, aggregate spend, or broad compatibility | Live/provider-specific custody, facilitator/finality, and spend-ledger evidence before those claims | +| auth.md | Credential provenance is not protected-action approval, and redaction remains provider-format sensitive | Provider-specific credential fixtures/fuzzing and gateway custody proof before live custody claims | +| auth.md + x402 | Interlock packets are non-authority readiness/evidence surfaces | Composite exact contracts, policy, one-use greenlights, verified gateway checks, payment/credential evidence, receipt/refusal/proof-gap chain | +| Runtime ingress | Known-family proposal compiler, not host-wide telemetry/interception | Per-runtime host adapter proof that consequential mutation cannot bypass gateway, or explicit bypass proof gap | + +Additional proof gaps: + +- No current `ServiceWorkflowAdmission` / `ServiceWorkflowHandle` source schema exists in the required boundary. +- No dedicated negative tests prove the new handle cannot satisfy policy, greenlight, gateway check, receipt, certificate, signer, payment, credential resolution, or mutation paths. +- No workflow-specific raw sibling inventory exists for handle carriage. +- No live host smokes, browser/A2A probes, external MCP Registry lookup, live x402 provider check, or customer gateway custody check were run in this audit. + +## Required Changes + +1. Add a runtime-agent gate section to the macro plan before any executable status. It must include the runtime suitability rows above, weakest-host rule, and explicit non-claims. + +2. Add generated-execution stress gates for loops, retries, branches, dynamic tool names, late-bound params, stale review, changed observed params, unobserved regions, and replay. The expected behavior must be refusal, recraft, read evidence, stop, or proof gap, never permission from handle/admission. + +3. Define raw sibling bypass posture for the handle workflow. At minimum inventory x402 raw signer/payment payload, direct MCP x402 call, auth.md raw bearer/direct HTTP/browser/network/token replay, shell/package manager/repo/deploy/database mutation, browser-side tools, generic network clients, and unmanaged MCP/tool-packet siblings. + +4. Require a continuation/handoff packet. It must survive compaction/restart by naming canonical sources, scratch status, exact candidate files, runtime target, allowed/forbidden tool surfaces, stop conditions, and eval commands. + +5. Keep MCP, OpenAPI, and A2A as catalog/proposal/operation evidence. The plan must say they are not enforcement unless a source-owned gateway check path is present. + +6. Keep x402 per-call and auth.md protected API call separate until a later composite fixture has exact event clearance. The plan must not imply that auth.md credential issuance plus x402 payment capability creates a service-gateway authority event. + +7. Add negative tests or test-plan requirements that `ServiceWorkflowHandle` / Badge cannot create or satisfy `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `Receipt`, `AuthorityCertificate`, signer input, `PaymentPayload`, `PAYMENT-SIGNATURE`, raw credential material, OpenAPI security authority, hosted/provider custody, settlement, or widened envelope scope. + +### Smallest Next Mechanism + +Before fixture planning, write one runtime-agent gate packet for `ServiceWorkflowAdmission` / `ServiceWorkflowHandle` with: + +- hard non-authority booleans; +- per-host suitability rows; +- generated-execution stress gates; +- raw sibling bypass inventory; +- continuation/handoff requirements; +- required proof-gap labels; +- focused closeout gates: `npm run quality:claims`, `npm run quality:architecture`, `npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts`, plus x402/auth.md adapter tests if the wording touches payment, signer custody, credential custody, or downstream finality. + +## Status Recommendation + +Verdict: `NEEDS_RUNTIME_PROFILE` with `NEEDS_AGENT_REVIEW` pressure preserved. + +Do not mark the macro plan `READY_FOR_AGENT_EXECUTION` unless the chair reconciles this report into runtime gates, proof gaps, and tasks. A safe macro status can be phase-planning oriented only if it explicitly blocks executable runtime claims until the required changes above exist. + +This sidecar does not choose the macro move, does not synthesize the final plan, and does not promote final status. + +## Commands Or Tools Used + +- `rg -n` over `/Users/joelchan/.codex/memories/MEMORY.md` for relevant prior Handshake runtime/x402/macro-plan context. +- `wc -l` over required source files to size the read set. +- `sed -n` on all required sources listed in `Files Read`. +- `sed -n` on additional source anchors for runtime ingress families, auth.md, x402 protected-tool profile/facade, HTTP admission, OpenAPI, MCP lane, codebase concerns, macro map, and macro tasks. +- `rg -n` for runtime, host, raw sibling, browser, A2A, OpenAPI, auth.md, x402, loop, retry, branch, dynamic, and stale posture anchors. +- `rg --files` to locate auth.md, MCP, OpenAPI/admission, x402 protected-tool, and runtime ingress source files. +- `git status --short -- .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/runtime-agent.md` +- `ls -la .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits` +- `apply_patch` to create only this audit report. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/slices.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/slices.md new file mode 100644 index 0000000..24e254c --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/slices.md @@ -0,0 +1,182 @@ +## Audit Scope + +Verdict: fail closed for implementation until the macro plan contains a full long-running Tier 1/Tier 2 program, not a widened version of the earlier minimal slice. + +Focus: execution slices and full-program sequencing for Tier 1/Tier 2 product simplification before Tier 3 progression. This audit does not select the macro move, does not synthesize the final plan, and does not promote final status. It pressure-tests what the future chair-owned macro plan must contain before implementation begins. + +The user has explicitly rejected a minimal slice and asked to boil the lake before Tier 3. That changes the required planning breadth, but it does not erase the source blockers: non-authority product nouns, generated-agent handle misuse, host-profile overclaiming, naming drift, external rail proof gaps, and validation absence remain blocking gates. + +## Source Boundary + +Authoritative source boundary: + +- Canonical repo truth: `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`. +- Macro-plan contract truth: `gsd-macro-plan/SKILL.md`, `macro-plan-contract.md`, `output-quality-bar.md`. +- Current run truth: `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md`, `source-snapshot.md`, `blocked-checks.md`. +- Derived planning evidence: `.planning/macro-map/*` and `.planning/codebase/*` files read below. These can guide planning, but tracked source, canonical docs, and tests win if facts disagree. +- Memory context was used only to avoid repeating prior drift mistakes: Tier 3 stays outside the kernel package, x402 remains narrow local/reference buyer-side proof, and prior green tests cannot be trusted after worktree drift. + +Boundary caveat: the input requires the future macro plan to read a larger source boundary than this sidecar was asked to read, including `FACET-MAP.md`, `EXPERIENCE-MAP.md`, `AGENT-RUNTIME-MAP.md`, `PROTECTED-ACTION-MAP.md`, `DECISIONS.md`, `TASKS.jsonl`, `views/*.md`, strategic run files, and protocol definition/architecture/layman docs. A future plan that does not reconcile that full boundary is not implementation-ready. + +## Files Read + +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` +- `/Users/joelchan/.codex/memories/MEMORY.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md` +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-map/MACRO-MAP.md` +- `.planning/macro-map/EXECUTION-MAP.md` +- `.planning/macro-map/MECHANISM-MAP.md` +- `.planning/macro-map/CONCERNS.md` +- `.planning/codebase/STRUCTURE.md` +- `.planning/codebase/TESTING.md` +- `README.md` +- `QUALITY.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` + +## Invariant At Stake + +Product simplification can make Handshake legible, but it must not launder standing evidence, review language, workflow handles, or friendly IDs into authority. + +The invariant is: + +```text +Passport / Admission / Badge / Handle are evidence and context only. +Fresh exact protected-action clearance is the only path to authority. +``` + +Any macro plan that lets a passport, admission, badge, handle, certificate, review surface, CLI command, MCP resource, SDK type, demo output, or product ID satisfy policy, produce a greenlight, perform a gateway check, invoke a signer, create payment material, mutate, export a receipt, or mint terminal authority evidence violates the product kernel. + +## Pass Conditions + +The future macro plan passes this slices audit only if it contains all of the following: + +- A full source reconciliation phase that snapshots canonical docs, macro-map artifacts, codebase maps, blocked checks, missing artifacts, stale artifacts, and proof gaps before source edits. +- Execution slices with objective, source evidence, inputs, outputs, owner, dependencies, stop conditions, proof gates, verification commands, rollback or abandonment criteria, and agent handoff needs. +- A long-running sequence for Tier 1 and Tier 2, not only `docs/internal/service-workflow-story.md` plus a schema stub. +- Explicit P0/P1 preservation from `.planning/macro-map/CONCERNS.md` as implementation blockers unless accepted and bounded by the chair/user. +- A field-level matrix for `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` proving every field is evidence, bounds, posture, refusal, proof gap, or correlation only. +- Negative tests proving handles cannot satisfy `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `Receipt`, `AuthorityCertificate`, signer invocation, payment material creation, or mutation. +- Generated-execution stress coverage for loops, retries, branches, dynamic tool construction, stale review surfaces, raw sibling paths, and agents passing handles as permission. +- Product surface convergence across docs, SDK, CLI, MCP, demos, examples, package exports, readback projections, and architecture tests without broadening authority. +- Protected-action gates for each touched action family, especially x402, that preserve exact candidate action, credential holder, gateway authority holder, raw sibling bypass posture, refusal/readback/proof-gap separation, and one-use greenlight semantics. +- Stop conditions that halt before Tier 3 if Tier 1/Tier 2 simplification lacks source-owned schema, negative tests, validation, sidecar reconciliation, and full repo gates. +- Rollback or abandonment criteria for authority drift, raw material leakage, protocol primitive creep, multi-host containment overclaim, external rail overclaim, or fixture/demo-first sequencing. +- An `AGENT-HANDOFF.md` sufficient for a fresh agent to resume without chat memory, including instruction sources, ignored context, tool contract, checkpoints, stop conditions, proof gaps, and next agent step. +- `TASKS.jsonl` lines that are assignable mechanisms with acceptance checks, not advice. +- Validation evidence from the macro-plan validator before any claim of execution readiness. + +## Failures + +Current blockers that the future macro plan must not smooth over: + +- P0: Passport, Admission, Badge, and `ServiceWorkflowHandle` can become ambient authority if they carry or imply policy, greenlight, gateway, signer, receipt, certificate, credential, payment, or mutation material. +- P0: Generated agents may pass a handle into tools as permission, especially inside loops, retries, dynamic tool calls, stale review flows, or branch-dependent execution. +- P1: Multi-host evidence is not native containment. Codex-local evidence is stronger than Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, or OpenAPI, and none can be generalized. +- P1: Passport/Admission/Badge names can leak into protocol areas, package exports, runtime dispatch, gateway paths, CLI/MCP commands, or demos. +- P1: Developer docs can become metaphor-only unless they include exact fields, forbidden interpretations, failure states, proof gates, and source-owned tests. +- P1: Free passport verification can blur into paid clearance unless the economic unit remains protected-event terminalization. +- The run's `blocked-checks.md` says no field-level acceptance matrix exists for `ServiceWorkflowAdmission` / `ServiceWorkflowHandle`. +- No negative test currently proves a handle cannot create or satisfy authority-bearing records or signer/payment/mutation behavior. +- No implemented schema or rendered readback artifact proves users see admission, handle, action request, clearance, receipt, refusal, and proof gap as separate states. +- No live external rail proof exists for x402 provider/facilitator behavior, auth.md deployment corpus, ERC-8004 standing, MCP Registry lookup, Agentic.Market listing, hosted custody, provider signer lifecycle, or settlement/finality. +- The macro-plan package has not yet been written or validated. + +Missing slices if the chair only follows the old minimal path: + +- Source-boundary reconciliation and stale-artifact classification slice. +- Product noun authority-boundary slice for Passport, Admission, Badge, Handle, Certificate, review surfaces, and IDs. +- Source-owned surface schema/projection slice for `ServiceWorkflowAdmission` and `ServiceWorkflowHandle`. +- Non-authority flag and negative-test slice. +- Naming/package/export guard slice. +- Runtime/generated-execution misuse slice. +- Protected-action field-level matrix slice. +- Evidence/readback/redaction slice. +- x402 current-wedge non-regression slice. +- Docs/SDK/CLI/MCP/demo/example convergence slice. +- Quality, package, and full-repo gate slice. +- Tier 3 stop-wall and handoff slice. +- Rollback, abandonment, and git-checkpoint slice. +- Fresh-agent handoff and continuation slice. + +## Proof Gaps + +- No full macro-plan package exists yet for this run, so there is no current `EXECUTION-SLICES.md`, `AGENT-HANDOFF.md`, `RUNTIME-GATES.md`, `PROTECTED-ACTION-GATES.md`, `EVIDENCE-PLAN.md`, `REVIEW-GATES.md`, `RISKS.md`, `DECISIONS.md`, or `TASKS.jsonl` to audit. +- No evidence shows the future plan has read the full source boundary required by the run input. +- No evidence shows the future plan has reconciled sidecar audits before chair synthesis. +- No evidence shows the future plan has stop conditions specific enough to halt implementation when a product noun becomes authority-bearing. +- No evidence shows rollback/abandonment criteria are attached to each slice rather than placed in a generic risk section. +- No evidence shows a fresh agent can execute the full long-running program without chat memory. +- No evidence shows Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicitly recorded. + +## Required Changes + +Required full-program phases: + +1. Source reconciliation and blocker preservation: classify canonical docs, scratch planning inputs, run-local files, missing full-boundary inputs, existing proof lanes, non-proofs, and open P0/P1 concerns. +2. Product boundary contract: define the noun set and forbidden interpretations so Passport/Admission/Badge/Handle remain evidence/context only. +3. Surface schema and readback design: specify `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` as regenerated projection/readback objects with hard non-authority flags and no durable protocol authority state. +4. Architecture and claim-boundary tests: add naming, import, package, root-export, surface-posture, and claim tests before publicizing any simplified noun. +5. Runtime and generated-execution stress: prove handles fail as permission across runtime ingress, MCP, browser/A2A/OpenAPI posture, loops, retries, branches, stale reviews, and raw sibling bypass probes. +6. Protected-action matrix: map every field and transition from admission to fresh action request, exact contract, policy/refusal, one-use greenlight, gateway check, receipt/refusal/proof gap, replay refusal, and certificate. +7. Product surface convergence: align docs, SDK, CLI, MCP, demos, examples, package exports, and readback language without creating new authority or claiming hosted operation. +8. x402 and adjacent-lane non-regression: keep the first wedge as one buyer-side `x402_payment.exact` per-call protected action and preserve signer material behind `VerifiedGatewayCheck`. +9. Evidence and redaction: prove raw credentials, tokens, payment payloads, payment signatures, private keys, raw provider secrets, and raw internal records cannot leak through product surfaces. +10. Validation and handoff: run macro-plan validation, preserve sidecar findings, define git checkpoints, produce fresh-agent handoff, and only then enter implementation planning. +11. Tier 3 admission wall: explicitly block Tier 3/hosted progression until all Tier 1/Tier 2 source gates pass or named proof gaps are accepted as non-authority. + +Gates that block implementation: + +- Macro-plan package not written and validator not run. +- Sidecar audits not reconciled by the chair. +- Any P0 concern remains open without a concrete test-backed mechanism. +- Missing field-level protected-action matrix. +- Missing negative tests for handle-as-permission and noun-to-authority drift. +- Missing runtime stress coverage for generated code behavior. +- Missing source-owned placement decision for the schema/projection. +- Missing rollback/abandonment criteria per slice. +- Missing full-source-boundary readback. +- Any claim of native host containment, external provider custody, settlement/finality, marketplace/certification, hosted operation, or Tier 3 readiness from current local/profile evidence. + +What cannot be delegated: + +- Final sequencing of the full program. +- Final status recommendation. +- Authority boundary claims. +- Acceptance of P0/P1 risk. +- Decision that a product noun is safe to expose in source or package surfaces. +- Decision to admit a new protocol primitive. +- Decision to unblock Tier 3. +- Determination that a proof gap is acceptable product posture. +- Reconciliation of sidecar conflicts. + +Sidecars can report pressure findings. The chair must own the final sequence and cannot outsource authority claims. + +Smallest next mechanism: + +Write `EXECUTION-SLICES.md` first, not source code. The first slice must be source-boundary reconciliation with a table of canonical sources, scratch sources, missing inputs, P0/P1 blockers, pass gates, stop conditions, rollback/abandonment criteria, and handoff needs. The second slice must be the non-authority product-noun contract plus negative-test plan. No implementation slice should precede those two. + +## Status Recommendation + +Recommendation to chair: keep implementation blocked until the full macro-plan package exists, validates, and reconciles this slices audit with the other sidecar reports. + +Do not mark the future plan ready for agent execution from a minimal docs/schema/test path. The user asked for a full program; the only acceptable handoff is a long-running, source-backed Tier 1/Tier 2 sequence with proof gates, stop conditions, rollback/abandonment criteria, and fresh-agent handoff. + +Do not let Tier 3 move forward from product-language simplification alone. Without non-authority flags, negative tests, runtime misuse coverage, protected-action matrix, and evidence/readback separation, the simplification becomes review theatre and ambient authority risk. + +## Commands Or Tools Used + +- Used `gsd-macro-plan` skill instructions and references. +- `rg -n "Tier 3|Tier 1|Tier 2|macro-plan|x402|product simplification|20260525|Handshake v0\\.0\\.2" /Users/joelchan/.codex/memories/MEMORY.md` +- `wc -l` on required source files. +- `sed -n` on required source files and current run files. +- `find .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification -maxdepth 1 -type f -print` +- `ls -la .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits` +- `mkdir -p .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits` +- `apply_patch` to add this report only. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md new file mode 100644 index 0000000..80d22c2 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md @@ -0,0 +1,34 @@ +# Blocked Checks + +## Map Eligibility + +The current macro map was decision-gated, not `READY_FOR_MACRO_PLAN`. The user has now explicitly authorized a full macro-plan pass and implementation sequence, but the original blockers remain execution gates. + +## Runtime Proof + +- No live Codex, Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, or OpenAPI runtime smoke was run for this workflow handle. +- Existing host-profile evidence is posture/profile evidence, not native containment. + +## Protected-Action Proof + +- No field-level acceptance matrix exists yet for `ServiceWorkflowAdmission` / `ServiceWorkflowHandle`. +- No negative test currently proves the handle cannot create or satisfy `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `Receipt`, `AuthorityCertificate`, signer invocation, payment material, or mutation. + +## Product Proof + +- No implemented schema or rendered readback artifact proves users see admission, handle, action request, clearance, receipt, refusal, and proof gap as separate states. +- No user comprehension evidence proves `Badge` will not be read as bearer auth. + +## External Rail Proof + +- No live x402 provider/facilitator behavior, auth.md deployment corpus, ERC-8004 standing, MCP Registry lookup, Agentic.Market listing, hosted custody, provider signer lifecycle, or settlement/finality evidence was verified for this run. + +## Validation Status + +The macro-plan package has been written and the structural validator currently passes: + +```text +Macro plan output is valid. +``` + +This validates package structure, not source implementation. Protected-action fixture readiness, multi-host runtime claims, public-surface convergence, live external rails, hosted operation, and Tier 3 remain blocked until their source proof gates pass or explicit proof gaps are recorded. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md new file mode 100644 index 0000000..fe53024 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md @@ -0,0 +1,88 @@ +# Tier 1 / Tier 2 Product Simplification Macro-Plan Input + +## Invariant At Stake + +Product simplification may hide protocol complexity from users, but it must not hide or weaken authority, gateway, evidence, refusal, proof-gap, isolation, or reconstruction boundaries. + +Passport, Admission, Badge, Handle, Certificate, review surfaces, and user-facing IDs are evidence and correlation surfaces only unless a source-owned protocol transition proves otherwise. + +## User Objective + +Boil the lake. Produce a full, execution-ready Tier 1 and Tier 2 Handshake product-simplification macro plan before Tier 3 progression, grounded in `.planning/codebase`, `.planning/macro-map`, and canonical repo docs. Use `gsd-macro-plan` with sidecar reviews, define 10-star success criteria, long-running end conditions, anti-patterns, proof gates, assignable tasks, validation, git checkpoints, and then move into implementation. + +## Ten-Star Success Criteria + +- Users see a simple product flow, not protocol internals. +- The product never implies that a passport, certificate, review screen, or ID is authority. +- Tier 1 and Tier 2 each have crisp product surfaces, not internal architecture exposed as UX. +- Every surfaced object has explicit `createsAuthority: false` unless it is truly an enforceable gateway-bound authority artifact. +- Passport references are split cleanly: `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, `serviceWorkflowHandleDigest`. +- Every simplification preserves reconstructable evidence. +- Every action path still has a protected-action boundary and gateway enforcement posture. +- Docs, demos, SDK, CLI, MCP surfaces, and examples converge on the same simplified product model. +- The plan contains full execution slices, not advice. +- Tier 3 is blocked until Tier 1 and Tier 2 product simplification have proof gates satisfied or explicit proof gaps recorded. + +## Long-Running End Conditions + +The exercise ends only when the macro plan can hand a fresh agent the full Tier 1/Tier 2 simplification program with enough context to execute without chat memory, including source evidence, slices, gates, risks, task records, and validation output. + +Implementation begins only after the full macro-plan package is validated and sidecar findings are reconciled. + +## Anti-Patterns To Avoid + +- "Simple" meaning basic, toy, or under-modeled. +- Hiding authority boundaries behind friendly language. +- Treating passport/admission/workflow IDs as trust, identity, permission, or reusable auth. +- Letting UX summaries drift from exact contracts. +- Turning `.planning/` scratch into repo-facing canon. +- Broadening into Tier 3 before Tier 1/Tier 2 surfaces are sharp. +- Producing a minimal slice and calling it the plan. +- Claiming gateway enforcement where the source only proves advisory posture. +- Letting product polish outrun receipt, refusal, proof-gap, and isolation mechanics. + +## Chair Interpretation + +The prior macro-map handoff is `NEEDS_USER_DECISION`, not `READY_FOR_MACRO_PLAN`. The user decision to proceed is now explicit, but it does not erase the map blockers. This run must preserve those blockers as proof gates while broadening the plan from the smallest surface slice into the full Tier 1 / Tier 2 simplification program. + +## Required Source Boundary + +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-map/MACRO-MAP.md` +- `.planning/macro-map/FACET-MAP.md` +- `.planning/macro-map/MECHANISM-MAP.md` +- `.planning/macro-map/EXECUTION-MAP.md` +- `.planning/macro-map/EXPERIENCE-MAP.md` +- `.planning/macro-map/AGENT-RUNTIME-MAP.md` +- `.planning/macro-map/PROTECTED-ACTION-MAP.md` +- `.planning/macro-map/CONCERNS.md` +- `.planning/macro-map/DECISIONS.md` +- `.planning/macro-map/TASKS.jsonl` +- `.planning/macro-map/views/*.md` +- `.planning/codebase/*.md` +- `README.md` +- `QUALITY.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/protocol-layman.md` + +## Non-Authority ID Model To Preserve + +The plan must define the following as correlation/reconstruction fields only: + +- `passportPackageDigest`: content-addressed digest of the presented evidence bundle. +- `passportPresentationId`: unique per service intake / presentation event. +- `admissionId`: service-side result after checking the passport. +- `serviceWorkflowHandleId`: carried workflow reference for context. +- `serviceWorkflowHandleDigest`: digest of the carried workflow reference. + +All five fields must have `createsAuthority: false`; none may prove identity, trust, spend approval, gateway acceptance, signer permission, mutation permission, receipt export, terminal certification, or reusable auth. + +## Initial Plan Status + +`READY_FOR_FULL_MACRO_PLAN_WITH_RECONCILED_BLOCKERS` + +This is not `READY_FOR_AGENT_EXECUTION` until the plan package, sidecar review, and validator pass. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md new file mode 100644 index 0000000..1d3c94c --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/source-snapshot.md @@ -0,0 +1,42 @@ +# Source Snapshot + +## Git State + +- Branch: `main` +- Upstream: `origin/main` +- Initial `git status --short`: clean + +## Canonical Product Truth + +- `README.md` says Handshake is protected action infrastructure for automated decision making and reduces one consequential automated action to an exact contract before mutation. +- `README.md` says product surfaces expose proposal/evidence without creating authority, and MCP is proposal/evidence only. +- `docs/internal/decisions.md` defines the current kernel chain as exact action contract -> policy decision -> one-use gateway-bound greenlight -> gateway check before mutation -> receipt/refusal/proof gap. +- `docs/internal/decisions.md` keeps hosted operation, provider custody, settlement/finality, marketplace/certification, cross-org trust, host-wide containment, aggregate spend, and broad x402 compatibility as proof gaps, outside claims, or cut lines. +- `docs/internal/protocol-notes.md` defines the primitive as reducing every consequential mutation attempt to an exact, inspectable, policy-evaluated, gateway-bound action contract before consequence. +- `QUALITY.md` and `STRUCTURE.md` require product surfaces to expose proposal/evidence/readback without becoming protocol authority. + +## Macro Map Truth + +- `.planning/macro-map/MACRO-HANDOFF.md` status is decision-gated and warns that Passport, Admission, Badge, and Handle are evidence/context only. +- `.planning/macro-map/MACRO-MAP.md` says the kernel authority chain should remain unchanged and the first mechanism belongs in product-surface admission/readback schema, not a new protocol primitive. +- `.planning/macro-map/CONCERNS.md` has open P0/P1 blockers for non-authority flags, handle misuse, multi-host overclaim, naming drift, metaphor-only docs, and free verifier versus paid clearance confusion. +- `.planning/macro-map/PROTECTED-ACTION-MAP.md` says the triggering consequence begins only when an admitted workflow tries to perform a protected action. +- `.planning/macro-map/AGENT-RUNTIME-MAP.md` says multi-host runtime claims must remain proof-gapped and host-specific. + +## Codebase Map Truth + +- `.planning/codebase/ARCHITECTURE.md` places authority in policy greenlight, gateway gate, verified gateway adapters, and replay-sensitive storage, not runtime ingress, HTTP admission, projections, CLI, MCP, SDK, or demos. +- `.planning/codebase/STRUCTURE.md` says Passport readback should be a projection over existing records, Admission changes belong in HTTP admission and route metadata only if needed, and service gateway language maps to existing gateway registry, credential custody, gateway gate, and adapter files. +- `.planning/codebase/CONCERNS.md` flags no current source-owned Passport primitive and warns that standalone Passport, Admission, ServiceGateway, or PrincipalAgentLink objects can duplicate existing authority-adjacent state. +- `.planning/codebase/TESTING.md` names the focused gates for simplification: `npm run quality:claims`, `npm run quality:architecture`, and focused protocol/runtime projection tests. + +## Source Boundary Status + +The source boundary is sufficient for full macro planning. The implementation phase must still source-open named files before edits and must not treat `.planning/` as canon. + +## Non-Proofs + +- No `ServiceWorkflowAdmission` or `ServiceWorkflowHandle` schema exists yet. +- No negative tests currently prove the new product nouns cannot create authority. +- No local demo connects an admitted workflow handle to one fresh x402 exact clearance. +- No live provider custody, settlement, hosted operation, native host containment, external registry acceptance, or marketplace trust is proven. diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md new file mode 100644 index 0000000..5ed8698 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -0,0 +1,31 @@ +# Validation + +## Macro-Plan Validator + +Command: + +```bash +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +``` + +Observed output: + +```text +Macro plan output is valid. +``` + +## Status Reconciliation + +The plan is implementation-ready only for the first bounded Tier 1 story/schema/test slice. It is not a claim that protected-action fixtures, multi-host runtime posture, SDK/CLI/MCP convergence, live rails, hosted operation, or Tier 3 are ready. + +Sidecar audit recommendations were reconciled as gates: + +- protected-action posture -> field matrix, false authority flags, negative tests, no fixture until surface proof exists; +- runtime-agent posture -> host-specific rows, raw sibling posture, generated-execution stress gates, no containment claim; +- product/DevEx posture -> one source-owned packet, first-use demo later, convergence after schema/tests; +- evidence posture -> validator output and git state must be recorded before implementation; +- slices posture -> full long-running program captured before source edits. + +## Git State + +`.planning/` is ignored by `.gitignore`, so normal `git status --short` does not show these artifacts. If the user wants planning artifacts committed, they must be force-added deliberately. From 61c17e2dec8587b41d7778b1b9018165deeee15a Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:18:39 +0800 Subject: [PATCH 002/144] Add service workflow admission surface --- STRUCTURE.md | 1 + docs/internal/decisions.md | 3 +- docs/internal/service-workflow-story.md | 98 ++++++++++ src/surfaces/index.ts | 1 + .../service-workflow-admission/index.ts | 117 ++++++++++++ .../workflow-admission-boundary.test.ts | 171 ++++++++++++++++++ 6 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 docs/internal/service-workflow-story.md create mode 100644 src/surfaces/service-workflow-admission/index.ts create mode 100644 test/architecture/workflow-admission-boundary.test.ts diff --git a/STRUCTURE.md b/STRUCTURE.md index 3dc2a10..ea08014 100644 --- a/STRUCTURE.md +++ b/STRUCTURE.md @@ -186,6 +186,7 @@ docs/internal/protocol-kernel-architecture.md docs/internal/protocol-layman.md docs/internal/protocol-notes.md docs/internal/release-admin-runbook.md +docs/internal/service-workflow-story.md ``` Long planning reports, source studies, and historical prompts belong outside the active repo tree or under `docs/internal/archive` only when there is a reason to retain provenance. diff --git a/docs/internal/decisions.md b/docs/internal/decisions.md index faa892d..ce38326 100644 --- a/docs/internal/decisions.md +++ b/docs/internal/decisions.md @@ -16,6 +16,7 @@ docs/internal/protocol-definition.md docs/internal/protocol-kernel-architecture.md docs/internal/protocol-layman.md docs/internal/protocol-notes.md +docs/internal/service-workflow-story.md ``` `.planning/` is scratch. Long plans, source studies, public-facing product docs, and historical prompts are not active repo truth. @@ -369,7 +370,7 @@ This checkout is an internal TypeScript protocol kernel. It should not carry lon Accepted: the active repo canon is compact and internal. -Former ADR, plan, product, protocol, business, reference, audit, and spec subtrees are no longer active repo truth. Durable decisions move into this file only when they protect implementation boundaries. Protocol definition lives in `docs/internal/protocol-definition.md`. Kernel architecture and schema mapping live in `docs/internal/protocol-kernel-architecture.md`. Plain-English translation lives in `docs/internal/protocol-layman.md`. Compact implementation notes live in `docs/internal/protocol-notes.md`. Planning, marketing, source studies, and historical prompts belong outside the active repo tree. +Former ADR, plan, product, protocol, business, reference, audit, and spec subtrees are no longer active repo truth. Durable decisions move into this file only when they protect implementation boundaries. Protocol definition lives in `docs/internal/protocol-definition.md`. Kernel architecture and schema mapping live in `docs/internal/protocol-kernel-architecture.md`. Plain-English translation lives in `docs/internal/protocol-layman.md`. Compact implementation notes live in `docs/internal/protocol-notes.md`. The service workflow story lives in `docs/internal/service-workflow-story.md` as a product-surface translation only; it does not create authority. Planning, marketing, source studies, and historical prompts belong outside the active repo tree. ## Structural Decision diff --git a/docs/internal/service-workflow-story.md b/docs/internal/service-workflow-story.md new file mode 100644 index 0000000..9f50c27 --- /dev/null +++ b/docs/internal/service-workflow-story.md @@ -0,0 +1,98 @@ +# Service Workflow Story + +This story is a product surface over the existing protocol kernel. It makes the +first-use path easier to understand, but it does not create a new authority +primitive. + +## Plain Flow + +```text +Agent shows Passport +-> Service returns ServiceWorkflowAdmission +-> Agent carries ServiceWorkflowHandle +-> Agent requests Clearance for one protected action +-> Handshake records Outcome +``` + +The plain words map to the protocol this way: + +| Plain word | Meaning | Not allowed to mean | +| ------------------------ | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | +| Passport | Evidence package the agent presents. | Identity, trust, permission, spend approval, signer access, or reusable auth. | +| ServiceWorkflowAdmission | Service-side accepted, refused, stale, or proof-gap mapping of presented evidence. | Policy decision, greenlight, gateway check, receipt, certificate, or mutation permission. | +| ServiceWorkflowHandle | Non-authority workflow context reference for later proposals and readback. | Badge-as-bearer-token, tool permission, retry permission, x402 payment approval, auth.md credential, or gateway pass. | +| Clearance | Fresh exact protected-action path for one event. | Workflow-level permission. | +| Outcome | Receipt, refusal, replay refusal, proof gap, or terminal certificate after the event path. | Downstream business success or future permission. | + +## Non-Authority IDs + +The service workflow surface may carry these correlation and reconstruction +fields: + +```text +passportPackageDigest +passportPresentationId +admissionId +serviceWorkflowHandleId +serviceWorkflowHandleDigest +``` + +These fields identify what was presented, how the service handled it, and which +workflow context the agent is carrying. They do not create authority. Every +surface that exposes them must make the boundary explicit: + +```text +createsAuthority: false +createsPolicyDecision: false +createsGreenlight: false +performsGatewayCheck: false +permitsMutation: false +exportsReceipt: false +mintsTerminalCertificate: false +freshActionContractRequired: true +``` + +## Protected Action Boundary + +A service can admit standing evidence into a workflow context. That is still +before protected action clearance. + +Every consequential event still needs: + +```text +CandidateAction +-> ActionContract +-> PolicyDecision +-> one-use Greenlight or Refusal +-> GatewayCheck before mutation +-> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` + +If the gateway cannot enforce the exact greenlight before consequence, the path +is advisory, not Handshake. + +## Recovery States + +| State | Meaning | Safe next move | +| -------------------- | ----------------------------------------------------------- | -------------------------------------------------------------- | +| `accepted` | The service recognizes the evidence for workflow context. | Create a fresh protected-action request when action is needed. | +| `refused` | The service rejects the evidence. | Replace evidence or abandon the workflow. | +| `stale` | A digest, expiry, metadata, or readiness reference drifted. | Reload current evidence. | +| `proof_gap` | The service cannot establish the claim. | Gather proof or keep the workflow blocked. | +| `quarantined` | Evidence or posture is unsafe. | Stop and isolate future attempts. | +| `clearance_required` | The handle exists, but event authority does not. | Create a fresh exact action contract candidate. | + +Refusal, proof gap, replay refusal, and support-bundle generation are not retry +permission. A new protected action requires a new exact contract. + +## Forbidden Shortcuts + +- Do not pass a workflow handle to a protected tool as permission. +- Do not put raw credentials, bearer tokens, private keys, x402 + `PaymentPayload`, or `PAYMENT-SIGNATURE` into Passport, Admission, or Handle. +- Do not treat an admission report as a receipt. +- Do not turn an `AuthorityCertificate` into a passport or badge. +- Do not let a rendered review summary substitute for the exact action contract. +- Do not claim hosted operation, provider custody, settlement finality, + marketplace trust, broad runtime containment, or cross-org trust from this + surface. diff --git a/src/surfaces/index.ts b/src/surfaces/index.ts index b16f4c2..dabb697 100644 --- a/src/surfaces/index.ts +++ b/src/surfaces/index.ts @@ -4,4 +4,5 @@ export * from "./outcome"; export * from "./product-launch-gate-resolution"; export * from "./proof-packets"; export * from "./release-proof"; +export * from "./service-workflow-admission"; export * from "./x402-protected-tool-acceptance"; diff --git a/src/surfaces/service-workflow-admission/index.ts b/src/surfaces/service-workflow-admission/index.ts new file mode 100644 index 0000000..d667950 --- /dev/null +++ b/src/surfaces/service-workflow-admission/index.ts @@ -0,0 +1,117 @@ +import { z } from "zod"; + +const sha256DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/); + +export const serviceWorkflowAdmissionSchemaVersion = "handshake.service-workflow-admission.v0.1" as const; + +export const serviceWorkflowClaimStatuses = ["accepted", "refused", "stale", "proof_gap", "quarantined"] as const; + +export type ServiceWorkflowClaimStatus = (typeof serviceWorkflowClaimStatuses)[number]; + +export const serviceWorkflowNextActionRequirements = [ + "fresh_action_contract_required", + "reload_evidence_required", + "replace_evidence_required", + "keep_blocked", + "stop_and_isolate", +] as const; + +export type ServiceWorkflowNextActionRequirement = (typeof serviceWorkflowNextActionRequirements)[number]; + +export const ServiceWorkflowAuthorityBoundarySchema = z.strictObject({ + createsAuthority: z.literal(false), + createsPolicyDecision: z.literal(false), + createsGreenlight: z.literal(false), + performsGatewayCheck: z.literal(false), + permitsMutation: z.literal(false), + exportsReceipt: z.literal(false), + mintsTerminalCertificate: z.literal(false), + containsCredentialMaterial: z.literal(false), + containsPaymentMaterial: z.literal(false), + widensOperatingEnvelope: z.literal(false), + isReusableAuth: z.literal(false), + isGatewayBinding: z.literal(false), + freshActionContractRequired: z.literal(true), +}); + +export type ServiceWorkflowAuthorityBoundary = z.infer; + +export const serviceWorkflowAuthorityBoundary = { + createsAuthority: false, + createsPolicyDecision: false, + createsGreenlight: false, + performsGatewayCheck: false, + permitsMutation: false, + exportsReceipt: false, + mintsTerminalCertificate: false, + containsCredentialMaterial: false, + containsPaymentMaterial: false, + widensOperatingEnvelope: false, + isReusableAuth: false, + isGatewayBinding: false, + freshActionContractRequired: true, +} as const satisfies ServiceWorkflowAuthorityBoundary; + +export const ServiceWorkflowClaimResultSchema = z.strictObject({ + claimRef: z.string().min(1), + claimDigest: sha256DigestSchema.nullable(), + status: z.enum(serviceWorkflowClaimStatuses), + reasonCodes: z.array(z.string().min(2)), + evidenceRefs: z.array(z.string().min(1)), + proofGapRefs: z.array(z.string().min(1)), +}); + +export type ServiceWorkflowClaimResult = z.infer; + +export const ServiceWorkflowRuntimePostureSchema = z.strictObject({ + runtimeRef: z.string().min(1), + hostProfileEvidenceRef: z.string().min(1).nullable(), + rawSiblingBypassPostureRef: z.string().min(1).nullable(), + nativeContainmentClaimed: z.literal(false), + proofGapRefs: z.array(z.string().min(1)), +}); + +export type ServiceWorkflowRuntimePosture = z.infer; + +export const ServiceWorkflowHandleSchema = z.strictObject({ + schemaVersion: z.literal(serviceWorkflowAdmissionSchemaVersion), + passportPackageDigest: sha256DigestSchema, + passportPresentationId: z.string().min(1), + admissionId: z.string().min(1), + serviceWorkflowHandleId: z.string().min(1), + serviceWorkflowHandleDigest: sha256DigestSchema, + issuedAt: z.string().datetime({ offset: true }), + expiresAt: z.string().datetime({ offset: true }).nullable(), + workflowBoundsDigest: sha256DigestSchema, + sourceAdmissionDigest: sha256DigestSchema, + runtimePostureDigest: sha256DigestSchema.nullable(), + authorityBoundary: ServiceWorkflowAuthorityBoundarySchema, + nextProtectedActionRequirement: z.literal("fresh_action_contract_required"), + allowedUse: z.literal("correlation_and_readback_context_only"), +}); + +export type ServiceWorkflowHandle = z.infer; + +export const ServiceWorkflowAdmissionSchema = z.strictObject({ + schemaVersion: z.literal(serviceWorkflowAdmissionSchemaVersion), + passportPackageDigest: sha256DigestSchema, + passportPresentationId: z.string().min(1), + admissionId: z.string().min(1), + admissionDigest: sha256DigestSchema, + serviceRef: z.string().min(1), + presentedAt: z.string().datetime({ offset: true }), + evaluatedAt: z.string().datetime({ offset: true }), + claimResults: z.array(ServiceWorkflowClaimResultSchema), + runtimePosture: z.array(ServiceWorkflowRuntimePostureSchema), + serviceWorkflowHandle: ServiceWorkflowHandleSchema, + authorityBoundary: ServiceWorkflowAuthorityBoundarySchema, + nextActionRequirement: z.enum(serviceWorkflowNextActionRequirements), + clearanceBoundary: z.literal("fresh_action_contract_required_for_each_protected_action"), + readbackBoundary: z.literal("admission_readback_is_not_receipt_evidence"), +}); + +export type ServiceWorkflowAdmission = z.infer; + +export function serviceWorkflowNonAuthorityBoundary(): ServiceWorkflowAuthorityBoundary { + return ServiceWorkflowAuthorityBoundarySchema.parse(serviceWorkflowAuthorityBoundary); +} diff --git a/test/architecture/workflow-admission-boundary.test.ts b/test/architecture/workflow-admission-boundary.test.ts new file mode 100644 index 0000000..066c218 --- /dev/null +++ b/test/architecture/workflow-admission-boundary.test.ts @@ -0,0 +1,171 @@ +import { describe, expect, it } from "bun:test"; +import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { join, relative } from "node:path"; +import { + ServiceWorkflowAdmissionSchema, + ServiceWorkflowHandleSchema, + serviceWorkflowNonAuthorityBoundary, +} from "../../src/surfaces/service-workflow-admission"; + +const digest = `sha256:${"a".repeat(64)}`; +const secondDigest = `sha256:${"b".repeat(64)}`; +const thirdDigest = `sha256:${"c".repeat(64)}`; +const fourthDigest = `sha256:${"d".repeat(64)}`; +const fifthDigest = `sha256:${"e".repeat(64)}`; +const sixthDigest = `sha256:${"f".repeat(64)}`; + +const forbiddenAuthorityRoots = ["src/protocol/areas", "src/adapters", "src/runtime/ingress", "src/mcp"]; +const workflowSurfaceNames = [ + "ServiceWorkflowAdmission", + "ServiceWorkflowHandle", + "serviceWorkflowHandleId", + "serviceWorkflowHandleDigest", + "passportPackageDigest", + "passportPresentationId", + "admissionId", +] as const; +const forbiddenMaterialFields = [ + "PaymentPayload", + "PAYMENT-SIGNATURE", + "rawCredentialMaterial", + "privateKey", + "signer", + "receiptExport", + "authorityCertificateMint", +] as const; + +describe("service workflow admission boundary", () => { + it("defines admission and handle as explicit non-authority surfaces", () => { + const admission = ServiceWorkflowAdmissionSchema.parse(validAdmission()); + + expect(admission.authorityBoundary).toEqual(serviceWorkflowNonAuthorityBoundary()); + expect(admission.serviceWorkflowHandle.authorityBoundary).toEqual(serviceWorkflowNonAuthorityBoundary()); + expect(admission.nextActionRequirement).toBe("fresh_action_contract_required"); + expect(admission.clearanceBoundary).toBe("fresh_action_contract_required_for_each_protected_action"); + expect(admission.readbackBoundary).toBe("admission_readback_is_not_receipt_evidence"); + expect(admission.serviceWorkflowHandle.allowedUse).toBe("correlation_and_readback_context_only"); + expect(admission.runtimePosture[0]?.nativeContainmentClaimed).toBe(false); + }); + + it("rejects attempts to turn admission or handle fields into authority", () => { + const admission = validAdmission(); + + expect(() => + ServiceWorkflowAdmissionSchema.parse({ + ...admission, + authorityBoundary: { ...admission.authorityBoundary, createsAuthority: true }, + }), + ).toThrow(); + expect(() => + ServiceWorkflowHandleSchema.parse({ + ...admission.serviceWorkflowHandle, + authorityBoundary: { ...admission.serviceWorkflowHandle.authorityBoundary, performsGatewayCheck: true }, + }), + ).toThrow(); + expect(() => + ServiceWorkflowHandleSchema.parse({ + ...admission.serviceWorkflowHandle, + nextProtectedActionRequirement: "handle_is_permission", + }), + ).toThrow(); + }); + + it("keeps raw credential, payment, receipt, and certificate material out of the surface output", () => { + const text = JSON.stringify(ServiceWorkflowAdmissionSchema.parse(validAdmission())); + const violations = forbiddenMaterialFields.filter((field) => text.includes(field)); + + expect(violations).toEqual([]); + }); + + it("keeps workflow admission nouns out of authority-bearing source roots", () => { + const violations: string[] = []; + for (const root of forbiddenAuthorityRoots) { + for (const file of walkTs(root)) { + const text = readFileSync(file, "utf8"); + for (const name of workflowSurfaceNames) { + if (text.includes(name)) violations.push(`${relative(process.cwd(), file)} mentions ${name}`); + } + } + } + + expect(violations.sort()).toEqual([]); + }); +}); + +function validAdmission() { + const authorityBoundary = serviceWorkflowNonAuthorityBoundary(); + return { + schemaVersion: "handshake.service-workflow-admission.v0.1", + passportPackageDigest: digest, + passportPresentationId: "passport-presentation-1", + admissionId: "service-workflow-admission-1", + admissionDigest: secondDigest, + serviceRef: "service:example", + presentedAt: "2026-05-25T09:00:00.000Z", + evaluatedAt: "2026-05-25T09:00:01.000Z", + claimResults: [ + { + claimRef: "participant-identity-binding:agent", + claimDigest: thirdDigest, + status: "accepted", + reasonCodes: ["recognized_standing_evidence"], + evidenceRefs: ["evidence:participant-identity-binding"], + proofGapRefs: [], + }, + { + claimRef: "provider-custody:live", + claimDigest: null, + status: "proof_gap", + reasonCodes: ["provider_custody_unverified"], + evidenceRefs: [], + proofGapRefs: ["proof-gap:provider-custody"], + }, + ], + runtimePosture: [ + { + runtimeRef: "runtime:codex-local", + hostProfileEvidenceRef: "host-profile:codex-local", + rawSiblingBypassPostureRef: "bypass-posture:x402-raw-sibling", + nativeContainmentClaimed: false, + proofGapRefs: ["proof-gap:host-wide-containment"], + }, + ], + serviceWorkflowHandle: { + schemaVersion: "handshake.service-workflow-admission.v0.1", + passportPackageDigest: digest, + passportPresentationId: "passport-presentation-1", + admissionId: "service-workflow-admission-1", + serviceWorkflowHandleId: "service-workflow-handle-1", + serviceWorkflowHandleDigest: fourthDigest, + issuedAt: "2026-05-25T09:00:01.000Z", + expiresAt: "2026-05-25T10:00:01.000Z", + workflowBoundsDigest: fifthDigest, + sourceAdmissionDigest: secondDigest, + runtimePostureDigest: sixthDigest, + authorityBoundary, + nextProtectedActionRequirement: "fresh_action_contract_required", + allowedUse: "correlation_and_readback_context_only", + }, + authorityBoundary, + nextActionRequirement: "fresh_action_contract_required", + clearanceBoundary: "fresh_action_contract_required_for_each_protected_action", + readbackBoundary: "admission_readback_is_not_receipt_evidence", + }; +} + +function walkTs(root: string): string[] { + if (!existsSync(root)) return []; + const stat = statSync(root); + if (stat.isFile()) return root.endsWith(".ts") ? [root] : []; + const files: string[] = []; + for (const entry of readdirSync(root)) { + const full = join(root, entry); + const entryStat = statSync(full); + if (entryStat.isDirectory()) { + files.push(...walkTs(full)); + continue; + } + if (entry.endsWith(".ts")) files.push(full); + } + return files; +} From a1cd5e5d739adc0e359fb51fea2f29a1059b5de5 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:21:10 +0800 Subject: [PATCH 003/144] Converge service workflow docs --- README.md | 17 ++++++++++++++ STRUCTURE.md | 1 + docs/internal/decisions.md | 1 + docs/internal/protocol-layman.md | 39 ++++++++++++++++++++++++++++++++ docs/internal/protocol-notes.md | 6 +++++ 5 files changed, 64 insertions(+) diff --git a/README.md b/README.md index a4737a7..86ddba6 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,23 @@ exposes proposal/evidence without creating authority. Public npm availability does not create authority. MCP Registry discoverability remains a proof gap until registry acceptance and lookup are verified. +First-use product surfaces should teach the service workflow as: + +```text +Show Passport +-> ServiceWorkflowAdmission +-> ServiceWorkflowHandle +-> Request Clearance for one protected action +-> Read Outcome +``` + +`Passport` means a presented evidence package, not identity or reusable auth. +`ServiceWorkflowAdmission` means service-side accepted/refused/stale/proof-gap +mapping, not policy. `ServiceWorkflowHandle` means correlation and readback +context only, not permission. Each protected action still requires a fresh exact +action contract, policy decision, one-use greenlight or refusal, and gateway +check before mutation. + Package: `handshake-protocol-kernel@0.2.7`. MCP name: `io.github.CreasyBear/handshake-protocol-kernel`. Runtime: Node.js `>=20`. License: Apache-2.0. Published package repository form: package artifact repository, not source mirror. diff --git a/STRUCTURE.md b/STRUCTURE.md index ea08014..ceb2b30 100644 --- a/STRUCTURE.md +++ b/STRUCTURE.md @@ -100,6 +100,7 @@ src/ surfaces/ boundary-manifest.ts outcome.ts + service-workflow-admission/ index.ts experimental.ts worker.ts diff --git a/docs/internal/decisions.md b/docs/internal/decisions.md index ce38326..db24fa6 100644 --- a/docs/internal/decisions.md +++ b/docs/internal/decisions.md @@ -43,6 +43,7 @@ Shared product/protocol vocabulary: - `protocol kernel`: the source-owned state machine and schemas for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. - `product surface`: CLI, MCP, SDK, docs, demo, or service-facing readback surfaces that expose proposal/evidence/readback without creating authority. +- `ServiceWorkflowAdmission` and `ServiceWorkflowHandle`: non-authority product-surface records for presented evidence, service-side admission status, correlation, and readback context. They do not create identity, policy decisions, greenlights, gateway checks, mutations, receipts, certificates, reusable auth, signer use, or spend approval; each protected action still requires a fresh exact action contract. - `AuthorityCertificate`: verifiable terminal evidence for one event. The certificate is terminal evidence, not permission, identity, settlement, hosted trust, or reusable auth. - Distribution is separate from authority. Public npm availability does not create authority, and MCP Registry discoverability remains a proof gap until verified. diff --git a/docs/internal/protocol-layman.md b/docs/internal/protocol-layman.md index 1981fc0..2d621af 100644 --- a/docs/internal/protocol-layman.md +++ b/docs/internal/protocol-layman.md @@ -29,6 +29,45 @@ certificate. A product surface is the CLI, MCP, SDK, docs, demo, or service-facing readback that exposes proposal and evidence without creating authority. +## The Service Workflow Surface + +The simple service-facing story is: + +```text +Show Passport +-> ServiceWorkflowAdmission +-> ServiceWorkflowHandle +-> Request Clearance +-> Read Outcome +``` + +That story hides protocol detail from the user. It does not hide authority. + +`Passport` is the evidence bundle the agent shows a service. It is not identity, +trust, permission, spend approval, signer access, or reusable auth. + +`ServiceWorkflowAdmission` is the service's accepted, refused, stale, or +proof-gap mapping of that presented evidence. It is not a policy decision, +greenlight, gateway check, receipt, certificate, or mutation permission. + +`ServiceWorkflowHandle` is a workflow context reference the agent can carry for +correlation and readback. It is not a badge, bearer token, retry permission, +x402 payment approval, auth.md credential, gateway pass, or receipt export. + +The surface may carry these IDs: + +```text +passportPackageDigest +passportPresentationId +admissionId +serviceWorkflowHandleId +serviceWorkflowHandleDigest +``` + +Those IDs help reconstruct which bundle was shown and which workflow context was +used. They do not authorize action. Every protected action still starts with a +fresh exact work order. + ## The Work Order A vague request is not enough. diff --git a/docs/internal/protocol-notes.md b/docs/internal/protocol-notes.md index 6d7b0bc..c7088ef 100644 --- a/docs/internal/protocol-notes.md +++ b/docs/internal/protocol-notes.md @@ -20,6 +20,12 @@ Handshake's category is protected actions for automated decision making. refusals, proof gaps, isolation, and terminal certificates. - A product surface is CLI, MCP, SDK, docs, demo, or service-facing readback that exposes proposal/evidence/readback without creating authority. +- The service workflow story is a product-surface translation only: + `Passport -> ServiceWorkflowAdmission -> ServiceWorkflowHandle -> fresh +protected-action clearance -> terminal outcome`. Passport, admission, and + handle records are evidence/readback context; they are not identity, policy, + greenlight, gateway check, mutation permission, receipt export, terminal + certificate, or reusable auth. - The certificate is terminal evidence, not permission, identity, settlement, hosted trust, or reusable auth. - Public npm availability does not create authority. MCP Registry From 025888fc5ffc897a9cd0b0b7a82c817eb17cb08c Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:30:14 +0800 Subject: [PATCH 004/144] Align active surfaces with service workflow model --- .planning/macro-plan/TASKS.jsonl | 12 +- .../audits/review-gates.md | 199 ++++++++++++++++++ .../validation.md | 30 +++ .../audits/evidence.md | 141 +++++++++++++ README.md | 5 + src/cli/LANE.md | 9 + src/cli/command-manifest.ts | 6 + src/cli/main.ts | 5 +- src/cli/output.ts | 1 + src/cli/x402/index.ts | 3 + src/mcp/LANE.md | 4 + src/mcp/catalog.ts | 12 ++ src/mcp/index.ts | 8 +- src/mcp/resources.ts | 2 + src/sdk/LANE.md | 9 + test/architecture/cli-command-posture.test.ts | 6 +- test/architecture/mcp-surface-posture.test.ts | 14 ++ test/cli/cli-evidence.test.ts | 8 +- 18 files changed, 463 insertions(+), 11 deletions(-) create mode 100644 .planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/review-gates.md create mode 100644 .planning/macro-plan/runs/20260525T174005-passport-admission-full/audits/evidence.md diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 2fd1cef..0889a2c 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -1,9 +1,9 @@ -{"id":"MPLAN-001","phase":"T0","slice":"T0-00","title":"Validate and checkpoint macro-plan package","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Implementation must start from a validated package, not chat-only planning.","acceptance":["Macro-plan validator reports valid output.","Sidecar audit files are present or missing reports are recorded.","Git status is inspected before checkpoint."],"non_goals":["Do not claim Tier 3 readiness from macro-plan validation."],"status":"open","proof_gate":"Macro-plan validator passes on .planning/macro-plan.","next_mechanism":"Run the macro-plan validator and record validation evidence."} -{"id":"MPLAN-002","phase":"T1","slice":"T1-01","title":"Create internal service workflow story","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-001"],"evidence":[".planning/macro-map/EXPERIENCE-MAP.md","docs/internal/protocol-layman.md","README.md"],"candidate_paths":["docs/internal/service-workflow-story.md"],"rationale":"The first user-facing simplification must teach the flow without implying authority.","acceptance":["Story maps Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, and Outcome to exact protocol/evidence boundaries.","Story includes forbidden interpretations for passport IDs, handle, certificate, review, and receipt.","Story includes refusal, replay, proof-gap, and isolation recovery language."],"non_goals":["Do not create public marketing claims or hosted-operation claims."],"status":"open","proof_gate":"quality:claims passes after the story doc is added.","next_mechanism":"Write docs/internal/service-workflow-story.md with noun mapping and non-authority cut lines."} -{"id":"MPLAN-003","phase":"T1","slice":"T1-02","title":"Implement non-authority service workflow surface schema","priority":"P0","owner":"surface-schema-implementer","runtime":"codex","depends_on":["MPLAN-002"],"evidence":[".planning/macro-map/MECHANISM-MAP.md",".planning/macro-map/views/ENG.md","src/surfaces/outcome.ts","src/surfaces/boundary-manifest.ts"],"candidate_paths":["src/surfaces/service-workflow-admission.ts","src/surfaces/index.ts"],"rationale":"The simplified product model needs a source-owned schema before demos or SDK/CLI/MCP surfaces use it.","acceptance":["Schema defines ServiceWorkflowAdmission and ServiceWorkflowHandle.","Schema includes passportPackageDigest, passportPresentationId, admissionId, serviceWorkflowHandleId, serviceWorkflowHandleDigest.","Schema sets createsAuthority, createsPolicyDecision, createsGreenlight, performsGatewayCheck, permitsMutation, exportsReceipt, and mintsTerminalCertificate to false and freshActionContractRequired to true."],"non_goals":["Do not add protocol primitive, gateway adapter, store migration, policy evaluator, or mutation runner."],"status":"open","proof_gate":"check:types passes and architecture gate accepts the surface posture.","next_mechanism":"Add src/surfaces/service-workflow-admission.ts following existing surface outcome conventions."} -{"id":"MPLAN-004","phase":"T1","slice":"T1-03","title":"Add workflow admission boundary tests","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["MPLAN-003"],"evidence":[".planning/codebase/TESTING.md","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"candidate_paths":["test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"The known failure mode is naming and surface drift into authority-bearing paths.","acceptance":["Tests fail if Passport, Badge, ServiceWorkflowAdmission, or ServiceWorkflowHandle appear as protocol primitives or authority exports.","Tests reject raw credential, token, PaymentPayload, PAYMENT-SIGNATURE, signer, receipt export, certificate, gateway check, policy, greenlight, and mutation fields on the surface.","Tests require the false non-authority flags."],"non_goals":["Do not weaken existing architecture tests to admit the new surface."],"status":"open","proof_gate":"quality:architecture and quality:claims pass.","next_mechanism":"Add focused architecture tests for workflow-admission boundary."} -{"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"open","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} -{"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"open","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} +{"id":"MPLAN-001","phase":"T0","slice":"T0-00","title":"Validate and checkpoint macro-plan package","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Implementation must start from a validated package, not chat-only planning.","acceptance":["Macro-plan validator reports valid output.","Sidecar audit files are present or missing reports are recorded.","Git status is inspected before checkpoint."],"non_goals":["Do not claim Tier 3 readiness from macro-plan validation."],"status":"completed","proof_gate":"Macro-plan validator passes on .planning/macro-plan.","next_mechanism":"Run the macro-plan validator and record validation evidence."} +{"id":"MPLAN-002","phase":"T1","slice":"T1-01","title":"Create internal service workflow story","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-001"],"evidence":[".planning/macro-map/EXPERIENCE-MAP.md","docs/internal/protocol-layman.md","README.md"],"candidate_paths":["docs/internal/service-workflow-story.md"],"rationale":"The first user-facing simplification must teach the flow without implying authority.","acceptance":["Story maps Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, and Outcome to exact protocol/evidence boundaries.","Story includes forbidden interpretations for passport IDs, handle, certificate, review, and receipt.","Story includes refusal, replay, proof-gap, and isolation recovery language."],"non_goals":["Do not create public marketing claims or hosted-operation claims."],"status":"completed","proof_gate":"quality:claims passes after the story doc is added.","next_mechanism":"Write docs/internal/service-workflow-story.md with noun mapping and non-authority cut lines."} +{"id":"MPLAN-003","phase":"T1","slice":"T1-02","title":"Implement non-authority service workflow surface schema","priority":"P0","owner":"surface-schema-implementer","runtime":"codex","depends_on":["MPLAN-002"],"evidence":[".planning/macro-map/MECHANISM-MAP.md",".planning/macro-map/views/ENG.md","src/surfaces/outcome.ts","src/surfaces/boundary-manifest.ts"],"candidate_paths":["src/surfaces/service-workflow-admission.ts","src/surfaces/index.ts"],"rationale":"The simplified product model needs a source-owned schema before demos or SDK/CLI/MCP surfaces use it.","acceptance":["Schema defines ServiceWorkflowAdmission and ServiceWorkflowHandle.","Schema includes passportPackageDigest, passportPresentationId, admissionId, serviceWorkflowHandleId, serviceWorkflowHandleDigest.","Schema sets createsAuthority, createsPolicyDecision, createsGreenlight, performsGatewayCheck, permitsMutation, exportsReceipt, and mintsTerminalCertificate to false and freshActionContractRequired to true."],"non_goals":["Do not add protocol primitive, gateway adapter, store migration, policy evaluator, or mutation runner."],"status":"completed","proof_gate":"check:types passes and architecture gate accepts the surface posture.","next_mechanism":"Add src/surfaces/service-workflow-admission.ts following existing surface outcome conventions."} +{"id":"MPLAN-004","phase":"T1","slice":"T1-03","title":"Add workflow admission boundary tests","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["MPLAN-003"],"evidence":[".planning/codebase/TESTING.md","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"candidate_paths":["test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"The known failure mode is naming and surface drift into authority-bearing paths.","acceptance":["Tests fail if Passport, Badge, ServiceWorkflowAdmission, or ServiceWorkflowHandle appear as protocol primitives or authority exports.","Tests reject raw credential, token, PaymentPayload, PAYMENT-SIGNATURE, signer, receipt export, certificate, gateway check, policy, greenlight, and mutation fields on the surface.","Tests require the false non-authority flags."],"non_goals":["Do not weaken existing architecture tests to admit the new surface."],"status":"completed","proof_gate":"quality:architecture and quality:claims pass.","next_mechanism":"Add focused architecture tests for workflow-admission boundary."} +{"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"completed","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} +{"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"completed","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} {"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"open","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} {"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} {"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"open","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/review-gates.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/review-gates.md new file mode 100644 index 0000000..da8bc03 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/review-gates.md @@ -0,0 +1,199 @@ +## Audit Scope + +Focus: review-gates audit for T2-01 SDK/exports surface posture. + +Question under audit: whether `ServiceWorkflowAdmission` should be exported from +the package root or remain surface-only, how SDK role-client guidance should +describe it, and whether the current SDK/package posture creates authority drift. + +## Source Boundary + +Canonical source beats planning scratch. `.planning/` was used only for the +active macro-plan handoff and T2-01 acceptance criteria. + +Read boundary: + +- Canon/doctrine: `AGENTS.md`, `README.md`, `docs/internal/decisions.md`, + `docs/internal/protocol-notes.md`, `docs/internal/service-workflow-story.md`, + `docs/internal/protocol-layman.md`, `STRUCTURE.md`, `QUALITY.md`. +- Active plan: `.planning/macro-plan/AGENT-HANDOFF.md`, + `.planning/macro-plan/TASKS.jsonl`, + `.planning/macro-plan/EXECUTION-SLICES.md`. +- SDK/export source: `src/sdk/surface-clients/index.ts`, + `src/sdk/surface-clients/runtime-client.ts`, + `src/sdk/surface-clients/policy-client.ts`, + `src/sdk/surface-clients/gateway-client.ts`, + `src/sdk/surface-clients/evidence-client.ts`, `src/sdk/LANE.md`, + `src/index.ts`, `src/surfaces/index.ts`, + `src/surfaces/service-workflow-admission/index.ts`, `package.json`. +- Export/package tests: `test/architecture/root-exports.test.ts`, + `test/architecture/package-surface.test.ts`, + `test/architecture/workflow-admission-boundary.test.ts`, + `test/sdk/role-clients.test.ts`. +- Package scripts: `scripts/build-package-bundles.mjs`, + `scripts/check-package-surface.mjs`, + `scripts/check-published-entrypoints.mjs`. + +## Files Read + +- `AGENTS.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/TASKS.jsonl` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/MACRO-PLAN.md` +- `README.md` +- `STRUCTURE.md` +- `QUALITY.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` +- `docs/internal/protocol-layman.md` +- `src/sdk/LANE.md` +- `src/sdk/surface-clients/index.ts` +- `src/sdk/surface-clients/runtime-client.ts` +- `src/sdk/surface-clients/policy-client.ts` +- `src/sdk/surface-clients/gateway-client.ts` +- `src/sdk/surface-clients/evidence-client.ts` +- `src/index.ts` +- `src/surfaces/index.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `package.json` +- `test/architecture/root-exports.test.ts` +- `test/architecture/package-surface.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `test/sdk/role-clients.test.ts` +- `scripts/build-package-bundles.mjs` +- `scripts/check-package-surface.mjs` +- `scripts/check-published-entrypoints.mjs` + +## Invariant At Stake + +SDK role clients can guide activation, proposal, policy evaluation, gateway +transport, and redacted readback, but they cannot infer authority from service +workflow evidence. `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` are +non-authority product-surface records. They must not become root-level protocol +primitives, role-client permission inputs, policy substitutes, gateway passes, +receipt evidence, signer access, or reusable auth. + +## Pass Conditions + +- `ServiceWorkflowAdmission` stays off the package root. +- `ServiceWorkflowAdmission` is exposed only as a surface schema if a public + import path is intentionally added; it must not be exported through + `./sdk/role-clients`. +- Role-client docs state that admission/handle values are evidence/readback + context only. +- `RuntimeClient` may cite admission/handle context only while producing fresh + proposal records or compiler refusals. +- `PolicyClient.evaluatePolicy()` still requires an exact action contract input; + admission/handle is not policy. +- `GatewayClient.gatewayCheck()` still requires gateway check input bound to a + one-use greenlight; admission/handle is not a gateway pass. +- `EvidenceClient` readback must distinguish admission evidence from receipt + timeline, downstream finality, replay refusal, and proof gaps. +- Root/package/export tests remain curated and fail if root or role-client + exports widen accidentally. + +## Failures + +1. SDK role-client guidance is not explicit enough for T2-01 closeout. + `README.md` explains the first-use flow and says + `ServiceWorkflowAdmission` is not policy and `ServiceWorkflowHandle` is not + permission. `src/sdk/LANE.md` explains role-client custody boundaries. But + the role-client guidance never names `ServiceWorkflowAdmission` or + `ServiceWorkflowHandle`, so it does not tell developers where those records + may appear: context/evidence refs for fresh proposals and readback only, + never as policy input, greenlight, gateway input, receipt, credential, or + role token. + +2. The package surface has an unresolved `surfaces` export posture. Build and + package checks require `dist/surfaces/index.mjs` and + `dist/surfaces/index.d.ts`, and `src/surfaces/index.ts` exports + `service-workflow-admission`. `package.json` does not expose a + `./surfaces` subpath. That is safe against accidental public authority drift, + but ambiguous for T2-01: if the admission schema is meant to be public, the + public import path is missing; if it is source-internal only, the package + currently ships an unaddressable dist artifact. + +No current source failure shows `ServiceWorkflowAdmission` exported from root or +from `./sdk/role-clients`. + +## Proof Gaps + +- No import smoke exists for a public `handshake-protocol-kernel/surfaces` + subpath because that subpath does not exist. +- No role-client doc/test currently asserts the exact admission/handle wording: + context-only, fresh action contract required, admission readback is not receipt + evidence. +- `root-exports.test.ts` would catch a root export by exact export-list drift, + but it does not have a named regression assertion for + `ServiceWorkflowAdmission` / `ServiceWorkflowHandle`. +- T2-01 status in `TASKS.jsonl` remains `open`; this audit does not promote it. + +## Required Changes + +1. Do not export `ServiceWorkflowAdmission` from the package root. + + Root export would place a product-surface admission record beside + `ActionContractSchema`, `PolicyDecisionSchema`, `GreenlightSchema`, + `GatewayCheckInputSchema`, `ReceiptSchema`, `verifiedGatewayCheckFromResult`, + and `HandshakeClient`. That makes admission look like a protocol primitive or + authority-bearing input. It is review theatre risk in package form. + +2. Keep `ServiceWorkflowAdmission` surface-only. + + If a public type/schema import is required, add a deliberate + `handshake-protocol-kernel/surfaces` package subpath with tests that assert + non-authority exports and forbid `PolicyDecision`, `Greenlight`, + `GatewayCheck`, `ReceiptExport`, `PaymentPayload`, signer, mutation, and + certificate-minting names. Do not use `./sdk/role-clients` for these schemas; + that subpath should stay role-client constructors plus safe transport/error + types. + +3. Patch role-client guidance before closing T2-01. + + The docs should say: + + - `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` are service + workflow context/readback records only. + - `RuntimeClient` may use their IDs/digests as declared assumptions, + evidence refs, or context while compiling/proposing a fresh exact action + contract. + - `PolicyClient.evaluatePolicy()` starts from exact contract input, not from + admission/handle. + - `GatewayClient.gatewayCheck()` starts from gateway-check input bound to a + one-use greenlight, not from admission/handle. + - `EvidenceClient` may read redacted evidence and receipt timelines, but an + admission readback is not receipt evidence or downstream success. + - No role client should retry protected work automatically because an + admission was accepted. + +4. Add named export-posture tests if a `./surfaces` subpath is introduced. + + Required assertions: root does not export `ServiceWorkflowAdmission*` or + `ServiceWorkflowHandle*`; role-clients do not export those schemas; the + surfaces subpath exports only non-authority surface schemas/constants/helpers. + +## Status Recommendation + +Conditional pass for current source posture; do not promote T2-01 to closed. + +Current source is safe on the central authority question: root does not export +`ServiceWorkflowAdmission`, role clients remain on an explicit non-root subpath, +and focused tests passed. The unresolved work is documentation and package +surface intent: either keep admission schema source-internal and stop implying a +public import, or add an explicit non-root `./surfaces` subpath with narrow +non-authority tests. Root export is the wrong move. + +## Commands Or Tools Used + +- `rg -n "T2-01|ServiceWorkflowAdmission|surface-clients|SDK|exports|macro-plan|audit" /Users/joelchan/.codex/memories/MEMORY.md` +- `sed -n '1,220p' /Users/joelchan/.codex/skills/handshake-grounding/SKILL.md` +- `pwd` +- `git status --short --branch` +- `sed -n` reads over the source boundary listed above +- `rg -n "ServiceWorkflowAdmission|ServiceWorkflowHandle|role-client|role client|surface client|surface-clients|sdk/role-clients|sdk/surface-clients|freshActionContractRequired|createsAuthority" . src test docs README.md package.json` +- `find .planning/macro-plan -maxdepth 4 -type d | sort` +- `find .planning/macro-plan/runs -maxdepth 3 -type f | sort` +- `nl -ba` reads for cited line anchors +- `npm run test -- test/architecture/root-exports.test.ts test/sdk/role-clients.test.ts test/architecture/package-surface.test.ts test/architecture/workflow-admission-boundary.test.ts` diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md index 5ed8698..afa5910 100644 --- a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -29,3 +29,33 @@ Sidecar audit recommendations were reconciled as gates: ## Git State `.planning/` is ignored by `.gitignore`, so normal `git status --short` does not show these artifacts. If the user wants planning artifacts committed, they must be force-added deliberately. + +## Implementation Checkpoints + +T1-01 through T1-03 landed in source as the service workflow story, non-authority +admission/handle surface, and workflow-admission boundary tests. Verified gates: +focused workflow boundary test, `npm run quality:claims`, +`npm run quality:architecture`, `npm run format:check`, `git diff --check`, and +full `npm run check:repo`. + +T1-04 landed canonical-doc convergence for the simplified flow. Verified gates: +`npm run quality:claims`, `npm run quality:architecture`, +`npm run format:check`, and `git diff --check`. + +T2-01 landed active CLI, MCP, and SDK surface alignment only. It did not add +commands, MCP authority tools, SDK methods, package-root exports, policy, +gateway, signer, mutation, receipt export, or terminal certificate behavior. +Verified gates: + +```bash +npm run test -- test/architecture/cli-command-posture.test.ts test/architecture/mcp-surface-posture.test.ts test/cli/cli-evidence.test.ts +npm run test -- test/architecture/mcp-surface-posture.test.ts test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-resource-redaction.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/workflow-admission-boundary.test.ts +npm run test -- test/architecture/root-exports.test.ts test/sdk/role-clients.test.ts test/architecture/package-surface.test.ts test/architecture/workflow-admission-boundary.test.ts +npm run check:types +npm run quality:architecture +npm run quality:claims +npm run format:check +git diff --check +``` + +Open next slice: MPLAN-007 / T2-02 local service workflow admission example. diff --git a/.planning/macro-plan/runs/20260525T174005-passport-admission-full/audits/evidence.md b/.planning/macro-plan/runs/20260525T174005-passport-admission-full/audits/evidence.md new file mode 100644 index 0000000..822d76c --- /dev/null +++ b/.planning/macro-plan/runs/20260525T174005-passport-admission-full/audits/evidence.md @@ -0,0 +1,141 @@ +## Audit Scope + +Focus: evidence. + +Assigned slice: T2-01 MCP surfaces only. + +Question audited: whether the simplified service workflow can improve MCP descriptions/resources while preserving the invariant that MCP is proposal/evidence only and `ServiceWorkflowHandle` cannot become permission. + +No source, docs, or tests were edited. + +## Source Boundary + +Required sources read: + +- `AGENTS.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/TASKS.jsonl` +- `README.md` +- `src/mcp/catalog.ts` +- `src/mcp/resources.ts` +- `src/mcp/x402-proposal.ts` +- `src/mcp/output.ts` +- `test/architecture/mcp-surface-posture.test.ts` + +Additional read-only sources used to resolve the current boundary: + +- `src/surfaces/boundary-manifest.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `test/mcp/mcp-schema-contract.test.ts` +- `test/mcp/mcp-resource-redaction.test.ts` +- `test/mcp/mcp-x402-proposal.test.ts` +- `package.json` +- `QUALITY.md` + +## Files Read + +- `AGENTS.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/TASKS.jsonl` +- `README.md` +- `src/mcp/catalog.ts` +- `src/mcp/resources.ts` +- `src/mcp/x402-proposal.ts` +- `src/mcp/output.ts` +- `src/surfaces/boundary-manifest.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `test/architecture/mcp-surface-posture.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `test/mcp/mcp-schema-contract.test.ts` +- `test/mcp/mcp-resource-redaction.test.ts` +- `test/mcp/mcp-x402-proposal.test.ts` +- `package.json` +- `QUALITY.md` + +## Invariant At Stake + +MCP can expose proposal and evidence/readback. MCP must not evaluate policy, create a greenlight, perform a gateway check, invoke a signer, mutate, export a receipt, mint a terminal certificate, or let a service workflow handle function as permission. + +The dangerous failure is not current MCP mutation. The dangerous failure is adding the simplified service workflow in a way that makes `ServiceWorkflowHandle`, passport IDs, admission IDs, or handle digests look like clearance. + +## Pass Conditions + +- MCP keeps exactly proposal/evidence/readback posture. +- `handshake.actions.x402_payment.propose` remains one fresh x402 action-contract proposal, not policy or gateway authority. +- MCP resources remain read-only and set false non-authority flags. +- Service workflow alignment is descriptive or evidentiary only. +- Any service workflow reference, if later added, is correlation/readback context only and cannot satisfy `delegatedAuthorityBinding`, `operatingEnvelopeId`, `gatewayRegistryEntryId`, trusted readiness, policy version, idempotency authority, greenlight, gateway check, signer, payment material, mutation, receipt export, or certificate minting. +- Tests fail if MCP imports authority paths, names credential material, outputs authority fields, or accepts mutation-shaped proposal input. + +## Failures + +Current authority posture: no failure found. Focused MCP/workflow tests pass. + +Concrete T2-01 alignment gap: + +- `README.md` teaches `Show Passport -> ServiceWorkflowAdmission -> ServiceWorkflowHandle -> Request Clearance -> Read Outcome`, and states handle is correlation/readback only. +- `src/mcp/catalog.ts` exposes the one x402 proposal tool and read-only resource templates, but the tool description only says it proposes one exact x402 protected action and does not authorize or execute. It does not teach the service workflow model or the handle boundary. +- `src/mcp/resources.ts` metadata payload for `handshake://metadata/actions/{actionClass}` only returns action class, proposal tool, and non-authority flags. It does not expose the service workflow boundary or the "fresh action contract required" rule. +- `src/mcp/resources.ts` challenge payloads are generic `recraft_request` records. They do not distinguish stale service workflow evidence, handle-as-permission misuse, or fresh-clearance-required remediation. + +Planning/test conflict: + +- T2-01 asks to align MCP descriptions with the service workflow model. +- `test/architecture/workflow-admission-boundary.test.ts` currently treats `src/mcp` as a forbidden authority root for the service workflow nouns and IDs. That is good against handle-as-permission drift, but it also blocks naive MCP description/resource alignment if exact names are added to `src/mcp/catalog.ts` or `src/mcp/resources.ts`. +- Therefore T2-01 needs a narrow test rule, not a broad weakening: allow descriptive/read-only MCP metadata only if false non-authority flags and fresh-contract language are present; continue forbidding proposal input fields and authority-path use. + +## Proof Gaps + +- No MCP-specific test currently proves the simplified service workflow is visible to MCP users as proposal/evidence-only. Current tests prove MCP stays non-authority, not that it teaches the simplified flow. +- No MCP-specific negative test distinguishes safe service workflow metadata from unsafe handle-as-permission input. +- `McpX402PaymentProposalInputSchema` has `correlationRef`, but no typed service workflow context posture. That is safer than accepting a handle as permission, but it means any future handle correlation would be opaque unless bounded by explicit metadata/resource tests. +- No MCP resource family exists for read-only service workflow admission or handle readback. Adding one could help reconstruction, but only if it is read-only evidence and cannot be used as a bearer permission URI. + +## Required Changes + +For T2-01, keep the change descriptive and evidentiary: + +1. Update MCP tool/resource descriptions to say the tool proposes fresh clearance for one protected action after any service workflow context; it does not authorize, execute, or treat workflow handles as permission. +2. Prefer read-only metadata over handle-bearing proposal input. A safe direction is a metadata resource such as `handshake://metadata/service-workflow` or added fields in `handshake://metadata/actions/{actionClass}` that state: + - passport/admission/handle are evidence or context only; + - fresh action contract is required for every protected action; + - MCP creates no policy decision, greenlight, gateway check, mutation, receipt export, or certificate. +3. If actual service workflow readback resources are added, keep them under evidence/readback, include the service workflow non-authority boundary flags, and never return credential material, payment material, receipt exports, raw internal records, greenlights, gateway check inputs, or mutation commands. +4. Do not add MCP policy tools, gateway tools, signer tools, mutation tools, or service-workflow-handle permission tools. +5. Do not let `ServiceWorkflowHandle` populate `delegatedAuthorityBinding`, trusted readiness, policy version, gateway registry, operating envelope, idempotency authority, or proposal bounds. +6. Tighten tests by splitting "MCP may describe/read service workflow context" from "MCP may use service workflow context as authority." The latter must remain forbidden. + +## Status Recommendation + +Current MCP posture passes as proposal/evidence only. + +T2-01 should proceed only as a narrow descriptive/resource alignment. It should not add handle-bearing permission semantics or new authority-shaped MCP tools. + +Smallest acceptable move: make MCP catalog/metadata teach "service workflow context is not clearance; fresh action contract required" and add tests proving the wording/resource remains non-authority. + +## Commands Or Tools Used + +- `sed -n '1,220p' /Users/joelchan/.codex/skills/handshake-grounding/SKILL.md` +- `rg -n "T2-01|MCP|x402-proposal|mcp-surface|proposal/evidence|proposal evidence|x402" /Users/joelchan/.codex/memories/MEMORY.md` +- `pwd` +- `git status --short --branch` +- `nl -ba AGENTS.md | sed -n '1,260p'` +- `nl -ba .planning/macro-plan/AGENT-HANDOFF.md | sed -n '1,260p'` +- `nl -ba .planning/macro-plan/TASKS.jsonl | sed -n '1,220p'` +- `nl -ba README.md | sed -n '1,260p'` +- `nl -ba src/mcp/catalog.ts | sed -n '1,260p'` +- `nl -ba src/mcp/resources.ts | sed -n '1,320p'` +- `nl -ba src/mcp/x402-proposal.ts | sed -n '1,920p'` +- `nl -ba src/mcp/output.ts | sed -n '1,320p'` +- `nl -ba test/architecture/mcp-surface-posture.test.ts | sed -n '1,360p'` +- `rg --files src/mcp test/mcp test/architecture | sort` +- `nl -ba src/surfaces/boundary-manifest.ts | sed -n '586,660p'` +- `nl -ba src/surfaces/service-workflow-admission/index.ts | sed -n '1,180p'` +- `nl -ba test/mcp/mcp-schema-contract.test.ts | sed -n '1,260p'` +- `nl -ba test/mcp/mcp-resource-redaction.test.ts | sed -n '1,260p'` +- `nl -ba test/mcp/mcp-x402-proposal.test.ts | sed -n '1,760p'` +- `nl -ba test/architecture/workflow-admission-boundary.test.ts | sed -n '1,320p'` +- `nl -ba package.json | sed -n '84,112p'` +- `nl -ba QUALITY.md | sed -n '120,150p'` +- `npm run test -- test/architecture/mcp-surface-posture.test.ts test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-resource-redaction.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/workflow-admission-boundary.test.ts` diff --git a/README.md b/README.md index 86ddba6..e8fa8a5 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ handshake install health --cwd . handshake-mcp ``` +In service-workflow terms, these CLI commands prepare local/readiness evidence +before any fresh `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, or +Request Clearance; they do not create admission, handle, clearance, or outcome +authority. + These commands do not create policy decisions, greenlights, gateway checks, payment material, mutations, receipts, or certificates. They establish local proposal readiness only. diff --git a/src/cli/LANE.md b/src/cli/LANE.md index b8c9c17..0b3a425 100644 --- a/src/cli/LANE.md +++ b/src/cli/LANE.md @@ -12,6 +12,10 @@ The first CLI slice can inspect a local APS report, verify a supplied terminal c Let an operator or operator automation inspect local/reference evidence with machine-readable JSON while preserving custody separation from runtime, gateway, and protocol authority. +Service workflow evidence may be displayed as admission/readback context. A +`ServiceWorkflowHandle` never makes a CLI command agent-safe, retry-safe, or +authorized to run protected work. + ## Constraints and assumptions The CLI is not an agent hot path. Runtime proposal belongs to SDK/MCP, gateway checks belong to gateway custody, and policy decisions remain kernel/control-plane authority. First-slice CLI commands are evidence or posture commands only. @@ -51,3 +55,8 @@ Extract after command metadata, JSON envelope, redaction posture, evidence wrapp ## Scope boundary The CLI may render local evidence and verify supplied terminal certificates. It must not evaluate policy, mint greenlights, perform gateway checks, start protected mutation processes, export raw receipts, or infer authorization from command success. + +It must also not infer authorization from `Passport`, +`ServiceWorkflowAdmission`, or `ServiceWorkflowHandle` records. Those records +can help an operator find evidence and proof gaps; protected action clearance +still requires a fresh exact action contract. diff --git a/src/cli/command-manifest.ts b/src/cli/command-manifest.ts index c1525cf..20681e9 100644 --- a/src/cli/command-manifest.ts +++ b/src/cli/command-manifest.ts @@ -21,6 +21,9 @@ export type CliCommandManifestEntry = { readonly nonGoals: readonly string[]; }; +export const cliServiceWorkflowPosture = + "CLI surface only: local setup, readiness, and evidence readback; does not create ServiceWorkflowAdmission, ServiceWorkflowHandle, clearance, policy decision, greenlight, gateway check, mutation, receipt export, or certificate." as const; + const sharedNonGoals = [ "policy evaluation", "gateway check", @@ -28,6 +31,7 @@ const sharedNonGoals = [ "credential custody", "raw record access", "process startup", + "workflow handle authority", ] as const; export const cliCommandManifest = [ @@ -249,5 +253,7 @@ export function cliSchemaOutput() { outputSchema: command.outputSchema, agentSafe: command.agentSafe, redactionPosture: command.redactionPosture, + nonGoals: command.nonGoals, + workflowPosture: cliServiceWorkflowPosture, })); } diff --git a/src/cli/main.ts b/src/cli/main.ts index 7457f33..d2f2b28 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -197,7 +197,10 @@ export function cliCommandErrorOutput(input: { retryability: "retryable_after_fix", commitState: "not_started", redactionProfileRef: "cli-error:v1-redacted", - warnings: ["Command failed before any authority, gateway check, signer use, or protected mutation."], + warnings: [ + "Command failed before any authority, gateway check, signer use, or protected mutation.", + "No ServiceWorkflowAdmission, ServiceWorkflowHandle, clearance, policy decision, greenlight, gateway check, signer use, or protected mutation was created.", + ], result: { errorCode: input.errorCode, message: input.message, diff --git a/src/cli/output.ts b/src/cli/output.ts index 0ebdc0c..61862c9 100644 --- a/src/cli/output.ts +++ b/src/cli/output.ts @@ -10,6 +10,7 @@ export const cliNonClaims = [ "marketplace certification", "clearing-house readiness", "cross-org AuthorityCertificate trust", + "service workflow admission or handle authority", ] as const; export type CliPlane = "operator" | "evidence"; diff --git a/src/cli/x402/index.ts b/src/cli/x402/index.ts index 6e1a684..32a500e 100644 --- a/src/cli/x402/index.ts +++ b/src/cli/x402/index.ts @@ -98,6 +98,7 @@ export async function installX402PaymentCommand(input: { cwd: string; inputValue evidenceRefs: [recordedRef].filter((ref): ref is string => typeof ref === "string"), warnings: [ "Compiled local x402 posture only; trusted readiness requires control-plane install registration and gateway posture evidence.", + "Trusted readiness is pre-contract service context only; it is not ServiceWorkflowAdmission, ServiceWorkflowHandle, policy, greenlight, gateway check, or mutation authority.", "No greenlight, signer use, gateway check, or mutation was performed.", ], result: { @@ -123,6 +124,7 @@ export async function probesX402PaymentCommand(input: { cwd: string; postureValu evidenceRefs: [recordedRef].filter((ref): ref is string => typeof ref === "string"), warnings: [ "Probe report classifies caller-supplied gateway posture evidence; it is not provider certification, authority, or execution proof.", + "Probe evidence is pre-contract service context only; it is not ServiceWorkflowAdmission, ServiceWorkflowHandle, policy, greenlight, gateway check, or mutation authority.", ], result: { ...report, @@ -154,6 +156,7 @@ export async function registerX402GatewayReadinessCommand(input: { ), warnings: [ "Trusted readiness binds pre-contract install, probe, gateway, policy, and credential posture only.", + "Trusted readiness is pre-contract service context only; it is not ServiceWorkflowAdmission, ServiceWorkflowHandle, policy, greenlight, gateway check, or mutation authority.", "No greenlight, signer use, gateway check, payment payload, or mutation was performed.", ], result: outcome.record diff --git a/src/mcp/LANE.md b/src/mcp/LANE.md index 202fba3..446f786 100644 --- a/src/mcp/LANE.md +++ b/src/mcp/LANE.md @@ -14,6 +14,7 @@ This lane defines a source-owned MCP catalog, strict `x402_payment.exact` propos - Let the host submit one exact buyer-side `x402_payment.exact` proposal candidate. - Let the host receive structured refusal, not-ready, stale-metadata, or proposal outcomes. - Let the host read redacted evidence projections through explicit resources. +- Let the host see service workflow admission and handle boundaries as read-only context when preparing a fresh protected-action proposal. - Let the local self-hosted packet prove the source-owned MCP stdio process can list tools, read resources, and call the proposal tool without creating authority. - Treat certificate resources as local terminal evidence references only; MCP does not mint, verify hosted trust, publish revocation state, or create cross-org certificate trust. @@ -24,6 +25,7 @@ This lane defines a source-owned MCP catalog, strict `x402_payment.exact` propos - Gateway custody, control-plane install, signer material, mutation execution, and terminal certificate minting live outside MCP. - Generated execution graph creation remains kernel-only in this checkout; MCP records that posture instead of creating a new HTTP authority path. - The first public proposal tool is `handshake.actions.x402_payment.propose`. +- A `ServiceWorkflowHandle` is correlation/readback context only. MCP must not use it as permission, payment approval, retry permission, credential posture, or proof that the gateway will accept the action. ## Core components @@ -82,3 +84,5 @@ Extract only after the catalog, proposal schema, resource mapping, process custo ## Scope boundary MCP can propose and display evidence. It cannot authorize, approve, pay, execute, recover, retry, export, certify, install, supervise processes, or hold mutation credentials. + +MCP can carry service workflow context into proposal preparation only if the proposal still becomes one fresh exact action contract. It must not treat admission, handle, badge, or certificate evidence as an executable grant. diff --git a/src/mcp/catalog.ts b/src/mcp/catalog.ts index 4e17c7e..a9a2a74 100644 --- a/src/mcp/catalog.ts +++ b/src/mcp/catalog.ts @@ -4,6 +4,17 @@ import { McpX402PaymentProposalInputSchema } from "./x402-proposal"; export const MCP_X402_PAYMENT_PROPOSE_TOOL = "handshake.actions.x402_payment.propose" as const; +export const mcpServiceWorkflowBoundary = { + acceptsWorkflowHandleContext: true, + workflowHandleCreatesAuthority: false, + freshActionContractRequired: true, + admissionCreatesPolicyDecision: false, + admissionCreatesGreenlight: false, + admissionPerformsGatewayCheck: false, + handlePermitsMutation: false, + handleExportsReceipt: false, +} as const; + export const mcpResourceTemplates = [ { uriTemplate: "handshake://metadata/actions/{actionClass}", @@ -96,6 +107,7 @@ export function mcpCatalogSnapshot() { schemaVersion: MCP_SCHEMA_VERSION, resources: mcpResourceTemplates, tools: mcpProposalTools, + serviceWorkflowBoundary: mcpServiceWorkflowBoundary, supportsParallelToolCalls: false, authorityCreated: false, gatewayCheckPerformed: false, diff --git a/src/mcp/index.ts b/src/mcp/index.ts index a13d302..c70b6f9 100644 --- a/src/mcp/index.ts +++ b/src/mcp/index.ts @@ -1,4 +1,10 @@ -export { mcpCatalogSnapshot, mcpProposalTools, mcpResourceTemplates, MCP_X402_PAYMENT_PROPOSE_TOOL } from "./catalog"; +export { + mcpCatalogSnapshot, + mcpProposalTools, + mcpResourceTemplates, + mcpServiceWorkflowBoundary, + MCP_X402_PAYMENT_PROPOSE_TOOL, +} from "./catalog"; export { McpStructuredContentSchema, MCP_SCHEMA_VERSION, McpToolResultSchema } from "./output"; export { parseMcpResourceUri, readMcpResource, McpResourceReadSchema } from "./resources"; export { diff --git a/src/mcp/resources.ts b/src/mcp/resources.ts index e724fdf..c5c96be 100644 --- a/src/mcp/resources.ts +++ b/src/mcp/resources.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { digestMcp, type McpJsonValue } from "./digest"; import { MCP_SCHEMA_VERSION } from "./output"; +import { mcpServiceWorkflowBoundary } from "./catalog"; export const McpResourceReadSchema = z.strictObject({ schemaVersion: z.literal(MCP_SCHEMA_VERSION), @@ -102,6 +103,7 @@ async function readPayload(parsed: ParsedMcpResourceUri, evidenceClient: McpEvid resourceVersion: "mcp-metadata.v1", actionClass: parsed.actionClass, proposalTool: "handshake.actions.x402_payment.propose", + serviceWorkflowBoundary: mcpServiceWorkflowBoundary, authorityCreated: false, gatewayCheckPerformed: false, mutationAttempted: false, diff --git a/src/sdk/LANE.md b/src/sdk/LANE.md index 5f134c2..581054d 100644 --- a/src/sdk/LANE.md +++ b/src/sdk/LANE.md @@ -12,6 +12,10 @@ Client ergonomics for invoking the reference HTTP surface. The SDK does not prov Let callers invoke public transition routes, route role-scoped tokens, parse typed success/error responses, and read redacted diagnostic evidence projections. +Service workflow admission and handle records may guide request construction +and readback. They are not SDK credentials, role tokens, policy decisions, +greenlights, gateway checks, retries, or mutation permissions. + ## Constraints and assumptions The client is outside the authority boundary. It may submit evidence or requests, but server-side protocol and gateway checks decide whether consequence can proceed. @@ -91,6 +95,11 @@ proposal records or compiler refusals only. They do not evaluate policy, greenlight, gateway-check, mutate, export receipts, mint certificates, recover, install, isolate, or sign. +If a caller starts from a `ServiceWorkflowHandle`, `RuntimeClient` still must +produce a fresh exact action-contract proposal. The handle can contribute +context and evidence refs only; it cannot satisfy policy, gateway, signer, or +receipt requirements. + `ControlPlaneClient` may register delegated authority refs and record terminal delegated authority status transitions through `control_plane` custody. Those methods manage delegated attempt-authority evidence and authority-ref isolation diff --git a/test/architecture/cli-command-posture.test.ts b/test/architecture/cli-command-posture.test.ts index 7d2701a..7ad8be2 100644 --- a/test/architecture/cli-command-posture.test.ts +++ b/test/architecture/cli-command-posture.test.ts @@ -1,7 +1,8 @@ import { describe, expect, it } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { cliCommandManifest } from "../../src/cli/command-manifest"; +import { cliCommandManifest, cliSchemaOutput, cliServiceWorkflowPosture } from "../../src/cli/command-manifest"; +import { cliNonClaims } from "../../src/cli/output"; const forbiddenCommandTerms = [ "run", @@ -102,6 +103,9 @@ describe("CLI command posture", () => { for (const field of requiredNonAuthorityFields) { expect(source).toContain(field); } + expect(cliNonClaims).toContain("service workflow admission or handle authority"); + expect(cliCommandManifest.every((command) => command.nonGoals.includes("workflow handle authority"))).toBe(true); + expect(cliSchemaOutput().every((command) => command.workflowPosture === cliServiceWorkflowPosture)).toBe(true); }); }); diff --git a/test/architecture/mcp-surface-posture.test.ts b/test/architecture/mcp-surface-posture.test.ts index 8d8222f..f85a589 100644 --- a/test/architecture/mcp-surface-posture.test.ts +++ b/test/architecture/mcp-surface-posture.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "bun:test"; import { readdirSync, readFileSync, statSync } from "node:fs"; import { join, relative } from "node:path"; +import { mcpCatalogSnapshot } from "../../src/mcp/catalog"; import { surfaceBoundaryManifest } from "../../src/surfaces/boundary-manifest"; describe("MCP surface posture", () => { @@ -71,6 +72,19 @@ describe("MCP surface posture", () => { expect(violations.sort()).toEqual([]); }); + + it("keeps service workflow context as MCP proposal metadata, not authority", () => { + expect(mcpCatalogSnapshot().serviceWorkflowBoundary).toEqual({ + acceptsWorkflowHandleContext: true, + workflowHandleCreatesAuthority: false, + freshActionContractRequired: true, + admissionCreatesPolicyDecision: false, + admissionCreatesGreenlight: false, + admissionPerformsGatewayCheck: false, + handlePermitsMutation: false, + handleExportsReceipt: false, + }); + }); }); function importsFrom(text: string): string[] { diff --git a/test/cli/cli-evidence.test.ts b/test/cli/cli-evidence.test.ts index 040d0d8..85e9197 100644 --- a/test/cli/cli-evidence.test.ts +++ b/test/cli/cli-evidence.test.ts @@ -117,8 +117,8 @@ describe("CLI evidence surface", () => { command: "schema", result: { commands: [ - { id: "schema", agentSafe: true }, - { id: "init", agentSafe: false }, + { id: "schema", agentSafe: true, nonGoals: expect.arrayContaining(["workflow handle authority"]) }, + { id: "init", agentSafe: false, workflowPosture: expect.stringContaining("does not create") }, { id: "doctor", agentSafe: true }, { id: "evidence.aps-report", agentSafe: true }, { id: "evidence.contract-view", agentSafe: true }, @@ -165,6 +165,10 @@ describe("CLI evidence surface", () => { nextAction: "run_schema", retryability: "retryable_after_fix", commitState: "not_started", + warnings: [ + "Command failed before any authority, gateway check, signer use, or protected mutation.", + "No ServiceWorkflowAdmission, ServiceWorkflowHandle, clearance, policy decision, greenlight, gateway check, signer use, or protected mutation was created.", + ], result: { errorCode: "cli_command_unsupported", message: "Unsupported command.", From 56f3cbdf6103a5d8560120957162522bd6417b99 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:38:08 +0800 Subject: [PATCH 005/144] Add service workflow admission demo --- .planning/macro-plan/TASKS.jsonl | 2 +- .../validation.md | 20 ++ .prettierignore | 1 + README.md | 5 +- examples/service-workflow-admission/README.md | 51 +++ .../output/.gitignore | 2 + examples/service-workflow-admission/run.ts | 303 ++++++++++++++++++ package.json | 1 + .../service-workflow-admission.test.ts | 115 +++++++ 9 files changed, 498 insertions(+), 2 deletions(-) create mode 100644 examples/service-workflow-admission/README.md create mode 100644 examples/service-workflow-admission/output/.gitignore create mode 100644 examples/service-workflow-admission/run.ts create mode 100644 test/product/service-workflow-admission.test.ts diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 0889a2c..bc4048a 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -4,7 +4,7 @@ {"id":"MPLAN-004","phase":"T1","slice":"T1-03","title":"Add workflow admission boundary tests","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["MPLAN-003"],"evidence":[".planning/codebase/TESTING.md","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"candidate_paths":["test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"The known failure mode is naming and surface drift into authority-bearing paths.","acceptance":["Tests fail if Passport, Badge, ServiceWorkflowAdmission, or ServiceWorkflowHandle appear as protocol primitives or authority exports.","Tests reject raw credential, token, PaymentPayload, PAYMENT-SIGNATURE, signer, receipt export, certificate, gateway check, policy, greenlight, and mutation fields on the surface.","Tests require the false non-authority flags."],"non_goals":["Do not weaken existing architecture tests to admit the new surface."],"status":"completed","proof_gate":"quality:architecture and quality:claims pass.","next_mechanism":"Add focused architecture tests for workflow-admission boundary."} {"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"completed","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} {"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"completed","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} -{"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"open","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} +{"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"completed","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} {"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} {"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"open","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} {"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"open","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md index afa5910..07e24c3 100644 --- a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -59,3 +59,23 @@ git diff --check ``` Open next slice: MPLAN-007 / T2-02 local service workflow admission example. + +T2-02 landed a runnable local `service-workflow-admission` example that +validates one admission/handle packet, composes the existing x402 protected +spend demo as the separate fresh-clearance path, and writes JSON plus Markdown +readback. It did not introduce a new protocol primitive, gateway fixture, +policy evaluator, signer path, mutation runner, public root export, hosted +operation claim, provider custody claim, settlement claim, or handle-as- +permission behavior. Verified gates: + +```bash +npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/product/service-workflow-admission.test.ts test/product/x402-protected-spend-demo-report.test.ts +npm run check:types +npm run quality:architecture +npm run quality:claims +npm run format:check +git diff --check +``` + +Open next slice: MPLAN-008 / T2-03 generated-agent and runtime misuse tests. diff --git a/.prettierignore b/.prettierignore index 346a145..8cd760e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,3 +10,4 @@ examples/x402-protected-spend/output examples/mcp-reference-transcript/output examples/self-hosted-activation/output examples/x402-protected-tool-profiles/output +examples/service-workflow-admission/output diff --git a/README.md b/README.md index e8fa8a5..ffd18bf 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,10 @@ it uses real local MCP stdio proposal/evidence proof; `npm run demo:aps` writes `examples/x402-protected-spend/output/latest.md` and is not hosted operation, not broad x402 compatibility; `npm run demo:adapter-sdk` writes `examples/external-adapter-sdk/output/latest.md` and is not policy evaluation, -not gateway check, not mutation. +not gateway check, not mutation; +`npm run demo:service-workflow-admission` writes +`examples/service-workflow-admission/output/latest.md` and is admission readback +plus handle context only, not clearance or authority. No adapter family defines the protocol. This package is not broad x402 compatibility, not live provider custody, hosted mutation authority, production diff --git a/examples/service-workflow-admission/README.md b/examples/service-workflow-admission/README.md new file mode 100644 index 0000000..30e5551 --- /dev/null +++ b/examples/service-workflow-admission/README.md @@ -0,0 +1,51 @@ +# Service Workflow Admission Example + +Status: local/source-owned product-surface proof +Scope: one non-authority service workflow admission and handle, followed by one +fresh x402 protected-action clearance path composed from the existing APS demo. + +## Invariant At Stake + +Admission and handle records can help a service correlate evidence and readback. +They cannot become identity, permission, policy, greenlight, gateway check, +receipt evidence, signer access, payment approval, or reusable auth. + +## Run + +From the repo root: + +```bash +npm run demo:service-workflow-admission +``` + +The demo writes: + +```text +examples/service-workflow-admission/output/latest.md +examples/service-workflow-admission/output/latest.json +``` + +The demo also refreshes `examples/x402-protected-spend/output/latest.json` by +running `npm run demo:aps` internally, then reads only the redacted local APS +report fields needed to show that protected-action clearance is separate from +workflow admission. + +## What This Proves + +- `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` parse through the + source-owned non-authority schemas. +- The five workflow IDs are correlation and reconstruction fields only. +- Admission readback is not receipt evidence. +- The workflow handle is not permission. +- x402 clearance appears only in the fresh protected-action path: + `ActionContract -> PolicyDecision -> one-use Greenlight -> GatewayCheck`. + +## What This Does Not Prove + +- No hosted operation. +- No provider custody. +- No settlement finality. +- No broad x402 compatibility. +- No host-wide containment. +- No reusable passport authority. +- No handle-as-permission. diff --git a/examples/service-workflow-admission/output/.gitignore b/examples/service-workflow-admission/output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/examples/service-workflow-admission/output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/examples/service-workflow-admission/run.ts b/examples/service-workflow-admission/run.ts new file mode 100644 index 0000000..8dabfbb --- /dev/null +++ b/examples/service-workflow-admission/run.ts @@ -0,0 +1,303 @@ +import { mkdir, writeFile } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; +import { + ServiceWorkflowAdmissionSchema, + ServiceWorkflowHandleSchema, + serviceWorkflowAdmissionSchemaVersion, + serviceWorkflowNonAuthorityBoundary, +} from "../../src/surfaces/service-workflow-admission"; + +const repoRoot = fileURLToPath(new URL("../..", import.meta.url)); +const outputDir = new URL("./output/", import.meta.url); +const outputJsonPath = new URL("./output/latest.json", import.meta.url); +const outputMarkdownPath = new URL("./output/latest.md", import.meta.url); +const x402OutputPath = `${repoRoot}/examples/x402-protected-spend/output/latest.json`; + +const generatedAt = "2026-05-25T00:00:00.000Z"; +const digest = (char: string) => `sha256:${char.repeat(64)}` as const; +const authorityBoundary = serviceWorkflowNonAuthorityBoundary(); + +await runExistingX402Demo(); +const x402Output = asRecord(await Bun.file(x402OutputPath).json(), "x402 output"); +const x402Report = asRecord(x402Output.report, "x402 report"); +const protectedAction = asRecord(x402Report.protectedAction, "x402 protectedAction"); +const authorityPath = asRecord(x402Report.authorityPath, "x402 authorityPath"); +const evidencePosture = asRecord(x402Report.evidencePosture, "x402 evidencePosture"); + +const workflowHandle = ServiceWorkflowHandleSchema.parse({ + schemaVersion: serviceWorkflowAdmissionSchemaVersion, + passportPackageDigest: digest("1"), + passportPresentationId: "passport-presentation:x402-demo-agent:001", + admissionId: "service-workflow-admission:x402-demo:001", + serviceWorkflowHandleId: "service-workflow-handle:x402-demo:001", + serviceWorkflowHandleDigest: digest("2"), + issuedAt: generatedAt, + expiresAt: "2026-05-25T01:00:00.000Z", + workflowBoundsDigest: digest("3"), + sourceAdmissionDigest: digest("4"), + runtimePostureDigest: digest("5"), + authorityBoundary, + nextProtectedActionRequirement: "fresh_action_contract_required", + allowedUse: "correlation_and_readback_context_only", +}); + +const admissionPacket = ServiceWorkflowAdmissionSchema.parse({ + schemaVersion: serviceWorkflowAdmissionSchemaVersion, + passportPackageDigest: workflowHandle.passportPackageDigest, + passportPresentationId: workflowHandle.passportPresentationId, + admissionId: workflowHandle.admissionId, + admissionDigest: workflowHandle.sourceAdmissionDigest, + serviceRef: "service:x402-demo-intake", + presentedAt: generatedAt, + evaluatedAt: "2026-05-25T00:00:01.000Z", + claimResults: [ + { + claimRef: "passport:evidence-bundle:x402-demo-agent", + claimDigest: workflowHandle.passportPackageDigest, + status: "accepted", + reasonCodes: ["standing_evidence_recognized_for_workflow_context"], + evidenceRefs: ["evidence:passport-package:x402-demo-agent"], + proofGapRefs: [], + }, + { + claimRef: "provider-custody:live-x402", + claimDigest: null, + status: "proof_gap", + reasonCodes: ["provider_custody_not_established_by_admission"], + evidenceRefs: [], + proofGapRefs: ["proof-gap:provider-custody-live-x402"], + }, + ], + runtimePosture: [ + { + runtimeRef: "runtime:codex-local", + hostProfileEvidenceRef: "host-profile:codex-local-x402", + rawSiblingBypassPostureRef: "bypass-posture:x402-raw-sibling", + nativeContainmentClaimed: false, + proofGapRefs: ["proof-gap:host-wide-containment"], + }, + ], + serviceWorkflowHandle: workflowHandle, + authorityBoundary, + nextActionRequirement: "fresh_action_contract_required", + clearanceBoundary: "fresh_action_contract_required_for_each_protected_action", + readbackBoundary: "admission_readback_is_not_receipt_evidence", +}); + +const output = { + schemaVersion: "handshake.demo.service-workflow-admission.v1", + generatedAt, + command: "npm run demo:service-workflow-admission", + invariant: + "Passport, admission, and handle records support correlation and readback only; fresh protected-action clearance carries authority.", + proofBoundary: "local_source_owned_product_surface", + outputFiles: { + markdown: "examples/service-workflow-admission/output/latest.md", + json: "examples/service-workflow-admission/output/latest.json", + composedProtectedActionJson: "examples/x402-protected-spend/output/latest.json", + }, + admissionPacket, + admissionReadback: { + readbackBoundary: admissionPacket.readbackBoundary, + admissionStatus: "accepted_with_proof_gap", + serviceWorkflowHandleId: workflowHandle.serviceWorkflowHandleId, + policyDecisionRef: null, + greenlightRef: null, + gatewayCheckRef: null, + mutationAttemptRef: null, + receiptRef: null, + authorityCertificateRef: null, + nextActionRequirement: "fresh_action_contract_required", + }, + workflowHandle, + freshClearanceRequest: { + actionClass: stringField(protectedAction, "actionClass"), + protectedSurfaceKind: stringField(protectedAction, "protectedSurfaceKind"), + resourceRef: stringField(protectedAction, "resourceRef"), + contextRefs: { + passportPackageDigest: workflowHandle.passportPackageDigest, + passportPresentationId: workflowHandle.passportPresentationId, + admissionId: workflowHandle.admissionId, + serviceWorkflowHandleId: workflowHandle.serviceWorkflowHandleId, + serviceWorkflowHandleDigest: workflowHandle.serviceWorkflowHandleDigest, + }, + contextAuthorityCreated: false, + freshActionContractRequired: true, + }, + freshClearanceAuthorityPath: { + actionClass: stringField(protectedAction, "actionClass"), + actionContractId: stringField(authorityPath, "actionContractId"), + policyDecisionId: stringField(authorityPath, "policyDecisionId"), + policyDecision: stringField(authorityPath, "policyDecision"), + greenlightId: stringField(authorityPath, "greenlightId"), + gateAttemptId: stringField(authorityPath, "gateAttemptId"), + gateDecision: stringField(authorityPath, "gateDecision"), + receiptId: stringField(authorityPath, "receiptId"), + changedParameterDecision: stringField(authorityPath, "changedParameterDecision"), + changedParameterReasonCode: stringField(authorityPath, "changedParameterReasonCode"), + replayDecision: stringField(authorityPath, "replayDecision"), + replayReasonCode: stringField(authorityPath, "replayReasonCode"), + }, + evidenceSeparation: { + admissionEvidenceRefs: admissionPacket.claimResults.flatMap((claim) => claim.evidenceRefs), + admissionProofGapRefs: admissionPacket.claimResults.flatMap((claim) => claim.proofGapRefs), + protectedActionOutcomeRefs: stringArrayField(evidencePosture, "surfaceOperationEvidenceRefs"), + protectedActionProofGapRefs: stringArrayField(evidencePosture, "proofGapRefs"), + protectedActionRefusalRefs: stringArrayField(evidencePosture, "refusalRefs"), + }, + authorityAudit: { + passportCreatedAuthority: false, + admissionCreatedAuthority: false, + handleCreatedAuthority: false, + readbackCreatedAuthority: false, + markdownCreatedAuthority: false, + freshClearanceRequiredForProtectedAction: true, + paymentMaterialInAdmissionOrHandle: false, + credentialMaterialInAdmissionOrHandle: false, + }, + nonClaims: [ + "hosted operation", + "provider custody", + "settlement finality", + "broad x402 compatibility", + "host-wide containment", + "reusable passport authority", + "handle-as-permission", + "receipt evidence from admission readback", + ], + proofGaps: [ + "provider_custody_not_established_by_admission", + "host_wide_containment_not_established_by_admission", + "downstream_finality_remains_x402_outcome_evidence_only", + ], + artifacts: [ + "docs/internal/service-workflow-story.md", + "src/surfaces/service-workflow-admission/index.ts", + "examples/x402-protected-spend/output/latest.json", + ], +} as const; + +const markdown = renderMarkdown(output); + +await mkdir(outputDir, { recursive: true }); +await writeFile(outputJsonPath, `${JSON.stringify(output, null, 2)}\n`); +await writeFile(outputMarkdownPath, markdown); + +console.log(markdown); +console.log("Wrote: examples/service-workflow-admission/output/latest.md"); +console.log("Wrote: examples/service-workflow-admission/output/latest.json"); + +async function runExistingX402Demo(): Promise { + const proc = Bun.spawn([process.execPath, "run", "./examples/x402-protected-spend/run.ts"], { + cwd: repoRoot, + stdout: "pipe", + stderr: "pipe", + }); + const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve(""); + const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve(""); + const exitCode = await proc.exited; + const stdout = await stdoutPromise; + const stderr = await stderrPromise; + if (exitCode !== 0 || stderr !== "") { + throw new Error(`x402 protected-spend demo failed: exit=${exitCode} stdout=${stdout} stderr=${stderr}`); + } +} + +function asRecord(value: unknown, label: string): Record { + if (typeof value !== "object" || value === null || Array.isArray(value)) { + throw new Error(`${label} must be an object.`); + } + return value as Record; +} + +function stringField(record: Record, key: string): string { + const value = record[key]; + if (typeof value !== "string") throw new Error(`${key} must be a string.`); + return value; +} + +function stringArrayField(record: Record, key: string): string[] { + const value = record[key]; + if (!Array.isArray(value)) throw new Error(`${key} must be an array.`); + if (!value.every((entry) => typeof entry === "string")) throw new Error(`${key} must contain strings.`); + return value; +} + +function renderMarkdown(report: typeof output): string { + return `# Service Workflow Admission Example + +Generated: ${report.generatedAt} + +Command: \`${report.command}\` + +## Invariant + +${report.invariant} + +## Admission Evidence + +| Field | Value | +| --- | --- | +| Passport package digest | \`${report.admissionPacket.passportPackageDigest}\` | +| Passport presentation ID | \`${report.admissionPacket.passportPresentationId}\` | +| Admission ID | \`${report.admissionPacket.admissionId}\` | +| Admission status | \`${report.admissionReadback.admissionStatus}\` | +| Creates authority | \`${report.admissionPacket.authorityBoundary.createsAuthority}\` | +| Creates policy decision | \`${report.admissionPacket.authorityBoundary.createsPolicyDecision}\` | +| Performs gateway check | \`${report.admissionPacket.authorityBoundary.performsGatewayCheck}\` | + +## Workflow Handle + +| Field | Value | +| --- | --- | +| Handle ID | \`${report.workflowHandle.serviceWorkflowHandleId}\` | +| Handle digest | \`${report.workflowHandle.serviceWorkflowHandleDigest}\` | +| Allowed use | \`${report.workflowHandle.allowedUse}\` | +| Next protected action requirement | \`${report.workflowHandle.nextProtectedActionRequirement}\` | +| Is reusable auth | \`${report.workflowHandle.authorityBoundary.isReusableAuth}\` | + +## Readback Boundary + +Admission readback is not receipt evidence. The handle is not permission. The +readback carries no policy decision, greenlight, gateway check, mutation, +receipt, certificate, credential material, x402 \`PaymentPayload\`, or +\`PAYMENT-SIGNATURE\`. + +## Fresh Clearance Path + +| Field | Value | +| --- | --- | +| Action class | \`${report.freshClearanceAuthorityPath.actionClass}\` | +| Action contract | \`${report.freshClearanceAuthorityPath.actionContractId}\` | +| Policy decision | \`${report.freshClearanceAuthorityPath.policyDecision}\` | +| Gateway decision | \`${report.freshClearanceAuthorityPath.gateDecision}\` | +| Replay decision | \`${report.freshClearanceAuthorityPath.replayDecision}\` | +| Changed parameter decision | \`${report.freshClearanceAuthorityPath.changedParameterDecision}\` | + +x402 clearance comes only from fresh \`ActionContract -> PolicyDecision -> +one-use Greenlight -> GatewayCheck\`. The workflow handle contributes context +only. + +## Evidence Separation + +| Evidence class | Refs | +| --- | --- | +| Admission evidence | ${report.evidenceSeparation.admissionEvidenceRefs.map((ref) => `\`${ref}\``).join(", ") || "none"} | +| Admission proof gaps | ${report.evidenceSeparation.admissionProofGapRefs.map((ref) => `\`${ref}\``).join(", ") || "none"} | +| Protected-action outcome evidence | ${report.evidenceSeparation.protectedActionOutcomeRefs.map((ref) => `\`${ref}\``).join(", ")} | +| Protected-action proof gaps | ${report.evidenceSeparation.protectedActionProofGapRefs.map((ref) => `\`${ref}\``).join(", ") || "none"} | +| Protected-action refusals | ${report.evidenceSeparation.protectedActionRefusalRefs.map((ref) => `\`${ref}\``).join(", ")} | + +## Non-Claims + +${report.nonClaims.map((claim) => `- ${claim}`).join("\n")} + +## Proof Gaps + +${report.proofGaps.map((gap) => `- ${gap}`).join("\n")} + +## Artifacts + +${report.artifacts.map((artifact) => `- \`${artifact}\``).join("\n")} +`; +} diff --git a/package.json b/package.json index a43a60b..e8cbe09 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "test": "bun test", "demo:self-hosted": "bun run ./examples/self-hosted-activation/run.ts", "demo:aps": "bun run ./examples/x402-protected-spend/run.ts", + "demo:service-workflow-admission": "bun run ./examples/service-workflow-admission/run.ts", "demo:adapter-sdk": "bun run ./examples/external-adapter-sdk/run.ts", "demo:x402-tool-profiles": "bun run ./examples/x402-protected-tool-profiles/run.ts", "demo:mcp-transcript": "bun run ./examples/mcp-reference-transcript/run.ts", diff --git a/test/product/service-workflow-admission.test.ts b/test/product/service-workflow-admission.test.ts new file mode 100644 index 0000000..46ecf0d --- /dev/null +++ b/test/product/service-workflow-admission.test.ts @@ -0,0 +1,115 @@ +import { describe, expect, it } from "bun:test"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { + ServiceWorkflowAdmissionSchema, + ServiceWorkflowHandleSchema, +} from "../../src/surfaces/service-workflow-admission"; + +const repoRoot = fileURLToPath(new URL("../..", import.meta.url)); +const outputJsonPath = `${repoRoot}/examples/service-workflow-admission/output/latest.json`; +const outputMarkdownPath = `${repoRoot}/examples/service-workflow-admission/output/latest.md`; + +describe("service workflow admission example", () => { + it("emits admission/readback context separately from fresh x402 clearance", async () => { + const proc = Bun.spawn([process.execPath, "run", "./examples/service-workflow-admission/run.ts"], { + cwd: repoRoot, + stdout: "pipe", + stderr: "pipe", + }); + const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve(""); + const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve(""); + const exitCode = await proc.exited; + const stdout = await stdoutPromise; + const stderr = await stderrPromise; + + expect(stderr).toBe(""); + expect(exitCode).toBe(0); + expect(stdout).toContain("# Service Workflow Admission Example"); + expect(stdout).toContain("Wrote: examples/service-workflow-admission/output/latest.md"); + expect(stdout).toContain("Wrote: examples/service-workflow-admission/output/latest.json"); + + const output = await Bun.file(outputJsonPath).json(); + const markdown = await Bun.file(outputMarkdownPath).text(); + const admission = ServiceWorkflowAdmissionSchema.parse(output.admissionPacket); + const handle = ServiceWorkflowHandleSchema.parse(output.workflowHandle); + + expect(output).toMatchObject({ + schemaVersion: "handshake.demo.service-workflow-admission.v1", + command: "npm run demo:service-workflow-admission", + proofBoundary: "local_source_owned_product_surface", + admissionReadback: { + policyDecisionRef: null, + greenlightRef: null, + gatewayCheckRef: null, + mutationAttemptRef: null, + receiptRef: null, + authorityCertificateRef: null, + nextActionRequirement: "fresh_action_contract_required", + }, + freshClearanceRequest: { + actionClass: "x402_payment.exact", + contextAuthorityCreated: false, + freshActionContractRequired: true, + }, + freshClearanceAuthorityPath: { + actionClass: "x402_payment.exact", + policyDecision: "greenlight", + gateDecision: "passed", + replayDecision: "refused", + replayReasonCode: "already_consumed", + changedParameterDecision: "refused", + changedParameterReasonCode: "params_mismatch", + }, + }); + expect(admission.authorityBoundary).toMatchObject({ + createsAuthority: false, + createsPolicyDecision: false, + createsGreenlight: false, + performsGatewayCheck: false, + permitsMutation: false, + exportsReceipt: false, + mintsTerminalCertificate: false, + containsCredentialMaterial: false, + containsPaymentMaterial: false, + freshActionContractRequired: true, + }); + expect(handle.authorityBoundary).toEqual(admission.authorityBoundary); + expect(handle.allowedUse).toBe("correlation_and_readback_context_only"); + expect(handle.nextProtectedActionRequirement).toBe("fresh_action_contract_required"); + + const admissionAndHandleText = JSON.stringify({ + admissionPacket: output.admissionPacket, + admissionReadback: output.admissionReadback, + workflowHandle: output.workflowHandle, + }); + for (const forbidden of ["PaymentPayload", "PAYMENT-SIGNATURE", "rawCredentialMaterial", "privateKey"]) { + expect(admissionAndHandleText).not.toContain(forbidden); + } + expect(output.evidenceSeparation.admissionEvidenceRefs).toEqual(["evidence:passport-package:x402-demo-agent"]); + expect(output.evidenceSeparation.protectedActionOutcomeRefs.length).toBeGreaterThan(0); + expect(output.evidenceSeparation.protectedActionRefusalRefs.length).toBeGreaterThan(0); + + for (const nonClaim of [ + "hosted operation", + "provider custody", + "settlement finality", + "broad x402 compatibility", + "host-wide containment", + "reusable passport authority", + "handle-as-permission", + ]) { + expect(output.nonClaims).toContain(nonClaim); + expect(markdown).toContain(nonClaim); + } + expect(markdown.toLowerCase()).toContain("admission readback is not receipt evidence"); + expect(markdown).toContain("The handle is not permission"); + expect(markdown).toContain("ActionContract -> PolicyDecision ->"); + + const source = readFileSync(`${repoRoot}/examples/service-workflow-admission/run.ts`, "utf8"); + expect(source).not.toContain("HandshakeKernel"); + expect(source).not.toContain("PolicyClient"); + expect(source).not.toContain("runX402WalletGateway"); + expect(source).not.toContain('from "../../src/runtime"'); + }); +}); From 539947d0d235682c04f63ed3dc19c876bc3a5de8 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:47:01 +0800 Subject: [PATCH 006/144] Add service workflow misuse gates --- .planning/macro-plan/EVIDENCE-PLAN.md | 20 +- .planning/macro-plan/TASKS.jsonl | 2 +- .../validation.md | 20 ++ examples/service-workflow-admission/README.md | 5 + examples/service-workflow-admission/run.ts | 62 +++++++ .../service-workflow-admission.test.ts | 171 ++++++++++++++++-- test/runtime/runtime-ingress.test.ts | 130 +++++++++++++ 7 files changed, 390 insertions(+), 20 deletions(-) diff --git a/.planning/macro-plan/EVIDENCE-PLAN.md b/.planning/macro-plan/EVIDENCE-PLAN.md index fe1d0ff..a440896 100644 --- a/.planning/macro-plan/EVIDENCE-PLAN.md +++ b/.planning/macro-plan/EVIDENCE-PLAN.md @@ -2,7 +2,14 @@ ## Current Evidence -The plan is grounded in canonical docs, the current macro map, and current codebase maps. Canon proves the authority chain and product-surface boundary. The macro map proves lens convergence around non-authority product simplification. The codebase maps identify source placement, tests, and proof gaps. Source implementation is still required for the new service workflow surface. +The plan is grounded in canonical docs, the current macro map, and current +codebase maps. Canon proves the authority chain and product-surface boundary. +The macro map proves lens convergence around non-authority product +simplification. The codebase maps identify source placement, tests, and proof +gaps. Tier 1 source implementation now owns the service workflow story, +non-authority admission/handle schemas, and boundary tests. Tier 2 source +implementation now owns active CLI/MCP/SDK posture alignment, the runnable local +service workflow admission example, and generated-agent/runtime misuse gates. Current structural validation result: @@ -43,6 +50,13 @@ npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/ Tier 2 example and integration verification will use a new focused product test plus existing x402/auth.md gateway tests when those surfaces are touched. +T2-03 generated-agent/runtime misuse verification: + +```bash +npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/runtime/runtime-ingress.test.ts +``` + Full closeout: ```bash @@ -125,7 +139,9 @@ No browser or visual evidence is required for the first Tier 1 implementation be Runtime artifacts to collect during Tier 2: -- runtime ingress negative cases; +- runtime ingress negative cases for dynamic/stale handle-context refusal; +- runtime ingress loop/retry cases proving handle evidence does not become + aggregate spend authority; - MCP proposal/readback output; - host profile posture rows; - raw sibling bypass inventory; diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index bc4048a..449f3db 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -5,6 +5,6 @@ {"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"completed","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} {"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"completed","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} {"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"completed","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} -{"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} +{"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"completed","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} {"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"open","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} {"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"open","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md index 07e24c3..61a2d1b 100644 --- a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -79,3 +79,23 @@ git diff --check ``` Open next slice: MPLAN-008 / T2-03 generated-agent and runtime misuse tests. + +T2-03 landed generated-agent and runtime misuse gates. The local service +workflow admission artifact now emits explicit non-authority misuse posture for +loop/retry handle reuse, changed parameters, dynamic tool construction, stale +rendered review, raw sibling x402 bypass, replay, and proof-gap cases. Runtime +ingress tests tie service workflow handle evidence to x402 stale/dynamic +refusal and loop/retry attempts while preserving fresh per-call action +contracts and no policy, greenlight, gateway check, signer, mutation, receipt, +or certificate records. Verified gates: + +```bash +npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/runtime/runtime-ingress.test.ts +npm run check:types +npm run quality:architecture +npm run quality:claims +npm run format:check +``` + +Open next slice: MPLAN-009 / T2-04 protected-action fixture gate. diff --git a/examples/service-workflow-admission/README.md b/examples/service-workflow-admission/README.md index 30e5551..323a118 100644 --- a/examples/service-workflow-admission/README.md +++ b/examples/service-workflow-admission/README.md @@ -39,6 +39,9 @@ workflow admission. - The workflow handle is not permission. - x402 clearance appears only in the fresh protected-action path: `ActionContract -> PolicyDecision -> one-use Greenlight -> GatewayCheck`. +- The generated-agent misuse posture lists loop/retry reuse, changed + parameters, dynamic tool construction, stale review, raw sibling bypass, + replay, and proof-gap cases as non-authority outcomes. ## What This Does Not Prove @@ -49,3 +52,5 @@ workflow admission. - No host-wide containment. - No reusable passport authority. - No handle-as-permission. +- No auth, policy, gateway admission, signer access, payment approval, receipt + evidence, or reusable clearance from admission or handle records. diff --git a/examples/service-workflow-admission/run.ts b/examples/service-workflow-admission/run.ts index 8dabfbb..6604d2e 100644 --- a/examples/service-workflow-admission/run.ts +++ b/examples/service-workflow-admission/run.ts @@ -145,6 +145,57 @@ const output = { protectedActionProofGapRefs: stringArrayField(evidencePosture, "proofGapRefs"), protectedActionRefusalRefs: stringArrayField(evidencePosture, "refusalRefs"), }, + generatedAgentMisusePosture: [ + { + scenario: "handle_reuse_in_loop", + generatedShape: "agent loop carries the same service workflow handle into another x402 attempt", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + resultingPosture: "separate_action_contract_or_refusal_required", + }, + { + scenario: "retry_after_changed_parameters", + generatedShape: "agent retries with changed amount, endpoint, payee, or request body after the handle was issued", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + resultingPosture: "changed_parameter_refusal_or_new_exact_contract_required", + }, + { + scenario: "dynamic_tool_construction", + generatedShape: "agent constructs a protected tool name or x402 endpoint dynamically from handle context", + expectedBoundary: "runtime_refusal_or_proof_gap", + acceptedAsAuthority: false, + resultingPosture: "recraft_request_before_contract", + }, + { + scenario: "stale_rendered_review", + generatedShape: "agent acts from a rendered review whose underlying protected-action parameters drifted", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + resultingPosture: "stale_review_cannot_authorize_changed_parameters", + }, + { + scenario: "raw_sibling_x402_bypass", + generatedShape: "agent calls direct MCP, browser, network, or x402 payment route outside the gateway", + expectedBoundary: "bypass_evidence_only", + acceptedAsAuthority: false, + resultingPosture: "stop_or_isolate_until_recovered", + }, + { + scenario: "replay_after_greenlight", + generatedShape: "agent reuses a prior greenlight or payment attempt after the handle stays valid", + expectedBoundary: "one_use_greenlight_only", + acceptedAsAuthority: false, + resultingPosture: "replay_refusal", + }, + { + scenario: "admission_proof_gap", + generatedShape: "agent treats accepted admission with proof gaps as clearance", + expectedBoundary: "proof_gap_not_authority", + acceptedAsAuthority: false, + resultingPosture: "fresh_action_contract_required_after_gap_resolution_or_refusal", + }, + ], authorityAudit: { passportCreatedAuthority: false, admissionCreatedAuthority: false, @@ -288,6 +339,17 @@ only. | Protected-action proof gaps | ${report.evidenceSeparation.protectedActionProofGapRefs.map((ref) => `\`${ref}\``).join(", ") || "none"} | | Protected-action refusals | ${report.evidenceSeparation.protectedActionRefusalRefs.map((ref) => `\`${ref}\``).join(", ")} | +## Generated-Agent Misuse Posture + +| Scenario | Boundary | Authority accepted | Resulting posture | +| --- | --- | --- | --- | +${report.generatedAgentMisusePosture + .map( + (item) => + `| \`${item.scenario}\` | \`${item.expectedBoundary}\` | \`${item.acceptedAsAuthority}\` | \`${item.resultingPosture}\` |`, + ) + .join("\n")} + ## Non-Claims ${report.nonClaims.map((claim) => `- ${claim}`).join("\n")} diff --git a/test/product/service-workflow-admission.test.ts b/test/product/service-workflow-admission.test.ts index 46ecf0d..043ae5e 100644 --- a/test/product/service-workflow-admission.test.ts +++ b/test/product/service-workflow-admission.test.ts @@ -12,25 +12,12 @@ const outputMarkdownPath = `${repoRoot}/examples/service-workflow-admission/outp describe("service workflow admission example", () => { it("emits admission/readback context separately from fresh x402 clearance", async () => { - const proc = Bun.spawn([process.execPath, "run", "./examples/service-workflow-admission/run.ts"], { - cwd: repoRoot, - stdout: "pipe", - stderr: "pipe", - }); - const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve(""); - const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve(""); - const exitCode = await proc.exited; - const stdout = await stdoutPromise; - const stderr = await stderrPromise; - - expect(stderr).toBe(""); - expect(exitCode).toBe(0); + const { output, markdown, source, stdout } = await runServiceWorkflowAdmissionDemo(); + expect(stdout).toContain("# Service Workflow Admission Example"); expect(stdout).toContain("Wrote: examples/service-workflow-admission/output/latest.md"); expect(stdout).toContain("Wrote: examples/service-workflow-admission/output/latest.json"); - const output = await Bun.file(outputJsonPath).json(); - const markdown = await Bun.file(outputMarkdownPath).text(); const admission = ServiceWorkflowAdmissionSchema.parse(output.admissionPacket); const handle = ServiceWorkflowHandleSchema.parse(output.workflowHandle); @@ -105,11 +92,161 @@ describe("service workflow admission example", () => { expect(markdown.toLowerCase()).toContain("admission readback is not receipt evidence"); expect(markdown).toContain("The handle is not permission"); expect(markdown).toContain("ActionContract -> PolicyDecision ->"); - - const source = readFileSync(`${repoRoot}/examples/service-workflow-admission/run.ts`, "utf8"); expect(source).not.toContain("HandshakeKernel"); expect(source).not.toContain("PolicyClient"); expect(source).not.toContain("runX402WalletGateway"); expect(source).not.toContain('from "../../src/runtime"'); }); + + it("keeps workflow handles unusable as protected-action authority under generated-agent misuse shapes", async () => { + const { output, markdown } = await runServiceWorkflowAdmissionDemo(); + const admission = ServiceWorkflowAdmissionSchema.parse(output.admissionPacket); + const handle = ServiceWorkflowHandleSchema.parse(output.workflowHandle); + + expect(handle.allowedUse).toBe("correlation_and_readback_context_only"); + expect(handle.nextProtectedActionRequirement).toBe("fresh_action_contract_required"); + expect(handle.authorityBoundary).toMatchObject({ + createsAuthority: false, + createsPolicyDecision: false, + createsGreenlight: false, + performsGatewayCheck: false, + permitsMutation: false, + exportsReceipt: false, + mintsTerminalCertificate: false, + isReusableAuth: false, + isGatewayBinding: false, + freshActionContractRequired: true, + }); + expect(output.freshClearanceRequest).toMatchObject({ + contextAuthorityCreated: false, + freshActionContractRequired: true, + }); + expect(Object.keys(output.freshClearanceRequest.contextRefs).sort()).toEqual( + [ + "admissionId", + "passportPackageDigest", + "passportPresentationId", + "serviceWorkflowHandleDigest", + "serviceWorkflowHandleId", + ].sort(), + ); + + const admissionAndHandleText = JSON.stringify({ + admissionPacket: output.admissionPacket, + workflowHandle: output.workflowHandle, + }); + for (const authorityField of [ + "policyDecisionRef", + "greenlightRef", + "gatewayCheckRef", + "mutationAttemptRef", + "receiptRef", + "authorityCertificateRef", + "signerRef", + "credentialRef", + "PaymentPayload", + "PAYMENT-SIGNATURE", + "gatewayCredentialBinding", + "delegatedAuthorityBinding", + "reusableClearance", + ]) { + expect(admissionAndHandleText).not.toContain(authorityField); + } + + for (const protectedActionAuthorityRef of [ + output.freshClearanceAuthorityPath.actionContractId, + output.freshClearanceAuthorityPath.policyDecisionId, + output.freshClearanceAuthorityPath.greenlightId, + output.freshClearanceAuthorityPath.gateAttemptId, + output.freshClearanceAuthorityPath.receiptId, + ]) { + expect(admissionAndHandleText).not.toContain(protectedActionAuthorityRef); + } + + expect(admission.runtimePosture).toEqual([ + expect.objectContaining({ + rawSiblingBypassPostureRef: "bypass-posture:x402-raw-sibling", + nativeContainmentClaimed: false, + proofGapRefs: ["proof-gap:host-wide-containment"], + }), + ]); + expect(output.admissionReadback).toMatchObject({ + policyDecisionRef: null, + greenlightRef: null, + gatewayCheckRef: null, + mutationAttemptRef: null, + receiptRef: null, + authorityCertificateRef: null, + nextActionRequirement: "fresh_action_contract_required", + }); + + expect(output.generatedAgentMisusePosture).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + scenario: "handle_reuse_in_loop", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "retry_after_changed_parameters", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "dynamic_tool_construction", + expectedBoundary: "runtime_refusal_or_proof_gap", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "stale_rendered_review", + expectedBoundary: "fresh_action_contract_required", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "raw_sibling_x402_bypass", + expectedBoundary: "bypass_evidence_only", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "replay_after_greenlight", + expectedBoundary: "one_use_greenlight_only", + acceptedAsAuthority: false, + }), + expect.objectContaining({ + scenario: "admission_proof_gap", + expectedBoundary: "proof_gap_not_authority", + acceptedAsAuthority: false, + }), + ]), + ); + for (const item of output.generatedAgentMisusePosture) { + expect(item.acceptedAsAuthority).toBe(false); + } + expect(markdown).toContain("Generated-Agent Misuse Posture"); + expect(markdown).toContain("dynamic_tool_construction"); + expect(markdown).toContain("raw_sibling_x402_bypass"); + }); }); + +async function runServiceWorkflowAdmissionDemo() { + const proc = Bun.spawn([process.execPath, "run", "./examples/service-workflow-admission/run.ts"], { + cwd: repoRoot, + stdout: "pipe", + stderr: "pipe", + }); + const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve(""); + const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve(""); + const exitCode = await proc.exited; + const stdout = await stdoutPromise; + const stderr = await stderrPromise; + + expect(stderr).toBe(""); + expect(exitCode).toBe(0); + + return { + stdout, + output: await Bun.file(outputJsonPath).json(), + markdown: await Bun.file(outputMarkdownPath).text(), + source: readFileSync(`${repoRoot}/examples/service-workflow-admission/run.ts`, "utf8"), + }; +} diff --git a/test/runtime/runtime-ingress.test.ts b/test/runtime/runtime-ingress.test.ts index 48d63a7..185e5f5 100644 --- a/test/runtime/runtime-ingress.test.ts +++ b/test/runtime/runtime-ingress.test.ts @@ -608,6 +608,66 @@ describe("runtime ingress adapter", () => { await expectNoRuntimeAuthorityRecords(fixture.store); }); + it("refuses stale or dynamic x402 handle context before protected-action authority", async () => { + const { fixture, runtimeConfig, proposal } = await installedX402IngressFixture(); + const handleEvidenceRef = "service-workflow-handle:x402-demo:001"; + const staleReviewRef = "review:stale-rendered-plan:x402-demo"; + + const result = await proposeRuntimeIngressActionContracts( + fixture.kernel, + { x402Payment: runtimeConfig }, + { + principalIntentRef: "intent:pay from stale service workflow review", + generatedCodeOrSpecRef: "runtime:dispatch-block-x402-stale-handle", + dispatchBoundaryRef: "dispatch-boundary:x402-stale-handle", + dispatches: [ + { + dispatchKind: "wrapped_x402_payment", + dispatchRef: "dispatch:x402-payment:stale-handle", + endpointUrl: proposal.endpointEvidence.endpointUrl, + payee: proposal.endpointEvidence.payee, + network: proposal.endpointEvidence.network, + token: proposal.endpointEvidence.token, + atomicAmount: "2000", + paymentRequirementsDigest: proposal.endpointEvidence.paymentRequirementsDigest, + dynamicToolConstructionDetected: true, + lateBoundParameterRefs: [handleEvidenceRef, staleReviewRef], + evidenceRefs: [handleEvidenceRef, staleReviewRef], + }, + ], + }, + ); + + expect(result.outcome).toBe("one_or_more_dispatches_refused"); + expect(result.responsePosture).toMatchObject({ + authorityCreated: false, + credentialMaterialIncluded: false, + greenlightCreated: false, + gatewayCheckPerformed: false, + mutationAttempted: false, + mutationCommandIncluded: false, + actionContractRefs: [], + nextAction: "recraft_request", + }); + expect(result.runtimeExecution.evidenceRefs).toEqual(expect.arrayContaining([handleEvidenceRef, staleReviewRef])); + expect(result.runtimeExecution.unobservedRegionRefs).toEqual([handleEvidenceRef, staleReviewRef]); + expect(result.generatedExecutionGraph.coverageStatus).toBe("unsupported_or_ambiguous"); + expect(result.generatedExecutionGraph.nodes[0]?.unsupportedReasonCodes).toEqual( + expect.arrayContaining(["runtime_ingress_dynamic_tool_construction", "runtime_ingress_late_bound_parameters"]), + ); + const proposalResult = result.proposals[0]; + if (!proposalResult || proposalResult.outcome !== "intent_compilation_refused") throw new Error("expected refusal"); + expect(proposalResult.refusalReasonCodes).toEqual( + expect.arrayContaining([ + "runtime_dynamic_tool_construction_detected", + "runtime_unobserved_regions_present", + "generated_execution_graph_not_contractable", + ]), + ); + expect(await recordCount(fixture.store, "action_contract")).toBe(0); + await expectNoRuntimeAuthorityRecords(fixture.store); + }); + it("refuses ambiguous x402 payment dispatch as unknown consequential behavior", async () => { const { fixture, runtimeConfig, proposal } = await installedX402IngressFixture(); @@ -759,6 +819,76 @@ describe("runtime ingress adapter", () => { await expectNoRuntimeAuthorityRecords(fixture.store); }); + it("records handle-context x402 retries as separate fresh contracts without aggregate spend authority", async () => { + const { fixture, runtimeConfig, proposal } = await installedX402IngressFixture(); + const handleEvidenceRef = "service-workflow-handle:x402-demo:001"; + const handleDigestRef = "service-workflow-handle-digest:sha256:2222222222222222"; + + const result = await proposeRuntimeIngressActionContracts( + fixture.kernel, + { x402Payment: runtimeConfig }, + { + principalIntentRef: "intent:retry paid request from service workflow context", + generatedCodeOrSpecRef: "runtime:dispatch-block-x402-handle-context-retry", + dispatchBoundaryRef: "dispatch-boundary:x402-handle-context-retry", + dispatches: [ + x402Dispatch(proposal, "dispatch:x402-payment:handle-context-1", { + atomicAmount: "2000", + evidenceRefs: [handleEvidenceRef, handleDigestRef], + }), + x402Dispatch(proposal, "dispatch:x402-payment:handle-context-2", { + atomicAmount: "2500", + evidenceRefs: [handleEvidenceRef, handleDigestRef], + retryOfDispatchRef: "dispatch:x402-payment:handle-context-1", + loopIteration: 1, + }), + ], + }, + ); + + expect(result.outcome).toBe("action_contracts_proposed"); + expect(result.responsePosture).toMatchObject({ + authorityCreated: false, + credentialMaterialIncluded: false, + greenlightCreated: false, + gatewayCheckPerformed: false, + mutationAttempted: false, + mutationCommandIncluded: false, + receiptExportCreated: false, + }); + expect(result.runtimeExecution.evidenceRefs).toEqual(expect.arrayContaining([handleEvidenceRef, handleDigestRef])); + expect(result.runtimeExecution.loopDetected).toBe(true); + expect(result.runtimeExecution.retryDetected).toBe(true); + expect(result.responsePosture.reasonCodes).toEqual( + expect.arrayContaining(["runtime_ingress_loop_detected", "runtime_ingress_retry_detected"]), + ); + const first = result.proposals[0]?.actionContract; + const second = result.proposals[1]?.actionContract; + if (!first || !second) throw new Error("expected two x402 contracts"); + expect(first.parameters).toMatchObject({ atomicAmount: "2000" }); + expect(second.parameters).toMatchObject({ atomicAmount: "2500" }); + expect(first.actionContractId).not.toBe(second.actionContractId); + expect(first.idempotencyKey).not.toBe(second.idempotencyKey); + expect(second.requiredPriorActionContractIds).toEqual([first.actionContractId]); + const contractAuthorityText = JSON.stringify({ + firstParameters: first.parameters, + firstBounds: first.bounds, + firstGatewayCredentialRefs: first.gatewayCredentialRefs, + firstDelegatedAuthorityRefs: first.delegatedAuthorityRefs, + secondParameters: second.parameters, + secondBounds: second.bounds, + secondGatewayCredentialRefs: second.gatewayCredentialRefs, + secondDelegatedAuthorityRefs: second.delegatedAuthorityRefs, + }); + expect(contractAuthorityText).not.toContain(handleEvidenceRef); + expect(contractAuthorityText).not.toContain(handleDigestRef); + expect(contractAuthorityText).not.toContain("PaymentPayload"); + expect(contractAuthorityText).not.toContain("PAYMENT-SIGNATURE"); + expect(contractAuthorityText).not.toContain("privateKey"); + expect(await recordCount(fixture.store, "action_contract")).toBe(2); + await expectNoRuntimeAuthorityRecords(fixture.store); + }); + it("records branched x402 dispatches as separate candidates without aggregate spend authority", async () => { const { fixture, runtimeConfig, proposal } = await installedX402IngressFixture(); From 0125173a0d9af504c84cb665029de249cc86b4fc Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:52:14 +0800 Subject: [PATCH 007/144] Gate service workflow protected action fixture --- .planning/macro-plan/EVIDENCE-PLAN.md | 11 +++ .planning/macro-plan/EXECUTION-SLICES.md | 2 +- .../macro-plan/PROTECTED-ACTION-GATES.md | 10 ++ .planning/macro-plan/TASKS.jsonl | 2 +- .../validation.md | 16 ++++ examples/service-workflow-admission/README.md | 3 + examples/service-workflow-admission/run.ts | 74 +++++++++++++++ .../service-workflow-admission.test.ts | 93 +++++++++++++++++++ 8 files changed, 209 insertions(+), 2 deletions(-) diff --git a/.planning/macro-plan/EVIDENCE-PLAN.md b/.planning/macro-plan/EVIDENCE-PLAN.md index a440896..0964217 100644 --- a/.planning/macro-plan/EVIDENCE-PLAN.md +++ b/.planning/macro-plan/EVIDENCE-PLAN.md @@ -57,6 +57,13 @@ npm run test -- test/product/service-workflow-admission.test.ts npm run test -- test/runtime/runtime-ingress.test.ts ``` +T2-04 protected-action fixture gate verification: + +```bash +npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts +``` + Full closeout: ```bash @@ -142,6 +149,10 @@ Runtime artifacts to collect during Tier 2: - runtime ingress negative cases for dynamic/stale handle-context refusal; - runtime ingress loop/retry cases proving handle evidence does not become aggregate spend authority; +- service workflow fixture gate proving handle context feeds one fresh + `x402_payment.exact` path without carrying payment material; +- auth.md provenance/proof-gap posture showing no composite credential plus + spend authority artifact; - MCP proposal/readback output; - host profile posture rows; - raw sibling bypass inventory; diff --git a/.planning/macro-plan/EXECUTION-SLICES.md b/.planning/macro-plan/EXECUTION-SLICES.md index ff942ec..9417679 100644 --- a/.planning/macro-plan/EXECUTION-SLICES.md +++ b/.planning/macro-plan/EXECUTION-SLICES.md @@ -559,7 +559,7 @@ The first fixture that connects service workflow admission to a protected action ### Objective -Connect one admitted workflow context to one fresh buyer-side `x402_payment.exact` action request, preserving auth.md as provenance if included and x402 as one exact per-call protected action. +Connect one admitted workflow context to one fresh buyer-side `x402_payment.exact` action request. Record auth.md as provenance/proof-gap only; do not compose auth.md credential authority with x402 spend authority in this fixture. ### Source Evidence diff --git a/.planning/macro-plan/PROTECTED-ACTION-GATES.md b/.planning/macro-plan/PROTECTED-ACTION-GATES.md index cb93019..fcc7c47 100644 --- a/.planning/macro-plan/PROTECTED-ACTION-GATES.md +++ b/.planning/macro-plan/PROTECTED-ACTION-GATES.md @@ -36,6 +36,16 @@ serviceWorkflowHandle -> fresh x402_payment.exact action request -> ActionContra The handle is context and evidence refs only. +Non-composite rail rule: + +```text +serviceWorkflowHandle -> fresh x402_payment.exact action request +serviceWorkflowHandle -> fresh auth_md_protected_api_call.exact action request +``` + +These are separate rails. No fixture may merge x402 spend authority and auth.md +credential authority into one authority artifact. + ## Authority Boundary Authority begins at exact policy evaluation over an `ActionContract`, then proceeds to one-use greenlight/refusal and gateway check. Admission and handle surfaces must explicitly state: diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 449f3db..281fe0d 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -6,5 +6,5 @@ {"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"completed","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} {"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"completed","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} {"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"completed","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} -{"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"open","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} +{"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"completed","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} {"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"open","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md index 61a2d1b..cb6b112 100644 --- a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -99,3 +99,19 @@ npm run format:check ``` Open next slice: MPLAN-009 / T2-04 protected-action fixture gate. + +T2-04 landed the protected-action fixture gate on the service workflow +admission example. The example now proves the workflow handle is +correlation-only context for one fresh `x402_payment.exact` path, records the +fresh ActionContract, PolicyDecision, Greenlight, GatewayCheck, and Receipt +refs separately from admission/readback, and verifies payment material appears +only as gateway evidence after verified gateway check. auth.md is explicitly +recorded as provenance/proof-gap posture only, not a composite credential plus +spend authority artifact. Verified gates: + +```bash +npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts +``` + +Open next slice: MPLAN-010 / T2-05 Tier 3 lock and final release gate. diff --git a/examples/service-workflow-admission/README.md b/examples/service-workflow-admission/README.md index 323a118..aac4146 100644 --- a/examples/service-workflow-admission/README.md +++ b/examples/service-workflow-admission/README.md @@ -42,6 +42,8 @@ workflow admission. - The generated-agent misuse posture lists loop/retry reuse, changed parameters, dynamic tool construction, stale review, raw sibling bypass, replay, and proof-gap cases as non-authority outcomes. +- auth.md is recorded as provenance or proof-gap posture only; it is not + composed with x402 spend into one fixture authority. ## What This Does Not Prove @@ -54,3 +56,4 @@ workflow admission. - No handle-as-permission. - No auth, policy, gateway admission, signer access, payment approval, receipt evidence, or reusable clearance from admission or handle records. +- No composite auth.md plus x402 authority artifact. diff --git a/examples/service-workflow-admission/run.ts b/examples/service-workflow-admission/run.ts index 6604d2e..083ffaa 100644 --- a/examples/service-workflow-admission/run.ts +++ b/examples/service-workflow-admission/run.ts @@ -22,7 +22,11 @@ const x402Output = asRecord(await Bun.file(x402OutputPath).json(), "x402 output" const x402Report = asRecord(x402Output.report, "x402 report"); const protectedAction = asRecord(x402Report.protectedAction, "x402 protectedAction"); const authorityPath = asRecord(x402Report.authorityPath, "x402 authorityPath"); +const actorsAndCustody = asRecord(x402Report.actorsAndCustody, "x402 actorsAndCustody"); const evidencePosture = asRecord(x402Report.evidencePosture, "x402 evidencePosture"); +const challengePhaseEvidence = phaseEvidence(x402Output, "0_sandbox_payment_required_challenge"); +const runtimeProposalPhaseEvidence = phaseEvidence(x402Output, "2_runtime_proposal"); +const gatewaySignaturePhaseEvidence = phaseEvidence(x402Output, "4_gateway_admission_and_signature"); const workflowHandle = ServiceWorkflowHandleSchema.parse({ schemaVersion: serviceWorkflowAdmissionSchemaVersion, @@ -138,6 +142,40 @@ const output = { replayDecision: stringField(authorityPath, "replayDecision"), replayReasonCode: stringField(authorityPath, "replayReasonCode"), }, + protectedActionFixtureGate: { + serviceWorkflowContextRole: "correlation_context_only", + contextAuthorityCreated: false, + freshActionContractRequired: true, + freshActionContractId: stringField(authorityPath, "actionContractId"), + policyDecisionId: stringField(authorityPath, "policyDecisionId"), + greenlightId: stringField(authorityPath, "greenlightId"), + gatewayCheckAttemptId: stringField(authorityPath, "gateAttemptId"), + receiptId: stringField(authorityPath, "receiptId"), + admissionReadbackReceiptRef: null, + paymentMaterialBoundary: { + admissionOrHandlePaymentMaterialIncluded: false, + runtimeCredentialMaterialVisible: stringField(runtimeProposalPhaseEvidence, "credentialMaterialVisibleToRuntime"), + signedRetryCountBeforeGateway: numberField(challengePhaseEvidence, "signedRetryCountBeforeGateway"), + signerInvocationBoundary: stringField(actorsAndCustody, "signerInvocationBoundary"), + paymentSignatureHeaderRef: nullableStringField(gatewaySignaturePhaseEvidence, "paymentSignatureHeaderRef"), + paymentPayloadRef: nullableStringField(gatewaySignaturePhaseEvidence, "paymentPayloadRef"), + paymentMaterialCreatedOnlyAfterVerifiedGatewayCheck: true, + }, + authMdBoundary: { + includedInFixture: false, + posture: "provenance_or_proof_gap_only", + compositeAuthorityCreated: false, + proofGapRef: "proof-gap:auth-md-not-composed-into-t2-04", + }, + }, + authMdPosture: { + includedInProtectedActionFixture: false, + authorityPosture: "provenance_or_proof_gap_only", + compositeAuthorityCreated: false, + separateProtectedActionRequired: + "auth_md_protected_api_call.exact_requires_fresh_action_contract_policy_greenlight_gateway_check", + proofGapRefs: ["proof-gap:auth-md-not-composed-into-t2-04"], + }, evidenceSeparation: { admissionEvidenceRefs: admissionPacket.claimResults.flatMap((claim) => claim.evidenceRefs), admissionProofGapRefs: admissionPacket.claimResults.flatMap((claim) => claim.proofGapRefs), @@ -274,6 +312,27 @@ function stringArrayField(record: Record, key: string): string[ return value; } +function numberField(record: Record, key: string): number { + const value = record[key]; + if (typeof value !== "number") throw new Error(`${key} must be a number.`); + return value; +} + +function nullableStringField(record: Record, key: string): string | null { + const value = record[key]; + if (value === null) return null; + if (typeof value !== "string") throw new Error(`${key} must be a string or null.`); + return value; +} + +function phaseEvidence(report: Record, phaseName: string): Record { + const phases = report.phases; + if (!Array.isArray(phases)) throw new Error("x402 output phases must be an array."); + const phase = phases.find((entry) => asRecord(entry, "x402 phase").phase === phaseName); + if (!phase) throw new Error(`x402 phase not found: ${phaseName}`); + return asRecord(asRecord(phase, "x402 phase").evidence, `${phaseName} evidence`); +} + function renderMarkdown(report: typeof output): string { return `# Service Workflow Admission Example @@ -329,6 +388,21 @@ x402 clearance comes only from fresh \`ActionContract -> PolicyDecision -> one-use Greenlight -> GatewayCheck\`. The workflow handle contributes context only. +## Protected-Action Fixture Gate + +| Field | Value | +| --- | --- | +| Context role | \`${report.protectedActionFixtureGate.serviceWorkflowContextRole}\` | +| Fresh contract required | \`${report.protectedActionFixtureGate.freshActionContractRequired}\` | +| Gateway check attempt | \`${report.protectedActionFixtureGate.gatewayCheckAttemptId}\` | +| Runtime credential material visible | \`${report.protectedActionFixtureGate.paymentMaterialBoundary.runtimeCredentialMaterialVisible}\` | +| Signed retry count before gateway | \`${report.protectedActionFixtureGate.paymentMaterialBoundary.signedRetryCountBeforeGateway}\` | +| Signer boundary | \`${report.protectedActionFixtureGate.paymentMaterialBoundary.signerInvocationBoundary}\` | +| Payment material after gateway only | \`${report.protectedActionFixtureGate.paymentMaterialBoundary.paymentMaterialCreatedOnlyAfterVerifiedGatewayCheck}\` | +| auth.md composite authority created | \`${report.protectedActionFixtureGate.authMdBoundary.compositeAuthorityCreated}\` | +| auth.md posture | \`${report.authMdPosture.authorityPosture}\` | +| auth.md separate action required | \`${report.authMdPosture.separateProtectedActionRequired}\` | + ## Evidence Separation | Evidence class | Refs | diff --git a/test/product/service-workflow-admission.test.ts b/test/product/service-workflow-admission.test.ts index 043ae5e..0ca5227 100644 --- a/test/product/service-workflow-admission.test.ts +++ b/test/product/service-workflow-admission.test.ts @@ -226,6 +226,99 @@ describe("service workflow admission example", () => { expect(markdown).toContain("dynamic_tool_construction"); expect(markdown).toContain("raw_sibling_x402_bypass"); }); + + it("gates the x402 fixture behind fresh clearance without leaking payment or auth.md authority", async () => { + const { output, markdown } = await runServiceWorkflowAdmissionDemo(); + const admission = ServiceWorkflowAdmissionSchema.parse(output.admissionPacket); + const handle = ServiceWorkflowHandleSchema.parse(output.workflowHandle); + + expect(output.protectedActionFixtureGate).toMatchObject({ + serviceWorkflowContextRole: "correlation_context_only", + contextAuthorityCreated: false, + freshActionContractRequired: true, + freshActionContractId: output.freshClearanceAuthorityPath.actionContractId, + policyDecisionId: output.freshClearanceAuthorityPath.policyDecisionId, + greenlightId: output.freshClearanceAuthorityPath.greenlightId, + gatewayCheckAttemptId: output.freshClearanceAuthorityPath.gateAttemptId, + receiptId: output.freshClearanceAuthorityPath.receiptId, + admissionReadbackReceiptRef: null, + paymentMaterialBoundary: { + admissionOrHandlePaymentMaterialIncluded: false, + runtimeCredentialMaterialVisible: "absent", + signedRetryCountBeforeGateway: 0, + signerInvocationBoundary: "after_verified_gateway_check_only", + paymentMaterialCreatedOnlyAfterVerifiedGatewayCheck: true, + }, + authMdBoundary: { + includedInFixture: false, + posture: "provenance_or_proof_gap_only", + compositeAuthorityCreated: false, + proofGapRef: "proof-gap:auth-md-not-composed-into-t2-04", + }, + }); + expect(output.protectedActionFixtureGate.paymentMaterialBoundary.paymentSignatureHeaderRef).toStartWith( + "credential:x402-payment-signature:", + ); + expect(output.protectedActionFixtureGate.paymentMaterialBoundary.paymentPayloadRef).toStartWith( + "credential:x402-payment-payload:", + ); + expect(output.authMdPosture).toEqual({ + includedInProtectedActionFixture: false, + authorityPosture: "provenance_or_proof_gap_only", + compositeAuthorityCreated: false, + separateProtectedActionRequired: + "auth_md_protected_api_call.exact_requires_fresh_action_contract_policy_greenlight_gateway_check", + proofGapRefs: ["proof-gap:auth-md-not-composed-into-t2-04"], + }); + + const admissionHandleAndReadbackText = JSON.stringify({ + admission, + handle, + admissionReadback: output.admissionReadback, + freshClearanceRequest: output.freshClearanceRequest, + }); + for (const forbidden of [ + output.protectedActionFixtureGate.paymentMaterialBoundary.paymentSignatureHeaderRef, + output.protectedActionFixtureGate.paymentMaterialBoundary.paymentPayloadRef, + "PaymentPayload", + "PAYMENT-SIGNATURE", + "auth_md_access_token", + "rawCredentialMaterial", + "privateKey", + ]) { + expect(admissionHandleAndReadbackText).not.toContain(forbidden); + } + const authMdPostureText = JSON.stringify(output.authMdPosture); + for (const forbidden of [ + "credentialRef", + "gatewayCredentialRefId", + "policyDecisionRef", + "greenlightRef", + "gatewayCheckRef", + "receiptRef", + "rawCredentialMaterial", + ]) { + expect(authMdPostureText).not.toContain(forbidden); + } + expect(output.freshClearanceRequest.contextRefs).toEqual({ + passportPackageDigest: handle.passportPackageDigest, + passportPresentationId: handle.passportPresentationId, + admissionId: handle.admissionId, + serviceWorkflowHandleId: handle.serviceWorkflowHandleId, + serviceWorkflowHandleDigest: handle.serviceWorkflowHandleDigest, + }); + expect(output.freshClearanceAuthorityPath).toMatchObject({ + actionClass: "x402_payment.exact", + policyDecision: "greenlight", + gateDecision: "passed", + changedParameterDecision: "refused", + changedParameterReasonCode: "params_mismatch", + replayDecision: "refused", + replayReasonCode: "already_consumed", + }); + expect(markdown).toContain("Protected-Action Fixture Gate"); + expect(markdown).toContain("auth.md composite authority created"); + }); }); async function runServiceWorkflowAdmissionDemo() { From ab382f7ff7890c57d3edd2751b1cd5a673a1c94a Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 18:59:07 +0800 Subject: [PATCH 008/144] Install hosted admission lock --- .planning/macro-plan/AGENT-HANDOFF.md | 30 ++++++++++++------- .planning/macro-plan/EVIDENCE-PLAN.md | 10 +++++++ .planning/macro-plan/TASKS.jsonl | 2 +- .../validation.md | 18 +++++++++++ README.md | 9 ++++++ docs/internal/decisions.md | 26 ++++++++++++++++ docs/internal/protocol-notes.md | 7 +++++ test/architecture/claim-boundary.test.ts | 28 +++++++++++++++++ 8 files changed, 119 insertions(+), 11 deletions(-) diff --git a/.planning/macro-plan/AGENT-HANDOFF.md b/.planning/macro-plan/AGENT-HANDOFF.md index 0dcf99c..6e8b276 100644 --- a/.planning/macro-plan/AGENT-HANDOFF.md +++ b/.planning/macro-plan/AGENT-HANDOFF.md @@ -112,11 +112,14 @@ If a gateway cannot enforce before consequence, this is advisory, not Handshake. ## Checkpoints -- After macro-plan validation: git checkpoint. -- After Tier 1 story/schema/tests pass focused gates: git checkpoint. -- After docs convergence passes claims/format checks: git checkpoint. -- After Tier 2 example/runtime gates pass: git checkpoint. -- Before any Tier 3 work: stop and report proof state. +- Macro-plan validation: committed. +- Tier 1 story/schema/tests and docs convergence: committed. +- Tier 2 active surface alignment, local example, runtime misuse gates, and + protected-action fixture gate: committed. +- Tier 3 admission lock and final release gate: committed after `npm run + check:repo`. +- Before any Tier 3 work: stop and confirm separate hosted workspace or fresh + Tier 1/Tier 2 kernel task. ## Stop Conditions @@ -148,10 +151,14 @@ Use `npm run check:repo` before claiming implementation closeout. ## Proof Gaps -- No source-owned service workflow admission schema exists yet. -- No negative tests yet prove the five non-authority IDs cannot create authority. -- No local service workflow example exists yet. -- No live provider custody, settlement, hosted operation, or native host containment is proven. +- No live provider custody, settlement, hosted operation, or native host + containment is proven. +- No marketplace/certification, cross-org trust, aggregate spend enforcement, + hosted org auth, retention/search, or hosted mutation authority is proven. +- auth.md plus x402 remains non-composite provenance/proof-gap posture unless a + future fresh action family clears its own gates. +- Tier 3 remains locked behind a separate hosted workspace or a new Tier 1/Tier + 2 kernel task with fresh proof gates. ## Non-Claims @@ -159,4 +166,7 @@ This handoff does not authorize Tier 3, hosted operation, provider custody, sett ## Next Agent Step -Implement Slice T1-01 and T1-02 together only far enough to make the boundary testable: add `docs/internal/service-workflow-story.md`, add `src/surfaces/service-workflow-admission.ts`, then add or update architecture tests so the new surface is provably non-authority. +No Tier 1/Tier 2 simplification slice remains open. If the user opens Tier 3, +start from the Tier 3 admission lock in `docs/internal/decisions.md` and route +hosted operation to a separate hosted workspace or a fresh Tier 1/Tier 2 kernel +task before changing protocol exports. diff --git a/.planning/macro-plan/EVIDENCE-PLAN.md b/.planning/macro-plan/EVIDENCE-PLAN.md index 0964217..8d7c746 100644 --- a/.planning/macro-plan/EVIDENCE-PLAN.md +++ b/.planning/macro-plan/EVIDENCE-PLAN.md @@ -64,6 +64,13 @@ npm run test -- test/product/service-workflow-admission.test.ts npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts ``` +T2-05 Tier 3 lock verification: + +```bash +npm run test -- test/architecture/claim-boundary.test.ts +npm run check:repo +``` + Full closeout: ```bash @@ -71,6 +78,8 @@ npm run format:check npm run check:repo ``` +Current full closeout status: `npm run check:repo` passes after MPLAN-010. + ## Replay And Refusal Cases Required cases: @@ -153,6 +162,7 @@ Runtime artifacts to collect during Tier 2: `x402_payment.exact` path without carrying payment material; - auth.md provenance/proof-gap posture showing no composite credential plus spend authority artifact; +- Tier 3 admission lock in canonical docs and claim-boundary tests; - MCP proposal/readback output; - host profile posture rows; - raw sibling bypass inventory; diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 281fe0d..672a5ff 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -7,4 +7,4 @@ {"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"completed","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} {"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"completed","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} {"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"completed","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} -{"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"open","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} +{"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"completed","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} diff --git a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md index cb6b112..a623dd1 100644 --- a/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md +++ b/.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md @@ -115,3 +115,21 @@ npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402- ``` Open next slice: MPLAN-010 / T2-05 Tier 3 lock and final release gate. + +T2-05 landed the Tier 3 admission lock and final release gate in canonical +docs plus claim-boundary tests. The lock states that service workflow +simplification is not a hosted-operation go-ahead, Tier 3 may consume or extend +the surface only after Tier 1/Tier 2 proof or explicit proof-gap posture, and +hosted operation or kernel-export needs must route to a separate hosted +workspace or a new Tier 1/Tier 2 kernel task with fresh proof gates. Verified +gates: + +```bash +npm run test -- test/architecture/claim-boundary.test.ts +npm run check:repo +``` + +Final status: MPLAN-001 through MPLAN-010 are complete. Tier 1/Tier 2 product +simplification is implemented and repo-gated. Tier 3 remains locked behind a +separate hosted workspace or fresh Tier 1/Tier 2 kernel task if hosted needs +require kernel changes. diff --git a/README.md b/README.md index ffd18bf..adbbbdc 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,15 @@ not gateway check, not mutation; `examples/service-workflow-admission/output/latest.md` and is admission readback plus handle context only, not clearance or authority. +Hosted admission lock: this service workflow simplification is not a +hosted-operation go-ahead. Hosted product work may consume the surface only +after the pre-hosted service workflow gates have source-owned proof or explicit +proof-gap posture. If hosted work needs hosted operation, provider custody, +settlement/finality, marketplace or certification, cross-org trust, aggregate +spend enforcement, hosted org auth, retention/search, or new kernel exports, +route it to a separate hosted workspace or a new pre-hosted kernel task. Do not +expand protocol kernel exports for hosted needs without fresh proof gates. + No adapter family defines the protocol. This package is not broad x402 compatibility, not live provider custody, hosted mutation authority, production hosted readiness, generic MCP/runtime control, host-wide containment, diff --git a/docs/internal/decisions.md b/docs/internal/decisions.md index db24fa6..46728b1 100644 --- a/docs/internal/decisions.md +++ b/docs/internal/decisions.md @@ -229,6 +229,32 @@ repo write, CI/deploy, cloud configuration, database/data-plane, marketplace, agent-management, or other protected actions remain proof contexts rather than execution-ready product surfaces. +## Hosted Admission Lock + +Accepted: pre-hosted product simplification is not a hosted-operation +go-ahead. + +Hosted product work may consume or extend the service workflow surface only +after the pre-hosted service workflow gates have source-owned proof or +explicitly accepted proof-gap posture. The current completed gates prove +non-authority admission/handle schema, active surface alignment, local example +readback, generated-agent misuse refusal, and one fresh `x402_payment.exact` +fixture gate. They do not prove hosted operation, provider/customer custody, +settlement/finality, marketplace or certification, cross-org trust, aggregate +spend enforcement, hosted org auth, retention/search, or hosted mutation +authority. + +If hosted work needs hosted operation, tenant/org auth, hosted custody, retention, +search, marketplace/certification, cross-org trust, aggregate spend, or new +protocol-kernel exports, route that work to a separate hosted workspace or a +new pre-hosted kernel task with its own generated execution shape, protected +action path, gateway authority holder, credential holder, bypass posture, +evidence path, proof-gap model, non-claims, and `npm run check:repo` proof. +That follow-on work must carry fresh proof gates. + +This checkout must not expand protocol kernel exports for hosted needs merely +because the service workflow product surface is now simpler. + ## Market And Expansion Scoring Boundary Accepted: market scoring is strategy input, not enforcement proof. A wedge can diff --git a/docs/internal/protocol-notes.md b/docs/internal/protocol-notes.md index c7088ef..19f16f3 100644 --- a/docs/internal/protocol-notes.md +++ b/docs/internal/protocol-notes.md @@ -31,6 +31,13 @@ protected-action clearance -> terminal outcome`. Passport, admission, and - Public npm availability does not create authority. MCP Registry discoverability remains a proof gap until registry acceptance and lookup are verified. +- Hosted admission lock: service workflow simplification is not a + hosted-operation go-ahead. Hosted work may consume the surface only after the + pre-hosted service workflow gates have source-owned proof or proof-gap + posture. Hosted operation, provider custody, settlement/finality, marketplace + or certification, cross-org trust, aggregate spend enforcement, hosted org + auth, retention/search, or new kernel exports require a separate hosted + workspace or a new pre-hosted kernel task with fresh proof gates. ## Required Separation diff --git a/test/architecture/claim-boundary.test.ts b/test/architecture/claim-boundary.test.ts index 78b5ded..eaeb940 100644 --- a/test/architecture/claim-boundary.test.ts +++ b/test/architecture/claim-boundary.test.ts @@ -176,6 +176,34 @@ describe("claim boundary", () => { "proof contexts rather than execution-ready product surfaces", ], }, + { + label: "hosted admission lock", + sources: [ + { name: "README.md", text: readme }, + { name: "docs/internal/decisions.md", text: decisions }, + { name: "docs/internal/protocol-notes.md", text: protocolNotes }, + ], + required: [ + "Hosted admission lock", + "not a hosted-operation go-ahead", + "pre-hosted service workflow gates", + "hosted operation", + "provider custody", + "settlement/finality", + "marketplace or certification", + "cross-org trust", + "aggregate spend enforcement", + "hosted org auth", + "retention/search", + "separate hosted workspace", + "new pre-hosted kernel task", + "fresh proof gates", + ], + forbiddenPatterns: [ + /service workflow simplification (?:creates|proves|unblocks) hosted operation/i, + /may expand protocol kernel exports for hosted needs/i, + ], + }, { label: "expansion admission criteria", sources: [ From bdcec056d710ce619e8c1746b2d784ccbc0b69d0 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 19:30:39 +0800 Subject: [PATCH 009/144] Reset architecture macro plan --- .planning/macro-plan/AGENT-HANDOFF.md | 234 +++--- .planning/macro-plan/DECISIONS.md | 196 +++-- .planning/macro-plan/EVIDENCE-PLAN.md | 226 +++--- .planning/macro-plan/EXECUTION-SLICES.md | 677 +++++------------- .planning/macro-plan/MACRO-PLAN.md | 355 +++++---- .../macro-plan/PROTECTED-ACTION-GATES.md | 225 +++--- .planning/macro-plan/README.md | 65 +- .planning/macro-plan/REVIEW-GATES.md | 129 +++- .planning/macro-plan/RISKS.md | 159 ++-- .planning/macro-plan/RUNTIME-GATES.md | 135 ++-- .planning/macro-plan/TASKS.jsonl | 16 +- .../audits/architecture-case-study-audit.md | 211 ++++++ .../audits/evidence-review-gates-audit.md | 234 ++++++ .../product-vocabulary-projection-audit.md | 198 +++++ .../protected-action-lifecycle-audit.md | 290 ++++++++ .../runtime-protected-action-gates-audit.md | 244 +++++++ .../blocked-checks.md | 30 + .../input.md | 108 +++ .../research-evidence.md | 37 + .../research.md | 66 ++ .../source-snapshot.md | 39 + .../validation.md | 35 + 22 files changed, 2557 insertions(+), 1352 deletions(-) create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/blocked-checks.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research-evidence.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/source-snapshot.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md diff --git a/.planning/macro-plan/AGENT-HANDOFF.md b/.planning/macro-plan/AGENT-HANDOFF.md index 6e8b276..3625bf7 100644 --- a/.planning/macro-plan/AGENT-HANDOFF.md +++ b/.planning/macro-plan/AGENT-HANDOFF.md @@ -2,171 +2,175 @@ ## Objective -Implement the Tier 1/Tier 2 Handshake product simplification program in order, starting with the non-authority service workflow story and surface contract. The user wants the macro plan completed first, then implementation. The first executable slice is deliberately small in code footprint but strict in proof: create the simplified product surface without creating authority. +Implement the architectural north-star correction: Handshake has one protocol +authority spine, and product vocabulary is projection/readback over that spine. +The goal is not another thin plan. It includes research, macro planning, +implementation, evaluation, sidecar review, full repo gates, and commits. ## Source Boundary -Read these first, in this order: - -1. `AGENTS.md` -2. `README.md` -3. `QUALITY.md` -4. `STRUCTURE.md` -5. `docs/internal/decisions.md` -6. `docs/internal/protocol-notes.md` -7. `docs/internal/protocol-layman.md` -8. `.planning/macro-plan/MACRO-PLAN.md` -9. `.planning/macro-plan/EXECUTION-SLICES.md` -10. `.planning/macro-plan/PROTECTED-ACTION-GATES.md` -11. `.planning/macro-plan/RUNTIME-GATES.md` -12. `.planning/macro-plan/TASKS.jsonl` - -`.planning/` is scratch except for this active execution handoff. Use it as planning evidence, not repo-facing product truth. +Canon lives in tracked repo docs/source/tests, not `.planning/`. The active +planning package for this run is +`.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/` and is +evidence for this execution only. Prior macro-plan runs are historical context, +not current closeout proof. ## Runtime Profile -Primary runtime is Codex in a workspace-write checkout with restricted network. Use `apply_patch` for edits. Use `rg` for discovery. Use focused tests before broad gates. Preserve dirty worktree state as user-owned. - -Multi-host posture is evidence-only: Codex, Claude Code, Hermes, OpenClaw, MCP, browser, A2A, OpenAPI, auth.md, and x402 do not share one runtime model. Do not claim native containment for any host from this plan. +Primary runtime is Codex in a workspace-write checkout with restricted network. +Use `rg` for discovery and `apply_patch` for edits. Multi-host posture remains +evidence-only; do not claim native containment for Codex, Claude Code, Hermes, +OpenClaw, MCP, browser, A2A, OpenAPI, auth.md, or x402. ## Instruction Sources -- `AGENTS.md`: invariant and doctrine. -- `QUALITY.md`: naming, quality, and boundary gates. -- `STRUCTURE.md`: source ownership. -- `docs/internal/*`: current product/protocol canon. -- `src/*/LANE.md`: lane ownership before source edits. -- `.planning/macro-plan/*`: execution program and stop conditions. +- `AGENTS.md` for doctrine and invariants. +- `QUALITY.md` and `STRUCTURE.md` for repo boundaries. +- `src/*/LANE.md` for lane-local ownership. +- `.planning/macro-plan/*` for execution plan and gates. ## Context Bundle -Core product move: - -```text -Passport -> evidence package the agent presents -ServiceWorkflowAdmission -> service-side accepted/refused/stale/proof-gap mapping -ServiceWorkflowHandle -> carried non-authority workflow context -Action Request -> fresh CandidateAction / ActionContract -Clearance -> PolicyDecision + one-use Greenlight/Refusal + GatewayCheck -Outcome -> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate -``` - -Non-authority IDs: - -```text -passportPackageDigest -passportPresentationId -admissionId -serviceWorkflowHandleId -serviceWorkflowHandleDigest -``` - -All are correlation/reconstruction refs only. +The live problem is not whether `src/surfaces` can exist. It can. The problem is +whether product vocabulary is described as a peer truth lane. Correct model: +projection/readback surfaces and role-scoped transition clients both sit under +one protocol authority spine. ## Ignored Context -Ignore older `.planning/macro/runs/20260525T141206-service-gateway-principal-agent-link/final/*` as a governing source. Treat historical Tier 3 plans as boundary reminders only. Do not use `.planning/` labels in repo-facing source, package scripts, public exports, or canonical docs. +Do not use older macro-plan validation or prior green tests as current-run +closeout evidence. Do not use `.planning/` labels in repo-facing source or +package exports. ## Tool Contract -Allowed: +Allowed: read/patch docs, source, tests, planning artifacts; run focused and +full repo gates; use sidecars for bounded audit only. Forbidden: protected +mutations outside user-authorized commands, broad network claims without +primary sources, and any authority claim not backed by source. -- read source, docs, tests, and planning artifacts; -- edit tracked docs, `src/surfaces`, architecture/product tests, examples, and narrowly related exports when required by the active slice; -- execute focused quality gates; -- use up to five subagents only when the user explicitly asks for delegation or sidecar work. +## Protected-Action Boundary -Forbidden: +Projection context stops before authority. Every protected action still requires +`CandidateAction / ActionContract -> PolicyDecision -> one-use Greenlight or +Refusal -> GatewayCheck -> Receipt / Refusal / ReplayRefusal / ProofGap / +AuthorityCertificate`. -- direct protected mutations outside user-authorized shell commands; -- broad network research unless requested or required for current unstable facts; -- rewriting protocol kernel state unless a slice proves a distinct enforceable transition; -- treating CLI, MCP, SDK, runtime ingress, docs, review screens, examples, certificates, passport IDs, or workflow handles as authority. +## Read First -## Subagent Topology +1. `AGENTS.md` +2. `README.md` +3. `QUALITY.md` +4. `STRUCTURE.md` +5. `docs/internal/decisions.md` +6. `docs/internal/protocol-notes.md` +7. `docs/internal/service-workflow-story.md` +8. `.planning/macro-plan/MACRO-PLAN.md` +9. `.planning/macro-plan/EXECUTION-SLICES.md` +10. `.planning/macro-plan/RUNTIME-GATES.md` +11. `.planning/macro-plan/PROTECTED-ACTION-GATES.md` +12. `.planning/macro-plan/TASKS.jsonl` -Use sidecars only for non-overlapping review or implementation scopes: +`.planning/` remains scratch. Do not turn planning labels into repo-facing +source or package surfaces. -- product/docs; -- surface/schema; -- architecture tests; -- runtime/agent negative tests; -- evidence/release gate. +## North-Star Model -No sidecar owns final authority claims, final plan status, or Tier 3 promotion. +```text +Projection/readback vocabulary + Passport / Admission / Handle / Clearance / Outcome / Certificate + over +One protected-action event spine + CandidateAction / ActionContract + -> PolicyDecision + -> one-use Greenlight or Refusal + -> GatewayCheck + -> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` -## Protected-Action Boundary +## Active Implementation Scope -Admission and handle stop before policy. Every protected action still requires: +Allowed: -```text -CandidateAction -ActionContract -PolicyDecision -one-use Greenlight or Refusal -GatewayCheckAttempt -Receipt / Refusal / ProofGap -``` +- patch canonical docs to replace dual-lane mental model with projection over + one authority spine; +- add or update architecture tests for projection-only language; +- update `src/surfaces/LANE.md` to clarify that surfaces are implementation + boundaries for projection/readback, not behavior owners; +- run focused gates and full repo gates; +- commit coherent checkpoints. -If a gateway cannot enforce before consequence, this is advisory, not Handshake. +Forbidden: -## Checkpoints +- add protocol primitives for Passport, Admission, Handle, Outcome, Badge, or + `ProtectedActionEvent`; +- widen root exports, CLI/MCP authority, SDK role powers, gateway adapters, or + hosted claims; +- treat receipts, certificates, support bundles, review screens, passports, or + workflow handles as future permission; +- claim hosted operation, provider custody, settlement/finality, marketplace + certification, cross-org trust, aggregate spend enforcement, host containment, + hosted org auth, or retention/search. -- Macro-plan validation: committed. -- Tier 1 story/schema/tests and docs convergence: committed. -- Tier 2 active surface alignment, local example, runtime misuse gates, and - protected-action fixture gate: committed. -- Tier 3 admission lock and final release gate: committed after `npm run - check:repo`. -- Before any Tier 3 work: stop and confirm separate hosted workspace or fresh - Tier 1/Tier 2 kernel task. +## Subagent Topology -## Stop Conditions +At most five sidecars: -Stop immediately if: +- architecture/case-study mechanisms; +- vocabulary/projection language; +- protected-action lifecycle mapping; +- runtime/protected-action gates; +- evidence/review/closeout. -- a Passport, Admission, Badge, or Handle object creates authority; -- `ServiceWorkflowHandle` is accepted as policy/gateway/signer/mutation evidence; -- raw credential, token, private key, `PaymentPayload`, or `PAYMENT-SIGNATURE` appears in passport/admission/handle records; -- a rendered review or docs summary is treated as permission; -- x402/auth.md fixture work precedes non-authority surface tests; -- Tier 3 work starts before Tier 1/Tier 2 proof gates close. +Sidecars may write audit reports only. The chair owns final sequencing, status, +authority claims, and commits. ## Evaluation Path -Start narrow: - ```bash +/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan npm run quality:claims npm run quality:architecture +npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts +npm run test -- test/runtime/runtime-ingress.test.ts test/product/service-workflow-admission.test.ts +npm run check:repo +git status --short --branch ``` -Then run focused slices: +## Stop Conditions -```bash -npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts -``` +Stop if: -Use `npm run check:repo` before claiming implementation closeout. +- product vocabulary becomes a peer authority lane; +- `ServiceWorkflowHandle` can satisfy policy, gateway, signer, mutation, + receipt, or certificate requirements; +- a case-study analogy is used as proof of Handshake capability; +- Tier 3/hosted pressure expands the kernel/package surface; +- full repo gate fails and no explicitly justified narrowed closeout exists. ## Proof Gaps -- No live provider custody, settlement, hosted operation, or native host - containment is proven. -- No marketplace/certification, cross-org trust, aggregate spend enforcement, - hosted org auth, retention/search, or hosted mutation authority is proven. -- auth.md plus x402 remains non-composite provenance/proof-gap posture unless a - future fresh action family clears its own gates. -- Tier 3 remains locked behind a separate hosted workspace or a new Tier 1/Tier - 2 kernel task with fresh proof gates. +- No live provider custody, x402 settlement/finality, facilitator operation, or + seller middleware is proven. +- No hosted operation, hosted org auth, retention/search, marketplace trust, or + cross-org trust is proven. +- No native host containment is proven. +- No finished UI product experience is proven by this architecture correction. ## Non-Claims -This handoff does not authorize Tier 3, hosted operation, provider custody, settlement finality, marketplace trust, cross-org trust, broad x402 compatibility, aggregate spend enforcement, broad runtime interception, or native host containment. +This handoff does not authorize Tier 3, hosted operation, provider custody, +settlement, marketplace trust, cross-org trust, aggregate spend enforcement, +host containment, or product UX completion. + +## Current Next Step + +Patch canonical docs and `test/architecture/claim-boundary.test.ts` so the repo +requires projection-over-spine language and forbids product/protocol peer-lane +truth claims. ## Next Agent Step -No Tier 1/Tier 2 simplification slice remains open. If the user opens Tier 3, -start from the Tier 3 admission lock in `docs/internal/decisions.md` and route -hosted operation to a separate hosted workspace or a fresh Tier 1/Tier 2 kernel -task before changing protocol exports. +Implement NPLAN-002 and NPLAN-003 first: canonical projection vocabulary plus +`src/surfaces/service-workflow-lifecycle-projections.ts` and its architecture +test. Do not begin hosted/Tier 3 work. diff --git a/.planning/macro-plan/DECISIONS.md b/.planning/macro-plan/DECISIONS.md index 3da3f24..25df196 100644 --- a/.planning/macro-plan/DECISIONS.md +++ b/.planning/macro-plan/DECISIONS.md @@ -1,109 +1,91 @@ # Decisions -## DEC-001 - -- ID: DEC-001 -- Status: Accepted -- Decision: Proceed from the decision-gated macro map into a full Tier 1/Tier 2 macro plan. -- Rationale: The user explicitly authorized the full plan and implementation sequence after reviewing the goal. -- Source: User instruction and `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md`. -- Revisit Trigger: If sidecar review finds an authority violation that cannot be converted into a concrete gate. - -## DEC-002 - -- ID: DEC-002 -- Status: Accepted -- Decision: Keep Passport as a docs/story input noun only. -- Rationale: Passport helps users understand presented standing evidence but is too authority-shaped for protocol or API authority. -- Source: `.planning/macro-map/MACRO-MAP.md`, `views/DESIGN.md`, `views/AUTHORITY.md`. -- Revisit Trigger: If user comprehension evidence shows Passport consistently implies identity or permission even with cut lines. - -## DEC-003 - -- ID: DEC-003 -- Status: Accepted -- Decision: Use `ServiceWorkflowAdmission` as the source/API surface output. -- Rationale: It is narrower than standalone Admission and makes the service-side mapping explicit. -- Source: `.planning/macro-map/MECHANISM-MAP.md`, `views/ENG.md`, `.planning/codebase/CONCERNS.md`. -- Revisit Trigger: If implementation reveals a clearer non-authority noun with stronger tests. - -## DEC-004 - -- ID: DEC-004 -- Status: Accepted -- Decision: Use `ServiceWorkflowHandle` as the carried workflow context object. -- Rationale: It is less authority-loaded than Badge and can carry context/digest refs with explicit false authority flags. -- Source: `views/DESIGN.md`, `views/DEVEX.md`, `views/AGENT.md`, `views/RUNTIME.md`. -- Revisit Trigger: If developers still treat handle as reusable permission in tests or review. - -## DEC-005 - -- ID: DEC-005 -- Status: Accepted -- Decision: Keep Badge as optional narrative shorthand only. -- Rationale: Badge is memorable but reads like bearer auth. It must not become schema, route, export, or protocol object. -- Source: `.planning/macro-map/FACET-MAP.md`, `views/CEO.md`, `views/DESIGN.md`. -- Revisit Trigger: If product copy requires removing Badge entirely to preserve the boundary. - -## DEC-006 - -- ID: DEC-006 -- Status: Accepted -- Decision: Split passport/admission/workflow IDs into five non-authority refs. -- Rationale: Correlation and reconstruction need stable refs, but no ref may create authority. -- Source: User-provided invariant and current macro-plan input. -- Revisit Trigger: If source implementation requires additional digests for canonicalization or redaction. - -## DEC-007 - -- ID: DEC-007 -- Status: Accepted -- Decision: First implementation home is docs plus `src/surfaces`, not `src/protocol/areas`. -- Rationale: No new enforceable transition exists; current protocol primitives already represent evidence, attempt bounds, exact contracts, policy, gateway, and readback. -- Source: `.planning/codebase/ARCHITECTURE.md`, `.planning/codebase/STRUCTURE.md`, `STRUCTURE.md`. -- Revisit Trigger: Only if a future source design identifies a distinct terminal or state-transition event. - -## DEC-008 - -- ID: DEC-008 -- Status: Accepted -- Decision: Tier 2 examples and runtime convergence wait for Tier 1 schema and boundary tests. -- Rationale: Demo-first would overclaim the product story before authority boundaries are source-enforced. -- Source: `.planning/macro-map/EXECUTION-MAP.md`, `.planning/macro-map/PROTECTED-ACTION-MAP.md`. -- Revisit Trigger: If a non-source prototype is requested separately and clearly marked throwaway. - -## DEC-009 - -- ID: DEC-009 -- Status: Accepted -- Decision: Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit. -- Rationale: Hosted operation must consume proven local/source-owned surfaces, not expand the kernel or package surface prematurely. -- Source: `docs/internal/decisions.md`, macro-plan objective, prior Tier 3 boundary guidance. -- Revisit Trigger: If the user starts a separate hosted workspace with explicit Tier 3 scope. - -## DEC-010 - -- ID: DEC-010 -- Status: Rejected -- Decision: Do not make Passport a protocol primitive. -- Rationale: It would duplicate evidence and authority-adjacent records without adding a gateway-enforced transition. -- Source: `.planning/codebase/CONCERNS.md`, `.planning/macro-map/MECHANISM-MAP.md`. -- Revisit Trigger: A future protocol decision proves a distinct enforceable state. - -## DEC-011 - -- ID: DEC-011 -- Status: Rejected -- Decision: Do not sell passport validation as the bought authority unit. -- Rationale: The economic unit remains protected-event terminalization and reconstructable evidence. -- Source: `views/CEO.md`, `docs/internal/decisions.md`. -- Revisit Trigger: Paid pilot evidence proves a separate validation product without weakening authority claims. - -## DEC-012 - -- ID: DEC-012 -- Status: Deferred -- Decision: Defer live x402/auth.md composite service gateway demo. -- Rationale: The surface and non-authority tests must land before composite external rails. -- Source: `.planning/macro-map/PROTECTED-ACTION-MAP.md`, `.planning/codebase/INTEGRATIONS.md`. -- Revisit Trigger: T2-04 starts after Tier 1 and early Tier 2 gates pass. +## NPLAN-D001 - One Authority Spine + +- Status: accepted +- Decision: Handshake architecture is one protocol authority spine with + projection/readback vocabulary over it. +- Rationale: Product/protocol peer lanes create ambiguity about where authority + lives. +- Source: user correction; `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md` +- Revisit trigger: only if a future source-owned transition changes the + authority spine. + +## NPLAN-D002 - Surfaces Are Implementation Boundaries + +- Status: accepted +- Decision: Keep `src/surfaces` and "surface" as implementation vocabulary, but + canonical docs must say surfaces expose projection/readback only and are not a + product truth lane. +- Rationale: Removing the folder would cause churn; correcting its meaning + addresses the real architectural risk. +- Source: `STRUCTURE.md`, `src/surfaces/LANE.md`, `test/architecture/surface-boundary-posture.test.ts` +- Revisit trigger: if package extraction needs a public projection subpath. + +## NPLAN-D002A - Projection Surfaces Versus Transition Clients + +- Status: accepted +- Decision: Canonical vocabulary must distinguish product projection/readback + surfaces from role-scoped protocol transition clients. +- Rationale: Some SDK/HTTP clients transport authority-bearing protocol + transitions, while product projection surfaces must remain non-authority. One + umbrella term hides that difference. +- Source: `runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md` +- Revisit trigger: if the SDK/client taxonomy changes. + +## NPLAN-D003 - ProtectedActionEvent As Lifecycle Projection Concept + +- Status: accepted +- Decision: Use `ProtectedActionEvent` as a documentation/testing lifecycle + concept in this run, source-owned through a `src/surfaces` projection map, not + as a stored protocol object. +- Rationale: The current protocol already has navigation/lifecycle matrices; a + new primitive would risk duplicating authority state. +- Source: `src/protocol/navigation`, `src/protocol/areas/action-attempt-lifecycle`, `docs/internal/protocol-notes.md` +- Revisit trigger: if source proves the existing lifecycle cannot express a + required terminal event projection. + +## NPLAN-D003A - Runtime Composition Gaps Are Blocking + +- Status: accepted +- Decision: Mixed-family same-envelope and x402/auth.md non-composition gates + are P0 for closeout. +- Rationale: Projection-over-spine fails if one generated block can blur + multiple authority contexts into a single runtime spine or composite + credential/payment artifact. +- Source: `runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md` +- Revisit trigger: after focused runtime tests prove the gate. + +## NPLAN-D003B - Authority Surface Naming Must Be Replaced + +- Status: accepted +- Decision: `sdk.policy` and similar clients should be described as + role-scoped protocol transition clients, not authority surfaces. +- Rationale: The kernel/policy transition owns authority. SDK clients transport + a role-scoped call into that transition. +- Source: `runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md` +- Revisit trigger: if a future client truly owns an enforceable authority + transition outside the kernel, which should be treated as a new protocol + design. + +## NPLAN-D004 - Case Studies Become Mechanism Rules + +- Status: accepted +- Decision: Stripe, Kubernetes/OPA, Vault, GitHub, AWS IAM, SLSA/Sigstore, + Vercel, and Cloudflare are used as mechanism references only. +- Rationale: Borrowed analogy can overclaim enforcement. Mechanism rules can be + tested. +- Source: `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md` +- Revisit trigger: if a later implementation imports a concrete standard or + certification. + +## NPLAN-D005 - Badge Remains Unsafe Shorthand + +- Status: accepted +- Decision: Badge remains forbidden as schema/protocol/export/route authority + vocabulary. If used in UI later, it must mean a read-only state label derived + from evidence. +- Rationale: Badge reads as bearer authority under generated-agent behavior. +- Source: `.planning/macro-map/DECISIONS.md`, `docs/internal/service-workflow-story.md`, `src/mcp/LANE.md` +- Revisit trigger: if a UI-only state-label component is designed with explicit + non-authority copy and tests. diff --git a/.planning/macro-plan/EVIDENCE-PLAN.md b/.planning/macro-plan/EVIDENCE-PLAN.md index 8d7c746..6389f91 100644 --- a/.planning/macro-plan/EVIDENCE-PLAN.md +++ b/.planning/macro-plan/EVIDENCE-PLAN.md @@ -1,180 +1,138 @@ # Evidence Plan -## Current Evidence +## Invariant At Stake -The plan is grounded in canonical docs, the current macro map, and current -codebase maps. Canon proves the authority chain and product-surface boundary. -The macro map proves lens convergence around non-authority product -simplification. The codebase maps identify source placement, tests, and proof -gaps. Tier 1 source implementation now owns the service workflow story, -non-authority admission/handle schemas, and boundary tests. Tier 2 source -implementation now owns active CLI/MCP/SDK posture alignment, the runnable local -service workflow admission example, and generated-agent/runtime misuse gates. +The closeout must prove the architectural correction, not just successful text +edits. Evidence must distinguish research, plan, implementation, test, review, +and residual proof gaps. -Current structural validation result: +## Evidence Artifacts -```text -Macro plan output is valid. -``` +| Artifact | Purpose | +| --- | --- | +| `runs/20260525T110908Z-architectural-north-star/input.md` | Immutable goal and source boundary | +| `runs/20260525T110908Z-architectural-north-star/research.md` | Primary-source case-study mechanisms | +| `runs/20260525T110908Z-architectural-north-star/source-snapshot.md` | Starting repo/source posture | +| `runs/20260525T110908Z-architectural-north-star/blocked-checks.md` | Preserved proof gaps and stop conditions | +| `runs/20260525T110908Z-architectural-north-star/audits/*.md` | Sidecar pressure reports | +| `runs/20260525T110908Z-architectural-north-star/validation.md` | Command and review closeout | + +## Current Evidence -Sidecar review result: all five assigned audit reports exist under `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/`. The reports recommend preserving protected-action, runtime, product, and evidence gates. The chair reconciliation narrows implementation readiness to the first Tier 1 story/schema/test slice and keeps protected-action fixtures, host containment claims, external rails, public-surface convergence, and Tier 3 blocked until source proof exists. +- Current run input, research, research-evidence, source snapshot, blocked + checks, and five sidecar audits exist. +- Macro-plan validator must be rerun after final plan edits. +- Source/docs/tests implementation evidence is not complete until focused gates + and `npm run check:repo` run after final changes. -## Verification Commands +## Command Evidence -Macro-plan validation: +Plan validation: ```bash /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan ``` -Observed output: - -```text -Macro plan output is valid. -``` - -Tier 1 documentation and surface verification: +Focused implementation gates: ```bash npm run quality:claims npm run quality:architecture -npm run check:types -git diff --check -``` - -Protocol simplification focused verification: - -```bash -npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts -``` - -Tier 2 example and integration verification will use a new focused product test plus existing x402/auth.md gateway tests when those surfaces are touched. - -T2-03 generated-agent/runtime misuse verification: - -```bash -npm run test -- test/product/service-workflow-admission.test.ts -npm run test -- test/runtime/runtime-ingress.test.ts -``` - -T2-04 protected-action fixture gate verification: - -```bash -npm run test -- test/product/service-workflow-admission.test.ts -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts +npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts +npm run test -- test/runtime/runtime-ingress.test.ts test/product/service-workflow-admission.test.ts ``` -T2-05 Tier 3 lock verification: - -```bash -npm run test -- test/architecture/claim-boundary.test.ts -npm run check:repo -``` - -Full closeout: +Closeout: ```bash npm run format:check npm run check:repo +git status --short --branch ``` -Current full closeout status: `npm run check:repo` passes after MPLAN-010. - -## Replay And Refusal Cases - -Required cases: +## Fixtures Or Examples -- handle reused after refusal; -- handle reused after proof gap; -- handle reused after consumed greenlight replay; -- changed payment amount or endpoint after admission; -- dynamic tool construction from handle; -- raw x402 payload supplied through admission; -- raw bearer/API token supplied through handle; -- gateway policy drift between admission and action request; -- credential-ref or authority-ref isolation before protected action; -- stale passport evidence or expired admission. +- `examples/service-workflow-admission/latest.json` and `latest.md` must remain + service workflow readbacks, not authority artifacts. +- Product/architecture fixtures must assert Passport, Admission, Handle, + Clearance, Outcome, and Certificate as projections over existing lifecycle + entries or explicit pre-contract evidence context. +- Runtime fixtures must cover mixed-family envelope refusal and x402/auth.md + non-composition, not one composite authority object. -Each case must stop before signer use, mutation, receipt export, or certificate minting unless a fresh exact contract clears through policy and gateway. +## Readback And Redaction Checks -## Review Prompts +- Readbacks may include correlation and reconstruction references, including + digest and presentation/admission/handle IDs, only when those IDs are marked + non-authority. +- Readbacks must not expose payment material, signer payloads, gateway-held + credentials, authority tokens, or live provider secrets. +- Redaction must preserve enough structure to reconstruct proposal, policy, + gateway check, receipt/refusal/proof gap, and terminal certificate posture + without turning evidence into reusable auth. -Use these review prompts before promoting implementation: +## Runtime Proof Artifacts -- Does any simplified noun imply permission? -- Can the user approve admission while the later action contract differs? -- Can an agent pass the handle directly into a protected tool? -- Can generated code mutate through a sibling route after admission? -- Does the readback distinguish admission, policy, gateway, downstream, receipt, refusal, replay, and proof gap? -- Does every public claim match the current source proof ledger? -- Does Tier 3 remain blocked? +- Runtime proof must include generated execution shape, runtime posture, + protected action path, gateway authority holder, raw or sibling bypass + posture, and surviving receipt/refusal/proof-gap evidence. +- Mixed-family runtime proof must show a same-envelope pass or an explicit + refusal before one projected workflow readback is assembled. +- x402/auth.md runtime proof must show separate exact contracts or refusal, + never one composite credential-plus-payment authority artifact. -## Fixtures Or Examples +## Evidence Not Yet Available -Planned fixture sequence: +- Post-implementation focused test outputs are not available until source/docs + edits land. +- Full `npm run check:repo` evidence is not available until after focused gates + pass. +- Hosted/Tier 3 proof remains unavailable by design in this run. +- Live provider custody, native host containment, registry acceptance, and + marketplace trust remain proof gaps. -1. Local service workflow admission fixture emits JSON and Markdown. -2. Negative fixture attempts to use handle as authority and is refused. -3. Later x402 fixture uses handle as context to create one fresh `x402_payment.exact` action request. -4. Output separates admission readback from protected-action terminal evidence. +## Verification Commands -Existing examples to mirror: +Use the command matrix above. Record exact outputs in +`runs/20260525T110908Z-architectural-north-star/validation.md`. -- `examples/self-hosted-activation/` -- `examples/x402-protected-spend/` -- `examples/external-adapter-sdk/` -- `examples/x402-protected-tool-profiles/` -- `examples/mcp-reference-transcript/` +## Evidence Success Criteria -## Readback And Redaction Checks +- Sidecar findings are resolved or carried as explicit proof gaps. +- Tests require projection-over-spine language and non-authority service + workflow semantics. +- Full repo gate passes before final implementation closeout. +- Git commits separate macro-plan reset from implementation when possible. -Readback must omit: +## Replay And Refusal Cases -- raw credentials; -- provider secret paths; -- private keys; -- bearer/API tokens; -- raw x402 `PaymentPayload`; -- `PAYMENT-SIGNATURE`; -- raw internal protocol records unless route admission explicitly allows a safe internal read; -- mutation commands hidden inside handle fields. +Evidence must include or preserve tests for replay refusal, policy/runtime +refusal, gateway refusal, stale handle/review refusal, mixed-family envelope +refusal, x402/auth.md non-composition refusal, and proof-gap readback. -Readback must include: +## Review Prompts -- explicit non-authority flags; -- accepted/refused/stale/proof-gap claim rows; -- digest/ref fields for reconstruction; -- fresh action contract requirement; -- proof gaps and next safe recovery moves. +- Does the diff preserve one authority spine? +- Does any product noun create authority or imply a second lane? +- Are sidecar P0 findings resolved in source/tests or recorded as proof gaps? +- Were focused gates and full repo gate run after final changes? ## Browser Or Visual Evidence -No browser or visual evidence is required for the first Tier 1 implementation because this is source/docs/schema/test work. If a review renderer or UI is introduced later, visual QA must verify that admission, handle, clearance, receipt, refusal, and proof-gap states are visibly separate and not summarized as one approval badge. +This correction is architecture/source owned, not a finished product UI slice. +Browser evidence is optional unless docs/demo pages or rendered service workflow +readbacks are changed. If visual/browser surfaces are touched, capture: -## Runtime Proof Artifacts +- rendered service workflow readback showing projection language; +- absence of authority, trusted identity, reusable credential, or badge-style + permission wording; +- console and route errors for the changed route; +- a note that visual readback is evidence only and not an enforcement boundary. -Runtime artifacts to collect during Tier 2: - -- runtime ingress negative cases for dynamic/stale handle-context refusal; -- runtime ingress loop/retry cases proving handle evidence does not become - aggregate spend authority; -- service workflow fixture gate proving handle context feeds one fresh - `x402_payment.exact` path without carrying payment material; -- auth.md provenance/proof-gap posture showing no composite credential plus - spend authority artifact; -- Tier 3 admission lock in canonical docs and claim-boundary tests; -- MCP proposal/readback output; -- host profile posture rows; -- raw sibling bypass inventory; -- generated-execution graph evidence for loop/retry/dynamic-tool cases; -- proof-gap readback for unverified hosts. - -## Evidence Not Yet Available +## Residual Proof Gaps To Preserve -- user comprehension evidence for Passport/Admission/Badge naming; -- live external x402 provider/facilitator behavior; -- provider-grade auth.md credential custody; -- browser/A2A/OpenAPI gateway-owned protected path evidence; -- native containment for non-Codex hosts; -- hosted operation, provider custody, retention, org auth, or Tier 3 cloud evidence; -- market willingness to pay for passport validation as a standalone product. +- No live provider custody or settlement finality. +- No hosted operation or hosted org auth. +- No marketplace/certification or cross-org trust. +- No native host containment. +- No finished product UI beyond source-owned docs/schema/demo/readback. diff --git a/.planning/macro-plan/EXECUTION-SLICES.md b/.planning/macro-plan/EXECUTION-SLICES.md index 9417679..81cfb83 100644 --- a/.planning/macro-plan/EXECUTION-SLICES.md +++ b/.planning/macro-plan/EXECUTION-SLICES.md @@ -1,679 +1,328 @@ # Execution Slices -## Slice T0-00 - Macro Package And Review Reconciliation +## Inputs -### ID - -T0-00 - -### Invariant Or Risk - -The plan itself can launder unresolved blockers into an executable-looking artifact. The chair must preserve source boundary, sidecar disagreement, non-proofs, and implementation gates. - -### Objective - -Produce a validated macro-plan package with source snapshot, sidecar reviews, evidence plan, runtime gates, protected-action gates, task records, and implementation entry. +- `.planning/macro-map/*` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/*` +- canonical docs under repo root and `docs/internal/` +- `src/protocol`, `src/surfaces`, `src/runtime`, `src/sdk`, `src/cli`, `src/mcp` +- architecture, runtime, and product tests -### Source Evidence - -- `.planning/macro-map/MACRO-HANDOFF.md` -- `.planning/macro-map/FACET-MAP.md` -- `.planning/codebase/*` -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-notes.md` -- `gsd-macro-plan` references and validator +## Outputs -### Inputs +- revised macro-plan package; +- canonical docs and source-owned projection map; +- architecture/runtime/product tests; +- validation, code-review, and git-checkpoint evidence. -Run input, source snapshot, sidecar audit reports, macro-map package, codebase maps, canonical docs. - -### Outputs +## Dependencies -`.planning/macro-plan/*`, `TASKS.jsonl`, validation output, git checkpoint. +- N1 depends on N0 macro-plan reset. +- N2 depends on canonical projection vocabulary. +- N3 depends on projection map and canonical vocabulary. +- N4 depends on projection vocabulary guards. +- N5 depends on all implementation and focused gates. -### Dependencies - -User authorization to continue from the decision-gated macro map. - -### Owner - -Chair. - -### Stop Conditions - -- The plan claims authority, hosted operation, provider custody, native host containment, settlement, or Tier 3 readiness. -- Sidecar reports are missing and no fallback is recorded. -- Validator fails and the package is not revised. - -### Proof Gates - -- Validator reports the macro plan output is valid. -- Sidecar reports exist or missing reports are explicitly recorded. -- `git status --short` is inspected before committing. - -### Verification Commands Or Checks +## Verification Commands Or Checks ```bash /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan -git status --short -``` - -### Rollback Or Abandonment Criteria - -Abandon the executable status if a sidecar finds a live authority or runtime blocker that cannot be turned into a concrete implementation gate. - -### Agent Handoff Needs - -Fresh agent reads `AGENT-HANDOFF.md`, this file, `TASKS.jsonl`, `PROTECTED-ACTION-GATES.md`, and `RUNTIME-GATES.md`. - -## Slice T1-01 - Service Workflow Story - -### ID - -T1-01 - -### Invariant Or Risk - -Users need a simple story, but the story cannot imply permission. If a story says the agent is "admitted" without separating clearance, this is advisory, not Handshake. - -### Objective - -Create `docs/internal/service-workflow-story.md` that teaches the simplified flow and maps each noun to existing protocol/evidence objects. - -### Source Evidence - -- `.planning/macro-map/EXPERIENCE-MAP.md` -- `.planning/macro-map/views/DESIGN.md` -- `.planning/macro-map/views/DEVEX.md` -- `docs/internal/protocol-layman.md` -- `README.md` -- `docs/internal/protocol-notes.md` - -### Inputs - -Noun set: Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, Outcome. Five non-authority IDs. Canonical protocol chain. - -### Outputs - -`docs/internal/service-workflow-story.md` - -### Dependencies - -T0-00. - -### Owner - -Product/docs implementer. - -### Stop Conditions - -- The doc says Passport, Admission, Badge, Handle, Certificate, or review creates permission. -- The doc collapses admission and clearance. -- The doc lacks refusal, proof-gap, replay, or isolation recovery states. - -### Proof Gates - -- Story states Passport is evidence package only. -- Story states Admission is service-side accepted/refused/stale/proof-gap mapping only. -- Story states Handle is workflow context only and requires fresh action contracts. -- Story states Clearance is exact policy plus one-use greenlight/refusal plus gateway check. -- Story states Outcome is receipt/refusal/replay refusal/proof gap/certificate evidence, not downstream success. - -### Verification Commands Or Checks - -```bash npm run quality:claims -git diff --check -``` - -### Rollback Or Abandonment Criteria - -Revert the doc slice if claim-boundary tests reject the language or if the doc needs a new authority primitive to make the story coherent. - -### Agent Handoff Needs - -Read `docs/internal/protocol-layman.md` and keep the new story shorter than a protocol spec but strict about non-authority. - -## Slice T1-02 - Surface Contract And Non-Authority IDs - -### ID - -T1-02 - -### Invariant Or Risk - -A product surface can create implied authority through fields and exports even when text says otherwise. - -### Objective - -Create `src/surfaces/service-workflow-admission.ts` defining `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, authority boundary fields, claim rows, and the five non-authority IDs. - -### Source Evidence - -- `.planning/macro-map/MECHANISM-MAP.md` -- `.planning/macro-map/views/ENG.md` -- `.planning/macro-map/views/AUTHORITY.md` -- `.planning/codebase/STRUCTURE.md` -- `.planning/codebase/CONVENTIONS.md` -- `src/surfaces/outcome.ts` -- `src/surfaces/boundary-manifest.ts` - -### Inputs - -Existing surface non-authority field conventions, Zod schema style, strict TypeScript settings. - -### Outputs - -- `src/surfaces/service-workflow-admission.ts` -- possibly `src/surfaces/index.ts` export if package posture allows, guarded by tests - -### Dependencies - -T1-01. - -### Owner - -Surface/schema implementer. - -### Stop Conditions - -- The file imports protocol internals that create policy, greenlight, gateway, receipt, certificate, store, or adapter authority. -- The schema carries raw token, key, `PaymentPayload`, `PAYMENT-SIGNATURE`, signer, credential material, receipt export, or certificate material. -- The schema can widen resources, actions, spend, gateway, or policy bounds. - -### Proof Gates - -- `createsAuthority: false` -- `createsPolicyDecision: false` -- `createsGreenlight: false` -- `performsGatewayCheck: false` -- `permitsMutation: false` -- `exportsReceipt: false` -- `mintsTerminalCertificate: false` -- `freshActionContractRequired: true` -- IDs defined: `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, `serviceWorkflowHandleDigest` - -### Verification Commands Or Checks - -```bash npm run quality:architecture -npm run check:types +npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts +npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/product/service-workflow-admission.test.ts +npm run check:repo ``` -### Rollback Or Abandonment Criteria +## Rollback Or Abandonment Criteria -Abandon source surface if a distinct enforceable protocol transition is truly required; return to macro planning before adding protocol state. +- Roll back docs wording if claim-boundary tests show it weakens authority + boundaries. +- Abandon projection-map implementation if it requires a stored protocol object; + return to protocol design first. +- Abandon runtime closeout if mixed-family or x402/auth.md tests reveal + composite authority that cannot be fixed in scope. +- Do not close the goal if full repo gate fails without an explicit user-owned + narrowed closeout. -### Agent Handoff Needs +## Agent Handoff Needs -Study existing `src/surfaces/outcome.ts` and `src/surfaces/boundary-manifest.ts`; follow their non-authority style. +Fresh agents must read `AGENT-HANDOFF.md`, `RUNTIME-GATES.md`, +`PROTECTED-ACTION-GATES.md`, sidecar audit reports, and `TASKS.jsonl` before +editing. They must preserve dirty user state and avoid treating `.planning/` +as repo-facing canon. -## Slice T1-03 - Naming, Claim, And Surface Boundary Guards +## Slice N0-00 - Research And Macro-Plan Reset ### ID -T1-03 +N0-00 ### Invariant Or Risk -Friendly nouns can drift into protocol areas, runtime dispatch, gateway execution, root exports, or public claims. +A plan can launder a weak analogy into product architecture. Research must +become mechanism rules, not borrowed authority. ### Objective -Add architecture and claim-boundary tests for Passport, Admission, Badge, `ServiceWorkflowAdmission`, and `ServiceWorkflowHandle`. +Record primary-source case-study research, reset the macro-plan package around +projection-over-one-spine, and preserve proof gaps. ### Source Evidence -- `.planning/codebase/TESTING.md` -- `.planning/codebase/CONCERNS.md` -- `test/architecture/naming-posture.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/surface-boundary-posture.test.ts` -- `test/architecture/root-exports.test.ts` - -### Inputs - -Existing architecture tests and package export posture. +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md` +- `README.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `src/surfaces/LANE.md` ### Outputs -- `test/architecture/workflow-admission-boundary.test.ts` or extensions to existing architecture tests -- claim-boundary vocabulary updates where needed - -### Dependencies - -T1-02. - -### Owner - -Architecture-test implementer. +- `runs/20260525T110908Z-architectural-north-star/input.md` +- `runs/20260525T110908Z-architectural-north-star/research.md` +- revised `.planning/macro-plan/*` ### Stop Conditions -- Tests rely only on prose while source exports can still imply authority. -- Tests allow `Badge` as API/schema/protocol noun. -- Tests allow handle fields to satisfy policy, gateway, signer, mutation, receipt, or certificate material. +- Any case study is used to claim Handshake has enforcement not proven in source. +- The plan preserves "product lane vs protocol lane" as a positive target. ### Proof Gates -- Surface object stays out of `src/protocol/areas/*`. -- Surface object stays out of gateway adapter execution paths. -- Root exports remain curated. -- Forbidden raw credential/payment/material fields are rejected. -- Non-authority booleans are required. +- Macro-plan validator passes. +- Sidecar audits exist or missing sidecars are recorded. -### Verification Commands Or Checks +### Verification ```bash -npm run quality:claims -npm run quality:architecture +/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan ``` -### Rollback Or Abandonment Criteria - -If guards become too string-scanny to prove boundary, add schema-level tests and import-boundary checks before continuing. - -### Agent Handoff Needs - -Do not weaken existing architecture tests to admit the new surface. - -## Slice T1-04 - Canonical Docs Convergence +## Slice N1-01 - Canonical Projection Language ### ID -T1-04 +N1-01 ### Invariant Or Risk -Docs can diverge: README may teach x402 mechanics while internal docs teach Passport/Admission, producing two product models. +Canonical docs currently use `product surface` and `protocol kernel` language +that is valid structurally but can be read as peer lanes of truth. ### Objective -Converge canonical docs on the simplified flow while preserving the current product kernel and proof ledger. +Patch canonical docs to say product vocabulary is projection/readback over the +single protected-action event spine. -### Source Evidence +### Candidate Paths - `README.md` -- `QUALITY.md` - `STRUCTURE.md` - `docs/internal/decisions.md` - `docs/internal/protocol-notes.md` - `docs/internal/protocol-layman.md` - `docs/internal/service-workflow-story.md` - -### Inputs - -Completed story and surface schema. - -### Outputs - -Tightly scoped documentation patches, not a broad rewrite. - -### Dependencies - -T1-01, T1-02, T1-03. - -### Owner - -Docs implementer. +- `src/surfaces/LANE.md` ### Stop Conditions -- Docs imply public package availability, MCP Registry, certificate, passport, or handle creates authority. -- Docs claim Tier 3 hosted operation or external provider custody. -- Docs remove proof gaps to sound simpler. +- Docs imply product vocabulary can create or reinterpret authority. +- Docs imply service workflow admission is policy/gateway admission. +- Docs imply certificate, receipt, outcome, or support bundle grants future + authority. ### Proof Gates -- `quality:claims` passes. -- Docs mention the simplified flow and exact protected-action chain together. -- Tier 3 remains blocked by explicit source gate. +- Canon states exactly one authority spine. +- Canon states projection/readback surfaces are implementation boundaries only. +- Canon preserves public npm/MCP/hosted proof gaps. -### Verification Commands Or Checks +### Verification ```bash npm run quality:claims npm run format:check ``` -### Rollback Or Abandonment Criteria - -Revert doc convergence if it creates a second inconsistent product story. - -### Agent Handoff Needs - -Patch canonical docs only after source schema and tests exist. - -## Slice T2-01 - SDK / CLI / MCP Surface Alignment - -### ID - -T2-01 - -### Invariant Or Risk - -Developer surfaces can make admission feel executable if they expose a handle before explaining clearance. - -### Objective - -Align SDK role-client guidance, CLI readback language, and MCP metadata/resource descriptions with the simplified product model without adding execution authority. - -### Source Evidence - -- `README.md` -- `src/cli/command-manifest.ts` -- `src/mcp/catalog.ts` -- `src/mcp/resources.ts` -- `src/sdk/surface-clients/index.ts` -- `.planning/codebase/STACK.md` -- `.planning/codebase/CONVENTIONS.md` - -### Inputs - -Tier 1 schema and docs. - -### Outputs - -Surface language updates, readback helper shapes, or docs-only references depending on source fit. - -### Dependencies - -T1-04. - -### Owner - -Surface integration implementer. - -### Stop Conditions - -- CLI gains mutation-shaped commands for admission. -- MCP tool exposure expands beyond proposal/evidence. -- SDK clients infer authority from admission readback. - -### Proof Gates - -- CLI command posture remains evidence/readiness/readback only. -- MCP remains proposal/evidence only. -- SDK role clients remain role-scoped and do not accept handle as permission. - -### Verification Commands Or Checks - -```bash -npm run quality:architecture -npm run test -- test/architecture/cli-command-posture.test.ts test/architecture/mcp-surface-posture.test.ts test/sdk/role-clients.test.ts -``` - -### Rollback Or Abandonment Criteria - -If alignment needs new public exports, pause for export posture review before continuing. - -### Agent Handoff Needs - -Keep changes sparse; do not redesign CLI/MCP. - -## Slice T2-02 - Local Service Workflow Example +## Slice N2-01 - ProtectedActionEvent Projection Map ### ID -T2-02 +N2-01 ### Invariant Or Risk -A demo can accidentally become a product claim if it hides proof gaps or implies live provider execution. +Friendly nouns will drift unless they map to one source-owned lifecycle. ### Objective -Create a local example that emits JSON and Markdown showing Passport presentation, service admission, workflow handle, fresh x402 action request, and separated readback states. - -### Source Evidence - -- `examples/self-hosted-activation/` -- `examples/x402-protected-spend/` -- `examples/external-adapter-sdk/` -- `test/product/*` -- `.planning/macro-map/EXPERIENCE-MAP.md` -- `.planning/macro-map/PROTECTED-ACTION-MAP.md` - -### Inputs - -Tier 1 schema and tests. - -### Outputs - -- `examples/service-workflow-admission/` -- product test for example output -- generated output contract in JSON and Markdown - -### Dependencies - -T2-01. +Define `ProtectedActionEvent` as a documentation/testing lifecycle concept and +source-own the product projection vocabulary through a `src/surfaces` lifecycle +projection map. Map each product noun to lifecycle evidence without adding a +stored protocol object. -### Owner +### Candidate Paths -Example implementer. +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` +- `docs/internal/decisions.md` +- `src/surfaces/service-workflow-lifecycle-projections.ts` +- `src/surfaces/index.ts` +- `test/architecture/claim-boundary.test.ts` +- `test/architecture/service-workflow-lifecycle-projection.test.ts` ### Stop Conditions -- Example claims live provider custody, hosted operation, settlement, broad x402 compatibility, or host containment. -- Example skips fresh `ActionContract`. -- Example treats handle readback as receipt evidence. +- Implementation adds a new protocol primitive without a separate transition + proposal. +- `ProtectedActionEvent` becomes a package export, store record, or gateway + input in this slice. ### Proof Gates -- Output includes false authority flags. -- Output distinguishes admission evidence from protected-action receipt/refusal/proof-gap. -- Product test asserts the example’s non-claims. +- Projection map names source authority stage for each noun. +- Projection map names forbidden authority interpretation for each noun. +- Tests require the mapping in canonical docs. +- Tests validate lifecycle keys against `actionAttemptLifecycleEntry()`. -### Verification Commands Or Checks +### Verification ```bash -npm run demo:service-workflow-admission -npm run test -- test/product/service-workflow-admission.test.ts +npm run test -- test/architecture/claim-boundary.test.ts ``` -### Rollback Or Abandonment Criteria - -Defer the example if it requires a new live external rail to look convincing. - -### Agent Handoff Needs - -Use existing examples as style references; emit stable Prettier-friendly JSON and Markdown. - -## Slice T2-03 - Runtime And Generated-Agent Misuse Tests +## Slice N3-01 - Dual-Lane Drift Guards ### ID -T2-03 +N3-01 ### Invariant Or Risk -Generated agents will reuse a handle in loops, retries, dynamic tool calls, stale review flows, browser/network paths, or raw sibling calls unless negative cases make that impossible to miss. +The phrase "product surface" can silently expand into a second lane of truth. ### Objective -Add runtime/product tests proving handle/admission cannot authorize protected actions and must recraft fresh action requests after drift, refusal, replay, proof gap, or isolation. - -### Source Evidence - -- `.planning/macro-map/AGENT-RUNTIME-MAP.md` -- `.planning/macro-map/views/AGENT.md` -- `.planning/macro-map/views/RUNTIME.md` -- `src/runtime/ingress/index.ts` -- `src/runtime/ingress/schemas.ts` -- `test/runtime/runtime-ingress.test.ts` - -### Inputs +Add claim-boundary tests that forbid product/protocol peer-lane language and +require projection-over-spine language. -Tier 1 schema, local example, runtime ingress tests. +### Candidate Paths -### Outputs - -Focused negative tests and updated evidence plan. - -### Dependencies - -T2-02. - -### Owner - -Runtime test implementer. +- `test/architecture/claim-boundary.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` ### Stop Conditions -- Tests require native host containment to pass. -- Tests treat runtime ingress as enforcement. -- Tests rely on a rendered review screen as permission. +- The tests are prose-only while source can still imply authority. +- The tests forbid legitimate implementation folder names such as + `src/surfaces` instead of forbidding peer truth claims. ### Proof Gates -- Loops and retries require fresh action contracts. -- Dynamic tool construction is refused or proof-gapped. -- Raw sibling bypass posture is visible. -- Stale rendered review cannot authorize changed parameters. +- Tests require `projection/readback` language. +- Tests forbid "product lane", "protocol lane", "separate product truth", and + product vocabulary as authority. +- Existing workflow admission non-authority tests still pass. -### Verification Commands Or Checks +### Verification ```bash -npm run test -- test/runtime/runtime-ingress.test.ts +npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts npm run quality:architecture ``` -### Rollback Or Abandonment Criteria - -If runtime tests expose a source bug in current ingress posture, stop implementation and fix the source bug before continuing product polish. - -### Agent Handoff Needs - -Do not claim browser, A2A, OpenAPI, Hermes, OpenClaw, Claude Code, or generic MCP containment from local tests. - -## Slice T2-04 - x402 / auth.md Protected-Action Fixture Gate +## Slice N4-01 - Runtime And Protected-Action Regression ### ID -T2-04 +N4-01 ### Invariant Or Risk -The first fixture that connects service workflow admission to a protected action can imply that admission cleared spend. +Generated agents will treat simpler vocabulary as permission unless runtime and +protected-action gates stay fresh. ### Objective -Connect one admitted workflow context to one fresh buyer-side `x402_payment.exact` action request. Record auth.md as provenance/proof-gap only; do not compose auth.md credential authority with x402 spend authority in this fixture. - -### Source Evidence - -- `src/adapters/x402-payment/*` -- `src/adapters/auth-md/*` -- `examples/x402-protected-spend/` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/integration/x402-d1-http.test.ts` -- `.planning/macro-map/PROTECTED-ACTION-MAP.md` - -### Inputs +Confirm or add regressions proving service workflow context only prepares +proposal context; each protected action still requires fresh exact clearance. +Add the sidecar-identified P0 gates for mixed-family same-envelope runtime +evidence and x402/auth.md non-composition. -Tier 1/Tier 2 admission example and runtime misuse tests. +### Candidate Paths -### Outputs - -Fixture or product test proving fresh contract, policy, gateway check, replay refusal, and proof-gap separation. - -### Dependencies - -T2-03. - -### Owner - -Protected-action fixture implementer. +- `test/runtime/runtime-ingress.test.ts` +- `test/runtime/auth-md-candidate-compilation.test.ts` +- `test/product/service-workflow-admission.test.ts` +- `examples/service-workflow-admission/` +- `.planning/macro-plan/RUNTIME-GATES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` ### Stop Conditions -- `PaymentPayload` or `PAYMENT-SIGNATURE` enters passport/admission/handle. -- Signer invocation occurs before verified gateway evidence. -- Fixture claims live provider custody, settlement, facilitator operation, seller middleware, or aggregate spend. +- A handle can be reused for loops/retries without a fresh action contract. +- Mixed-family runtime dispatch evidence can combine mismatched tenant, + organization, principal, agent, run, runtime adapter, operating envelope, + gateway registry, or authority-holder context into one runtime spine. +- x402/auth.md generated composition creates a composite authority artifact. +- x402/auth.md fixture output suggests composite authority. +- Payment/signature/credential material leaks into admission or handle records. ### Proof Gates -- Fresh `ActionContract` is created for the protected action. -- Policy and gateway evidence remain separate. -- Replay refusal and downstream proof gap are recorded distinctly. -- Handle is context only. +- Existing misuse tests pass. +- Mixed-family dispatch families must share one generated execution envelope or + refuse before runtime evidence is projected as one spine. +- x402 and auth.md composition must become separate candidates or refusal, never + a single composite authority contract. +- Any new projection fields have explicit non-authority semantics. -### Verification Commands Or Checks +### Verification ```bash -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts -npm run quality:claims +npm run test -- test/runtime/runtime-ingress.test.ts test/product/service-workflow-admission.test.ts ``` -### Rollback Or Abandonment Criteria - -Defer auth.md composite behavior unless credential holder, gateway holder, refusal boundary, and raw credential redaction are source-proven. - -### Agent Handoff Needs - -Treat x402/auth.md as evidence rails until exact clearance; do not merge them into a composite authority artifact. - -## Slice T2-05 - Tier 3 Lock And Release Gate +## Slice N5-01 - Review, Evaluation, And Commit Closeout ### ID -T2-05 +N5-01 ### Invariant Or Risk -Hosted Tier 3 pressure can pull unfinished product simplification into hosted claims and package creep. +The branch can look clean while preserving a weak conceptual split. Review must +verify the goal, not just tests. ### Objective -Add a release/admission gate stating Tier 3 cannot consume or extend the simplified surface until Tier 1 and Tier 2 gates are verified or proof-gapped. - -### Source Evidence - -- `docs/internal/decisions.md` -- `.planning/macro-map/MACRO-HANDOFF.md` -- Memory-derived prior Tier 3 boundary guidance -- `README.md` - -### Inputs - -Completed Tier 1/Tier 2 gates. - -### Outputs +Run sidecar review, macro validation, focused gates, full repo gate, record +evidence/proof gaps, and commit coherent checkpoints. -Decision entry or internal gate doc update, plus final repo gate evidence. +### Candidate Paths -### Dependencies - -T2-04. - -### Owner - -Release gate owner. +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md` +- `.planning/macro-plan/REVIEW-GATES.md` +- `.planning/macro-plan/EVIDENCE-PLAN.md` +- git commit history ### Stop Conditions -- Tier 3 hosted operation starts from unverified local surface behavior. -- Protocol kernel exports expand for hosted needs without separate Tier 1/Tier 2 proof. -- Product language claims clearing-house, marketplace, certification, settlement, or cross-org trust. +- Sidecars identify a P0/P1 that cannot be resolved or recorded as a proof gap. +- `npm run check:repo` fails and no narrowed equivalent is justified. +- Working tree contains unrelated or unstaged goal changes at closeout. ### Proof Gates - `npm run check:repo` passes. -- Tier 3 proof gaps are explicit. -- Any required hosted workspace boundary is recorded separately. +- Macro-plan validator passes. +- Sidecar findings are resolved or recorded. +- Git status is clean after final commit. -### Verification Commands Or Checks +### Verification ```bash npm run check:repo -git status --short +git status --short --branch ``` - -### Rollback Or Abandonment Criteria - -If Tier 3 needs a kernel change, split it back into Tier 1/Tier 2 before hosted work continues. - -### Agent Handoff Needs - -Do not implement hosted operation in this checkout as part of simplification unless the user explicitly opens a separate Tier 3 workspace. diff --git a/.planning/macro-plan/MACRO-PLAN.md b/.planning/macro-plan/MACRO-PLAN.md index 23ed099..cf6ff20 100644 --- a/.planning/macro-plan/MACRO-PLAN.md +++ b/.planning/macro-plan/MACRO-PLAN.md @@ -2,200 +2,293 @@ ## Invariant At Stake -Tier 1 and Tier 2 product simplification may hide protocol complexity from users, but it must not hide authority. A user can see a clean flow, an agent can carry a workflow handle, and a service can accept standing evidence, but no Passport, Admission, Badge, Handle, Certificate, review screen, or ID can become identity, permission, reusable auth, policy approval, gateway acceptance, signer permission, receipt export, terminal certification, or mutation authority. +Handshake must not split into product truth and protocol truth. Product +vocabulary may make service intake legible, but it must be a non-authority +projection/readback over one protected-action event spine. -The protected-action invariant remains exact: +The single authority spine remains: ```text -standing evidence --> service-side admission/readback --> bounded workflow context --> fresh protected-action request --> exact ActionContract +CandidateAction / ActionContract -> PolicyDecision -> one-use Greenlight or Refusal -> GatewayCheck before mutation -> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate ``` +Passport, Admission, Handle, Clearance, Outcome, Certificate, Badge-like labels, +review screens, CLI output, MCP resources, SDK helpers, demos, and support +bundles can only project, request, or read this spine. They cannot create a peer +lane that authorizes, reinterprets, or bypasses it. + ## Source Boundary | Source | Role | Status | | --- | --- | --- | -| `.planning/macro-map/MACRO-HANDOFF.md` | Handoff from Passport / Admission / Badge macro map | Decision-gated, now user-authorized for full planning | -| `.planning/macro-map/MACRO-MAP.md` | Selected macro move and non-proofs | Derived planning evidence | -| `.planning/macro-map/FACET-MAP.md`, `views/*.md` | CEO, ENG, DESIGN, DEVEX, AGENT, RUNTIME, AUTHORITY pressure | Independent lens evidence | -| `.planning/macro-map/MECHANISM-MAP.md`, `EXECUTION-MAP.md`, `EXPERIENCE-MAP.md`, `AGENT-RUNTIME-MAP.md`, `PROTECTED-ACTION-MAP.md` | Mechanism, sequencing, experience, runtime, and authority maps | Required plan inputs | -| `.planning/codebase/ARCHITECTURE.md`, `STRUCTURE.md`, `CONVENTIONS.md`, `TESTING.md`, `CONCERNS.md`, `INTEGRATIONS.md`, `STACK.md` | Placement, testing, conventions, proof gaps, integrations, and package posture | Derived evidence; source-check during implementation | -| `README.md`, `QUALITY.md`, `STRUCTURE.md` | Package posture, quality language, source ownership | Canon | -| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Product kernel, proof ledger, expansion admission, current protocol notes | Canon | -| `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md` | Definition, architecture, and plain-language translation | Canon | -| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/*` | Input packet, source snapshot, blocked checks, sidecar audits, validation | Current run evidence | +| `.planning/macro-map/MACRO-HANDOFF.md` | Passport / Admission / Badge macro map | Derived planning input, decision-gated but user-authorized for correction | +| `.planning/macro-map/*` | Lens maps, concerns, decisions, tasks | Derived planning evidence | +| `.planning/codebase/*` | Repo architecture, testing, integrations, concerns | Derived evidence; source-check before canon | +| `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/*` | Current input, research, snapshot, sidecar audits, validation | Current run evidence | +| `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md` | Doctrine, orientation, quality, structure | Canon | +| `docs/internal/decisions.md`, `protocol-notes.md`, `protocol-layman.md`, `service-workflow-story.md` | Product/protocol canon and plain translation | Canon | +| `src/protocol`, `src/surfaces`, `src/runtime`, `src/cli`, `src/mcp`, `examples/service-workflow-admission`, `test/*` | Source-owned behavior and proof gates | Mechanism truth | + +## Research Mechanisms + +Primary-source research is recorded in +`.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md`. +The imported mechanisms are: + +- Stripe PaymentIntents: one lifecycle object with explicit statuses and + idempotency, not multiple truth lanes. +- Kubernetes Admission / OPA: request-time chokepoints and rejection before + persistence or mutation. +- Vault: custody, leases, renewal, revocation, and audit; handles do not become + raw secret material. +- GitHub deployment environments: protection rules before execution proceeds. +- AWS IAM: default deny and explicit deny overriding convenience. +- SLSA / artifact attestations: provenance and certificates are terminal + evidence, not future permission. +- Vercel / Cloudflare: product copy names scope and method; verification is + repeated instead of assuming stale context remains valid. + +These are mechanisms only. They do not prove Handshake hosted operation, +provider custody, marketplace trust, or host containment. ## Current Evidence -The current kernel already has the protected-action authority spine: exact contracts, policy decisions, one-use greenlights/refusals, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. Canonical docs make product surfaces non-authority by definition. Runtime ingress is proposal-only. MCP is proposal/evidence-only. CLI and SDK surfaces are role-scoped but do not infer authority from evidence reads. Gateway adapters mutate only after verified gateway evidence. - -The macro map converges on the same architectural conclusion: do not add a Passport protocol primitive; do not make Admission a policy decision; do not make Badge reusable auth. The right product simplification is a surface/readback layer that translates standing evidence into service workflow admission, then forces every protected action into fresh clearance. - -The codebase map points to `src/surfaces` as the first implementation home. It also names the verification lanes: claim-boundary tests, naming-posture tests, surface-boundary posture tests, protocol compilation/policy/gateway tests, runtime-ingress tests, and product/demo tests when examples change. +- The existing protocol kernel already owns exact contracts, policy decisions, + one-use greenlights/refusals, gateway checks, receipts, refusals, proof gaps, + isolation, and terminal certificates. +- The existing service workflow admission schema already hard-codes + non-authority boundaries for admission and handle records. +- Sidecar audits found the right source shape but unsafe vocabulary pressure: + `product surface` is overloaded, `sdk.policy` is currently named as an + authority surface, product projection terms lack one source-owned lifecycle + map, and runtime composition needs same-envelope/non-composition gates. +- The current run has primary-source research, source snapshot, blocked checks, + and five sidecar audits under + `runs/20260525T110908Z-architectural-north-star/`. ## Non-Proofs -This plan does not prove live x402 provider custody, settlement finality, seller middleware, facilitator operation, broad x402 compatibility, hosted operation, external registry lookup, marketplace trust, cross-org passport trust, native host containment, browser-side control, aggregate spend enforcement, provider-grade auth.md credential lifecycle, or Tier 3 hosted product readiness. - -It also does not prove that users will interpret Badge correctly. The plan resolves that by using `ServiceWorkflowHandle` as the source/API noun and treating Badge as optional narrative copy only. User-facing simplicity must come from state separation and explicit non-authority fields, not from a magical noun. +This plan does not prove live x402 provider custody, settlement/finality, +facilitator operation, seller middleware, marketplace trust, cross-org trust, +aggregate spend enforcement, hosted operation, hosted org auth, +retention/search, broad runtime containment, or user comprehension of the +projection vocabulary. ## Selected Macro Move -Build a two-tier simplification program: +Replace "dual product/protocol lanes" with this architecture: ```text -Tier 1: Source-owned non-authority surface contract - -> service workflow story - -> ServiceWorkflowAdmission / ServiceWorkflowHandle schema - -> non-authority ID fields - -> architecture and claim-boundary guards - -> docs and plain-language convergence - -Tier 2: Activation and readback convergence - -> SDK/CLI/MCP/example surfaces use the same model - -> generated-agent and runtime misuse gates - -> local fixture connects admitted workflow context to one fresh x402 exact action request - -> receipt/refusal/proof-gap readback remains event-specific - -> Tier 3 remains blocked until proof gates pass or proof gaps are explicit +Projection vocabulary + Passport / ServiceWorkflowAdmission / ServiceWorkflowHandle / Clearance / Outcome + over +ProtectedActionEvent lifecycle + exact contract -> policy/refusal -> one-use greenlight -> gateway check -> terminal evidence + enforced by +Gateway-owned mutation adapters and protocol kernel transitions + reconstructed through +Receipts, refusals, proof gaps, isolation, terminal certificates, and support bundles ``` -The five non-authority ID fields are part of the surface contract only: +The repo may keep `src/surfaces` as an implementation folder, but canonical docs +must split three concepts: -```text -passportPackageDigest -passportPresentationId -admissionId -serviceWorkflowHandleId -serviceWorkflowHandleDigest -``` - -Each field must carry `createsAuthority: false` at the surface-object level and must not satisfy policy, gateway, signer, mutation, receipt, or certificate requirements. +- product projection/readback surfaces: non-authority surfaces for service + workflow, evidence, reports, demos, and copy; +- role-scoped protocol transition clients: SDK/HTTP clients that transport a + specific protocol transition under custody and kernel/gateway authority; +- the protocol authority spine: the only place that creates policy decisions, + one-use greenlights/refusals, gateway checks, receipts, refusals, proof gaps, + isolation, and terminal certificates. -## Plan Status - -`READY_FOR_AGENT_EXECUTION` - -The executable claim is narrow: a bounded agent can start the first implementation slice from `AGENT-HANDOFF.md` without chat-only context. This status does not mean all Tier 1/Tier 2 work is implemented, and it does not mean Tier 3 can start. Former decision-gated concerns are resolved into implementation gates: the user accepted a full plan plus implementation sequence, while non-authority, runtime, protected-action, evidence, and review checks remain required stop conditions. +None of these are peer product/protocol truth lanes. Product projection +surfaces never create authority. Role-scoped transition clients do not make +product nouns authoritative; they are transport into the protocol authority +spine. ## Execution Thesis -The simplification succeeds by changing the user’s first model, not by changing the authority spine. - -The user should see: - -```text -Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome -``` - -The implementation must still preserve: +The correction succeeds by making projection subordinate to protocol authority +in both language and mechanism: + +1. Canonical docs name one protected-action event spine. +2. Source owns a service-workflow lifecycle projection map under `src/surfaces`. +3. Architecture tests require product vocabulary to remain projection/readback. +4. Runtime/protected-action tests prove mixed-family and x402/auth.md + composition cannot blur authority contexts. +5. Review and evidence gates distinguish planning proof from execution proof. + +## Ten-Star Success Criteria + +- Exactly one authority spine is named and enforced in docs, source, and tests. +- Product nouns are explicitly projection/readback nouns, never authority nouns. +- Canonical docs no longer imply product/protocol peer lanes. +- `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` remain schema-level + non-authority records. +- A source-owned service workflow lifecycle projection map ties Passport, + Admission, Handle, Clearance, Outcome, and Certificate to existing lifecycle + entries or explicit pre-contract evidence context. +- Passport IDs remain correlation/reconstruction fields only. +- Badge remains forbidden as a schema/protocol/export noun; if it appears, it is + read-only state label language only. +- Case-study research is captured as mechanism rules with source URLs. +- Runtime misuse remains covered for loops, retries, stale handles, dynamic + tools, raw sibling bypass, stale review, replay, and proof gaps. +- Mixed-family runtime blocks either share one execution envelope or fail before + being projected as one runtime spine. +- x402/auth.md composition remains separate exact contracts or refusal; no + composite credential-plus-payment authority artifact is created. +- Hosted/Tier 3 remains blocked unless a separate hosted workspace or fresh + pre-hosted kernel task proves the missing gates. +- A fresh agent can resume from `AGENT-HANDOFF.md` without chat memory. + +## Execution Slices + +This package decomposes the correction into: ```text -Evidence refs -> CandidateAction -> ActionContract -> PolicyDecision -> one-use Greenlight/Refusal -> GatewayCheck -> Receipt/Refusal/ProofGap +N0 - Research and macro-plan reset +N1 - Canonical projection-over-spine language +N2 - ProtectedActionEvent projection mapping +N3 - Architecture guards against dual-lane drift +N4 - Runtime/protected-action regression gates +N5 - Review, validation, full repo gate, and commit closeout ``` -Tier 1 creates the non-authority model and proves it cannot create authority. Tier 2 connects that model to activation, runtime, and example surfaces so developers do not meet raw protocol internals first. Tier 3 stays locked until the local/source-owned simplification path is coherent. +Each slice is detailed in `EXECUTION-SLICES.md` and assigned in `TASKS.jsonl`. ## Non-Goals -- Do not add `Passport`, `Admission`, `Badge`, or `ServiceWorkflowHandle` as protocol primitives. -- Do not widen `OperatingEnvelope.allowedResources` from a passport or handle. -- Do not let a handle become a bearer token, greenlight, gateway pass, credential ref, signer input, payment payload, receipt, certificate, or mutation command. -- Do not claim hosted operation, provider custody, settlement, marketplace trust, cross-org trust, native host containment, aggregate spend enforcement, live provider verification, or Tier 3 readiness. -- Do not turn `.planning/` artifacts into repo-facing source names, package scripts, public exports, or canonical docs. -- Do not build a full x402/auth.md live demo before surface non-authority gates exist. +- Do not add a new protocol primitive for Passport, Admission, Handle, Outcome, + Certificate, Badge, or `ProtectedActionEvent` unless a separate source-owned + transition proposal proves a new enforceable state. +- Do not remove `src/surfaces`; correct its meaning instead. +- Do not widen package exports, CLI/MCP authority, SDK role powers, gateway + adapters, or hosted claims. +- Do not claim live provider custody, x402 settlement, facilitator operation, + seller middleware, marketplace certification, cross-org trust, aggregate spend + enforcement, native host containment, hosted org auth, or retention/search. +- Do not treat the case studies as evidence that Handshake already has their + enforcement properties. ## Target State -Tier 1 target state: +Canon says: -- `docs/internal/service-workflow-story.md` explains Passport, Service Admission, Workflow Handle, Action Request, Clearance, and Outcome in plain language. -- `src/surfaces/service-workflow-admission.ts` defines `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` as non-authority product-surface records. -- Tests prove the new surface cannot create or satisfy policy, greenlight, gateway check, mutation, receipt, certificate, signer use, payment material, raw credentials, or resource widening. -- Canonical docs use the simplified flow without overclaiming. +```text +Product vocabulary is projection/readback over one protected-action event spine. +The protocol kernel remains the source-owned authority state machine. +Projection surfaces expose proposal, context, evidence, and readback only. +``` -Tier 2 target state: +Source/tests prove: -- README first-use, protocol-layman docs, SDK role-client guidance, CLI/MCP descriptions, and examples converge on the same simplified flow. -- A local example emits JSON and Markdown for service workflow admission and a fresh x402 action request path. -- Runtime and generated-agent negative cases cover loops, retries, branches, dynamic tool construction, stale review, changed observed parameters, raw sibling bypass, replay, proof gaps, and isolation. -- Product tests prove admission/readback and protected-action outcome evidence remain separate. +- The service workflow schema cannot create authority. +- Canonical docs must contain projection-over-spine wording. +- Canonical docs must not describe product/protocol as peer authority lanes. +- Product vocabulary cannot appear in protocol areas or root authority exports + as a shortcut. +- Runtime handles can assist proposal context only; each protected action still + creates a fresh exact contract and reaches a fresh policy/gateway boundary. ## Decisions -- Accept `Passport` as a docs/story input noun only. -- Accept `ServiceWorkflowAdmission` as the source/API surface output noun. -- Accept `ServiceWorkflowHandle` as the carried workflow context noun. -- Treat `Badge` as optional narrative shorthand only; do not make it a schema, protocol, export, or route noun. -- Split non-authority IDs into `passportPackageDigest`, `passportPresentationId`, `admissionId`, `serviceWorkflowHandleId`, and `serviceWorkflowHandleDigest`. -- Keep the first implementation in docs, `src/surfaces`, architecture tests, and product tests before any x402/auth.md fixture expansion. -- Keep Tier 3 blocked until Tier 1/Tier 2 gates are verified or explicitly recorded as proof gaps. - -## Blocking Concerns - -The plan carries strict implementation gates: - -- Non-authority flags are mandatory on admission and handle objects. -- The handle must not be accepted as policy, gateway, signer, mutation, receipt, or certificate evidence. -- Multi-host runtime posture must stay host-specific and proof-gap aware. -- Source placement must remain outside protocol areas unless a future source-owned transition proves a new enforceable state. -- Product docs must include exact fields, failure states, and proof gates; metaphor-only docs are insufficient. -- Protected-event terminalization remains the economic unit; passport validation is adoption plumbing, not the bought authority claim. +- Keep `src/surfaces` as a source-owned implementation boundary. +- Rename the mental model from `product surface vs protocol kernel` to + `projection/readback surface over protocol authority spine`. +- Use `ProtectedActionEvent` as a documentation/testing lifecycle concept + source-owned through a `src/surfaces` projection map. Do not create a stored + protocol object yet. +- Keep Passport as presentation evidence, Admission as service-side mapping, + Handle as context/readback reference, Clearance as fresh protected-action path, + and Outcome as terminal readback projection. +- Treat Badge as unsafe shorthand unless explicitly marked as a read-only state + label derived from evidence. -## Runtime And Protected-Action Summary +## Risks And Proof Gaps -Runtime posture: +- The word `surface` is entrenched in code. The mitigation is explicit docs and + tests saying surface means projection/readback implementation boundary. +- `Admission` remains overloaded with HTTP admission and service workflow + admission. The mitigation is explicit naming and tests that block policy/gate + implications. +- Product UX is not solved by this slice. The result is source-owned + architecture and proof language, not a finished app front door. +- Hosted/Tier 3 pressure remains a kernel-creep risk and stays blocked. -| Target | Evidence | Posture | -| --- | --- | --- | -| Codex | Existing local profile/readiness and MCP proposal evidence | Strongest local profile; no host-wide containment claim | -| Claude Code | Managed/profile parity artifacts in current x402 protected-tool lane | Profile evidence only | -| Hermes | Tool-packet/profile artifact | Profile evidence only | -| OpenClaw | Tool-packet/profile artifact | Profile evidence only | -| MCP | Local proposal/evidence server and read-only resources | Proposal/readback only | -| x402 | One buyer-side exact per-call local proof lane | Protected-action family; no live provider/settlement claim | -| auth.md | Provenance and credential-custody evidence profile | Evidence and future protected API call family | -| Browser, A2A, OpenAPI | Operation, route, and side-channel evidence contexts | Proof-gap surfaces until gateway-owned path exists | +## Blocking Concerns -Protected-action posture: the first Tier 2 fixture may connect an admitted workflow handle to one `x402_payment.exact` action request, but only after the handle is proven non-authority. The handle may help populate context and evidence refs. It cannot skip candidate action, exact contract, policy, one-use greenlight/refusal, gateway check, or terminal readback. +These are accepted-risk items for executing this correction plan only. They are +not accepted as product truth, hosted claims, or release-complete posture. Each +P0/P1 below is either assigned to an execution slice or preserved as a proof gap +until source/tests prove the mechanism. + +- P0: `product surface` remains overloaded until canonical docs split product + projection/readback surfaces from role-scoped protocol transition clients. +- P0: `sdk.policy` and similar clients must not be named authority surfaces; + they must be framed as custody-scoped transport into kernel transitions. +- P0: product projection terms need a source-owned lifecycle projection map or + docs remain the only guard. +- P0: mixed-family runtime blocks must prove one execution envelope or refuse. +- P0: x402/auth.md composition must not produce one composite authority object. +- P1: full product UX is still not implemented; this run corrects architecture + and source-owned projection semantics. ## Verification Gates -- Execute `npm run quality:claims` after canonical docs or public language changes. -- Execute `npm run quality:architecture` after source surfaces, naming, exports, CLI, MCP, SDK, or adapter posture changes. -- Execute the focused protocol simplification slice when proposal/evidence/readback paths change: `npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts`. -- Execute product/demo tests after adding the service workflow example. -- Execute `npm run format:check` and `npm run check:repo` before claiming implementation closeout. -- Validate this macro-plan package with `/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan`. +- Macro-plan validator: + `/Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan` +- Focused claim/architecture gates: + `npm run quality:claims` + `npm run quality:architecture` + `npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts` +- Runtime/product regression where touched: + `npm run test -- test/runtime/runtime-ingress.test.ts test/product/service-workflow-admission.test.ts` +- Closeout: + `npm run format:check` + `npm run check:repo` -## Risks And Proof Gaps +## Runtime And Protected-Action Summary -Primary risk: the friendly product layer becomes authority-shaped. The mitigation is schema-level non-authority flags, architecture gates, product tests, runtime negative cases, and refusal/proof-gap readback. +Runtime posture remains evidence-only. Codex, Claude Code, Hermes, OpenClaw, +MCP, browser, A2A, OpenAPI, auth.md, and x402 do not share one containment +model. Runtime ingress may record generated-execution evidence and propose +contracts only. -Secondary risk: Tier 2 tries to prove too much too early. The mitigation is a local/source-owned fixture first, explicit non-claims, and no live-provider or hosted claim until a separate evidence packet proves it. +Protected-action posture remains one event at a time. Projection vocabulary may +help prepare context, but every consequential action still requires a fresh +exact contract, policy/refusal, one-use greenlight when allowed, gateway check +before mutation, and terminal receipt/refusal/replay/proof-gap/certificate +evidence. x402/auth.md composition and mixed-family dispatches are blocking +runtime gates until focused tests prove separation or refusal. -Long-run risk: Tier 3 pressure causes kernel/package creep. The mitigation is a hard gate: Tier 3 may consume the simplified Tier 1/Tier 2 surface only after source gates pass; if Tier 3 needs kernel changes, those return as separate Tier 1/Tier 2 work. +## Long-Running End Condition -## Handoff To Phase Planning +The run is complete only when research, macro plan, implementation, evaluation, +sidecar/review evidence, and git commits all support one conclusion: Handshake +has one protocol authority spine, and product vocabulary is projection/readback +over that spine. -Detailed phase planning should start from `EXECUTION-SLICES.md`, not from chat memory. Slice T1-01 is the first implementation step: create the internal story doc and source-owned surface contract skeleton in a way that is immediately testable. Slice T1-02 and T1-03 add the strict schema and guard tests. Tier 2 slices begin only after Tier 1 gates pass. +## Handoff To Phase Planning -Fresh agents must read `AGENT-HANDOFF.md`, `PROTECTED-ACTION-GATES.md`, `RUNTIME-GATES.md`, and `TASKS.jsonl` before editing source. They must source-open named files before implementation and preserve user-owned dirty state. +Detailed phase work starts from `EXECUTION-SLICES.md` and `TASKS.jsonl`, not +from chat memory. The first implementation slice is canonical docs plus +claim-boundary guards. The second implementation slice source-owns the service +workflow lifecycle projection map under `src/surfaces`. Runtime P0 gates follow +before closeout. Fresh agents must read `AGENT-HANDOFF.md`, +`RUNTIME-GATES.md`, `PROTECTED-ACTION-GATES.md`, and sidecar audits before +editing. ## Smallest Next Mechanism -Implement the Tier 1 surface spine: +Install a source-owned `Product Vocabulary Is Projection Only` guard in +canonical docs and `test/architecture/claim-boundary.test.ts`, then run the +focused claim/architecture gates before touching broader examples. -```text -docs/internal/service-workflow-story.md -src/surfaces/service-workflow-admission.ts -test/architecture/workflow-admission-boundary.test.ts -``` +## Plan Status -The story and schema must define the five non-authority IDs, require fresh action contracts for protected events, and prove the surface cannot create authority. +`READY_FOR_AGENT_EXECUTION` diff --git a/.planning/macro-plan/PROTECTED-ACTION-GATES.md b/.planning/macro-plan/PROTECTED-ACTION-GATES.md index fcc7c47..4f2463c 100644 --- a/.planning/macro-plan/PROTECTED-ACTION-GATES.md +++ b/.planning/macro-plan/PROTECTED-ACTION-GATES.md @@ -1,145 +1,156 @@ # Protected-Action Gates -## Source Boundary - -| Source | Protected-Action Role | Status | -| --- | --- | --- | -| `.planning/macro-map/PROTECTED-ACTION-MAP.md` | Authority, gateway, bypass, and readback map | Derived gate input | -| `.planning/macro-map/views/AUTHORITY.md` | Non-authority and field-boundary pressure | Lens evidence | -| `.planning/macro-map/views/RUNTIME.md` | x402/auth.md and host-profile proof gaps | Lens evidence | -| `.planning/codebase/ARCHITECTURE.md`, `CONCERNS.md`, `INTEGRATIONS.md` | Current authority placement and integration boundaries | Derived codebase evidence | -| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Canon product/protocol boundary | Canon | -| `src/adapters/x402-payment/wallet-gateway.ts` | Current signer boundary after verified gateway evidence | Source anchor for implementation phase | -| `src/adapters/auth-md/gateway.ts` | Current credentialed API fixture after verified gateway evidence | Source anchor for implementation phase | - -## Protected-Action Triggers - -Protected-action gates apply when an admitted workflow attempts: +## Invariant At Stake -- `x402_payment.exact`; -- `auth_md_protected_api_call.exact`; -- credentialed service call; -- external API mutation; -- package install, repo write, preview deploy, cloud config, CI/release, or database/data-plane mutation; -- browser-side paid or consequential action; -- any generated tool call with side effects. +Every consequential mutation must pass through the single protected-action +authority spine. Projection/readback vocabulary cannot become a shortcut around +candidate compilation, exact contract, policy, one-use greenlight/refusal, +gateway check, or terminal evidence. -## Candidate Actions +## Source Boundary -The admission surface may help produce context for a fresh candidate action. It cannot be the candidate action. It cannot be an action contract. It cannot carry a policy result. It cannot carry a one-use greenlight. It cannot carry gateway check evidence. +Protected-action truth lives in `src/protocol`, `src/adapters`, gateway tests, +runtime tests, product tests, and canonical docs. This planning file defines +gates only; it does not create authority or gateway enforcement. -First admitted Tier 2 candidate: +## Authority Spine ```text -serviceWorkflowHandle -> fresh x402_payment.exact action request -> ActionContract +runtime/projection context +-> CandidateAction +-> ActionContract +-> PolicyDecision +-> one-use Greenlight or Refusal +-> GatewayCheck before mutation +-> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate ``` -The handle is context and evidence refs only. +## Protected-Action Triggers -Non-composite rail rule: +- any generated runtime dispatch that may mutate a protected surface; +- any x402 payment attempt; +- any auth.md-backed protected API call; +- any package/repo/preview/cloud/database/deploy mutation path; +- any retry, branch, loop, or sibling call that changes endpoint, payee, + resource, gateway, credential, delegated authority, body digest, or payment + requirement. -```text -serviceWorkflowHandle -> fresh x402_payment.exact action request -serviceWorkflowHandle -> fresh auth_md_protected_api_call.exact action request -``` +## Candidate Actions -These are separate rails. No fixture may merge x402 spend authority and auth.md -credential authority into one authority artifact. +Candidate actions are proposed commitments only. Passport, Admission, Handle, +Badge-like labels, Clearance wording, Outcome readback, and Certificate evidence +can provide context or references, but they cannot satisfy candidate creation or +contract proposal requirements. ## Authority Boundary -Authority begins at exact policy evaluation over an `ActionContract`, then proceeds to one-use greenlight/refusal and gateway check. Admission and handle surfaces must explicitly state: - -```text -createsAuthority: false -createsPolicyDecision: false -createsGreenlight: false -performsGatewayCheck: false -permitsMutation: false -exportsReceipt: false -mintsTerminalCertificate: false -freshActionContractRequired: true -``` +Authority begins only at exact policy greenlight and is usable only once after a +gateway verifies the same exact contract before mutation. Refusals, proof gaps, +isolation, stale posture, and explicit deny conditions dominate projection +convenience. ## Gateway Or Enforcement Boundary -The gateway check remains the final pre-mutation enforcement point. For x402, payment material and `PAYMENT-SIGNATURE` remain behind the gateway and only appear after verified gateway evidence. For auth.md, raw credential material remains outside protocol records and credential resolution occurs after gateway check. - -If a path cannot enforce at the gateway before mutation, this is advisory, not Handshake. +The gateway check is the final pre-mutation enforcement point. SDK clients, +HTTP routes, CLI commands, MCP resources, demos, review screens, receipts, and +projection maps are not gateway enforcement. ## Raw Sibling Or Bypass Posture -The plan must preserve raw sibling posture: +Raw sibling package managers, x402 signers, auth.md credentials, browser tools, +direct HTTP/network calls, shell commands, cloud/deploy APIs, and database paths +must be prevented, isolated, or recorded as bypass/proof-gap evidence. Projection +vocabulary cannot claim containment over them. -- raw x402 payment payload input is forbidden; -- raw bearer/API tokens are forbidden; -- direct HTTP, MCP, browser, package manager, shell, network, cloud, deploy, or database paths are bypass/proof-gap surfaces unless wrapped by a gateway-owned protected path; -- dynamic endpoint/tool construction requires refusal or recrafting; -- stale metadata, changed observed parameters, consumed greenlight replay, idempotency mismatch, gateway policy drift, authority-ref isolation, and credential-ref isolation require refusal or a fresh exact contract. +## Generated-Execution Stress Coverage -## Field-Level Acceptance Matrix +Coverage must include loops, retries, branches, dynamic tool construction, +late-bound parameters, stale review/handle evidence, changed observed +parameters, raw sibling paths, replay, ambiguous commits, proof gaps, isolation, +mixed-family same-envelope checks, and x402/auth.md non-composition. -| Field Or Surface | May Carry | Must Not Carry | Authority Posture | -| --- | --- | --- | --- | -| `passportPackageDigest` | digest of evidence bundle | identity trust, spend approval, signer material | evidence only | -| `passportPresentationId` | unique intake/presentation ref | policy decision, gateway admission | correlation only | -| `admissionId` | service-side accepted/refused/stale/proof-gap result ref | greenlight, receipt, certificate | readback only | -| `serviceWorkflowHandleId` | workflow context ref | bearer auth, tool permission, credential ref | context only | -| `serviceWorkflowHandleDigest` | digest of handle payload | resource widening, payment payload, signature | integrity only | -| `ServiceWorkflowAdmission` | claim rows, evidence refs, proof gaps, bounds digest | mutation permission, policy/gateway outputs | product surface | -| `ServiceWorkflowHandle` | context refs, expiry, next action requirements | raw secrets, receipts, certificates, signer refs | product surface | -| Action Request | candidate action input | reusable authority | proposal candidate | -| `ActionContract` | exact protected action commitment | execution proof | proposed commitment | -| `PolicyDecision` | allow/refuse/review/halt/quarantine decision | gateway check or mutation proof | policy authority | -| `Greenlight` | one exact gateway-bound use | reusable auth | one-use authority candidate | -| `GatewayCheckAttempt` | pre-mutation enforcement evidence | downstream business success | gateway authority | -| `Receipt` / `ProofGap` | terminal evidence/readback | future permission | terminal evidence | +## Evidence Readback Separation -## Generated-Execution Stress Coverage +Receipts, refusals, replay refusals, proof gaps, authority certificates, +support bundles, release proof, and projection maps are readback/evidence. They +must distinguish gateway admission from downstream execution/finality and must +not become permission for future attempts. -Tests and fixtures must cover: +## Receipt Refusal Proof-Gap Evidence -- loops that reuse the handle; -- retries after refusal, proof gap, replay, or isolation; -- branches that change endpoint, amount, resource, payee, gateway, or credential refs; -- dynamic tool names and late-bound parameters; -- stale rendered review; -- parallel proposals from one handle; -- raw sibling MCP/x402/browser/network/package-manager paths; -- generated code that emits a safe-looking output while attempting unsafe work. +Every terminal projection must identify whether the source event is a receipt, +policy/gateway/runtime refusal, replay refusal, proof gap, isolation consequence, +or terminal certificate. Missing evidence stays a proof gap. -## Evidence Readback Separation +## Projection Vocabulary Matrix -Admission readback is not protected-action receipt evidence. Readback must distinguish: - -- passport evidence; -- service admission result; -- workflow handle context; -- candidate action; -- action contract; -- policy decision; -- greenlight or refusal; -- gateway check; -- credential resolution after gateway check; -- mutation attempt; -- downstream observation; -- receipt; -- refusal; -- replay refusal; -- proof gap; -- optional terminal certificate. +| Product noun | Allowed use | Required protected-action gate | Forbidden meaning | +| --- | --- | --- | --- | +| Passport | Presented evidence package digest/reference | Fresh candidate and exact contract still required | identity, trust, permission, reusable auth | +| ServiceWorkflowAdmission | Service-side accepted/refused/stale/proof-gap mapping | No policy/gateway authority until fresh clearance | policy approval, gateway admission, receipt | +| ServiceWorkflowHandle | Correlation/readback context for later proposals | May only populate context refs on a fresh request | bearer token, retry permission, greenlight | +| Clearance | Fresh protected-action path | Must include policy/refusal and gateway check before mutation | workflow-level permission | +| Outcome | Terminal event projection | Must derive from receipt/refusal/replay/proof-gap/certificate evidence | downstream success or future authority | +| Certificate | Terminal verification evidence | Must be terminal and verifiable; never pre-action | permission, identity, settlement, hosted trust | +| Badge-like UI | Read-only state label derived from evidence | No schema/protocol/export route authority | executable grant or bearer credential | + +The source-owned projection map for these terms belongs under `src/surfaces` and +must validate any lifecycle keys against the existing action-attempt lifecycle. +It must not add a stored protocol object. -## Receipt Refusal Proof-Gap Evidence +## Field-Level Acceptance Matrix -Receipts prove the Handshake chain, not downstream business success. Refusals are durable product outcomes, not noise. Proof gaps are explicit missing, stale, contradictory, or unavailable evidence. Replay refusal proves one-use authority was already consumed or duplicated. None of these outcomes grants retry permission without a fresh exact contract. +| Field/material | Allowed in projection | Authority posture | +| --- | --- | --- | +| `passportPackageDigest` | yes | correlation only | +| `passportPresentationId` | yes | presentation event only | +| `admissionId` | yes | service-side mapping only | +| `serviceWorkflowHandleId` | yes | readback/context only | +| `serviceWorkflowHandleDigest` | yes | context integrity only | +| `ActionContract` refs | context refs only | proposed commitment, not permission | +| `PolicyDecision` refs | readback after source record | protocol authority state only | +| `Greenlight` refs | never as projection input authority | one-use gateway-bound only | +| `GatewayCheck` refs | readback after source record | enforcement evidence only | +| raw credential/payment/signature material | no | gateway/custody only | + +## x402/auth.md Gates + +- x402 remains one buyer-side `x402_payment.exact` per-call path. +- PaymentPayload and `PAYMENT-SIGNATURE` remain behind a verified gateway check. +- auth.md evidence can support provenance/custody posture but cannot combine + with x402 into composite authority. +- A generated block containing both auth.md and x402 must produce separate fresh + exact contracts or a refusal/proof gap. It cannot produce one composite + credential-plus-payment authority artifact. +- External sandbox/live provider, settlement/finality, facilitator operation, + seller middleware, aggregate spend enforcement, and provider custody remain + proof gaps unless separately proven. + +## Hosted/Tier 3 Gate + +Service workflow projection clarity is not hosted-operation readiness. Hosted +operation, hosted org auth, retention/search, marketplace trust, cross-org +trust, or new kernel exports require a separate hosted workspace or fresh +pre-hosted kernel task. ## Non-Claims -No Passport, Admission, Badge, Handle, Certificate, review surface, MCP tool, OpenAPI route, A2A task, x402 payment capability, auth.md credential issuance, runtime profile, host activation artifact, npm package, or registry listing creates authority. +These gates do not prove hosted operation, provider/customer custody, +settlement/finality, facilitator operation, seller middleware, marketplace +trust, cross-org trust, aggregate spend enforcement, native host containment, +or product UX completion. ## Blocked Checks -- Field-level negative tests do not exist yet. -- Workflow-handle-specific raw sibling inventory does not exist yet. -- Live external rails are unverified. -- Hosted operation and native host containment remain proof gaps. +- live x402 custody and settlement; +- provider/customer gateway custody; +- hosted operation and hosted org auth; +- marketplace/certification and cross-org trust; +- broad runtime interception or raw sibling inventory; +- UI/product comprehension proof. + +## Stop Condition + +Stop if any projection noun is accepted as policy input authority, gateway +binding, signer/custody material, mutation command, receipt export, certificate +minting input, or reusable authorization. diff --git a/.planning/macro-plan/README.md b/.planning/macro-plan/README.md index 38e4d02..edc85f4 100644 --- a/.planning/macro-plan/README.md +++ b/.planning/macro-plan/README.md @@ -1,47 +1,36 @@ -# Tier 1 / Tier 2 Product Simplification Macro Plan +# Macro Plan Package -## Scope +Run: `20260525T110908Z-architectural-north-star` +Status: `READY_FOR_AGENT_EXECUTION` -This package turns the current Passport / Admission / Badge macro map into a full Tier 1 and Tier 2 execution program. The goal is not a small story slice. The goal is to make Handshake simpler to use while preserving the exact contract, policy, one-use greenlight or refusal, gateway check, receipt, refusal, proof-gap, isolation, and reconstruction boundaries. +## Invariant -Tier 3 progression is blocked until Tier 1 and Tier 2 product surfaces are sharp, source-backed, and verified or proof-gapped. +Product vocabulary is projection/readback over one protected-action authority +spine. It is not a second lane of truth. -## Source Map +## Package -| Source | Role | Status | -| --- | --- | --- | -| `.planning/macro-map/*` | Current macro-map package and lens evidence | Derived planning input | -| `.planning/codebase/*` | Current codebase map for placement, tests, conventions, integrations, and concerns | Derived evidence; implementation must source-check | -| `README.md`, `QUALITY.md`, `STRUCTURE.md` | Current package posture, quality rules, source ownership | Canon | -| `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | Product kernel, proof ledger, protocol notes, expansion gates | Canon | -| `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md` | Protocol definition, architecture, and plain-language guide | Canon | -| `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/*` | Run input, source snapshot, sidecar audits, validation evidence | This plan run | +- `MACRO-PLAN.md` - chair-owned north-star plan and status. +- `EXECUTION-SLICES.md` - ordered implementation and verification slices. +- `TASKS.jsonl` - assignable next mechanisms. +- `AGENT-HANDOFF.md` - fresh-agent context. +- `RUNTIME-GATES.md` - generated-agent and host-runtime checks. +- `PROTECTED-ACTION-GATES.md` - authority, gateway, signer, and evidence gates. +- `EVIDENCE-PLAN.md` - proof collection and command matrix. +- `REVIEW-GATES.md` - sidecar and closeout review rules. +- `RISKS.md` - P0/P1 risks and proof gaps. +- `DECISIONS.md` - run decisions. -## Sidecar Review +## Current Run Evidence -Five sidecar auditors completed bounded reports: +- `runs/20260525T110908Z-architectural-north-star/input.md` +- `runs/20260525T110908Z-architectural-north-star/research.md` +- `runs/20260525T110908Z-architectural-north-star/source-snapshot.md` +- `runs/20260525T110908Z-architectural-north-star/blocked-checks.md` +- `runs/20260525T110908Z-architectural-north-star/audits/*` +- `runs/20260525T110908Z-architectural-north-star/validation.md` -- execution slices and full-program sequencing; -- protected-action posture and non-authority ID model; -- runtime and generated-agent posture; -- evidence, validation, and closeout gates; -- product, design, DevEx, and adoption. +## Smallest Next Mechanism -The chair owns sequencing, status, authority claims, and implementation entry. Sidecars pressure-test the plan; they do not promote proof gaps into authority. - -## Status - -This macro plan is validated as an implementation handoff for the first bounded Tier 1 story/schema/test slice and a full long-running program for the remaining Tier 1 and Tier 2 simplification work. It does not claim protected-action fixture readiness, runtime containment, Tier 3 readiness, hosted operation, external provider custody, settlement finality, marketplace trust, host-wide containment, or reusable passport authority. - -## Artifact Index - -- `MACRO-PLAN.md`: governing plan, scope, target state, and implementation entry. -- `EXECUTION-SLICES.md`: full Tier 1 and Tier 2 slices with proof gates and stop conditions. -- `AGENT-HANDOFF.md`: fresh-agent execution context and first implementation step. -- `RUNTIME-GATES.md`: host/runtime suitability and continuation gates. -- `PROTECTED-ACTION-GATES.md`: authority, gateway, field-level, bypass, readback, and proof-gap gates. -- `EVIDENCE-PLAN.md`: commands, examples, fixtures, review prompts, and unavailable evidence. -- `REVIEW-GATES.md`: sidecar and review gate reconciliation. -- `RISKS.md`: tracked risks with owners and mitigations. -- `DECISIONS.md`: accepted, rejected, deferred, and revisit-triggered decisions. -- `TASKS.jsonl`: assignable next mechanisms for planning and implementation. +Install canonical projection-over-spine language and a claim-boundary guard that +fails if product/protocol peer-lane language returns. diff --git a/.planning/macro-plan/REVIEW-GATES.md b/.planning/macro-plan/REVIEW-GATES.md index dae95a7..7037854 100644 --- a/.planning/macro-plan/REVIEW-GATES.md +++ b/.planning/macro-plan/REVIEW-GATES.md @@ -1,76 +1,129 @@ # Review Gates +## Invariant At Stake + +The chair owns final authority claims. Sidecars can pressure-test, but they +cannot promote a plan to ready or declare implementation complete. + ## Gate Summary -| Gate | Evidence | Status | -| --- | --- | --- | -| CEO | Buyer story and economic unit reviewed in macro-map lens | Keep language, contain it | -| Engineering | Source placement and tests reviewed in macro-map lens | Surface first, no protocol primitive | -| Design | User mental model reviewed in macro-map lens | State separation required | -| DevEx | First-use path and docs/SDK/CLI/MCP reviewed in macro-map lens | Converge surfaces after schema | -| Agent | Generated-agent misuse reviewed in macro-map lens | Handle misuse tests required | -| Runtime | Multi-host posture reviewed in macro-map lens | Host-specific proof gaps required | -| Protected Action | Authority and gateway boundary reviewed in macro-map lens | Non-authority matrix required | -| Evidence | Macro-plan validation and proof gaps | Validator and sidecar reconciliation required | +The review system must reject three failure classes: -## Sidecar Review +- architectural drift back into dual product/protocol authority lanes; +- product vocabulary that becomes identity, permission, reusable auth, receipt + substitute, or gateway shortcut; +- evidence that proves planning effort but not source-owned mechanism. -Sidecar audits are expected under `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/audits/`: +The plan can be promoted only when every gate below either passes with current +evidence or records a named proof gap that does not undermine the next slice. -- `slices.md` -- `protected-action.md` -- `runtime-agent.md` -- `evidence.md` -- `product-devex-design.md` +## Sidecar Review -All five sidecar reports are present. The chair reconciled them by narrowing implementation readiness to the first Tier 1 story/schema/test slice. Protected-action fixture work, multi-host runtime claims, public-surface convergence, and Tier 3 remain gated until their source proof exists. Sidecar findings can add gates, risks, and task details; they cannot authorize weaker authority claims. +At most five sidecars: -| Report | Chair Reconciliation | +| Report | Scope | | --- | --- | -| `audits/slices.md` | Full-program slices are captured in `EXECUTION-SLICES.md`; implementation starts only after macro validation. | -| `audits/protected-action.md` | Field-level matrix and negative-test requirements are captured in `PROTECTED-ACTION-GATES.md`; protected-action fixtures stay gated. | -| `audits/runtime-agent.md` | Host-specific posture and generated-execution stress gates are captured in `RUNTIME-GATES.md`; no generic multi-host execution claim. | -| `audits/evidence.md` | Validator result and status reconciliation are recorded in `EVIDENCE-PLAN.md` and run-local `validation.md`. | -| `audits/product-devex-design.md` | 10-star product criteria and convergence plan are captured in execution slices and tasks; public ergonomics wait for source schema/tests. | +| `architecture-case-study-audit.md` | Mechanism quality and case-study misuse | +| `product-vocabulary-projection-audit.md` | Product vocabulary and dual-lane language | +| `protected-action-lifecycle-audit.md` | Lifecycle/projection mapping | +| `runtime-protected-action-gates-audit.md` | Runtime misuse and protected-action gates | +| `evidence-review-gates-audit.md` | Evidence, validation, review, and commit closeout | + +The chair has accepted the sidecar reports as pressure inputs, not authority. +Resolved findings must appear in docs/source/tests. Unresolved findings remain +explicit proof gaps in `RISKS.md`, `blocked-checks.md`, or validation closeout. ## CEO Gate -Pass condition: the buyer story centers on protected-event clearing and reconstruction, not passport validation as authority. Passport validation may be free/open adoption plumbing. Paid value remains protected-event terminalization, retention/readback/export, and gateway readiness. +Question: does this make the product smaller, harder, sharper, and easier to +adopt without broadening the wedge? -Fail condition: the product sells trusted agents, reusable badges, passport permissions, marketplace certification, settlement, cross-org trust, or hosted clearing before proof. +Pass condition: the correction makes Handshake legible as protected-action +infrastructure for one cleared event lifecycle. It must not sell dashboards, +identity, agent trust, hosted clearing, marketplace certification, generic +observability, or approval theatre as the product. ## Engineering Gate -Pass condition: first implementation lives in `docs/internal`, `src/surfaces`, and architecture/product tests. It does not add `src/protocol/areas/passport`, protocol object registry entries, gateway adapter authority, root authority exports, or store migrations. +Question: can the mechanism be enforced and tested from source? -Fail condition: source placement makes a surface noun look like protocol state without a distinct enforceable transition. +Pass condition: there is one protocol authority spine, source-owned projection +mapping, focused tests for non-authority product nouns, and no widened package +exports, protocol primitives, gateway adapters, CLI/MCP authority, or hosted +claims. Any `sdk.policy`-like role client must be named as transition transport +under custody, not as a product authority surface. ## Design Gate -Pass condition: the user-facing model separates Passport evidence, Service Admission, Workflow Handle, Action Request, Clearance, Gateway Check, and Outcome. The review surface does not show one approval badge over mixed states. +Question: does simplification hide protocol complexity without lying about +authority? -Fail condition: admission review is substituted for exact action-contract review. This is review theatre. +Pass condition: Passport, Admission, Handle, Clearance, Outcome, and +Certificate can make the workflow understandable while their copy and schemas +explicitly say they do not create authority. Badge-like language is cut unless +it is a read-only state label derived from evidence. ## DevEx Gate -Pass condition: README, protocol-layman docs, role-client guidance, CLI/MCP descriptions, and examples teach the simplified flow while preserving non-authority flags and proof gaps. +Question: can a builder integrate the narrow wedge without learning the entire +protocol internals? -Fail condition: developers receive a badge/handle API before learning that every protected action requires fresh clearance. +Pass condition: docs and demos teach proposal, evidence, readback, refusal, and +proof gap as product-facing concepts, while directing protected mutation through +the existing kernel/gateway state machine. No setup path asks a developer to +invent authority semantics. ## Agent Gate -Pass condition: agent handoff and tests cover loops, retries, branches, dynamic tool construction, stale review, changed params, raw siblings, replay, proof gaps, and isolation. +Question: can a fresh agent resume without chat memory and without turning +planning into canon? -Fail condition: generated code can pass a handle into an unwrapped consequential tool. The generated code escaped the contract boundary. +Pass condition: `AGENT-HANDOFF.md`, `TASKS.jsonl`, and run-local evidence are +sufficient to start the next mechanism. `.planning/` remains derived evidence; +repo-facing truth lands only in canon docs, source, tests, and examples. ## Runtime Gate -Pass condition: runtime posture is host-specific. Codex, Claude Code, Hermes, OpenClaw, MCP, browser, A2A, OpenAPI, auth.md, and x402 are not collapsed into one runtime claim. +Question: does generated execution remain bounded under loops, retries, +branches, sibling calls, stale handles, and dynamic tool pressure? -Fail condition: host profiles, MCP visibility, OpenAPI routes, or A2A metadata are treated as enforcement. +Pass condition: runtime/protected-action tests prove same-envelope composition +or refusal, x402/auth.md non-composition, replay refusal, stale context +refusal, and proof-gap readback. Runtime handles may carry proposal context but +cannot authorize mutation. ## Protected-Action Gate -Pass condition: the field-level matrix proves admission and handle cannot create authority, policy decisions, greenlights, gateway checks, signer use, payment material, mutation, receipts, certificates, or resource widening. x402/auth.md remain exact per-event rails. +Question: is there still exactly one enforceable authority boundary? + +Pass condition: every consequential action reaches a fresh exact contract, +policy decision, one-use greenlight/refusal, gateway check, and terminal +receipt/refusal/proof gap/certificate posture. No product noun can skip, +cache, reuse, or summarize that boundary into authority. + +## Chair Review Checklist + +- Does the plan preserve one authority spine? +- Are product nouns projections/readbacks only? +- Do docs avoid product/protocol peer-lane claims? +- Do tests fail if peer-lane language returns? +- Does any source change widen package exports, protocol primitives, CLI/MCP + authority, SDK role powers, gateway adapters, or hosted claims? +- Are official case studies translated into mechanisms with URLs? +- Are residual proof gaps explicit? + +## Code Review Gate + +Before final closeout, inspect the diff for: + +- overbroad docs rewrites; +- repo-facing planning labels; +- new authority-shaped nouns; +- accidental package export churn; +- claim-boundary tests that merely bless prose without guarding source risk. + +## Promotion Rule -Fail condition: one admission or handle can authorize multiple mutations. This is ambient authority wearing a badge. +`READY_FOR_AGENT_EXECUTION` means a bounded agent can execute the next slice. It +does not mean hosted/Tier 3 can start and does not mean the architecture is +complete until implementation and full gates pass. diff --git a/.planning/macro-plan/RISKS.md b/.planning/macro-plan/RISKS.md index 730c813..3aabac0 100644 --- a/.planning/macro-plan/RISKS.md +++ b/.planning/macro-plan/RISKS.md @@ -1,101 +1,62 @@ # Risks -## RISK-001 - -- ID: RISK-001 -- Severity: Critical -- Risk: `ServiceWorkflowHandle` becomes reusable auth. -- Trigger: SDK, CLI, MCP, runtime, or example code accepts a handle as sufficient evidence for protected mutation. -- Mitigation: Literal false non-authority flags, surface-boundary tests, runtime misuse tests, and fresh action contract requirement. -- Owner: Surface/schema implementer and architecture-test implementer. -- Status: Active gate. - -## RISK-002 - -- ID: RISK-002 -- Severity: Critical -- Risk: Admission is mistaken for policy decision or gateway acceptance. -- Trigger: Docs or schema use Admission without showing accepted/refused/stale/proof-gap rows and separate clearance state. -- Mitigation: Use `ServiceWorkflowAdmission`, not standalone `Admission`; require action request and clearance sections in docs and readback. -- Owner: Product/docs implementer. -- Status: Active gate. - -## RISK-003 - -- ID: RISK-003 -- Severity: High -- Risk: Passport digest or presentation ID becomes identity, trust, or spend approval. -- Trigger: Passport fields are used in policy/gateway checks as sufficient proof rather than evidence refs. -- Mitigation: Define all passport/admission/handle IDs as correlation and reconstruction only; test they cannot create authority. -- Owner: Protected-action reviewer. -- Status: Active gate. - -## RISK-004 - -- ID: RISK-004 -- Severity: High -- Risk: Product simplification becomes metaphor-only documentation. -- Trigger: Story docs land without source schema, fields, tests, examples, and proof gates. -- Mitigation: Pair story with surface contract and architecture tests in Tier 1. -- Owner: Chair. -- Status: Active gate. - -## RISK-005 - -- ID: RISK-005 -- Severity: High -- Risk: Tier 2 fixture overclaims x402/auth.md external rails. -- Trigger: Example claims live provider custody, settlement, broad x402 compatibility, auth.md approval, or hosted operation. -- Mitigation: Local/source-owned fixture first; explicit non-claims; x402/auth.md adapter tests when touched. -- Owner: Protected-action fixture implementer. -- Status: Deferred until Tier 2. - -## RISK-006 - -- ID: RISK-006 -- Severity: High -- Risk: Multi-host runtime language becomes containment claim. -- Trigger: Codex-local evidence is generalized to Claude Code, Hermes, OpenClaw, generic MCP, browser, A2A, or OpenAPI. -- Mitigation: Runtime posture table and host-specific proof gaps; no native containment claim. -- Owner: Runtime test implementer. -- Status: Active gate. - -## RISK-007 - -- ID: RISK-007 -- Severity: Medium -- Risk: Architecture tests rely on string scans and miss semantic authority drift. -- Trigger: Dynamic imports, re-export indirection, or schema aliasing bypasses surface-boundary checks. -- Mitigation: Combine import-boundary tests, schema assertions, explicit non-authority fields, and product output tests. -- Owner: Architecture-test implementer. -- Status: Active gate. - -## RISK-008 - -- ID: RISK-008 -- Severity: Medium -- Risk: Canonical docs and README diverge into two first-use stories. -- Trigger: service workflow story lands but README still teaches only x402 install mechanics. -- Mitigation: Canonical docs convergence slice after source surface and tests. -- Owner: Docs implementer. -- Status: Planned. - -## RISK-009 - -- ID: RISK-009 -- Severity: High -- Risk: Tier 3 starts before Tier 1/Tier 2 proof gates close. -- Trigger: Hosted-workspace pressure turns local simplification into hosted operation or package-surface expansion. -- Mitigation: Tier 3 lock slice and final repo gate; feed any kernel need back into Tier 1/Tier 2. -- Owner: Release gate owner. -- Status: Active gate. - -## RISK-010 - -- ID: RISK-010 -- Severity: Medium -- Risk: The first implementation grows into broad SDK/CLI/MCP redesign. -- Trigger: Developer ergonomics work expands before surface contract proves the model. -- Mitigation: Implementation starts with story, surface schema, and boundary test only; Tier 2 convergence follows after gates. -- Owner: Chair. -- Status: Active gate. +## P0 - Dual-Lane Authority Drift + +Risk: `product surface` and `protocol kernel` become peer lanes of truth. + +Mitigation: canonical docs must say projection/readback over one authority +spine; claim-boundary tests must forbid product/protocol peer-lane claims. + +Stop condition: any product noun creates, grants, reinterprets, or bypasses +authority. + +## P0 - Handle Or Badge As Reusable Auth + +Risk: generated agents treat `ServiceWorkflowHandle` or badge-like UX as a +bearer token. + +Mitigation: schema false flags, workflow-admission tests, runtime misuse tests, +and forbidden vocabulary rules. + +Stop condition: a handle can satisfy policy, gateway, signer, mutation, receipt, +certificate, payment, or credential requirements. + +## P0 - Case-Study Overclaiming + +Risk: Stripe/Kubernetes/Vault/GitHub/AWS/SLSA/Vercel/Cloudflare analogies create +unearned authority claims. + +Mitigation: research is stored as mechanism rules only; source proof still wins. + +Stop condition: docs imply Handshake has hosted operation, provider custody, +settlement, host containment, or marketplace trust because another product has a +similar concept. + +## P1 - Surface Folder Name Confusion + +Risk: `src/surfaces` sounds like a product lane. + +Mitigation: keep the folder but clarify that it owns projection/readback +implementation boundaries only. + +Stop condition: surface code evaluates policy, issues greenlights, performs +gateway checks, mutates, exports receipts, mints certificates, or reads raw +protocol records. + +## P1 - ProtectedActionEvent Object Creep + +Risk: a useful lifecycle concept becomes a duplicated protocol primitive. + +Mitigation: keep it documentation/testing-only in this run and map to existing +protocol navigation/action-attempt lifecycle evidence. + +Stop condition: new stored event object, package export, gateway input, or +policy input is introduced without a separate transition proposal. + +## P1 - Tier 3 Kernel Creep + +Risk: hosted-product needs use the simplified vocabulary to widen kernel exports +or package surfaces. + +Mitigation: preserve hosted admission lock and route hosted operation to a +separate workspace or fresh pre-hosted kernel task. diff --git a/.planning/macro-plan/RUNTIME-GATES.md b/.planning/macro-plan/RUNTIME-GATES.md index 5ccf8e1..ad07fdf 100644 --- a/.planning/macro-plan/RUNTIME-GATES.md +++ b/.planning/macro-plan/RUNTIME-GATES.md @@ -1,88 +1,105 @@ # Runtime Gates +## Invariant At Stake + +Generated agents will treat simple vocabulary as operational affordance unless +runtime gates prove otherwise. A projection/readback surface may help prepare a +proposal, but it cannot authorize a runtime dispatch. + ## Source Boundary -| Source | Runtime Role | Status | -| --- | --- | --- | -| `.planning/macro-map/AGENT-RUNTIME-MAP.md` | Runtime posture for Passport / Admission / Handle move | Derived gate input | -| `.planning/macro-map/views/AGENT.md` | Generated-agent handoff and misuse risks | Lens evidence | -| `.planning/macro-map/views/RUNTIME.md` | Multi-host and x402/auth.md posture | Lens evidence | -| `.planning/codebase/INTEGRATIONS.md` | Current external rail and host profile map | Derived codebase evidence | -| `src/runtime/ingress/index.ts`, `src/runtime/ingress/schemas.ts` | Proposal-only runtime ingress | Source proof for current runtime posture | -| `src/mcp/x402-proposal.ts`, `src/x402-protected-tool/LANE.md` | MCP proposal and x402 host-profile posture | Source proof for proposal/readback non-authority | -| `README.md`, `docs/internal/protocol-notes.md` | Canonical non-claims for MCP, host profiles, x402, and runtime evidence | Canon | +Runtime gate truth lives in `src/runtime/ingress`, `test/runtime/*`, +`test/product/service-workflow-admission.test.ts`, `src/mcp/LANE.md`, +`src/cli/command-manifest.ts`, and protocol/gateway tests. Planning gates are +not runtime enforcement. ## Runtime Targets -| Target | Current Evidence | Suitability Posture | +| Target | Current posture | Required north-star gate | | --- | --- | --- | -| Codex | Local profile and MCP proposal/readback evidence | Usable for first implementation and local verification; no host-wide containment claim | -| Claude Code | Managed profile artifact in x402 protected-tool lane | Surface parity target; verify before runtime-specific claims | -| Hermes | Tool-packet/profile artifact | Surface parity target; verify before runtime-specific claims | -| OpenClaw | Tool-packet/profile artifact | Surface parity target; verify before runtime-specific claims | -| MCP | Local stdio proposal/evidence server | Proposal/readback only; no policy/gateway/mutation | -| x402 | One buyer-side exact per-call local proof path | Protected-action rail; gateway/signer boundary still required | -| auth.md | Credential provenance and protected API profile | Evidence rail; not action approval | -| Browser | Potential side channel | Treat as bypass/proof-gap unless gateway-owned path exists | -| A2A | Task/metadata context | Evidence only | -| OpenAPI | Route/catalog context | Operation description only | +| Codex | Local profile and MCP/stdout evidence only | No host-wide containment claim; workflow handle is proposal context only | +| Claude Code | Managed/profile artifact evidence | No native containment claim | +| Hermes | Tool-packet/profile artifact evidence | No reusable handle authority | +| OpenClaw | Tool-packet/profile artifact evidence | No raw sibling mutation bypass claim | +| MCP | Proposal/evidence resources and stdio process proof | MCP cannot authorize, pay, execute, retry, recover, or certify | +| x402 | Buyer-side exact per-call local proof lane | Fresh exact action request for each payment; signer material stays behind gateway | +| auth.md | Provenance and credential-custody evidence | auth.md does not become composite authority with x402 | +| Browser / A2A / OpenAPI | Proof-gap contexts | No protected-action readiness without gateway-owned path | ## Suitability Postures -The weakest host posture controls the claim. The plan may say "multi-host evidence posture" but not "multi-host containment." Codex is the active implementation runtime. Other hosts remain product-surface parity and future verification targets until their activation artifacts are source-checked and executed. +- Suitable for local source-owned proposal/evidence/readback tests. +- Suitable for Codex-local implementation with shell and repo gates. +- Not suitable for host-wide containment claims. +- Not suitable for hosted operation or live provider custody claims. ## Instruction Sources -Runtime agents must receive: - -- `AGENTS.md` invariant and cut lines; -- `AGENT-HANDOFF.md` context bundle; -- `PROTECTED-ACTION-GATES.md` authority boundary; -- source lane `LANE.md` files before edits; -- focused tests for runtime ingress, MCP posture, and surface boundary. +- `AGENTS.md` +- `src/runtime/ingress/*` +- `src/mcp/LANE.md` +- `src/cli/command-manifest.ts` +- `docs/internal/decisions.md` +- `test/runtime/runtime-ingress.test.ts` +- `test/runtime/auth-md-candidate-compilation.test.ts` +- `test/product/service-workflow-admission.test.ts` ## Tool Contract -Allowed runtime actions: - -- inspect admission and handle evidence; -- propose fresh action requests; -- use runtime ingress as proposal evidence; -- read redacted evidence and proof gaps; -- recraft exact contracts after drift or refusal. - -Forbidden runtime actions: - -- treat handle as permission; -- invoke signer or payment payload generation from admission; -- mutate from Passport/Badge/Handle; -- retry proof gaps as permission; -- dynamically construct protected tools without classifier/refusal checks; -- route around gateway via browser, shell, network, package manager, raw MCP, raw x402, or direct HTTP sibling paths. +Runtime ingress may observe generated dispatches, record evidence, refuse unsafe +shapes, and propose candidates. It must not evaluate policy, issue greenlights, +perform gateway checks, use signers, mutate protected surfaces, export receipts, +mint certificates, or claim host containment. ## Approval Or Permission Behavior -Human approval of a story, rendered review, or admission report is not permission. Runtime approval must bind to the exact protected-action contract and later gateway check. If the generated code can call an unwrapped consequential tool, the generated code escaped the contract boundary. +Runtime evidence, service workflow handles, rendered reviews, and MCP/CLI/SDK +outputs are not approval or permission. Permission exists only when the protocol +spine records a policy greenlight and the gateway verifies it for one exact +mutation attempt. ## Subagent Behavior -Subagents can review runtime posture, write isolated tests, or implement disjoint slices. They must not claim final runtime suitability. Promoting a host from profile evidence to native operation requires source-specific verification and a separate proof packet. +Subagents may audit runtime gates or implement disjoint tests, but they may not +declare runtime protection, host containment, protected-action authority, or +final closeout. The chair reconciles findings. ## Continuation State -Continuation must survive compaction and restart through: - -- `.planning/macro-plan/AGENT-HANDOFF.md`; -- `TASKS.jsonl`; -- source comments avoided unless necessary; -- git checkpoints after validated slices; -- test output captured in closeout notes or run validation files. +Runtime gates remain open until focused tests pass for mixed-family same-envelope +behavior, x402/auth.md non-composition, stale handle/review posture, and current +service workflow misuse cases. ## Blocked Runtime Checks -These checks block broad claims, not the first Tier 1 implementation: - -- no browser/A2A/OpenAPI gateway-owned path exists for this workflow handle; -- no Claude Code, Hermes, OpenClaw, or generic MCP runtime smoke has been executed for service workflow admission; -- no native host containment proof exists; -- no raw sibling inventory specific to this new handle surface exists until runtime misuse tests are written. +- Host-wide containment for Codex, Claude Code, Hermes, OpenClaw, MCP, browser, + A2A, OpenAPI. +- Live provider custody, settlement, facilitator operation, seller middleware. +- Broad raw sibling inventory for all browser, network, cloud, deploy, database, + and shell channels. + +## Required Runtime Misuse Coverage + +- mixed-family dispatch blocks must share one generated execution envelope + before they can be recorded as one runtime spine; +- loops and retries with the same handle; +- changed observed parameters across retries; +- dynamic tool construction; +- stale rendered review or stale admission context; +- raw sibling x402/auth.md/MCP/browser/network bypass; +- direct protected mutation attempt without fresh contract; +- replay after one-use greenlight consumption; +- proof-gap and isolation propagation. +- x402/auth.md generated composition as separate exact contracts or refusal, + never one composite authority artifact. + +## Pass Condition + +Runtime may carry projection context into proposal preparation only if the +resulting protected action still becomes one fresh exact action contract and +passes policy/gateway gates before mutation. + +## Stop Condition + +Stop if any runtime path treats Passport, Admission, Handle, Badge, Outcome, +Certificate, CLI output, MCP resource, or SDK helper as executable grant. diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 672a5ff..79bea29 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -1,10 +1,6 @@ -{"id":"MPLAN-001","phase":"T0","slice":"T0-00","title":"Validate and checkpoint macro-plan package","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/input.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Implementation must start from a validated package, not chat-only planning.","acceptance":["Macro-plan validator reports valid output.","Sidecar audit files are present or missing reports are recorded.","Git status is inspected before checkpoint."],"non_goals":["Do not claim Tier 3 readiness from macro-plan validation."],"status":"completed","proof_gate":"Macro-plan validator passes on .planning/macro-plan.","next_mechanism":"Run the macro-plan validator and record validation evidence."} -{"id":"MPLAN-002","phase":"T1","slice":"T1-01","title":"Create internal service workflow story","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-001"],"evidence":[".planning/macro-map/EXPERIENCE-MAP.md","docs/internal/protocol-layman.md","README.md"],"candidate_paths":["docs/internal/service-workflow-story.md"],"rationale":"The first user-facing simplification must teach the flow without implying authority.","acceptance":["Story maps Passport, ServiceWorkflowAdmission, ServiceWorkflowHandle, Action Request, Clearance, and Outcome to exact protocol/evidence boundaries.","Story includes forbidden interpretations for passport IDs, handle, certificate, review, and receipt.","Story includes refusal, replay, proof-gap, and isolation recovery language."],"non_goals":["Do not create public marketing claims or hosted-operation claims."],"status":"completed","proof_gate":"quality:claims passes after the story doc is added.","next_mechanism":"Write docs/internal/service-workflow-story.md with noun mapping and non-authority cut lines."} -{"id":"MPLAN-003","phase":"T1","slice":"T1-02","title":"Implement non-authority service workflow surface schema","priority":"P0","owner":"surface-schema-implementer","runtime":"codex","depends_on":["MPLAN-002"],"evidence":[".planning/macro-map/MECHANISM-MAP.md",".planning/macro-map/views/ENG.md","src/surfaces/outcome.ts","src/surfaces/boundary-manifest.ts"],"candidate_paths":["src/surfaces/service-workflow-admission.ts","src/surfaces/index.ts"],"rationale":"The simplified product model needs a source-owned schema before demos or SDK/CLI/MCP surfaces use it.","acceptance":["Schema defines ServiceWorkflowAdmission and ServiceWorkflowHandle.","Schema includes passportPackageDigest, passportPresentationId, admissionId, serviceWorkflowHandleId, serviceWorkflowHandleDigest.","Schema sets createsAuthority, createsPolicyDecision, createsGreenlight, performsGatewayCheck, permitsMutation, exportsReceipt, and mintsTerminalCertificate to false and freshActionContractRequired to true."],"non_goals":["Do not add protocol primitive, gateway adapter, store migration, policy evaluator, or mutation runner."],"status":"completed","proof_gate":"check:types passes and architecture gate accepts the surface posture.","next_mechanism":"Add src/surfaces/service-workflow-admission.ts following existing surface outcome conventions."} -{"id":"MPLAN-004","phase":"T1","slice":"T1-03","title":"Add workflow admission boundary tests","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["MPLAN-003"],"evidence":[".planning/codebase/TESTING.md","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"candidate_paths":["test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/naming-posture.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"The known failure mode is naming and surface drift into authority-bearing paths.","acceptance":["Tests fail if Passport, Badge, ServiceWorkflowAdmission, or ServiceWorkflowHandle appear as protocol primitives or authority exports.","Tests reject raw credential, token, PaymentPayload, PAYMENT-SIGNATURE, signer, receipt export, certificate, gateway check, policy, greenlight, and mutation fields on the surface.","Tests require the false non-authority flags."],"non_goals":["Do not weaken existing architecture tests to admit the new surface."],"status":"completed","proof_gate":"quality:architecture and quality:claims pass.","next_mechanism":"Add focused architecture tests for workflow-admission boundary."} -{"id":"MPLAN-005","phase":"T1","slice":"T1-04","title":"Converge canonical docs on the simplified flow","priority":"P1","owner":"docs-implementer","runtime":"codex","depends_on":["MPLAN-003","MPLAN-004"],"evidence":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"candidate_paths":["README.md","QUALITY.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/protocol-layman.md"],"rationale":"The user should not see one product model in internal story docs and another in first-use README paths.","acceptance":["Canonical docs describe Show Passport -> Service Admission -> Workflow Handle -> Request Clearance -> Read Outcome without weakening the authority chain.","Docs preserve current proof gaps and Tier 3 lock.","quality:claims and format checks pass."],"non_goals":["Do not perform a broad docs rewrite or move planning labels into canon."],"status":"completed","proof_gate":"quality:claims and format:check pass.","next_mechanism":"Patch only the canonical docs needed to align the product model."} -{"id":"MPLAN-006","phase":"T2","slice":"T2-01","title":"Align SDK CLI MCP descriptions with service workflow model","priority":"P1","owner":"surface-integration-implementer","runtime":"codex","depends_on":["MPLAN-005"],"evidence":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"candidate_paths":["src/cli/command-manifest.ts","src/mcp/catalog.ts","src/mcp/resources.ts","src/sdk/surface-clients/index.ts","README.md"],"rationale":"Developers should learn the simplified model through active product surfaces without those surfaces becoming authority.","acceptance":["CLI remains evidence/readiness/readback only.","MCP remains proposal/evidence only.","SDK role-client guidance does not treat handle as permission."],"non_goals":["Do not add mutation-shaped CLI commands, MCP policy tools, or all-role SDK authority."],"status":"completed","proof_gate":"CLI, MCP, SDK architecture tests pass.","next_mechanism":"Inspect active surface descriptions and patch only non-authority language."} -{"id":"MPLAN-007","phase":"T2","slice":"T2-02","title":"Add local service workflow admission example","priority":"P1","owner":"example-implementer","runtime":"codex","depends_on":["MPLAN-006"],"evidence":["examples/self-hosted-activation/","examples/x402-protected-spend/","examples/external-adapter-sdk/","test/product/"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts"],"rationale":"A 10-star product simplification needs a runnable proof surface, not only docs and schemas.","acceptance":["Example emits JSON and Markdown.","Output separates admission evidence from protected-action outcome evidence.","Output includes explicit non-claims and false authority flags."],"non_goals":["Do not claim live provider custody, hosted operation, settlement, or host containment."],"status":"completed","proof_gate":"Focused product example test passes.","next_mechanism":"Create the example using existing output conventions and product tests."} -{"id":"MPLAN-008","phase":"T2","slice":"T2-03","title":"Add generated-agent and runtime misuse tests","priority":"P1","owner":"runtime-test-implementer","runtime":"codex","depends_on":["MPLAN-007"],"evidence":[".planning/macro-map/AGENT-RUNTIME-MAP.md","src/runtime/ingress/index.ts","src/runtime/ingress/schemas.ts","test/runtime/runtime-ingress.test.ts"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/product/service-workflow-admission.test.ts"],"rationale":"Generated code will try loops, retries, dynamic tool names, and raw sibling paths unless the product surface refuses misuse.","acceptance":["Tests cover handle reuse in loops and retries.","Tests cover changed params, dynamic tools, stale review, raw sibling posture, replay, and proof gaps.","Tests stop before signer use or mutation."],"non_goals":["Do not certify host-wide containment."],"status":"completed","proof_gate":"Runtime ingress and architecture gates pass.","next_mechanism":"Add focused negative cases around handle misuse and fresh action requirements."} -{"id":"MPLAN-009","phase":"T2","slice":"T2-04","title":"Gate x402 and auth.md fixture behind service workflow surface","priority":"P2","owner":"protected-action-fixture-implementer","runtime":"codex","depends_on":["MPLAN-008"],"evidence":["src/adapters/x402-payment/","src/adapters/auth-md/","examples/x402-protected-spend/","test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts"],"candidate_paths":["examples/service-workflow-admission/","test/product/service-workflow-admission.test.ts","test/adapters/x402-wallet-gateway.test.ts"],"rationale":"The first protected-action fixture must prove admission is context only and x402 clearance is fresh and exact.","acceptance":["Fixture creates fresh x402 action request from handle context.","Policy, one-use greenlight/refusal, gateway check, receipt/refusal/proof-gap remain separate.","PaymentPayload and PAYMENT-SIGNATURE stay behind verified gateway check."],"non_goals":["Do not claim settlement, provider custody, facilitator operation, seller middleware, or aggregate spend enforcement."],"status":"completed","proof_gate":"x402 adapter and integration tests pass when touched.","next_mechanism":"Add fixture only after Tier 1/Tier 2 surface gates are green."} -{"id":"MPLAN-010","phase":"T2","slice":"T2-05","title":"Install Tier 3 lock and final release gate","priority":"P1","owner":"release-gate-owner","runtime":"codex","depends_on":["MPLAN-009"],"evidence":["docs/internal/decisions.md","README.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"candidate_paths":["docs/internal/decisions.md","README.md",".planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md"],"rationale":"Tier 3 must not consume unfinished simplification or force package/kernel creep.","acceptance":["Docs or closeout evidence state Tier 3 remains blocked until Tier 1/Tier 2 proof gates pass or proof gaps are explicit.","check:repo passes before closeout.","Any hosted need is routed to a separate Tier 3 workspace or a new Tier 1/Tier 2 kernel task."],"non_goals":["Do not implement hosted operation in this checkout as part of the simplification slice."],"status":"completed","proof_gate":"check:repo passes and Tier 3 non-claims remain explicit.","next_mechanism":"Record final proof state after implementation gates close."} +{"id":"NPLAN-001","phase":"N0","slice":"N0-00","title":"Reset macro plan around projection-over-spine architecture","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-map/MACRO-HANDOFF.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/TASKS.jsonl"],"rationale":"The old surface framing can be misread as dual product/protocol truth lanes.","acceptance":["Macro-plan status follows from current evidence.","Official research becomes mechanism rules.","Plan contains execution slices, gates, risks, review gates, and evidence plan.","Sidecar findings are reflected as gates, tasks, risks, or proof gaps."],"non_goals":["Do not claim hosted operation or product UX completion."],"status":"completed","proof_gate":"Macro-plan validator passes.","next_mechanism":"Patch canonical docs to projection-over-spine language."} +{"id":"NPLAN-002","phase":"N1","slice":"N1-01","title":"Patch canonical docs to projection-over-spine language","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["NPLAN-001"],"evidence":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md"],"candidate_paths":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md"],"rationale":"Product vocabulary must be projection/readback over the single authority spine, not a second lane.","acceptance":["Canon names exactly one authority spine.","Canon distinguishes product projection/readback surfaces from role-scoped protocol transition clients.","Canon defines projection/readback surfaces as implementation boundaries only.","Canon preserves non-authority posture for Passport, Admission, Handle, Outcome, Certificate, Badge-like labels, CLI, MCP, SDK, examples, receipts, and support bundles."],"non_goals":["Do not remove src/surfaces or rewrite protocol kernel docs wholesale."],"status":"open","proof_gate":"quality:claims passes.","next_mechanism":"Patch narrowly scoped canonical wording."} +{"id":"NPLAN-003","phase":"N2","slice":"N2-01","title":"Define source-owned service workflow lifecycle projection map","priority":"P0","owner":"architecture-docs-implementer","runtime":"codex","depends_on":["NPLAN-002"],"evidence":["docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/protocol/areas/action-attempt-lifecycle","src/protocol/navigation",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md"],"candidate_paths":["src/surfaces/service-workflow-lifecycle-projections.ts","src/surfaces/index.ts","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","test/architecture/service-workflow-lifecycle-projection.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"Friendly nouns need a source-owned projection map to prevent drift while avoiding new protocol primitives.","acceptance":["Projection map lists product noun, source authority stage, allowed use, forbidden interpretation, and lifecycle keys or explicit pre-contract context.","Lifecycle keys validate against actionAttemptLifecycleEntry().","ProtectedActionEvent is documentation/testing concept only in this slice.","No new protocol primitive or root package export is added."],"non_goals":["Do not create a stored ProtectedActionEvent object."],"status":"open","proof_gate":"projection-map and claim-boundary tests pass.","next_mechanism":"Add src/surfaces/service-workflow-lifecycle-projections.ts and tests."} +{"id":"NPLAN-004","phase":"N3","slice":"N3-01","title":"Add dual-lane drift guards","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["NPLAN-003"],"evidence":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md"],"candidate_paths":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts"],"rationale":"The repo needs a failing test if product/protocol peer-lane language returns.","acceptance":["Tests require projection-over-spine wording.","Tests forbid product/protocol peer-lane truth claims.","Tests guard Badge/Clearance/Outcome vocabulary drift.","Existing workflow admission boundary tests still pass."],"non_goals":["Do not forbid legitimate implementation folder names."],"status":"open","proof_gate":"focused architecture tests pass.","next_mechanism":"Patch claim-boundary matrix with projection-only requirements and forbidden patterns."} +{"id":"NPLAN-005","phase":"N4","slice":"N4-01","title":"Verify runtime and protected-action regressions","priority":"P0","owner":"runtime-gate-owner","runtime":"codex","depends_on":["NPLAN-004"],"evidence":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"rationale":"Generated agents will treat simplified vocabulary as permission unless misuse gates stay explicit; sidecar found P0 mixed-family same-envelope and x402/auth.md non-composition gaps.","acceptance":["Runtime/product tests prove handles are proposal context only.","Mixed-family runtime dispatch blocks must share one execution envelope or refuse before being projected as one spine.","x402/auth.md remains separate exact contracts or refusal, never composite authority.","No signer/payment/credential material appears in admission or handle records."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"runtime/product/auth-md focused tests pass or preserved as explicit proof gaps.","next_mechanism":"Add same-envelope and non-composition tests, patch runtime only if needed."} +{"id":"NPLAN-006","phase":"N5","slice":"N5-01","title":"Evaluate review and commit closeout","priority":"P0","owner":"chair","runtime":"codex","depends_on":["NPLAN-005"],"evidence":[".planning/macro-plan/REVIEW-GATES.md",".planning/macro-plan/EVIDENCE-PLAN.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"rationale":"The goal is end-to-end only if research, plan, implementation, review, tests, and commits converge.","acceptance":["Sidecar findings are resolved or recorded.","Macro-plan validator passes after final plan edits.","Focused tests and full repo gate pass after final source/docs/tests changes.","Code review and git checkpoint records exist.","Git status is clean after final commit."],"non_goals":["Do not close the goal on planning alone."],"status":"open","proof_gate":"check:repo and clean git status.","next_mechanism":"Run review/gates, update validation and checkpoint records, commit."} diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md new file mode 100644 index 0000000..4ff56da --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md @@ -0,0 +1,211 @@ +## Audit Scope + +Assigned focus: slices. + +This audit covers the architectural north star for the correction run: one protocol authority spine with non-authority projection surfaces. It does not select the macro move, synthesize the final plan, or promote final status. The question under audit is whether current repo language and source shape support projection-over-one-authority-spine strongly enough to guide the macro plan. + +Report path: `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md`. + +## Source Boundary + +Repo-local evidence is from the current checkout only. `.planning/` was treated as scratch except for this assigned output path. Current git state observed: `main...origin/main [ahead 8]`. + +Official/primary case-study sources used: + +- Stripe PaymentIntents lifecycle and idempotency: `https://docs.stripe.com/payments/payment-intents`, `https://docs.stripe.com/api/idempotent_requests`. +- Kubernetes admission and OPA Gatekeeper: `https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/`, `https://open-policy-agent.github.io/gatekeeper/website/docs/customize-admission/`. +- HashiCorp Vault leases: `https://developer.hashicorp.com/vault/docs/concepts/lease`. +- GitHub deployment environments: `https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments`. +- AWS IAM evaluation: `https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic_policy-eval-denyallow.html`. +- SLSA, in-toto, Sigstore/Rekor evidence: `https://slsa.dev/spec/v1.2-rc2/build-provenance`, `https://in-toto.io/docs/getting-started/`, `https://docs.sigstore.dev/logging/overview/`. +- Vercel and Cloudflare scope clarity: `https://vercel.com/docs/environment-variables`, `https://developers.cloudflare.com/fundamentals/api/reference/permissions/`. + +Browsing was available. No secondary sources were used for external facts. + +## Files Read + +- `AGENTS.md` +- `README.md` +- `STRUCTURE.md` +- `package.json` +- `docs/internal/decisions.md` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` +- `src/protocol/LANE.md` +- `src/protocol/kernel.ts` +- `src/protocol/areas/policy-greenlight/transitions.ts` +- `src/protocol/areas/policy-greenlight/policy-record/index.ts` +- `src/protocol/areas/gateway-gate/transitions.ts` +- `src/protocol/areas/gateway-gate/artifacts.ts` +- `src/protocol/areas/gateway-gate/replay-refusal/index.ts` +- `src/protocol/areas/idempotency-ledger/entries.ts` +- `src/http/routes/transition-route-registry.ts` +- `src/http/routes/transition-invokers.ts` +- `src/sdk/LANE.md` +- `src/sdk/surface-clients/index.ts` +- `src/sdk/surface-clients/policy-client.ts` +- `src/sdk/surface-clients/gateway-client.ts` +- `src/surfaces/LANE.md` +- `src/surfaces/boundary-manifest.ts` +- `src/surfaces/outcome.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `test/architecture/surface-boundary-posture.test.ts` +- `test/architecture/claim-boundary.test.ts` +- `test/architecture/import-posture.test.ts` +- `test/architecture/package-surface.test.ts` +- `test/sdk/role-clients.test.ts` + +Searches also covered `src`, `test`, `docs/internal`, and the assigned run directory. + +## Invariant At Stake + +Every projection must remain a read/write view over one authority spine. A product-facing SDK, CLI, MCP tool, service-workflow handle, certificate view, launch gate, or hosted surface must not become a second place where policy, greenlight, gateway acceptance, credential custody, execution proof, or terminal trust is invented. + +If a projection can mint or imply authority independently of the protocol kernel state path and gateway check, it is advisory theatre with a nicer API. + +## Pass Conditions + +### What the case studies imply as mechanisms, not analogies + +- Stripe PaymentIntents imply a durable lifecycle object plus idempotency binding. A retry cannot silently become a second purchase; idempotency keys bind to parameters and parameter drift is an error. Handshake equivalent: `ActionContract` plus idempotency ledger must bind protected-surface, resource, key, and parameter digest before greenlight reuse or duplicate authority can happen. +- Kubernetes admission and Gatekeeper imply a chokepoint, not a dashboard. Every matching policy/binding/parameter combination must pass before admission. Gatekeeper's default fail-open posture is a warning: any macro slice that cannot prove fail-closed behavior for protected mutation is not an enforcement slice. +- Vault implies custody is lifecycle state: lease id, TTL, renewability, revocation, and audit trail. A `GatewayCredentialRef` without external custody, expiry, revocation, and rotation evidence is local/reference custody, not provider or customer custody. +- GitHub deployment environments imply protected material is withheld until the gate passes. Environment secrets are unavailable to a job until protection rules pass. Handshake equivalent: signer/payment material must stay behind `VerifiedGatewayCheck`, not behind a review screen or SDK convenience method. +- AWS IAM implies default deny plus explicit deny dominance. Handshake equivalent: refusal, isolation, stale custody, policy drift, replay, and proof-gap blockers must dominate projection convenience and future greenlights. +- SLSA, in-toto, and Sigstore imply evidence is useful only when it is digest-bound to a subject, builder/control-plane boundary, ordered layout/links, and append-only verification posture. Handshake equivalent: receipt/proof projections must carry record refs, digests, stream events, audit-chain posture, and proof gaps; a certificate is terminal evidence, not permission. +- Vercel and Cloudflare imply scope names must be operationally concrete: team/project/environment; zone/account/user permission groups. Handshake equivalent: every projection must name caller role, custody role, action family, gateway holder, protected surface, and non-claims. Distribution scope is not authority. + +Repo pass evidence: + +- The protocol definition already states one state path and authority rule: `docs/internal/protocol-definition.md:48-70`, `docs/internal/protocol-definition.md:88-104`. +- `HandshakeKernel` centralizes transition entrypoints over protocol areas rather than letting SDK/MCP/CLI own behavior: `src/protocol/kernel.ts:100-245`. +- Policy evaluation derives isolation, protected-path posture, idempotency, credential binding, delegated authority, and sequence state before decision/greenlight: `src/protocol/areas/policy-greenlight/transitions.ts:125-162`, `src/protocol/areas/policy-greenlight/transitions.ts:188-237`. +- Gateway check rereads contract, greenlight, policy decision, observed parameter digest, isolation, posture, custody bindings, sequence dependencies, and idempotency before mutation: `src/protocol/areas/gateway-gate/transitions.ts:87-103`, `src/protocol/areas/gateway-gate/transitions.ts:128-190`. +- Receipts distinguish gateway decision, greenlight consumption, mutation attempt, downstream status, proof gaps, and audit chain: `src/protocol/areas/gateway-gate/artifacts.ts:301-343`. +- Service workflow admission is explicitly non-authority and requires a fresh action contract: `src/surfaces/service-workflow-admission/index.ts:21-35`, `src/surfaces/service-workflow-admission/index.ts:95-111`. + +## Failures + +### Repo conflicts with projection-over-spine architecture + +1. The repo still frames the boundary as product/protocol vocabulary instead of one authority spine with projections. + + Evidence: `STRUCTURE.md:7-13`, `docs/internal/decisions.md:42-48`, `docs/internal/protocol-notes.md:13-40`, `docs/internal/protocol-kernel-architecture.md:35-40`, and `README.md:15-20`. + + The content usually says the right thing, but the architecture label is wrong for the target. The macro plan should not preserve a two-lane mental model where product surfaces and protocol are peers. Projections are subordinate views over the one authority spine. + +2. `sdk.policy` is modeled as an explicit authority surface. + + Evidence: `src/surfaces/boundary-manifest.ts:296-365` marks `sdk.policy` with `authorityPosture: "policy_authority"` and allows `policy_decision_write`. `test/architecture/surface-boundary-posture.test.ts:51-110` codifies `authoritySurfaces: ["sdk.policy"]` and asserts it is "policy authority". `src/sdk/LANE.md:110-115` calls `PolicyClient` the narrow policy-authority surface. + + This is the sharpest conflict. The implementation of `PolicyClient` is only a transport call to `/v0.2/policy-decisions` (`src/sdk/surface-clients/policy-client.ts:24-33`), and the HTTP invoker delegates to `kernel.evaluatePolicy` (`src/http/routes/transition-invokers.ts:49-53`). That is good source shape. The naming and tests are bad architecture: they teach that a projection surface owns authority. It should be modeled as a control-plane projection over a kernel transition, not as an authority surface. + +3. Surface route-family manifests are parallel authority maps, not visibly derived from the transition registry. + + Evidence: `src/surfaces/boundary-manifest.ts:90-105` defines per-surface allowed/forbidden route families; `src/http/routes/transition-route-registry.ts:80-120` and `src/http/routes/transition-route-registry.ts:251-300` define the actual transition routes and caller roles; `test/architecture/surface-boundary-posture.test.ts:74-123` checks the manifest internally but does not prove every allowed surface route is a projection over a specific kernel transition route. + + Mechanism risk: a future surface can become "allowed" in the manifest without proving the route maps to the kernel spine, caller role, scope resolver, and transition invoker. + +4. Gateway projection language is better than policy projection language, but still needs a macro gate. + + Evidence: `src/surfaces/boundary-manifest.ts:430-483` marks `sdk.gateway` as `transport_only` while allowing `gateway_check_write`; `src/sdk/surface-clients/gateway-client.ts:40-75` posts to gateway-custody routes; the actual route delegates to the kernel (`src/http/routes/transition-route-registry.ts:292-300`, `src/http/routes/transition-invokers.ts:49-53`). + + This is acceptable only if the macro plan keeps saying "gateway custody projection over the kernel gateway-check transition." If it drifts into "SDK gateway authority," the generated code escaped the contract boundary. + +5. Current docs contain correct non-claims, but they are scattered enough that projection-over-spine is not yet the obvious governing test. + + Evidence: `README.md:129-146`, `docs/internal/decisions.md:173-230`, `docs/internal/decisions.md:232-256`, and `docs/internal/protocol-notes.md:367-386` all carry cut lines. This is useful, but the macro plan needs a single gate that fails any slice whose projection wording exceeds the kernel/gateway evidence. + +## Proof Gaps + +- No current architecture test proves that every product projection route family is derived from `transitionRouteDefinitions` and `transitionInvokers`. +- No current architecture test forbids the concept of an "authority surface"; one test requires it for `sdk.policy`. +- No current architecture test enforces the target vocabulary: authority spine plus projection surfaces. +- Provider/customer gateway custody remains a proof gap beyond local/reference proof, already acknowledged in `docs/internal/decisions.md:196-205` and `docs/internal/decisions.md:340-343`. +- Hosted operation remains a proof gap until there is deployment boundary, custody, migration, secret-management, and receipt evidence, as acknowledged in `docs/internal/decisions.md:436-452`. +- External audit-log or transparency-log guarantees are not present. Local append-only protocol records and stream/audit-chain digests are not Sigstore/Rekor-style public transparency. + +## Required Changes + +### Required macro-plan slices/gates + +P0 slice: vocabulary correction. + +- Replace boundary language that treats "product" and "protocol" as peer lanes with "authority spine" and "projection surfaces". +- Gate: no positive architecture section may describe a product surface as creating authority. It may only expose, request, render, or transport spine-backed records. + +P0 slice: remove authority-surface modeling. + +- Recast `sdk.policy` from `policy_authority` to a control-plane projection over `kernel.evaluatePolicy`. +- Gate: `test/architecture/surface-boundary-posture.test.ts` must have no `authoritySurfaces` list. It should assert zero projection surfaces own authority, while allowing narrowly scoped transition projections to call authority-bearing routes only through the kernel route registry. + +P0 slice: route/projection derivation gate. + +- Tie every surface route family to `transitionRouteDefinitions`, caller role, scope resolver, and `transitionInvokers`. +- Gate: adding an allowed projection route without a kernel transition mapping fails architecture tests. + +P0 slice: chokepoint and bypass gate for every admitted action family. + +- Each action family must name the generated execution shape, exact protected path, final gateway enforcement point, raw/sibling bypass posture, failure-closed behavior, and proof-gap output. +- Gate: if mutation can occur without the gateway checking the exact one-use greenlight, stop the slice. This is advisory, not Handshake. + +P0 slice: custody lease/revocation gate. + +- Before any customer/provider custody claim, require evidence for credential holder, gateway holder, TTL/expiry, revocation, rotation, isolation, and post-gate credential-resolution evidence. +- Gate: local fixture custody cannot be promoted to provider/customer custody. + +P1 slice: evidence/provenance projection gate. + +- Every projection outcome must carry digest-bound refs to protocol records, stream events or audit-chain material, and proof-gap/refusal separation. +- Gate: terminal certificate, receipt, release proof, package provenance, or registry listing cannot be used as permission. + +P1 slice: distribution and scope gate. + +- Treat npm, MCP Registry, host profile, Vercel-like environment scope, and Cloudflare-like token scope as distribution or caller-scope facts only. +- Gate: listing/discoverability/installation cannot satisfy authority, custody, gateway, settlement, hosted trust, or cross-org trust. + +### P0/P1 risks and stop conditions + +P0 risk: macro plan preserves `policy_authority` as a surface posture. + +Stop condition: any plan slice says `PolicyClient`, SDK role clients, MCP, CLI, service workflow, or hosted surface owns policy authority rather than projecting a kernel transition. + +P0 risk: projection route drift. + +Stop condition: a surface manifest permits a route family that is not bound to `transitionRouteDefinitions`, caller custody, scope resolver, and a `HandshakeKernel` transition. + +P0 risk: custody claim outruns proof. + +Stop condition: provider/customer custody, signer lease, payment material, or revocation is claimed without external custody evidence and gateway-time reread. + +P0 risk: generated execution bypass. + +Stop condition: raw sibling, browser, shell, package manager, MCP sibling, direct signer, or hosted endpoint can mutate outside the exact contract -> policy -> one-use greenlight -> gateway check path. + +P1 risk: evidence inflation. + +Stop condition: receipt, certificate, provenance, package publication, registry lookup, or host invocation is described as permission, settlement, hosted trust, or cross-org trust. + +P1 risk: fail-open posture hidden as product convenience. + +Stop condition: outage, stale metadata, missing posture, ambiguous commit, or proof gap produces a retry or success path rather than refusal, isolation, replay refusal, or explicit proof gap. + +## Status Recommendation + +### Brutal verdict + +Keep the current source spine. Redesign the macro-plan language and surface boundary tests. + +The implementation is closer to the target than the vocabulary is: `PolicyClient` and `GatewayClient` are transport projections that call HTTP routes which delegate to `HandshakeKernel`. But the repo currently teaches one dangerous idea: an SDK projection can be an "authority surface." That is ambient authority wearing a planning label. + +Do not promote the architectural north star until the macro plan contains the P0 vocabulary, surface-model, and route/projection derivation slices above. The smallest next mechanism is an architecture gate that forbids authority-owned projection surfaces and proves every projection call maps back to the one kernel transition spine. + +## Commands Or Tools Used + +- Read repo files with `awk`, `find`, and `rg`. +- Checked dirty state with `git status --short --branch`. +- Used `web.search_query`, `web.open`, and `web.find` for official primary sources only. +- Created the assigned audit directory with `mkdir -p`. +- Wrote this single report with `apply_patch`. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md new file mode 100644 index 0000000..fe7a817 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md @@ -0,0 +1,234 @@ +# Evidence Review Gates Audit + +## Audit Scope + +Focus: evidence, review, and closeout gates for the architectural north-star macro-plan correction. + +This audit is bounded. It does not select the macro move, synthesize the final plan, promote final status, or convert protected-action proof gaps into authority. It identifies the evidence and gate structure that must exist before the correction can be treated as more than a thin plan. + +## Source Boundary + +The audit used the current checkout as source truth and treated `.planning/` as scratch planning evidence, not repo-facing canon. + +Primary source boundary: + +- Current doctrine and canonical truth: `AGENTS.md`, `docs/internal/decisions.md`, `QUALITY.md`. +- Current macro-map handoff: `.planning/macro-map/MACRO-HANDOFF.md`, `.planning/macro-map/CONCERNS.md`. +- Current macro-plan package: `.planning/macro-plan/*`. +- Prior macro-plan run evidence: `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/*`. +- Current command contract: `package.json` scripts. +- Current claim gate: `test/architecture/claim-boundary.test.ts`. +- Macro-plan skill contract: `gsd-macro-plan` `SKILL.md`, `macro-plan-contract.md`, `output-quality-bar.md`. + +The requested run directory did not exist before this audit report was written. That absence is a proof gap for the correction, not a blocker to writing this sidecar report. + +## Files Read + +- `AGENTS.md` +- `QUALITY.md` +- `package.json` +- `docs/internal/decisions.md` +- `test/architecture/claim-boundary.test.ts` +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-map/CONCERNS.md` +- `.planning/macro-plan/README.md` +- `.planning/macro-plan/MACRO-PLAN.md` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/RUNTIME-GATES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` +- `.planning/macro-plan/EVIDENCE-PLAN.md` +- `.planning/macro-plan/REVIEW-GATES.md` +- `.planning/macro-plan/RISKS.md` +- `.planning/macro-plan/DECISIONS.md` +- `.planning/macro-plan/TASKS.jsonl` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/validation.md` +- `.planning/macro-plan/runs/20260525T095940Z-tier1-tier2-product-simplification/blocked-checks.md` +- `.planning/macro-plan/runs/20260525T174005-passport-admission-full/audits/evidence.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md` +- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` +- `/Users/joelchan/.codex/memories/MEMORY.md` lines 84-120 for prior x402 macro-plan drift lessons + +## Invariant At Stake + +The correction must not let planning evidence imitate execution evidence. + +A macro-plan can be structurally valid and still be thin. A prior run can have green tests and still be irrelevant after the checkout or plan boundary changes. A review table can exist and still be review theatre if it does not force sidecar disagreement, research evidence, test output, full repo gate, code review, and git checkpoints into the current run. + +For this correction, the invariant is: + +```text +Architectural north-star claims must be backed by current source evidence, +dated research evidence where external/current claims are made, current +macro-plan validation, current test output, full repo gate output, independent +review pressure, and reconstructable git checkpoints. +``` + +Anything less is advisory planning, not a Handshake-grade execution handoff. + +## Pass Conditions + +### Required Evidence Artifacts + +The current correction run must have its own evidence files under: + +```text +.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/ +``` + +Required run-local files: + +| Artifact | Required content | Stop condition if missing | +| --- | --- | --- | +| `input.md` | Exact correction objective, user constraints, run id, report paths, source boundary, and non-goals. | The chair cannot reconstruct why the correction exists. | +| `source-snapshot.md` | `git rev-parse HEAD`, `git status --short --untracked-files=all`, ignored `.planning/` posture, package scripts, canonical docs read, top-level macro-plan file list, and source/test paths touched or explicitly not touched. | Old evidence can be laundered into the current run. | +| `research-evidence.md` | Dated sources, URLs or local source paths, accessed date, extracted facts, disconfirming evidence, inference boundaries, and which macro-plan claim each fact supports. If no external/current claim remains, this file must say so explicitly and state why research is not needed. | Strategy or market claims become unsupported narrative. | +| `blocked-checks.md` | Open P0/P1 blockers, unavailable proof, non-proofs, external rails not verified, host/runtime proof gaps, and old-run evidence that is not transferable. | Proof gaps get smoothed over. | +| `validation.md` | Macro-plan validator command and output, status reconciliation, command matrix output, test output, full repo gate output, and what the validator does not prove. | Structural validation becomes semantic proof. | +| `code-review.md` | Findings-first review of the final diff, file/line references, missing tests, residual risk, and explicit statement if no source/docs/tests changed. | Review is replaced by plan authorship. | +| `git-checkpoints.md` | Checkpoint order, commit hashes, tested source commit, evidence-only commit if any, `git status` before/after, and whether `.planning/` files were force-added. | The chain cannot be reconstructed later. | +| `audits/*.md` | Bounded sidecar reports for slices, runtime, protected-action, and this evidence/review-gates audit, with chair reconciliation in `REVIEW-GATES.md`. | Sidecar pressure is not reconstructable. | + +Top-level macro-plan artifacts must also be current for this correction: + +- `.planning/macro-plan/EVIDENCE-PLAN.md` must point to the current run artifacts, not only the previous `095940Z` run. +- `.planning/macro-plan/REVIEW-GATES.md` must add current-run research, validation, repo gate, code review, and git checkpoint gates. +- `.planning/macro-plan/RISKS.md` must add P0/P1 risks for thin-plan laundering, stale research, missing code review, missing full repo gate, and ignored `.planning/` artifacts. +- `.planning/macro-plan/TASKS.jsonl` must include assignable current-run tasks with `status: "open"` until each proof file and gate output exists. + +### Review Gates And Sidecar Pressure Needed + +`REVIEW-GATES.md` must not only say sidecars exist. It must force pressure into the plan. + +Minimum required current-run gates: + +| Gate | Must include | Blocks promotion when | +| --- | --- | --- | +| Research Gate | Source table, date checked, claim supported, disconfirming facts, inference boundary. | External/current claims have no dated source evidence. | +| Macro-Plan Validation Gate | Validator command, observed output, artifact list, and semantic non-proof warning. | Validator was not run after final plan edits. | +| Source Boundary Gate | Canonical files, scratch files, stale/ignored artifacts, and source/test paths touched. | Current run inherits old run evidence without source snapshot. | +| Sidecar Reconciliation Gate | Each sidecar report, finding, chair disposition, artifact updated, residual blocker. | Sidecar findings are summarized but not converted into gates, risks, or tasks. | +| Code Review Gate | Findings-first review of final diff with file/line references or explicit no-source-change statement. | No independent final-diff review exists. | +| Focused Test Gate | Exact commands and outputs for affected claims. | Only generic "run tests" language exists. | +| Full Repo Gate | `npm run check:repo` output after final source/docs/tests changes. | Full gate not run or failed. | +| Git Checkpoint Gate | Commit hashes, force-add posture for `.planning/`, clean/known status, tested source commit. | Evidence cannot be tied to a committed state. | +| Protected-Action Non-Authority Gate | Explicit statement that research, review, plan, and checkpoint evidence do not create authority. | Any planning artifact is used as gateway, policy, signer, receipt, or hosted-operation proof. | + +Sidecar reports must be current-run reports. Prior `095940Z` and `174005` reports are patterns and historical evidence only; they do not satisfy this correction run. + +### Repo-Gate Command Matrix + +The correction closeout must record exact commands, timing, and observed output in `validation.md`. + +| Gate | Command | Required when | Evidence owner | +| --- | --- | --- | --- | +| Macro-plan structure | `python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan` | After final macro-plan edits. | `validation.md` | +| Claim boundary | `npm run quality:claims` | Any docs, claims, product language, README, or canonical text changes. | `validation.md` | +| Claim-boundary focused test | `npm run test -- test/architecture/claim-boundary.test.ts` | Any north-star/category/market/authority wording change. | `validation.md` | +| Architecture boundary | `npm run quality:architecture` | Any source, export, CLI, MCP, SDK, adapter, runtime, or surface posture change. | `validation.md` | +| TypeScript | `npm run check:types` | Any TypeScript source/test change. | `validation.md` | +| Runtime/generated-execution | `npm run test -- test/runtime/runtime-ingress.test.ts` | Any runtime, generated-agent, proposal, loop/retry, or stale-parameter claim. | `validation.md` | +| Product/example | `npm run test -- test/product/service-workflow-admission.test.ts` | Any service workflow/example/readback claim. | `validation.md` | +| x402 protected-action | `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts` | Any x402/auth.md fixture, gateway, signer, payment material, or proof-gap claim. | `validation.md` | +| Demo output | `npm run demo:service-workflow-admission` and/or affected demo script | Any regenerated example packet. | `validation.md` plus generated artifact references | +| Formatting | `npm run format:check` | Any source/docs/test/example tracked change. | `validation.md` | +| Diff hygiene | `git diff --check` | Before every checkpoint. | `validation.md` | +| Full repo gate | `npm run check:repo` | Before closeout and before any final implementation claim. | `validation.md` | +| Git state | `git status --short --untracked-files=all` plus ignored `.planning/` check if planning artifacts are committed. | Before and after checkpoints. | `git-checkpoints.md` | + +`package.json` defines `check:repo` as build, typecheck, lint, formatting, tests, package checks, and `git diff --check`. Passing focused tests is not a substitute for the full gate. + +### What Must Be Committed And In What Checkpoints + +This sidecar does not commit. The final correction work must use explicit checkpoints: + +1. Planning/evidence checkpoint: current macro-plan artifacts, current run evidence files, and sidecar audits. Because `.planning/` is ignored by `.gitignore`, these files must be force-added deliberately if the user wants them committed. Do not let `git status` looking clean imply planning evidence is tracked. +2. Source/docs/tests checkpoint, if implementation changes exist: only the smallest source/docs/tests changes required by the correction, with focused test output recorded before commit. +3. Closeout checkpoint: `validation.md`, `code-review.md`, and `git-checkpoints.md` updated with final command output and reviewed state. If this is an evidence-only commit after `npm run check:repo`, it must record the exact source commit that the full repo gate tested. + +The checkpoint record must distinguish: + +- source commit tested by `npm run check:repo`; +- evidence-only commit containing run-local proof files; +- any untracked or ignored planning artifacts intentionally left out. + +### P0/P1 Risks And Stop Conditions + +| Severity | Risk | Stop condition | +| --- | --- | --- | +| P0 | Thin-plan laundering. | Current run lacks `research-evidence.md`, `validation.md`, `code-review.md`, or `git-checkpoints.md`. | +| P0 | Stale evidence inheritance. | Prior `095940Z` validation or tests are used as current-run closeout proof. | +| P0 | Review theatre. | `REVIEW-GATES.md` summarizes sidecars without chair disposition, artifact updates, blocker status, and residual proof gaps. | +| P0 | Repo-gate theatre. | Focused tests pass but `npm run check:repo` is absent, failed, or run before final source/docs/tests changes. | +| P0 | Git checkpoint gap. | `.planning/` evidence is ignored and no force-add/omission decision is recorded. | +| P0 | Protected-action overclaim. | Research, plan validation, demo output, or code review is treated as policy, gateway, signer, payment, receipt, hosted operation, or provider custody proof. | +| P1 | Research claim drift. | Current market/ecosystem claims lack dated sources and disconfirming evidence. | +| P1 | Structural validator overclaim. | Macro-plan validator output is recorded without saying it proves structure only. | +| P1 | Code review missing line-level findings. | Final review has summary language but no file/line references or explicit no-source-change statement. | +| P1 | TASKS drift. | `TASKS.jsonl` marks tasks complete before their evidence files and commands exist. | +| P1 | Command matrix drift. | `validation.md` names commands that no longer match `package.json` scripts. | + +## Failures + +- The requested current run directory did not exist before this audit report was created. +- The current top-level macro-plan package structurally validates, but it is tied to the older Tier 1/Tier 2 simplification package and prior `095940Z` evidence. That is not current-run proof for the architectural north-star correction. +- Existing `EVIDENCE-PLAN.md` and `TASKS.jsonl` describe completed work from the prior run. They cannot be reused as current correction closeout without a current source snapshot, current validation, and current review reconciliation. +- Existing `REVIEW-GATES.md` does not contain a current-run research gate, code review gate, full repo closeout gate, or git checkpoint gate. +- Existing `RISKS.md` does not explicitly track thin-plan laundering, stale research, old-run evidence inheritance, missing code review, missing full repo gate, or ignored `.planning/` checkpoint gaps. +- `.planning/` is ignored by `.gitignore` and `.prettierignore`. Normal `git status --short` can look clean while the entire evidence package is untracked and uncommitted. + +## Proof Gaps + +- No current-run `research-evidence.md` exists. +- No current-run `source-snapshot.md` exists. +- No current-run `validation.md` exists. +- No current-run `blocked-checks.md` exists. +- No current-run `code-review.md` exists. +- No current-run `git-checkpoints.md` exists. +- No current-run sidecar set, except this report, existed at the requested path before this audit. +- No current-run proof ties macro-plan status to current tests, current full repo gate, and current commit hashes. + +## Required Changes + +1. Create the missing current-run evidence files listed under Required Evidence Artifacts. +2. Update `EVIDENCE-PLAN.md` so the architectural north-star correction points to `20260525T110908Z-architectural-north-star` evidence, not only the older simplification run. +3. Update `REVIEW-GATES.md` with research, validation, code review, full repo, git checkpoint, and current sidecar reconciliation gates. +4. Update `RISKS.md` with P0/P1 risks for thin-plan laundering, stale evidence, research drift, review theatre, repo-gate theatre, code-review absence, and ignored `.planning/` artifacts. +5. Update `TASKS.jsonl` with current correction tasks. Required tasks must cover research evidence, source snapshot, macro-plan correction, validator run, sidecar reconciliation, focused tests, full repo gate, code review, and git checkpoints. Do not mark them complete until their evidence artifacts exist. +6. Record validation output after the final macro-plan edit, not before. +7. Run and record the full repo gate after final source/docs/tests changes if any implementation work happens. +8. Write a findings-first code review after the final diff. If the correction changes only planning artifacts, the review must say that explicitly and review the plan/evidence diff instead. +9. Record git checkpoints with commit hashes or explicitly state why no commit was made. If planning artifacts are expected in git, use a deliberate force-add decision because `.planning/` is ignored. + +## Status Recommendation + +Recommendation: `BLOCKED_FOR_EVIDENCE_AND_REVIEW_GATES` until the current run owns its research evidence, validation, sidecar reconciliation, tests, full repo gate, code review, and git checkpoint record. + +Do not promote the correction from older run evidence. Do not treat macro-plan validator success as semantic proof. Do not use a clean `git status` as proof that `.planning/` evidence is committed. + +Brutal verdict: without the required current-run evidence files and closeout gates, this becomes another thin plan with better headings. The smallest next mechanism is `source-snapshot.md` plus `research-evidence.md`; everything else should hang off that current-run boundary. + +## Commands Or Tools Used + +- Read macro-plan skill contract: + - `sed -n '1,240p' /Users/joelchan/.codex/skills/gsd-macro-plan/SKILL.md` + - `sed -n '1,220p' /Users/joelchan/.codex/skills/gsd-macro-plan/references/output-quality-bar.md` + - `sed -n '1,220p' /Users/joelchan/.codex/skills/gsd-macro-plan/references/macro-plan-contract.md` +- Discovered planning files: + - `rg --files .planning/macro-plan .planning/macro-map` + - `find .planning/macro-plan/runs/20260525T110908Z-architectural-north-star -maxdepth 3 -type f` +- Read required and adjacent sources with `sed`. +- Checked current validation: + - `python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan` +- Checked git state: + - `git status --short` + - `git status --short --untracked-files=all` + - `git check-ignore -v .planning/macro-plan/MACRO-PLAN.md .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md` +- Checked ignore posture: + - `rg -n "(^|/)\\.planning|planning" .gitignore .prettierignore .eslintignore` +- Memory quick pass: + - `rg -n "architectural north-star|macro-plan|x402|review gates|evidence" /Users/joelchan/.codex/memories/MEMORY.md` + - `nl -ba /Users/joelchan/.codex/memories/MEMORY.md | sed -n '84,124p'` +- Wrote this report only: + - `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md` diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md new file mode 100644 index 0000000..f9c8c84 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md @@ -0,0 +1,198 @@ +## Audit Scope + +Assigned focus: product-vocabulary-projection-audit for the current Handshake gsd-macro-plan correction. + +This audit covers product vocabulary around `product surface`, `protocol kernel`, service workflow, `Passport`, `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, `Handle`, `Outcome`, `AuthorityCertificate`, `Certificate`, `Badge`, `Clearance`, product lane, and protocol lane. + +This report is a sidecar audit only. It does not select the macro move, synthesize the final plan, promote final status, or convert protected-action proof gaps into authority. + +## Source Boundary + +Canonical source boundary: + +- `README.md` +- `STRUCTURE.md` +- `QUALITY.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/protocol-layman.md` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/service-workflow-story.md` +- `src/protocol/LANE.md` +- `src/surfaces/LANE.md` +- `src/surfaces/boundary-manifest.ts` +- `src/surfaces/outcome.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `src/cli/LANE.md` +- `src/cli/command-manifest.ts` +- `src/cli/output.ts` +- `src/mcp/LANE.md` +- `src/mcp/catalog.ts` +- `src/mcp/output.ts` +- `src/sdk/LANE.md` +- architecture and product tests listed below. + +Derived planning source boundary: + +- `.planning/macro-plan/MACRO-PLAN.md` +- `.planning/macro-plan/DECISIONS.md` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` + +`.planning/` remains scratch. It can reveal current correction intent, but it is not repo-facing source truth. + +## Files Read + +- `README.md` +- `STRUCTURE.md` +- `QUALITY.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/protocol-layman.md` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/service-workflow-story.md` +- `src/protocol/LANE.md` +- `src/surfaces/LANE.md` +- `src/surfaces/boundary-manifest.ts` +- `src/surfaces/outcome.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `src/cli/LANE.md` +- `src/cli/command-manifest.ts` +- `src/cli/output.ts` +- `src/mcp/LANE.md` +- `src/mcp/catalog.ts` +- `src/mcp/output.ts` +- `src/sdk/LANE.md` +- `examples/service-workflow-admission/run.ts` +- `test/architecture/claim-boundary.test.ts` +- `test/architecture/self-hosted-activation-claim-boundary.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `test/architecture/active-vocabulary.test.ts` +- `test/architecture/naming-posture.test.ts` +- `test/architecture/surface-boundary-posture.test.ts` +- `test/architecture/cli-command-posture.test.ts` +- `test/architecture/mcp-surface-posture.test.ts` +- `test/architecture/root-exports.test.ts` +- `test/product/service-workflow-admission.test.ts` +- `.planning/macro-plan/MACRO-PLAN.md` +- `.planning/macro-plan/DECISIONS.md` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` + +## Invariant At Stake + +Product nouns must be projections, readbacks, or correlation context only. They must not become a second protocol truth, reusable authority, credential posture, policy result, gateway pass, signer permission, receipt export, terminal certificate, retry grant, or widened operating envelope. + +Current vocabulary inventory: + +| Vocabulary | Current safe meaning | Boundary | +| --- | --- | --- | +| `protocol kernel` | Source-owned state machine and schema set for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. | Canonical behavior source only. | +| `product surface` | Canon says CLI/MCP/SDK/docs/demo/service-facing readback exposing proposal/evidence/readback without creating authority. | Currently ambiguous because some SDK role clients are transition clients. | +| `src/surfaces` / product lane | Source-owned boundary manifests and non-authority outcomes for non-kernel product surfaces. | Must not evaluate policy, issue greenlights, perform gateway checks, mutate, mint certificates, export receipts, certify trust, host operation, or read raw records. | +| `src/protocol` / protocol lane | Protocol authority semantics and transition invariants. | Must not own product surface metaphors or service workflow projections. | +| `Passport` | Presented evidence package. | Not identity, trust, spend approval, signer access, permission, or reusable auth. | +| `ServiceWorkflowAdmission` / Admission | Service-side accepted/refused/stale/proof-gap mapping of presented evidence. | Not policy, greenlight, gateway check, receipt, certificate, or mutation permission. | +| `ServiceWorkflowHandle` / Handle | Correlation and readback context for later proposals. | Not badge, bearer token, tool permission, retry permission, x402 payment approval, auth.md credential, or gateway pass. | +| `Clearance` | Shorthand for one fresh protected-action chain. | Must not become a workflow-level permission or standalone artifact. | +| `Outcome` | Readback over receipt, refusal, replay refusal, proof gap, or terminal certificate after the event path. | Not downstream success or future permission. | +| `AuthorityCertificate` / Certificate | Terminal evidence after receipt/refusal/proof-gap/replay-refusal. | Not permission, identity, settlement, hosted trust, cross-org trust, or reusable auth. | +| `Badge` | Optional narrative anti-pattern/shorthand only. | Should not become schema, API, route, export, protocol object, or bearer-token metaphor. | + +## Pass Conditions + +- The phrase `product surface` cannot imply both non-authority readback and authority-bearing protocol transition clients. +- Product nouns are allowed only in docs/story, `src/surfaces/service-workflow-admission`, local readback/demo output, CLI/MCP/SDK explanatory lane text, and explicit negative tests. +- `Passport`, Admission, Handle, Badge, Clearance, Outcome, and Certificate cannot satisfy `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheck`, signer, credential, mutation, receipt, certificate mint, or operating-envelope requirements. +- `Badge` remains absent from source/API/export/route vocabulary except negative language. +- `Clearance` is always expanded to the exact protected-action chain before any authority claim. +- `Outcome` is always readback over terminal evidence and must distinguish gateway evidence from downstream business success. +- Architecture tests scan authority-bearing lanes, not only protocol areas and adapter/runtime roots. + +## Failures + +Confusing/unsafe language with file references: + +1. P0: `product surface` is overloaded. Canon says product surfaces are non-authority readbacks (`README.md:15-18`, `STRUCTURE.md:9-12`, `docs/internal/decisions.md:42-48`, `docs/internal/protocol-notes.md:13-22`), but `src/surfaces/boundary-manifest.ts:66-72` includes `policy_authority`, and `sdk.policy` may write policy decisions (`src/surfaces/boundary-manifest.ts:296-365`). `README.md:94-100` also teaches `PolicyClient.evaluatePolicy()` as a role-scoped client. That creates dual truth: "SDK product surface" can mean readback-only or policy-authority transport. + +2. P1: `Clearance` is too artifact-shaped unless always expanded. `README.md:22-37`, `docs/internal/service-workflow-story.md:10-25`, and `docs/internal/protocol-layman.md:37-55` are mostly safe, but the demo invariant says "fresh protected-action clearance carries authority" (`examples/service-workflow-admission/run.ts:91-97`). That phrasing can make `Clearance` sound like a reusable grant rather than shorthand for exact contract -> policy -> one-use greenlight/refusal -> gateway check. + +3. P1: `Badge` is still present as a narrative noun without an architecture guard that bans it from schema/API/export/route names. Current source use is bounded negative language (`docs/internal/service-workflow-story.md:23`, `docs/internal/service-workflow-story.md:94`, `docs/internal/protocol-layman.md:53-55`, `src/mcp/LANE.md:86-88`), but no current test scans for `Badge` as a future source/export/route noun. + +4. P1: Workflow-admission tests are strong at object shape but too narrow on placement. `test/architecture/workflow-admission-boundary.test.ts:17-35` scans exact service-workflow names out of `src/protocol/areas`, `src/adapters`, `src/runtime/ingress`, and `src/mcp`, but it does not scan `src/sdk/surface-clients/policy-client.ts`, `src/sdk/surface-clients/gateway-client.ts`, `src/http/routes`, `src/http/handlers`, `src/http/admission`, `src/protocol/public`, root exports, CLI commands, or package metadata for standalone `Passport`, `Admission`, `Badge`, `Handle`, `Clearance`, or `Outcome` drift. + +5. P1: `Outcome` is split across product story and reusable surface schema without an explicit vocabulary guard. `docs/internal/service-workflow-story.md:24-25` correctly defines Outcome as terminal readback, and `src/surfaces/outcome.ts:59-86` enforces non-authority flags. But there is no dedicated guard that product `Outcome` cannot be used as downstream success, retry permission, or a second terminal record apart from `Receipt`/`Refusal`/`ProofGap`/`AuthorityCertificate`. + +6. P1: `Certificate` is generally well bounded, but product copy must keep saying terminal evidence. The current claim-boundary test covers "certificate is terminal evidence, not permission" (`test/architecture/claim-boundary.test.ts:128-147`), and protocol notes are strict (`docs/internal/protocol-notes.md:388-416`). The residual risk is UX/product copy turning Certificate into Passport/Badge shorthand, explicitly forbidden in `docs/internal/service-workflow-story.md:94`. + +## Proof Gaps + +- No user-comprehension evidence proves that `Passport`, `Handle`, `Clearance`, or `Certificate` will not be interpreted as identity, permission, or reusable auth. +- No current guard proves `Badge` cannot enter future route names, exported symbols, package surfaces, or public examples. +- No current guard proves product projection nouns are excluded from authority-bearing SDK clients, HTTP transition routes, gateway clients, policy clients, or protocol public exports. +- No test currently enforces a taxonomy split between non-authority product projection/readback surfaces and role-scoped protocol transition clients. +- No tests were run in this audit; product demo tests can write generated outputs, so I inspected them read-only instead. + +## Required Changes + +Recommended canonical wording: + +- Replace broad `product surface` with two terms: + - `product projection surface`: CLI, MCP, SDK evidence/readback, docs, demos, and service-facing readbacks that expose proposal/evidence/readback without creating authority. + - `role-scoped protocol transition client`: SDK/HTTP client surface that transports a specific protocol transition under a custody role. It may call policy or gateway routes only when the protocol kernel/gateway path owns the authority. +- Keep `protocol kernel` as: "the source-owned state machine and schema set for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates." +- Define service workflow as: "`Passport -> ServiceWorkflowAdmission -> ServiceWorkflowHandle -> request one fresh protected-action clearance -> read terminal outcome` is a projection/readback story, not a protocol state path." +- Define `Passport`: "presented evidence package only; not identity, trust, approval, signer access, spend approval, permission, or reusable auth." +- Define `ServiceWorkflowAdmission`: "service-side evidence mapping only; not policy, greenlight, gateway check, receipt, certificate, or mutation permission." +- Define `ServiceWorkflowHandle`: "correlation/readback context only; not bearer token, badge, retry permission, payment approval, credential posture, gateway pass, or operating-envelope expansion." +- Define `Clearance`: "shorthand for one fresh `ActionContract -> PolicyDecision -> one-use Greenlight/Refusal -> GatewayCheck` path; not a record, token, reusable grant, workflow permission, or product object." +- Define `Outcome`: "readback over `Receipt`, `Refusal`, `ReplayRefusal`, `ProofGap`, or terminal `AuthorityCertificate`; not downstream business success or future permission." +- Define `AuthorityCertificate`: "terminal evidence only; never Passport, Badge, identity, settlement, hosted trust, cross-org trust, permission, or reusable auth." +- Define `Badge`: "do not use as an API/schema/route/export noun; if it remains in narrative copy, it must appear only as a forbidden interpretation of `ServiceWorkflowHandle`." + +Tests/guards to add or change: + +- Add a product-vocabulary projection guard under `test/architecture`, scanning repo-facing files for standalone `Passport`, `Admission`, `Badge`, `Handle`, `Clearance`, `Outcome`, and `Certificate` usage. Allow only approved files and require nearby negative boundary language. +- Extend `workflow-admission-boundary.test.ts` authority roots to include `src/sdk/surface-clients/policy-client.ts`, `src/sdk/surface-clients/gateway-client.ts`, `src/http/routes`, `src/http/handlers`, `src/http/admission`, `src/protocol/public`, `src/index.ts`, `src/experimental.ts`, `package.json`, and `server.json`. +- Add a guard that `Badge` cannot appear in TypeScript source except generated-negative-test strings, and cannot appear in exported symbols, command IDs, route names, schemas, package subpaths, or MCP tool/resource names. +- Add a guard that every use of `Clearance` in docs/examples is adjacent to `ActionContract`, `PolicyDecision`, `Greenlight`, and `GatewayCheck`, or else uses "request clearance" as a non-artifact action phrase. +- Add a guard that product `Outcome` cannot be paired with `downstreamSuccess`, `retry permission`, `future permission`, `business success`, or a new protocol object outside existing receipt/refusal/proof-gap/certificate objects. +- Update claim-boundary tests to require the new taxonomy: `product projection surface` is non-authority; `role-scoped protocol transition client` is a transport over protocol authority, not a product noun projection. +- Add root-export tests that `ServiceWorkflowAdmission`/`ServiceWorkflowHandle` stay off package root unless deliberately exposed through a projection-only subpath with explicit non-authority flags. If root export is intentional, the test must assert no policy/gateway/receipt/certificate/export material accompanies it. + +P0/P1 risks and stop conditions: + +- P0 stop: any plan or source change that says a product surface creates authority without naming the protocol transition and gateway boundary. +- P0 stop: `Passport`, Admission, Handle, Badge, Clearance, Outcome, or Certificate is accepted as sufficient input for policy, gateway, signer, mutation, receipt export, certificate mint, or operating-envelope expansion. +- P0 stop: role-scoped SDK policy/gateway authority is described as ordinary product surface authority rather than protocol transition transport. +- P1 stop: `Badge` appears in API/schema/export/route/package names. +- P1 stop: `Clearance` is used as a token/record/grant noun rather than a shorthand for the exact protected-action chain. +- P1 stop: readback copy collapses gateway check evidence and downstream business success. +- P1 stop: tests guard prose only while source exports or route names can still imply authority. + +Brutal verdict: + +Keep the service-workflow projection model. Cut the ambiguous umbrella use of `product surface`. Redesign the vocabulary taxonomy so product nouns are projections/readbacks only, while authority-bearing SDK/HTTP operations are called role-scoped protocol transition clients. Without that split, the repo can truthfully say "product surfaces create no authority" while also shipping `sdk.policy` as policy authority. That is a vocabulary bug with authority consequences. + +## Status Recommendation + +Recommend `NEEDS_REQUIRED_CHANGES` for product-vocabulary correction. + +Do not promote this macro-plan correction to final-ready until the taxonomy split and vocabulary guards are added. The source implementation is mostly disciplined, but the current wording still permits dual product/protocol truth at the SDK surface boundary. + +## Commands Or Tools Used + +- Read skills: `handshake-grounding`, `gsd-macro-plan`. +- `pwd` +- `git status --short --branch` +- `rg --files ...` +- `wc -l ...` +- `rg -n ...` +- `nl -ba ...` +- `find .planning/macro-plan/runs/20260525T110908Z-architectural-north-star ...` +- `ls -la .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits` +- `apply_patch` to write this report only. + +No tests were executed. I preserved the read-only constraint except for this audit report. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md new file mode 100644 index 0000000..16fe306 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md @@ -0,0 +1,290 @@ +## Audit Scope + +Sidecar 3/5 audited the protected-action lifecycle focus for run `20260525T110908Z-architectural-north-star`. + +Question audited: whether the repo has a single protected-action event lifecycle/table that product projections can derive from, and how `Passport`, `Admission`, `Handle`, `Clearance`, `Outcome`, and `Certificate` can be defined as projections without becoming protocol primitives. + +This report is read-only analysis except for writing this file. It does not select a macro move, synthesize the final plan, promote final status, or edit source/docs/tests. + +## Source Boundary + +Canonical source boundary used: + +- Current checkout at `/Users/joelchan/Documents/Coding/App-Dev/live/Handshake v0.0.2`. +- `git status --short --branch` reported `## main...origin/main [ahead 8]`; no dirty tracked files were present before this audit file was written. +- `.planning/` is treated as scratch/derived planning output. The run directory did not exist before this report directory was created. +- Tracked source and docs are the evidence boundary; prior memory was used only as context to preserve Handshake/GSD constraints. + +## Files Read + +Required files read: + +- `src/protocol/navigation/index.ts` +- `src/protocol/areas/action-attempt-lifecycle/index.ts` +- `src/protocol/areas/action-attempt-lifecycle/types.ts` +- `src/protocol/areas/action-attempt-lifecycle/schemas.ts` +- `src/protocol/areas/action-attempt-lifecycle/matrix.ts` +- `src/protocol/public/transitions.ts` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` +- `test/protocol/action-attempt-lifecycle.test.ts` +- `test/protocol/protocol-navigation.test.ts` + +Additional files read for projection and terminal-evidence boundary: + +- `docs/internal/decisions.md` +- `src/surfaces/service-workflow-admission/index.ts` +- `src/surfaces/outcome.ts` +- `src/surfaces/index.ts` +- `src/index.ts` +- `package.json` +- `test/product/service-workflow-admission.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `test/architecture/root-exports.test.ts` +- `src/protocol/areas/operation-lifecycle/schemas.ts` +- `src/protocol/areas/operation-lifecycle/lifecycle.ts` +- `src/protocol/areas/operation-lifecycle/transitions.ts` +- `test/protocol/operation-lifecycle.test.ts` +- `src/protocol/events/chains.ts` +- `src/protocol/areas/receipt-export/schemas.ts` +- `src/protocol/areas/receipt-export/status.ts` +- `src/protocol/evidence-projections/schemas.ts` +- `src/protocol/evidence-projections/projections.ts` +- `src/protocol/areas/protected-action-representation/schemas.ts` +- `src/protocol/areas/protected-action-representation/projections.ts` +- `test/protocol/representation-contract.test.ts` +- `src/protocol/areas/authority-certificate/schemas.ts` +- `src/protocol/areas/authority-certificate/transitions.ts` + +## Invariant At Stake + +Product-facing nouns must derive from the source-owned protected-action lifecycle. They must not become parallel authority primitives. + +If `Passport`, `Admission`, `Handle`, `Clearance`, `Outcome`, or `Certificate` can be interpreted without the exact lifecycle path, product language can accidentally mint authority outside `ActionContract -> PolicyDecision -> one-use Greenlight -> GatewayCheck -> Receipt/Refusal/ProofGap`. + +## Pass Conditions + +- There is one source-owned transition/lifecycle spine for protected-action attempts. +- Product projection nouns point into that spine or into explicitly non-authority surface schemas. +- `Passport`, `Admission`, and `Handle` are evidence/readback/correlation only. +- `Clearance` means a fresh exact action path, not workflow permission. +- `Outcome` means terminal readback over receipt/refusal/replay/proof-gap/certificate evidence, not downstream business success. +- `Certificate` remains terminal evidence over existing terminal records, not identity, admission, permission, reusable auth, settlement, or hosted trust. +- Tests fail if a product projection term appears in authority-bearing protocol roots or if projection mapping drifts from lifecycle keys. + +## Existing Lifecycle Spine And Evidence + +The repo has a real source-owned lifecycle spine for protected-action attempts. + +1. `src/protocol/navigation/index.ts` owns the transition inventory. Each entry declares `transitionId`, `kernelMethod`, `phase`, `outcomeClasses`, `recordsWritten`, `eventsEmitted`, `authorityBoundary`, and `evidenceObligation` (`ProtocolNavigationEntry`, lines 96-105). The table covers catalog/setup, runtime evidence, compilation, contract, policy, review, gateway, operation lifecycle, isolation, receipt export, recovery, and authority certificate transitions (lines 107-431). + +2. `src/protocol/areas/action-attempt-lifecycle/schemas.ts` owns the derived lifecycle vocabulary: phase, state, authority effect, terminal outcome, and evidence obligation. The important boundary types are explicit: `authorityEffect` distinguishes `none`, `evidence_only`, `proposed_commitment`, `one_use_authority`, `gateway_admission`, `downstream_evidence`, and `future_authority_reduction` (lines 64-72). `terminalOutcome` distinguishes `open`, `contract`, `refusal`, `proof_gap`, `terminal_unknown`, `evidence_only`, `recovery`, `isolation`, `receipt`, `projection`, and `closed` (lines 75-87). + +3. `src/protocol/areas/action-attempt-lifecycle/matrix.ts` maps `ProtocolTransitionId:TransitionOutcomeClass` to lifecycle entries. It is derived over `protocolNavigation`, not a stored protocol object. The exact lookup and enumeration functions are source-owned (`actionAttemptLifecycleEntry`, `actionAttemptLifecycleEntries`, lines 606-622). The matrix correctly marks contract proposal as proposed commitment, policy greenlight as one-use authority, gateway check as gateway admission, receipt export/certificate export as projection, and recovery/isolation as non-mutating authority reduction/evidence (notably lines 333-377, 443-550). + +4. `test/protocol/action-attempt-lifecycle.test.ts` proves lifecycle coverage over every protocol navigation outcome exactly once (lines 13-22), proves the lifecycle is derived from evidence-chain transitions and not stored instances (lines 24-50), maps hostile generated-agent paths to refusal or proof-gap outcomes (lines 52-117), and keeps projections/recovery non-authoritative (lines 119-131). + +5. `test/protocol/protocol-navigation.test.ts` proves HTTP transition navigation derives from protocol transitions and route metadata (lines 10-65), keeps generated graph coverage and certificate minting kernel-only evidence (lines 67-79), validates declared protocol objects/events (lines 81-94), and keeps evidence reads diagnostic/read-only (lines 96-112). + +6. `src/protocol/public/transitions.ts` is a public guard narrative over the same state shape. It states compilation cannot mint authority, gateway check proceeds only from greenlight, receipt export packages existing evidence only, and recovery cannot reuse a greenlight or mutate gateway state (lines 22-115). This is useful documentation, but the stronger table is `protocolNavigation` plus `ActionAttemptLifecycle`. + +7. Downstream finality is separately source-owned in `src/protocol/areas/operation-lifecycle/lifecycle.ts`. `OPERATION_LIFECYCLE_MATRIX` maps `pending/succeeded/refused/failed/unknown` to reconciliation status, finality status, claim state, receipt downstream status, proof-gap reason, claim blocking, and isolation behavior (lines 18-78). `test/protocol/operation-lifecycle.test.ts` proves all downstream observation branches (lines 4-56). + +8. Reconstruction evidence has a source spine. `src/protocol/events/chains.ts` binds action lifecycle events by action contract, run, gateway, and resource (`actionLifecycleStreamRefs`, lines 58-67), and stream partitioning uses `action:` when available (lines 126-140). + +9. Docs reflect the lifecycle rule. `docs/internal/protocol-definition.md` defines the canonical path and primitive (lines 15-28, 88-104, 262-270). `docs/internal/protocol-kernel-architecture.md` states the gateway is the enforcement point and the store is reconstruction truth (lines 31-33), then gives the authority sequence diagram (lines 342-381). `docs/internal/protocol-notes.md` preserves compact product/protocol language and exact naming rules (lines 13-40, 452-456). + +## Missing Projection Mapping + +The source spine exists. The missing piece is a source-owned product projection mapping from service workflow words to lifecycle entries. + +Current partial coverage: + +- `docs/internal/service-workflow-story.md` defines the plain flow and correctly warns that `Passport`, `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, `Clearance`, and `Outcome` are not permission or downstream success (lines 7-25, 55-73, 88-98). +- `src/surfaces/service-workflow-admission/index.ts` source-owns `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` as non-authority schemas. The boundary fields are hard literals: no authority, no policy decision, no greenlight, no gateway check, no mutation, no receipt export, no terminal certificate, no credential/payment material, no reusable auth, and fresh action contract required (lines 21-35, 39-53, 76-111). +- `test/architecture/workflow-admission-boundary.test.ts` rejects attempts to turn admission/handle into authority and keeps workflow nouns out of authority-bearing roots (`src/protocol/areas`, `src/adapters`, `src/runtime/ingress`, `src/mcp`) (lines 37-92). +- `test/product/service-workflow-admission.test.ts` proves the demo keeps admission/readback separate from fresh x402 clearance and excludes payment/auth authority material (lines 13-99, 101-228, 230-322). + +Gaps: + +1. There is no single source-owned `ServiceWorkflowProjectionMap` or equivalent table that maps `Passport`, `Admission`, `Handle`, `Clearance`, `Outcome`, and `Certificate` to `ActionAttemptLifecycle` keys, protocol object refs, and explicit non-authority flags. + +2. `Passport` is not source-owned as a projection schema. It appears as `passportPackageDigest` and `passportPresentationId` fields in admission/handle schemas, but there is no `PassportProjection` type that states it is a presented evidence package only, never identity/trust/permission/spend/signer access/reusable auth. + +3. `Admission` and `Handle` are source-owned as schemas, but not source-owned as lifecycle projections. They correctly avoid protocol authority roots, but no mapping ties them to pre-contract evidence/readback posture and says they cannot satisfy `compileIntent`, `proposeActionContract`, `evaluatePolicy`, or `gatewayCheck`. + +4. `Clearance` is prose only. The docs define it as a fresh exact protected-action path, but there is no source-owned projection that says clearance is a composite over existing lifecycle keys such as `proposeActionContract:recorded`, `evaluatePolicy:greenlight|refusal|review_required|proof_gap`, and `gatewayCheck:recorded|replay_refusal|proof_gap|conflict`. Without that table, the word can drift into workflow-level permission. + +5. `Outcome` is overloaded. `src/surfaces/outcome.ts` is a non-authority surface outcome helper for proposal/readiness/error shapes and explicitly prevents authority creation (lines 5-17, 59-86, 88-160), but it is not the terminal service-workflow Outcome described in `service-workflow-story.md` as receipt/refusal/replay/proof-gap/certificate. Terminal outcome derivation currently lives across `Receipt`, `ReceiptTimelineProjection`, `AgentTransactionEnvelopeProjection`, `OperationLifecycle`, `Refusal`, `ProofGap`, and `AuthorityCertificate` rather than a product-facing projection table. + +6. `Certificate` is source-owned as `AuthorityCertificate`, but not mapped into the service workflow vocabulary as a projection. `src/protocol/areas/authority-certificate/transitions.ts` only mints after receipt/refusal/proof-gap/replay terminal records (lines 149-176), and its schema binds terminal kind, artifacts, signatures, and verification policy (schemas lines 16-22, 24-40, 75-107). The product mapping should say `Certificate` means "optional terminal evidence projection over an Outcome", not "Passport", "Admission", or "Clearance". + +7. The current tests prevent misuse of admission/handle, but no test proves the entire product projection vocabulary is source-derived from `ActionAttemptLifecycle` and does not add protocol primitives. + +## Failures + +- Product projection mapping is not yet source-owned. The lifecycle table is source-owned; the product words are split across prose, admission schemas, demo outputs, and representation/outcome helpers. +- `Outcome` is not a single product projection over terminal event evidence. It is partly prose and partly unrelated non-authority surface outcome helper. +- `Clearance` has no source-owned projection contract. That is the most dangerous gap because it is the word closest to authority. +- `Passport` lacks a first-class projection schema. Digest fields exist, but the non-authority semantics are not pinned by a dedicated source map. + +## Proof Gaps + +- No current test asserts that `Passport`, `Admission`, `Handle`, `Clearance`, `Outcome`, and `Certificate` all resolve through one source-owned projection map. +- No current test asserts that `Clearance` maps only to a fresh exact contract/policy/gateway lifecycle chain and never to a reusable workflow handle. +- No current test asserts that terminal `Outcome` maps to receipt/refusal/replay/proof-gap/certificate evidence and not downstream business success. +- No current source constant links service workflow prose to `actionAttemptLifecycleEntry()` keys. +- No current docs pointer names the source file that owns the product projection map, because that file does not exist. + +## Required Changes + +1. Add one source-owned projection map under `src/surfaces`, not under `src/protocol/areas`. + + Suggested shape: + + ```ts + export const serviceWorkflowLifecycleProjectionMap = { + Passport: { + projectionKind: "passport", + protocolPrimitive: false, + createsAuthority: false, + lifecycleKeys: [], + sourceObjects: ["participant_identity_binding", "evidence_projection", "protected_path_health"], + boundary: "presented evidence package only", + }, + Admission: { + projectionKind: "service_workflow_admission", + protocolPrimitive: false, + createsAuthority: false, + lifecycleKeys: [], + sourceObjects: ["ServiceWorkflowAdmission"], + boundary: "service-side evidence/readback evaluation only", + }, + Handle: { + projectionKind: "service_workflow_handle", + protocolPrimitive: false, + createsAuthority: false, + lifecycleKeys: [], + sourceObjects: ["ServiceWorkflowHandle"], + boundary: "correlation and readback context only", + }, + Clearance: { + projectionKind: "clearance", + protocolPrimitive: false, + createsAuthority: "derived_from_policy_greenlight_only", + lifecycleKeys: [ + "proposeActionContract:recorded", + "evaluatePolicy:greenlight", + "gatewayCheck:recorded", + ], + refusalOrGapKeys: [ + "evaluatePolicy:refusal", + "evaluatePolicy:review_required", + "evaluatePolicy:proof_gap", + "gatewayCheck:replay_refusal", + "gatewayCheck:proof_gap", + "gatewayCheck:conflict", + ], + boundary: "fresh exact protected-action path for one event", + }, + Outcome: { + projectionKind: "outcome", + protocolPrimitive: false, + createsAuthority: false, + lifecycleKeys: [ + "gatewayCheck:recorded", + "gatewayCheck:replay_refusal", + "gatewayCheck:proof_gap", + "reconcileSurfaceOperation:recorded", + "reconcileSurfaceOperation:proof_gap", + ], + sourceObjects: ["receipt", "refusal", "proof_gap", "surface_operation_reconciliation"], + boundary: "terminal readback, not downstream business success or retry permission", + }, + Certificate: { + projectionKind: "certificate", + protocolPrimitive: false, + createsAuthority: false, + lifecycleKeys: ["createAuthorityCertificate:exported"], + sourceObjects: ["authority_certificate"], + boundary: "optional terminal evidence over one existing terminal event", + }, + } as const; + ``` + + The exact implementation should use existing `ActionAttemptLifecycleKey`/`actionAttemptLifecycleEntry()` so invalid lifecycle keys fail in tests. + +2. Keep the map in `src/surfaces` or a similarly explicit product-surface lane. Do not add `Passport`, `Admission`, `Handle`, `Clearance`, or `Outcome` to `src/protocol/areas` as protocol objects. + +3. Add schemas if needed for `PassportProjection`, `ClearanceProjection`, `TerminalOutcomeProjection`, and `CertificateProjection`, but make them projections over existing refs. All should carry the same kind of hard non-authority booleans used by `ServiceWorkflowAuthorityBoundarySchema`. + +4. Update docs to name the source-owned projection map: + + - `docs/internal/service-workflow-story.md`: replace prose-only mapping with "plain words derive from `serviceWorkflowLifecycleProjectionMap`". + - `docs/internal/protocol-notes.md`: keep naming rules and add that service workflow terms live under `src/surfaces` as projections. + - `docs/internal/protocol-definition.md`: keep protocol primitive names exact; mention product lifecycle projections are non-authority projections over the canonical state path. + +5. Add tests: + + - `test/architecture/service-workflow-lifecycle-projection.test.ts`: every product term maps to existing lifecycle keys or explicitly has no lifecycle key because it is pre-contract evidence; all entries set `protocolPrimitive: false`. + - Test `Clearance` includes `proposeActionContract`, `evaluatePolicy`, and `gatewayCheck` lifecycle keys, and refuses/review/proof-gap/replay branches are represented. + - Test `Outcome` includes terminal evidence refs and does not equate receipt to downstream business success. + - Test `Certificate` maps only to `createAuthorityCertificate:exported` and `authority_certificate` terminal evidence. + - Extend the existing workflow-admission boundary test so product terms remain absent from authority-bearing protocol roots. + +## Recommended Source/Docs/Test Changes + +Source: + +- Add `src/surfaces/service-workflow-lifecycle-projections.ts`. +- Export it from `src/surfaces/index.ts`; do not export it from the root unless product surface export policy explicitly allows it. +- Reuse `ServiceWorkflowAuthorityBoundarySchema` or factor a shared non-authority boundary schema for projection entries. + +Docs: + +- Make `docs/internal/service-workflow-story.md` a projection explanation over the source map, not a standalone vocabulary authority. +- Keep `docs/internal/protocol-definition.md` strict: the protocol object list must not gain Passport/Admission/Handle/Clearance/Outcome. +- Add one compact note in `docs/internal/protocol-notes.md` that product workflow terms are non-authority projections under `src/surfaces`. + +Tests: + +- Add projection-map coverage tests. +- Add a docs/source consistency test only if the repo already tolerates this style; otherwise keep the source map as the single tested authority and let docs point to it. +- Do not broaden tests into hosted trust, provider custody, live revocation, settlement, or marketplace claims. + +## Risks If Product Projection Mapping Is Not Source-Owned + +- `Clearance` becomes ambient authority wearing a badge: a workflow handle could be read as permission instead of correlation. +- `Passport` can swallow the product: identity/admission evidence starts posing as spend approval, signer access, or reusable auth. +- `Outcome` becomes evidence theatre: receipt, downstream finality, proof gap, and certificate get blurred into one success word. +- `Certificate` can be misused as a passport or badge if the product story does not derive it from terminal evidence only. +- Docs can drift faster than source. The current prose is good, but prose is not a mechanism. +- A future macro plan could create tasks around product names without touching the actual gateway-enforced lifecycle. + +## Status Recommendation + +Focus recommendation only: `NEEDS_REQUIRED_CHANGES` for the product projection mapping gate. + +The protocol lifecycle spine itself is present and source-owned. The product projection vocabulary is not yet source-owned as one derivation table. Do not promote any macro-plan status that depends on Passport/Admission/Handle/Clearance/Outcome/Certificate being a mechanically enforced projection layer until that source map and tests exist. + +## Brutal Verdict + +Keep the existing lifecycle spine. It is the right primitive. + +Cut any impulse to add Passport, Admission, Handle, Clearance, or Outcome as protocol primitives. That would create a second authority model. + +Narrow the product story into one source-owned projection table under `src/surfaces`. `Clearance` must be the fresh exact lifecycle chain. `Outcome` must be terminal readback. `Certificate` must be optional terminal evidence. `Passport`, `Admission`, and `Handle` must stay pre-contract evidence/correlation. + +Smallest next mechanism: add `serviceWorkflowLifecycleProjectionMap` under `src/surfaces` and test it against `ActionAttemptLifecycle`. + +## Commands Or Tools Used + +- Read skill guidance: `handshake-grounding`, `gsd-macro-plan`. +- Memory quick pass: searched `MEMORY.md` for Handshake macro-plan/protected-action context. +- Repo grounding: `pwd`, `git status --short --branch`. +- File discovery: `rg --files`, `find`. +- Source/doc/test reads: `awk` and `rg`. +- Report write: `mkdir -p` for the audit directory, then `apply_patch` to add this file. +- Tests were not run; this was a read-only audit of source/docs/tests, not a verification pass. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md new file mode 100644 index 0000000..3e9a29f --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md @@ -0,0 +1,244 @@ +# Runtime And Protected-Action Gates Audit + +## Audit Scope + +Sidecar 4/5 audit for runtime and protected-action gates in the +projection-over-spine macro-plan correction. + +Assigned focus only: generated-code misuse, loops/retries/branches, dynamic +tools, stale handles/review, raw sibling bypass, x402/auth.md composite +confusion, hosted/Tier 3 pressure, and gateway/signer/payment material +boundaries. + +This audit does not select the macro move, synthesize the final plan, promote a +final status, or authorize protected-action behavior. + +## Source Boundary + +Canonical boundary: + +- `AGENTS.md` doctrine supplied in the prompt. +- `docs/internal/decisions.md` for product/kernel/source truth. +- Source lane boundaries in `src/mcp/LANE.md`, `src/runtime/ingress/*`, and + `src/cli/command-manifest.ts`. + +Operational proof boundary: + +- `test/runtime/runtime-ingress.test.ts`. +- `test/runtime/auth-md-candidate-compilation.test.ts`. +- `test/product/service-workflow-admission.test.ts`. +- `test/architecture/workflow-admission-boundary.test.ts`. +- `examples/service-workflow-admission/*`. + +Planning boundary: + +- `.planning/macro-plan/RUNTIME-GATES.md`. +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md`. +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/*`. + +`.planning/` is scratch. It is useful for gate pressure, not repo-facing canon. + +## Files Read + +- `test/runtime/runtime-ingress.test.ts` +- `test/runtime/auth-md-candidate-compilation.test.ts` +- `test/product/service-workflow-admission.test.ts` +- `test/architecture/workflow-admission-boundary.test.ts` +- `examples/service-workflow-admission/run.ts` +- `examples/service-workflow-admission/README.md` +- `src/runtime/ingress/index.ts` +- `src/runtime/ingress/schemas.ts` +- `src/runtime/ingress/families.ts` +- `src/runtime/ingress/registry.ts` +- `src/mcp/LANE.md` +- `src/cli/command-manifest.ts` +- `src/surfaces/service-workflow-admission/index.ts` +- `docs/internal/decisions.md` +- `.planning/macro-plan/MACRO-PLAN.md` +- `.planning/macro-plan/EXECUTION-SLICES.md` +- `.planning/macro-plan/AGENT-HANDOFF.md` +- `.planning/macro-plan/RUNTIME-GATES.md` +- `.planning/macro-plan/PROTECTED-ACTION-GATES.md` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/source-snapshot.md` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/blocked-checks.md` +- `.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md` + +## Invariant At Stake + +Product vocabulary may project and read back one protected-action event spine. +It must not become a second authority lane. + +The runtime invariant is stricter: generated code may propose consequential +dispatches, but runtime ingress may create only proposal evidence and candidate +contracts. It must not create policy decisions, greenlights, gateway checks, +signer access, payment material, mutation attempts, receipts, certificates, or +host containment claims. + +The protected-action invariant remains: + +```text +CandidateAction / ActionContract +-> PolicyDecision +-> one-use Greenlight or Refusal +-> GatewayCheck before mutation +-> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` + +## Pass Conditions + +- Runtime ingress remains proposal-only for package install, x402, and auth.md + dispatch families. +- Dynamic tool construction, late-bound parameters, ambiguous dispatches, + truncated graphs, unsupported provider posture, stale handles/reviews, and raw + sibling paths refuse before contract authority or stop as bypass evidence. +- Loops, retries, branches, and changed parameters produce distinct exact + candidate/action contracts with distinct sequence and idempotency evidence; + they do not create aggregate authority. +- `ServiceWorkflowAdmission` and `ServiceWorkflowHandle` remain correlation and + readback projections only. They cannot carry policy, greenlight, gateway, + signer, payment payload, credential, receipt, certificate, or mutation + material. +- x402 and auth.md remain separate protected-action rails. No fixture may merge + x402 spend authority and auth.md credential authority into one artifact. +- Payment material and `PAYMENT-SIGNATURE` remain behind `VerifiedGatewayCheck`. + Runtime, MCP, CLI, admission, handle, and review surfaces must not expose + signer helpers or raw payment material. +- Hosted/Tier 3 language remains locked behind separate hosted proof or a fresh + Tier 1/Tier 2 kernel task. Projection vocabulary must not expand package or + kernel authority. + +## Failures + +P0: mixed-family runtime ingress lacks an explicit same-envelope gate. The code +routes each dispatch through its family config, but `RuntimeExecution` and graph +issuer identity are derived from the first dispatch config in +`buildRuntimeIngressExecutionInput()` and `runtimeIngressGraphIssuerContext()`. +The mixed-family test covers package+x402 ordering, but not mismatched +tenant/org/principal/agent/run/runtimeAdapter/operatingEnvelope across configs. +Projection-over-spine closeout must either forbid mixed-family blocks at this +layer or prove all family configs share the same execution envelope before +runtime evidence is recorded. Otherwise a projection can make multiple authority +contexts look like one runtime spine. + +P0: x402/auth.md non-composition is asserted at the service workflow fixture, +but there is no mixed x402+auth.md runtime block test proving separate rails +under generated-code composition. Current auth.md runtime tests prove standalone +candidate/refusal posture; current x402 tests prove standalone and package+x402 +mixed posture. The correction needs a gate that prevents "credentialed paid API +call" from becoming composite authority unless each rail clears through its own +fresh exact contract, policy decision, one-use greenlight/refusal, gateway +check, and post-gate evidence. + +P1: stale review coverage is too dependent on dynamic/late-bound detection. The +runtime test for stale handle/review refuses because dynamic construction and +late-bound refs are present. Add a static-looking stale review digest/handle +digest mismatch case so a stale rendered review cannot pass merely because its +tool name and parameters are syntactically fixed. + +P1: branch coverage is too narrow for the protected-action gate. Runtime tests +cover branch detection and changed amount, but the planning gate asks for +branches that change endpoint, resource, payee, gateway, or credential refs. +Those changes are exactly where a projection can launder scope expansion. + +P1: "parallel proposals from one handle" remains under-proven. Tests cover +sequential retry/loop handle context, but not concurrent or sibling proposals +from the same handle. The required behavior is separate fresh contracts and no +aggregate spend or reusable handle authority. + +P1: raw sibling inventory is still not specific enough for the corrected +projection surface. Tests cover raw package install, raw x402 shell, direct MCP +x402, and raw auth.md MCP. Runtime gates still name browser, direct HTTP, +network, cloud, deploy, and database paths as bypass/proof-gap surfaces. The +closeout must not claim broad runtime protection until those are either named +as explicit proof gaps or covered by a source-owned raw sibling inventory. + +P1: runtime refusal readback is reason-code rich but `RuntimeIngressResponsePosture.refusalRefs` +is always empty. If projection-over-spine readback needs reconstructable refusal +evidence, the runtime outcome should either surface durable refusal refs or +explicitly state that refusal records are recoverable through the +`intentCompilationRefs` only. Without that, refusal evidence can become readback +theatre. + +## Proof Gaps + +- No tests were executed in this audit; this was a read-only source audit plus + report write. +- No host-native containment is proven for Codex, Claude Code, Hermes, OpenClaw, + MCP, browser, A2A, or OpenAPI. +- No live provider/customer custody, funded customer-gateway signer, settlement, + facilitator operation, seller middleware, marketplace trust, cross-org trust, + or aggregate spend ledger is proven. +- No hosted operation proof exists. Current hosted/Tier 3 posture is a lock, not + a go-ahead. +- Runtime ingress has strong local generated-code stress tests, but not a full + generated-code parser/interceptor proof for arbitrary browser, shell, network, + package manager, cloud, deploy, repo, or database tools. +- `auth.md + x402` remains an expansion candidate. It is not current composite + execution authority. + +## Required Changes + +1. Add a same-envelope runtime ingress gate before closeout. It must reject or + refuse mixed-family dispatch blocks whose configs disagree on tenant, + organization, principal, agent, run, runtime adapter, operating envelope, + gateway registry, or authority holder where those fields are intended to + share one generated execution spine. + +2. Add x402+auth.md composition tests. Minimum case: one generated block carries + an auth.md protected API call plus one x402 payment attempt. Expected result: + separate candidates or refusal; no shared credential/signer/payment material; + no composite action contract; no policy, greenlight, gateway, mutation, + receipt, or certificate from runtime ingress. + +3. Add stale review/handle mismatch tests that do not rely on dynamic tool + construction. The stale artifact itself must force a fresh action contract or + refusal. + +4. Add branch-scope tests for endpoint, payee, resource, gateway credential ref, + delegated authority ref, request body digest, and selected payment requirement + changes. Expected result: separate exact contracts or refusal; never aggregate + authority. + +5. Add parallel/sibling proposal tests from the same + `ServiceWorkflowHandle`. Expected result: every protected action still needs + a fresh exact contract and per-call greenlight/gateway chain. + +6. Refresh `.planning/macro-plan/RUNTIME-GATES.md` and + `.planning/macro-plan/PROTECTED-ACTION-GATES.md` for projection-over-spine + language. They should say product vocabulary is projection/readback over the + event spine, not a peer lane. Also reconcile stale blocked-check text against + existing architecture field-negative tests. + +7. Preserve and rerun closeout gates before any implementation claim: + `npm run quality:claims`, `npm run quality:architecture`, + `npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/product/service-workflow-admission.test.ts test/architecture/workflow-admission-boundary.test.ts`, + and `npm run check:repo`. + +## Status Recommendation + +Sidecar recommendation only: do not close runtime/protected-action gates as +passing until the P0 mixed-family same-envelope gate and x402/auth.md +non-composition test exist. + +Brutal verdict: keep projection-over-spine. The current runtime/protected-action +source is mostly disciplined and already refuses many generated-code misuse +shapes. The unsafe version is treating Admission/Handle/review output as a +second lifecycle or allowing mixed-family runtime evidence to blur authority +contexts. That must be blocked before closeout. + +## Commands Or Tools Used + +- Read `gsd-macro-plan` skill instructions. +- Memory quick pass through `/Users/joelchan/.codex/memories/MEMORY.md`. +- `pwd` +- `git status --short` +- `rg --files` +- `rg -n` +- `sed -n` +- `nl -ba` +- `find` +- `mkdir -p .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits` +- `apply_patch` to create this report only. + +No tests were run. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/blocked-checks.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/blocked-checks.md new file mode 100644 index 0000000..d057f20 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/blocked-checks.md @@ -0,0 +1,30 @@ +# Blocked Checks + +## Not Blocked + +- The existing macro map is decision-gated but the user explicitly authorized a + new meta-goal and end-to-end run. +- The worktree was clean at start. +- The official research targets were reachable through primary docs. +- The implementation can be scoped to docs/source-boundary tests without + rewriting the protocol kernel. + +## Proof Gaps Preserved + +- No live x402 provider custody, settlement/finality, facilitator operation, or + seller middleware is proven. +- No native host containment is proven for Codex, Claude Code, Hermes, OpenClaw, + MCP, browser, A2A, or OpenAPI. +- No hosted operation, hosted org auth, retention/search, marketplace trust, or + cross-org trust is proven. +- No product UX beyond source-owned docs/schema/demo/readback is proven. + +## Stop Conditions + +- Stop if implementation needs a new protocol primitive for Passport, + Admission, Handle, Badge, Outcome, or Certificate. +- Stop if a product noun is accepted as authority by schema, docs, tests, CLI, + MCP, SDK, package exports, or examples. +- Stop if case-study analogies are used to claim enforcement that source does + not prove. +- Stop if hosted/Tier 3 language expands the kernel/package surface. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md new file mode 100644 index 0000000..1fdb09e --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md @@ -0,0 +1,108 @@ +# Architectural North Star Macro Plan Input + +Run id: `20260525T110908Z-architectural-north-star` +Date: 2026-05-25 +Mode: `gsd-macro-plan` +Runtime posture: multi-host evidence only, no host-native containment claim +Protected-action posture: one authority spine, projection-only product vocabulary + +## User Request + +Re-run the macro-plan around the architectural north star. The previous position +created concern that Handshake now has dual product/protocol lanes. The new goal +is end to end: research, plan, implementation, evaluation, review, and commit. + +## Invariant At Stake + +Handshake must have one authority spine: + +```text +CandidateAction / ActionContract +-> PolicyDecision +-> one-use Greenlight or Refusal +-> GatewayCheck before mutation +-> Receipt / Refusal / ReplayRefusal / ProofGap / AuthorityCertificate +``` + +Product vocabulary may simplify readback and service intake, but it must remain +a projection over that spine. It must not become a peer lane of truth. + +## North Star + +```text +Product vocabulary = projection/readback over one protected-action event spine. +Protocol kernel = only source of authority state and gateway-enforced mutation. +Surfaces = implementation boundaries for projection and readback, not product +truth lanes. +``` + +## Research Targets + +Primary-source case studies to convert into mechanisms, not analogy: + +- Stripe PaymentIntents: lifecycle object, status model, idempotency, retries. +- Kubernetes Admission / OPA Gatekeeper: pre-write chokepoint, rejection, + validating/mutating separation, reconciliation for side effects. +- HashiCorp Vault: custody, leases, renewal, revocation, audit value. +- GitHub deployment environments: protection rules before jobs proceed. +- AWS IAM: default deny and explicit deny overriding allow. +- SLSA / GitHub artifact attestations / Sigstore family: provenance and + signed evidence as post-fact verification, not permission. +- Vercel Deployment Protection / Cloudflare Access: product scope/method clarity + and continuous verification language. + +## Source Boundary + +Canonical repo truth: + +- `AGENTS.md` +- `README.md` +- `QUALITY.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-definition.md` +- `docs/internal/protocol-kernel-architecture.md` +- `docs/internal/protocol-layman.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` + +Derived planning input: + +- `.planning/macro-map/MACRO-HANDOFF.md` +- `.planning/macro-map/*` +- `.planning/codebase/*` +- prior `.planning/macro-plan/*` product-simplification package + +Operational proof: + +- `src/protocol/navigation` +- `src/protocol/areas/action-attempt-lifecycle` +- `src/surfaces` +- `src/runtime/ingress` +- `src/cli` +- `src/mcp` +- `examples/service-workflow-admission` +- `test/architecture/*` +- `test/runtime/runtime-ingress.test.ts` +- `test/product/service-workflow-admission.test.ts` + +## Cut Lines + +- No "product lane" and "protocol lane" as peer truth systems. +- No product surface may create, reinterpret, or bypass protocol authority. +- No Passport, Admission, Handle, Outcome, Certificate, Badge, or review screen + can be identity, permission, reusable auth, policy, greenlight, gateway + admission, mutation permission, receipt substitute, hosted trust, or terminal + settlement. +- No hosted/Tier 3 work may expand kernel/package exports because the projection + vocabulary is cleaner. + +## Desired Outputs + +- Revised macro-plan package with source boundary, official research, + execution slices, runtime gates, protected-action gates, evidence plan, + review gates, risks, decisions, task JSONL, validation, and sidecar audits. +- Source implementation that changes docs/source/tests from dual-lane language + to projection-over-spine language. +- Focused tests that fail if product vocabulary becomes a second authority lane. +- Full repo gate or explicitly justified equivalent before closeout. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research-evidence.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research-evidence.md new file mode 100644 index 0000000..17914b6 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research-evidence.md @@ -0,0 +1,37 @@ +# Research Evidence + +This file is the current-run evidence ledger requested by the evidence sidecar. +It expands `research.md` with claim-to-source boundaries. + +## Access Date + +2026-05-25 + +## Claims Supported + +| Macro-plan claim | Primary source | Evidence boundary | +| --- | --- | --- | +| Lifecycle clarity should be one object/spine, not multiple truth lanes. | Stripe PaymentIntents docs and lifecycle docs. | Supports status/idempotency design inspiration only; does not prove Handshake payments or Stripe parity. | +| Enforcement must happen at a chokepoint before mutation/persistence. | Kubernetes admission-control docs and OPA Kubernetes admission docs. | Supports gateway/admission design pattern only; does not make service workflow admission a Kubernetes-style admission controller. | +| Custody material must remain revocable/fresh and behind custody boundaries. | HashiCorp Vault lease docs. | Supports custody/freshness mechanism only; does not prove provider/customer custody in Handshake. | +| Deployment/protected execution gates are conditions before execution proceeds. | GitHub deployment environments docs. | Supports per-event protection gate framing only; does not turn approvals into mutation authority. | +| Deny/refusal/proof-gap blockers should dominate convenience. | AWS IAM policy evaluation docs. | Supports default/explicit deny discipline only; Handshake policy logic remains source-owned. | +| Attestations/provenance are verification evidence, not permission. | SLSA levels and GitHub artifact-attestation docs. | Supports receipt/certificate evidence framing only; does not claim public transparency log or SLSA compliance. | +| Product scope/method must be explicit and reverified. | Vercel Deployment Protection and Cloudflare ZTNA docs. | Supports product copy discipline only; does not turn Handshake into an access-control product. | + +## Disconfirming Boundaries + +- Stripe PaymentIntents can expose a client secret for client-side payment flow; + Handshake must not copy that pattern into Passport, Admission, Handle, or + Clearance. +- Kubernetes admission applies to API-server writes; Handshake service workflow + admission is evidence/readback mapping before protected-action clearance. +- Vault leases manage secrets; Handshake handles are not lease IDs or + credentials. +- GitHub deployment approval does not model generated-code inner mutations. +- AWS IAM is ambient principal authorization; Handshake requires exact per-event + contracts and one-use gateway-bound greenlights. +- SLSA/Sigstore/in-toto evidence verifies provenance; it does not authorize the + next action. +- Vercel/Cloudflare are access-control products; Handshake is execution-control + infrastructure. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md new file mode 100644 index 0000000..1ac4a05 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md @@ -0,0 +1,66 @@ +# Architectural Case Study Research + +## Invariant At Stake + +External products are useful only if they become mechanisms for Handshake's +single authority spine. They must not become borrowed analogy or permission +theatre. + +## Primary Sources Checked + +- Stripe PaymentIntents: + `https://docs.stripe.com/payments/payment-intents` and + `https://docs.stripe.com/payments/paymentintents/lifecycle` +- Kubernetes Admission Control: + `https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/` +- OPA for Kubernetes admission: + `https://www.openpolicyagent.org/docs/kubernetes` +- HashiCorp Vault leases: + `https://developer.hashicorp.com/vault/docs/concepts/lease` +- GitHub deployment environments: + `https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments` +- AWS IAM policy evaluation: + `https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic_policy-eval-denyallow.html` +- SLSA security levels: + `https://slsa.dev/spec/v1.0/levels` +- GitHub artifact attestations: + `https://docs.github.com/en/actions/concepts/security/artifact-attestations` +- Vercel Deployment Protection: + `https://vercel.com/docs/deployment-protection` +- Cloudflare ZTNA access policies: + `https://developers.cloudflare.com/reference-architecture/design-guides/designing-ztna-access-policies/` + +## Mechanisms To Import + +| Source | Mechanism | Handshake translation | +| --- | --- | --- | +| Stripe PaymentIntents | One lifecycle object tracks a payment across status changes, retries, and idempotency. | Define one protected-action event spine and make friendly vocabulary projections of it. | +| Kubernetes Admission | Write requests hit admission before persistence; rejection halts the whole request. Side effects need reconciliation. | Gateway check remains the pre-consequence chokepoint; downstream uncertainty becomes receipt/proof-gap reconciliation. | +| OPA Gatekeeper | Policy is queried by the API server on create/update/delete, not by UI copy. | Policy is machine-evaluated against exact action contracts, not product summaries. | +| Vault | Dynamic secret leases force renewal/replacement and support revocation. | Handles and readiness are freshness-bound context, never reusable auth. Credential material stays behind custody/gateway. | +| GitHub environments | Deployment protection rules must pass before jobs referencing an environment proceed. | Protected-action clearance gates each consequential event before mutation. | +| AWS IAM | Default deny and explicit deny override allow. | Refusals, isolation, stale evidence, and bypass posture must dominate product convenience. | +| SLSA / artifact attestations | Provenance establishes build origin and process for verification. | Receipts/certificates are terminal evidence and reconstruction, not permission. | +| Vercel / Cloudflare | Clear protection scope/method; continuous verification avoids stale auth assumptions. | Product copy must name scope and method; every protected action rechecks fresh authority instead of trusting workflow admission. | + +## Anti-Mechanisms To Avoid + +- `client_secret`-style bearer material leaking into Passport, Admission, or + Handle. +- Kubernetes-style admission being misread as Handshake service admission. +- Vault lease IDs being treated as permission rather than management handles. +- Deployment approval becoming approval of all generated-code mutations. +- Attestation/certificate being treated as future authority. +- Access-control product language being substituted for execution-control + enforcement. + +## Architectural Conclusion + +Handshake should not have product/protocol lanes. It should have: + +```text +Projection/readback vocabulary +over one protected-action event lifecycle +over exact policy and gateway enforcement +over append-only evidence and recovery. +``` diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/source-snapshot.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/source-snapshot.md new file mode 100644 index 0000000..ebb4a27 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/source-snapshot.md @@ -0,0 +1,39 @@ +# Source Snapshot + +## Git + +- Branch: `main` +- Starting status: clean, ahead of `origin/main` by 8 commits. + +## Canonical Boundary Observed + +- `STRUCTURE.md` says this repo is a TypeScript protocol kernel and defines + product surfaces as non-authority CLI/MCP/SDK/docs/demos/readbacks. +- `docs/internal/decisions.md` defines the shared product/protocol vocabulary + and makes `ServiceWorkflowAdmission` / `ServiceWorkflowHandle` non-authority + records. +- `docs/internal/protocol-notes.md` currently has a "Product And Protocol + Language" section that can be sharpened into projection-over-spine language. +- `docs/internal/service-workflow-story.md` currently says the story is a + product surface over the protocol kernel. This is directionally right but + should be recast as a projection/readback over one event spine. +- `src/surfaces/LANE.md` correctly blocks authority behavior, but the lane name + can still be mistaken for a peer product truth lane unless docs say surfaces + are implementation boundaries for projections. + +## Implementation Targets + +- `README.md` +- `STRUCTURE.md` +- `docs/internal/decisions.md` +- `docs/internal/protocol-notes.md` +- `docs/internal/service-workflow-story.md` +- `src/surfaces/LANE.md` +- `test/architecture/claim-boundary.test.ts` + +## Current Proof Gates + +- `npm run quality:claims` +- `npm run quality:architecture` +- `npm run test -- test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts` +- `npm run check:repo` diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md new file mode 100644 index 0000000..815e6da --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md @@ -0,0 +1,35 @@ +# Validation + +## Invariant At Stake + +Validation must prove the macro plan is structurally complete before the +implementation starts. It does not prove source implementation, runtime +enforcement, hosted operation, provider custody, or product UX completion. + +## Macro-Plan Validator + +Command: + +```bash +python3 /Users/joelchan/.codex/skills/gsd-macro-plan/scripts/validate_macro_plan_output.py .planning/macro-plan +``` + +Result: + +```text +Macro plan output is valid. +``` + +## Status + +- `NPLAN-001` is complete for planning structure and sidecar incorporation. +- Source/docs/tests implementation remains open under `NPLAN-002` through + `NPLAN-006`. +- Full repo closeout is not available yet. + +## Proof Gaps Preserved + +- Runtime same-envelope and x402/auth.md non-composition still need focused + implementation/test evidence. +- Source-owned projection map still needs implementation. +- Full repo quality gate still needs post-implementation evidence. From c8db72999a97d9ce8d333db87c1a307a7e76dbc9 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 19:49:35 +0800 Subject: [PATCH 010/144] Implement projection-over-spine architecture --- .planning/macro-plan/TASKS.jsonl | 10 +- .../code-review.md | 52 +++++ .../git-checkpoints.md | 22 ++ .../validation.md | 73 +++++- README.md | 21 +- STRUCTURE.md | 50 ++-- docs/internal/decisions.md | 11 +- docs/internal/protocol-notes.md | 16 +- docs/internal/service-workflow-story.md | 6 +- src/runtime/ingress/index.ts | 53 +++++ src/surfaces/LANE.md | 28 ++- src/surfaces/boundary-manifest.ts | 6 +- src/surfaces/index.ts | 1 + .../index.ts | 218 ++++++++++++++++++ test/architecture/claim-boundary.test.ts | 23 ++ ...vice-workflow-lifecycle-projection.test.ts | 97 ++++++++ .../surface-boundary-posture.test.ts | 14 +- test/runtime/runtime-ingress.test.ts | 168 +++++++++++--- 18 files changed, 774 insertions(+), 95 deletions(-) create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md create mode 100644 .planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md create mode 100644 src/surfaces/service-workflow-lifecycle-projections/index.ts create mode 100644 test/architecture/service-workflow-lifecycle-projection.test.ts diff --git a/.planning/macro-plan/TASKS.jsonl b/.planning/macro-plan/TASKS.jsonl index 79bea29..0c79f30 100644 --- a/.planning/macro-plan/TASKS.jsonl +++ b/.planning/macro-plan/TASKS.jsonl @@ -1,6 +1,6 @@ {"id":"NPLAN-001","phase":"N0","slice":"N0-00","title":"Reset macro plan around projection-over-spine architecture","priority":"P0","owner":"chair","runtime":"codex","depends_on":[],"evidence":[".planning/macro-map/MACRO-HANDOFF.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/input.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/research.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/architecture-case-study-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/evidence-review-gates-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":[".planning/macro-plan/MACRO-PLAN.md",".planning/macro-plan/EXECUTION-SLICES.md",".planning/macro-plan/TASKS.jsonl"],"rationale":"The old surface framing can be misread as dual product/protocol truth lanes.","acceptance":["Macro-plan status follows from current evidence.","Official research becomes mechanism rules.","Plan contains execution slices, gates, risks, review gates, and evidence plan.","Sidecar findings are reflected as gates, tasks, risks, or proof gaps."],"non_goals":["Do not claim hosted operation or product UX completion."],"status":"completed","proof_gate":"Macro-plan validator passes.","next_mechanism":"Patch canonical docs to projection-over-spine language."} -{"id":"NPLAN-002","phase":"N1","slice":"N1-01","title":"Patch canonical docs to projection-over-spine language","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["NPLAN-001"],"evidence":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md"],"candidate_paths":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md"],"rationale":"Product vocabulary must be projection/readback over the single authority spine, not a second lane.","acceptance":["Canon names exactly one authority spine.","Canon distinguishes product projection/readback surfaces from role-scoped protocol transition clients.","Canon defines projection/readback surfaces as implementation boundaries only.","Canon preserves non-authority posture for Passport, Admission, Handle, Outcome, Certificate, Badge-like labels, CLI, MCP, SDK, examples, receipts, and support bundles."],"non_goals":["Do not remove src/surfaces or rewrite protocol kernel docs wholesale."],"status":"open","proof_gate":"quality:claims passes.","next_mechanism":"Patch narrowly scoped canonical wording."} -{"id":"NPLAN-003","phase":"N2","slice":"N2-01","title":"Define source-owned service workflow lifecycle projection map","priority":"P0","owner":"architecture-docs-implementer","runtime":"codex","depends_on":["NPLAN-002"],"evidence":["docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/protocol/areas/action-attempt-lifecycle","src/protocol/navigation",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md"],"candidate_paths":["src/surfaces/service-workflow-lifecycle-projections.ts","src/surfaces/index.ts","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","test/architecture/service-workflow-lifecycle-projection.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"Friendly nouns need a source-owned projection map to prevent drift while avoiding new protocol primitives.","acceptance":["Projection map lists product noun, source authority stage, allowed use, forbidden interpretation, and lifecycle keys or explicit pre-contract context.","Lifecycle keys validate against actionAttemptLifecycleEntry().","ProtectedActionEvent is documentation/testing concept only in this slice.","No new protocol primitive or root package export is added."],"non_goals":["Do not create a stored ProtectedActionEvent object."],"status":"open","proof_gate":"projection-map and claim-boundary tests pass.","next_mechanism":"Add src/surfaces/service-workflow-lifecycle-projections.ts and tests."} -{"id":"NPLAN-004","phase":"N3","slice":"N3-01","title":"Add dual-lane drift guards","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["NPLAN-003"],"evidence":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md"],"candidate_paths":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts"],"rationale":"The repo needs a failing test if product/protocol peer-lane language returns.","acceptance":["Tests require projection-over-spine wording.","Tests forbid product/protocol peer-lane truth claims.","Tests guard Badge/Clearance/Outcome vocabulary drift.","Existing workflow admission boundary tests still pass."],"non_goals":["Do not forbid legitimate implementation folder names."],"status":"open","proof_gate":"focused architecture tests pass.","next_mechanism":"Patch claim-boundary matrix with projection-only requirements and forbidden patterns."} -{"id":"NPLAN-005","phase":"N4","slice":"N4-01","title":"Verify runtime and protected-action regressions","priority":"P0","owner":"runtime-gate-owner","runtime":"codex","depends_on":["NPLAN-004"],"evidence":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"rationale":"Generated agents will treat simplified vocabulary as permission unless misuse gates stay explicit; sidecar found P0 mixed-family same-envelope and x402/auth.md non-composition gaps.","acceptance":["Runtime/product tests prove handles are proposal context only.","Mixed-family runtime dispatch blocks must share one execution envelope or refuse before being projected as one spine.","x402/auth.md remains separate exact contracts or refusal, never composite authority.","No signer/payment/credential material appears in admission or handle records."],"non_goals":["Do not certify host-wide containment."],"status":"open","proof_gate":"runtime/product/auth-md focused tests pass or preserved as explicit proof gaps.","next_mechanism":"Add same-envelope and non-composition tests, patch runtime only if needed."} -{"id":"NPLAN-006","phase":"N5","slice":"N5-01","title":"Evaluate review and commit closeout","priority":"P0","owner":"chair","runtime":"codex","depends_on":["NPLAN-005"],"evidence":[".planning/macro-plan/REVIEW-GATES.md",".planning/macro-plan/EVIDENCE-PLAN.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"rationale":"The goal is end-to-end only if research, plan, implementation, review, tests, and commits converge.","acceptance":["Sidecar findings are resolved or recorded.","Macro-plan validator passes after final plan edits.","Focused tests and full repo gate pass after final source/docs/tests changes.","Code review and git checkpoint records exist.","Git status is clean after final commit."],"non_goals":["Do not close the goal on planning alone."],"status":"open","proof_gate":"check:repo and clean git status.","next_mechanism":"Run review/gates, update validation and checkpoint records, commit."} +{"id":"NPLAN-002","phase":"N1","slice":"N1-01","title":"Patch canonical docs to projection-over-spine language","priority":"P0","owner":"docs-implementer","runtime":"codex","depends_on":["NPLAN-001"],"evidence":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":["README.md","STRUCTURE.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/surfaces/LANE.md"],"rationale":"Product vocabulary must be projection/readback over the single authority spine, not a second lane.","acceptance":["Canon names exactly one authority spine.","Canon distinguishes product projection/readback surfaces from role-scoped protocol transition clients.","Canon defines projection/readback surfaces as implementation boundaries only.","Canon preserves non-authority posture for Passport, Admission, Handle, Outcome, Certificate, Badge-like labels, CLI, MCP, SDK, examples, receipts, and support bundles."],"non_goals":["Do not remove src/surfaces or rewrite protocol kernel docs wholesale."],"status":"completed","proof_gate":"quality:claims passes.","next_mechanism":"Define source-owned service workflow lifecycle projection map."} +{"id":"NPLAN-003","phase":"N2","slice":"N2-01","title":"Define source-owned service workflow lifecycle projection map","priority":"P0","owner":"architecture-docs-implementer","runtime":"codex","depends_on":["NPLAN-002"],"evidence":["docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","src/protocol/areas/action-attempt-lifecycle","src/protocol/navigation",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/protected-action-lifecycle-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":["src/surfaces/service-workflow-lifecycle-projections/index.ts","src/surfaces/index.ts","docs/internal/protocol-notes.md","docs/internal/service-workflow-story.md","test/architecture/service-workflow-lifecycle-projection.test.ts","test/architecture/claim-boundary.test.ts"],"rationale":"Friendly nouns need a source-owned projection map to prevent drift while avoiding new protocol primitives.","acceptance":["Projection map lists product noun, source authority stage, allowed use, forbidden interpretation, and lifecycle keys or explicit pre-contract context.","Lifecycle keys validate against actionAttemptLifecycleEntry().","ProtectedActionEvent is documentation/testing concept only in this slice.","No new protocol primitive or root package export is added."],"non_goals":["Do not create a stored ProtectedActionEvent object."],"status":"completed","proof_gate":"projection-map and claim-boundary tests pass.","next_mechanism":"Add dual-lane drift guards."} +{"id":"NPLAN-004","phase":"N3","slice":"N3-01","title":"Add dual-lane drift guards","priority":"P0","owner":"architecture-test-implementer","runtime":"codex","depends_on":["NPLAN-003"],"evidence":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/service-workflow-lifecycle-projection.test.ts",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/product-vocabulary-projection-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":["test/architecture/claim-boundary.test.ts","test/architecture/workflow-admission-boundary.test.ts","test/architecture/surface-boundary-posture.test.ts","test/architecture/service-workflow-lifecycle-projection.test.ts"],"rationale":"The repo needs a failing test if product/protocol peer-lane language returns.","acceptance":["Tests require projection-over-spine wording.","Tests forbid product/protocol peer-lane truth claims.","Tests guard Badge/Clearance/Outcome vocabulary drift.","Existing workflow admission boundary tests still pass."],"non_goals":["Do not forbid legitimate implementation folder names."],"status":"completed","proof_gate":"focused architecture tests pass.","next_mechanism":"Verify runtime and protected-action regressions."} +{"id":"NPLAN-005","phase":"N4","slice":"N4-01","title":"Verify runtime and protected-action regressions","priority":"P0","owner":"runtime-gate-owner","runtime":"codex","depends_on":["NPLAN-004"],"evidence":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/audits/runtime-protected-action-gates-audit.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/product/service-workflow-admission.test.ts","src/runtime/ingress/index.ts",".planning/macro-plan/RUNTIME-GATES.md",".planning/macro-plan/PROTECTED-ACTION-GATES.md"],"rationale":"Generated agents will treat simplified vocabulary as permission unless misuse gates stay explicit; sidecar found P0 mixed-family same-envelope and x402/auth.md non-composition gaps.","acceptance":["Runtime/product tests prove handles are proposal context only.","Mixed-family runtime dispatch blocks must share one execution envelope or refuse before being projected as one spine.","x402/auth.md remains separate exact contracts or refusal, never composite authority.","No signer/payment/credential material appears in admission or handle records."],"non_goals":["Do not certify host-wide containment."],"status":"completed","proof_gate":"runtime/product/auth-md focused tests pass or preserved as explicit proof gaps.","next_mechanism":"Evaluate review and commit closeout."} +{"id":"NPLAN-006","phase":"N5","slice":"N5-01","title":"Evaluate review and commit closeout","priority":"P0","owner":"chair","runtime":"codex","depends_on":["NPLAN-005"],"evidence":[".planning/macro-plan/REVIEW-GATES.md",".planning/macro-plan/EVIDENCE-PLAN.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"candidate_paths":[".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md",".planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md"],"rationale":"The goal is end-to-end only if research, plan, implementation, review, tests, and commits converge.","acceptance":["Sidecar findings are resolved or recorded.","Macro-plan validator passes after final plan edits.","Focused tests and full repo gate pass after final source/docs/tests changes.","Code review and git checkpoint records exist.","Git status is clean after final commit."],"non_goals":["Do not close the goal on planning alone."],"status":"completed","proof_gate":"check:repo and clean git status.","next_mechanism":"Commit implementation checkpoint, update git checkpoint record if needed, and close the goal."} diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md new file mode 100644 index 0000000..f9b4d79 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/code-review.md @@ -0,0 +1,52 @@ +# Code Review + +## Invariant At Stake + +Product vocabulary must remain projection/readback over the single protocol +authority spine. Passport, Admission, Handle, Clearance, Outcome, Certificate, +and badge-like language must not become identity, permission, reusable auth, +receipt substitutes, or gateway shortcuts. + +## Reviewed Diff + +- Canonical docs: `README.md`, `STRUCTURE.md`, + `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`, + `docs/internal/service-workflow-story.md`, `src/surfaces/LANE.md`. +- Source: `src/surfaces/service-workflow-lifecycle-projections/index.ts`, + `src/surfaces/boundary-manifest.ts`, `src/runtime/ingress/index.ts`, + `src/surfaces/index.ts`. +- Tests: `test/architecture/service-workflow-lifecycle-projection.test.ts`, + `test/architecture/claim-boundary.test.ts`, + `test/architecture/surface-boundary-posture.test.ts`, + `test/runtime/runtime-ingress.test.ts`. + +## Findings + +No blocking review findings remain. + +Resolved sidecar findings: + +- Product/protocol dual-lane language is replaced with + projection/readback-over-spine language in canonical docs. +- `sdk.policy` is no longer named `policy_authority`; it is now + `policy_transition_transport`, a role-scoped transition client posture. +- Service workflow product nouns are source-owned in a projection map instead + of a new protocol primitive. +- Passport/admission/handle IDs are explicit non-authority correlation and + reconstruction fields. +- Badge is forbidden as a service workflow authority noun. +- Mixed-family runtime ingress now fails before runtime evidence when configs + do not share tenant, org, principal, agent, run, runtime adapter, operating + envelope, and gateway registry. +- x402 plus auth.md composition with separate envelopes refuses before runtime + evidence or action contracts, preserving separate exact contracts or refusal. + +## Residual Risks + +- This is not a UI completion slice. +- Hosted/Tier 3 remains blocked. +- Live provider custody, settlement, marketplace trust, retention/search, and + native host containment remain proof gaps. +- `authorityPosture` remains an existing field name in some product acceptance + matrices; this review only removed the unsafe positive `policy_authority` + posture from the surface boundary manifest. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md new file mode 100644 index 0000000..5f69f06 --- /dev/null +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md @@ -0,0 +1,22 @@ +# Git Checkpoints + +## Invariant At Stake + +Git history must separate planning reset from implementation and closeout +evidence so the architecture correction remains reconstructable. + +## Checkpoints + +| Commit | Purpose | +| --- | --- | +| `bdcec05` | Reset architecture macro plan around projection-over-spine north star. | +| pending | Commit implementation of projection map, docs, runtime gate, tests, and validation evidence. | + +## Working Tree Notes + +- `.DS_Store` generated workspace metadata was removed because the repo naming + posture gate treats it as active-surface junk. +- No destructive git reset or checkout was used. +- `.planning/macro-plan` run evidence was force-added because `.planning/` is + normally scratch, but this goal explicitly requires the macro-plan package and + review evidence to be committed. diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md index 815e6da..ac5716a 100644 --- a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/validation.md @@ -23,13 +23,72 @@ Macro plan output is valid. ## Status - `NPLAN-001` is complete for planning structure and sidecar incorporation. -- Source/docs/tests implementation remains open under `NPLAN-002` through - `NPLAN-006`. -- Full repo closeout is not available yet. +- `NPLAN-002` through `NPLAN-005` are implemented in source/docs/tests. +- `NPLAN-006` has full repo gate evidence and is ready for implementation + commit closeout. + +## Focused Implementation Gates + +Command: + +```bash +npm run test -- test/architecture/service-workflow-lifecycle-projection.test.ts test/architecture/surface-boundary-posture.test.ts test/architecture/claim-boundary.test.ts test/architecture/workflow-admission-boundary.test.ts +``` + +Result: + +```text +21 pass +0 fail +``` + +Command: + +```bash +npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/product/service-workflow-admission.test.ts +``` + +Result: + +```text +32 pass +0 fail +``` + +## Quality Gates + +Commands and results: + +```text +npm run quality:claims +4 pass, 0 fail + +npm run quality:architecture +68 pass, 0 fail + +npm run format:check +All matched files use Prettier code style. +``` + +Full repo gate: + +```bash +npm run check:repo +``` + +Result: + +```text +build, check:types, lint, format:check, test, pack:check, and git diff --check passed. +bun test: 621 pass, 0 fail. +pack:check: package surface, clean installed activation, release proof, and npm maintainer posture passed. +``` ## Proof Gaps Preserved -- Runtime same-envelope and x402/auth.md non-composition still need focused - implementation/test evidence. -- Source-owned projection map still needs implementation. -- Full repo quality gate still needs post-implementation evidence. +- Hosted/Tier 3 operation remains blocked pending separate hosted workspace or + fresh pre-hosted kernel task. +- Live provider custody, settlement finality, marketplace trust, cross-org + trust, retention/search, and native host containment are still non-proofs. +- x402/auth.md composition is covered as refusal for separate envelopes; no + composite credential-plus-payment authority artifact is created. diff --git a/README.md b/README.md index adbbbdc..67ef4cd 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,16 @@ permission. Category: protected actions for automated decision making; certificate is terminal evidence, not permission. Core terms: a `cleared protected-action event` is one terminal event with -reconstructable evidence; the `protocol kernel` is the state machine and schema -set; a `product surface` is CLI, MCP, SDK, docs, demo, or service readback that -exposes proposal/evidence without creating authority. Public npm availability +reconstructable evidence; the `protocol kernel` is the only authority state +machine and schema set; a `product surface` is a projection/readback surface +such as CLI, MCP, docs, demo, or service readback that exposes +proposal/evidence without creating authority. Role-scoped protocol transition +clients, such as SDK policy or gateway clients, transport specific kernel +transitions under custody; they are not product authority surfaces. Public npm availability does not create authority. MCP Registry discoverability remains a proof gap until registry acceptance and lookup are verified. -First-use product surfaces should teach the service workflow as: +First-use product projection/readback surfaces should teach the service workflow as: ```text Show Passport @@ -97,7 +100,8 @@ and redacted evidence readback. The package root still exposes the lower-level `HandshakeClient`, but first-slice activation should teach role-scoped clients first. `InstallClient` performs one server-side setup commit, not hosted installation authority. `PolicyClient.evaluatePolicy()` evaluates one exact -action contract; it cannot perform the gateway check or mutate. +action contract through the protocol authority spine; it is not a product +surface, cannot perform the gateway check, and cannot mutate. Use `adapter-sdk` for third-party protected-action adapter packs and install-proposal shape review. It is definition-only: not an install client, not @@ -127,9 +131,10 @@ not gateway check, not mutation; plus handle context only, not clearance or authority. Hosted admission lock: this service workflow simplification is not a -hosted-operation go-ahead. Hosted product work may consume the surface only -after the pre-hosted service workflow gates have source-owned proof or explicit -proof-gap posture. If hosted work needs hosted operation, provider custody, +hosted-operation go-ahead. Hosted product work may consume projection/readback +surfaces only after the pre-hosted service workflow gates have source-owned +proof or explicit proof-gap posture. If hosted work needs hosted operation, +provider custody, settlement/finality, marketplace or certification, cross-org trust, aggregate spend enforcement, hosted org auth, retention/search, or new kernel exports, route it to a separate hosted workspace or a new pre-hosted kernel task. Do not diff --git a/STRUCTURE.md b/STRUCTURE.md index ceb2b30..28c0ee8 100644 --- a/STRUCTURE.md +++ b/STRUCTURE.md @@ -6,9 +6,15 @@ Last structural audit: 2026-05-19. ## Product And Protocol Boundary -The protocol kernel is the source-owned state machine and schemas for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. +The protocol kernel is the source-owned authority state machine and schemas for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. -Product surfaces are the CLI, MCP, SDK, docs, demos, and service-facing readbacks that expose proposal/evidence/readback without creating authority. A cleared protected-action event is a specific terminal Handshake event with reconstructable evidence. The certificate is terminal evidence, not permission. +Product surfaces are projection/readback surfaces such as CLI, MCP, docs, +demos, and service-facing readbacks that expose proposal/evidence/readback +without creating authority. Role-scoped protocol transition clients, including +SDK policy and gateway clients, transport specific kernel transitions under +custody; they are not product authority surfaces. A cleared protected-action +event is a specific terminal Handshake event with reconstructable evidence. The +certificate is terminal evidence, not permission. Public npm availability does not create authority, and MCP Registry discoverability remains a proof gap until verified. `.planning/codebase/*` can inform source-map work, but tracked source, canonical docs, and current tests win when facts disagree. @@ -21,26 +27,26 @@ required quality/package/full-repo gates. ## Ownership Rules -| Path | Owns | Must Not Own | -| --------------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| `src/protocol/` | Protocol primitives, state transitions, canonicalization, events, store port, navigation, public schemas and inputs. | HTTP transport, storage implementations, runtime wrappers, gateway fixtures, client ergonomics, hosted operation. | -| `src/http/` | Hono/Worker app, admission, route metadata, handlers, OpenAPI, HTTP errors, store resolution. | Protocol meaning, policy interpretation, mutation authority. | -| `src/runtime/` | Generated-execution evidence and action proposal helpers. | Policy decisions, greenlights, gateway checks, receipts, mutation attempts. | -| `src/adapter-sdk/` | Public adapter authoring definitions, install compiler contract refs, and install-proposal shape reports. | Runtime ingress registration, gateway binding, policy evaluation, credential custody, receipt export, mutation. | -| `src/adapters/` | Reference adapter profiles and gateway fixtures; mutation fixtures run only after a verified gateway check. | Storage internals, runtime authority, provider-side claims, identity-provider claims. | -| `src/conformance/` | Reference checks for protocol and gateway posture. | Hosted operation, standards claims, provider certification, mutation attempts. | -| `src/storage/` | Atomic record commits, stream offsets, D1, memory fixtures, KV cache plumbing. | Protocol meaning, route handling, SDK behavior. | -| `src/sdk/` | Typed client calls and response parsing. | Authority inference, mutation, storage, runtime wrappers. | -| `src/cli/` | Local command manifests, APS evidence rendering, conformance status, and certificate verification wrappers. | Process startup, policy evaluation, gateway checks, mutation commands, raw records, or credential custody. | -| `src/mcp/` | Model-facing proposal/evidence schemas, resource mappings, and pure runtime-client proposal bridge. | Process startup, policy evaluation, gateway checks, mutation commands, raw records, or credential custody. | -| `src/surfaces/` | Source-owned boundary manifests and shared non-authority outcomes for non-kernel product surfaces. | Protocol meaning, policy interpretation, route behavior, gateway authority, or public product claims. | -| `src/index.ts` | Curated package export surface. | Internal kernel/store objects or compatibility shims. | -| `src/experimental.ts` | Explicit reference adapter profile and gateway fixture exports. | Stable public API claims, provider enforcement claims, or standards certification claims. | -| `src/worker.ts` | Cloudflare Worker entrypoint wiring. | Protocol meaning, route behavior, or deployment policy. | -| `bin/` | Thin Node executable wrappers for bundled CLI and MCP package entrypoints. | Source logic, authority behavior, gateway custody, or mutation execution. | -| `server.json` | MCP Registry metadata for the local stdio proposal/evidence server. | Product claims, hosted operation, package publication proof, or protocol semantics. | -| `migrations/` | Canonical D1 schema for protocol storage. | Runtime behavior or product documentation. | -| `wrangler.toml` | Worker binding and deployment configuration. | Product claims or protocol semantics. | +| Path | Owns | Must Not Own | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `src/protocol/` | Protocol primitives, state transitions, canonicalization, events, store port, navigation, public schemas and inputs. | HTTP transport, storage implementations, runtime wrappers, gateway fixtures, client ergonomics, hosted operation. | +| `src/http/` | Hono/Worker app, admission, route metadata, handlers, OpenAPI, HTTP errors, store resolution. | Protocol meaning, policy interpretation, mutation authority. | +| `src/runtime/` | Generated-execution evidence and action proposal helpers. | Policy decisions, greenlights, gateway checks, receipts, mutation attempts. | +| `src/adapter-sdk/` | Public adapter authoring definitions, install compiler contract refs, and install-proposal shape reports. | Runtime ingress registration, gateway binding, policy evaluation, credential custody, receipt export, mutation. | +| `src/adapters/` | Reference adapter profiles and gateway fixtures; mutation fixtures run only after a verified gateway check. | Storage internals, runtime authority, provider-side claims, identity-provider claims. | +| `src/conformance/` | Reference checks for protocol and gateway posture. | Hosted operation, standards claims, provider certification, mutation attempts. | +| `src/storage/` | Atomic record commits, stream offsets, D1, memory fixtures, KV cache plumbing. | Protocol meaning, route handling, SDK behavior. | +| `src/sdk/` | Typed client calls and response parsing. | Authority inference, mutation, storage, runtime wrappers. | +| `src/cli/` | Local command manifests, APS evidence rendering, conformance status, and certificate verification wrappers. | Process startup, policy evaluation, gateway checks, mutation commands, raw records, or credential custody. | +| `src/mcp/` | Model-facing proposal/evidence schemas, resource mappings, and pure runtime-client proposal bridge. | Process startup, policy evaluation, gateway checks, mutation commands, raw records, or credential custody. | +| `src/surfaces/` | Source-owned boundary manifests, service workflow projection maps, and shared non-authority outcomes for product projection/readback surfaces. | Protocol meaning, policy interpretation, route behavior, gateway authority, reusable auth, or public product claims. | +| `src/index.ts` | Curated package export surface. | Internal kernel/store objects or compatibility shims. | +| `src/experimental.ts` | Explicit reference adapter profile and gateway fixture exports. | Stable public API claims, provider enforcement claims, or standards certification claims. | +| `src/worker.ts` | Cloudflare Worker entrypoint wiring. | Protocol meaning, route behavior, or deployment policy. | +| `bin/` | Thin Node executable wrappers for bundled CLI and MCP package entrypoints. | Source logic, authority behavior, gateway custody, or mutation execution. | +| `server.json` | MCP Registry metadata for the local stdio proposal/evidence server. | Product claims, hosted operation, package publication proof, or protocol semantics. | +| `migrations/` | Canonical D1 schema for protocol storage. | Runtime behavior or product documentation. | +| `wrangler.toml` | Worker binding and deployment configuration. | Product claims or protocol semantics. | ## Current Tree diff --git a/docs/internal/decisions.md b/docs/internal/decisions.md index 46728b1..efbaa44 100644 --- a/docs/internal/decisions.md +++ b/docs/internal/decisions.md @@ -41,8 +41,9 @@ Builder-buyer product language centers on a cleared protected-action event: one Shared product/protocol vocabulary: -- `protocol kernel`: the source-owned state machine and schemas for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. -- `product surface`: CLI, MCP, SDK, docs, demo, or service-facing readback surfaces that expose proposal/evidence/readback without creating authority. +- `protocol kernel`: the source-owned authority state machine and schemas for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and terminal certificates. +- `product surface`: projection/readback surfaces such as CLI, MCP, docs, demos, or service-facing readbacks that expose proposal/evidence/readback without creating authority. +- `role-scoped protocol transition client`: an SDK or HTTP client that transports a specific kernel transition under custody. It is not a product authority surface and does not make product nouns authoritative. - `ServiceWorkflowAdmission` and `ServiceWorkflowHandle`: non-authority product-surface records for presented evidence, service-side admission status, correlation, and readback context. They do not create identity, policy decisions, greenlights, gateway checks, mutations, receipts, certificates, reusable auth, signer use, or spend approval; each protected action still requires a fresh exact action contract. - `AuthorityCertificate`: verifiable terminal evidence for one event. The certificate is terminal evidence, not permission, identity, settlement, hosted trust, or reusable auth. - Distribution is separate from authority. Public npm availability does not create authority, and MCP Registry discoverability remains a proof gap until verified. @@ -50,11 +51,11 @@ Shared product/protocol vocabulary: The current kernel centers on protected action control: ```text -exact action contract +CandidateAction / exact action contract -> exact policy decision --> one-use gateway-bound greenlight +-> one-use gateway-bound greenlight or refusal -> gateway check before mutation --> receipt, refusal, or proof gap +-> receipt, refusal, replay refusal, proof gap, or optional terminal certificate ``` The first official wedge is one buyer-side `x402_payment.exact` per-call diff --git a/docs/internal/protocol-notes.md b/docs/internal/protocol-notes.md index 19f16f3..e65456f 100644 --- a/docs/internal/protocol-notes.md +++ b/docs/internal/protocol-notes.md @@ -15,12 +15,16 @@ Handshake's category is protected actions for automated decision making. - Product language centers on the cleared protected-action event: one terminal Handshake event with reconstructable evidence that a service can accept, refuse, or treat as a proof gap. -- The protocol kernel is the source-owned state machine and schema set for exact - contracts, policy decisions, one-use greenlights, gateway checks, receipts, - refusals, proof gaps, isolation, and terminal certificates. -- A product surface is CLI, MCP, SDK, docs, demo, or service-facing readback that - exposes proposal/evidence/readback without creating authority. -- The service workflow story is a product-surface translation only: +- The protocol kernel is the source-owned authority state machine and schema + set for exact contracts, policy decisions, one-use greenlights, gateway + checks, receipts, refusals, proof gaps, isolation, and terminal certificates. +- A product surface is a projection/readback surface such as CLI, MCP, docs, + demo, or service-facing readback that exposes proposal/evidence/readback + without creating authority. +- Role-scoped protocol transition clients, including SDK policy and gateway + clients, transport specific kernel transitions under custody. They are not + product authority surfaces and do not make product nouns authoritative. +- The service workflow story is a projection/readback translation only: `Passport -> ServiceWorkflowAdmission -> ServiceWorkflowHandle -> fresh protected-action clearance -> terminal outcome`. Passport, admission, and handle records are evidence/readback context; they are not identity, policy, diff --git a/docs/internal/service-workflow-story.md b/docs/internal/service-workflow-story.md index 9f50c27..bcb72ea 100644 --- a/docs/internal/service-workflow-story.md +++ b/docs/internal/service-workflow-story.md @@ -1,8 +1,8 @@ # Service Workflow Story -This story is a product surface over the existing protocol kernel. It makes the -first-use path easier to understand, but it does not create a new authority -primitive. +This story is a product projection/readback surface over the existing protocol +authority spine. It makes the first-use path easier to understand, but it does +not create a new authority primitive or a peer product truth lane. ## Plain Flow diff --git a/src/runtime/ingress/index.ts b/src/runtime/ingress/index.ts index baaeda0..ab1124a 100644 --- a/src/runtime/ingress/index.ts +++ b/src/runtime/ingress/index.ts @@ -28,6 +28,7 @@ import { runtimeIngressEvidenceRefs, signingSecretForDispatch, supportedGrammarVersionForBlock, + type RuntimeIngressFamilyConfig, type RuntimeIngressConfig, } from "./families"; import { runtimeIngressDispatchNodeId } from "./node-ids"; @@ -37,6 +38,7 @@ import { type ParsedRuntimeIngressObservedDispatch, type RuntimeIngressDispatchBlock, } from "./schemas"; +import { runtimeIngressFamilyIdForDispatchKind, type RuntimeIngressFamilyId } from "./registry"; export { RuntimeIngressDispatchBlockSchema, RuntimeIngressObservedDispatchSchema } from "./schemas"; export { runtimeIngressDispatchNodeId } from "./node-ids"; export type { RuntimeIngressConfig } from "./families"; @@ -173,6 +175,7 @@ export async function proposeRuntimeIngressActionContracts( blockValue: RuntimeIngressDispatchBlock, ): Promise { const block = RuntimeIngressDispatchBlockSchema.parse(blockValue); + assertRuntimeIngressSameEnvelope(config, block); const runtimeExecution = await protocol.createRuntimeExecution( await buildRuntimeIngressExecutionInput(config, block), ); @@ -532,6 +535,56 @@ function runtimeIngressDispatchRefusalReasonCodes(block: ParsedRuntimeIngressDis return unique(block.dispatches.flatMap((dispatch) => dispatchSpecificRefusalReasonCodes(dispatch))); } +const runtimeIngressSameEnvelopeFields = [ + "tenantId", + "organizationId", + "principalId", + "agentId", + "runId", + "runtimeAdapterId", + "operatingEnvelopeId", + "gatewayRegistryRef", +] as const satisfies readonly (keyof RuntimeIngressFamilyConfig)[]; + +function assertRuntimeIngressSameEnvelope( + config: RuntimeIngressConfig, + block: ParsedRuntimeIngressDispatchBlock, +): void { + const familyConfigs = uniqueRuntimeIngressFamilyConfigs(config, block); + if (familyConfigs.length <= 1) return; + + const base = familyConfigs[0]; + if (!base) return; + for (const candidate of familyConfigs.slice(1)) { + for (const field of runtimeIngressSameEnvelopeFields) { + if (candidate.config[field] !== base.config[field]) { + throw new Error( + [ + "Runtime ingress mixed-family dispatch block requires one same-envelope projection.", + `${candidate.familyId} config ${field} does not match ${base.familyId}.`, + "Split the generated execution block into separate protected-action proposals or align the execution envelope before projection.", + ].join(" "), + ); + } + } + } +} + +function uniqueRuntimeIngressFamilyConfigs( + config: RuntimeIngressConfig, + block: ParsedRuntimeIngressDispatchBlock, +): { familyId: RuntimeIngressFamilyId; config: RuntimeIngressFamilyConfig }[] { + const familyConfigs = new Map(); + for (const dispatch of block.dispatches) { + const familyId = runtimeIngressFamilyIdForDispatchKind(dispatch.dispatchKind); + if (!familyId) throw new Error(`Runtime ingress dispatch family is not registered: ${dispatch.dispatchKind}`); + if (!familyConfigs.has(familyId)) { + familyConfigs.set(familyId, runtimeConfigForDispatch(config, dispatch)); + } + } + return [...familyConfigs].map(([familyId, familyConfig]) => ({ familyId, config: familyConfig })); +} + async function createFinalizedToolCallDraft( protocol: Pick, compileInput: CompileIntentInput, diff --git a/src/surfaces/LANE.md b/src/surfaces/LANE.md index eff9af3..62fa641 100644 --- a/src/surfaces/LANE.md +++ b/src/surfaces/LANE.md @@ -2,15 +2,21 @@ ## Authority owner -Shared boundary manifests for SDK, CLI, MCP, and other non-kernel product surfaces. +Shared boundary manifests, service workflow projection maps, and non-authority +outcomes for projection/readback surfaces. ## Current proof claim -This lane records source-owned surface posture only. It does not create protocol authority, route behavior, SDK behavior, CLI behavior, MCP behavior, or gateway enforcement. +This lane records source-owned projection posture only. It does not create +protocol authority, route behavior, SDK behavior, CLI behavior, MCP behavior, +or gateway enforcement. ## Use cases -Give architecture tests one canonical contract for surface ids, custody roles, allowed route families, forbidden route families, forbidden imports, forbidden credential shapes, required non-authority flags, and claim-boundary labels. +Give architecture tests one canonical contract for surface ids, custody roles, +allowed route families, forbidden route families, forbidden imports, forbidden +credential shapes, required non-authority flags, service workflow lifecycle +projection mapping, and claim-boundary labels. ## Constraints and assumptions @@ -18,7 +24,21 @@ Surface manifests are guardrails for implementation and review. The protocol ker ## Core components -`boundary-manifest.ts` defines the shared surface boundary table consumed by architecture tests. `activation-gate.ts` defines the evidence-scoped activation verdict report, required success criteria, and blocking anti-patterns used to decide whether local proof can unblock later operated-surface work. `product-launch-gate-resolution.ts` defines selected, raised-bar, blocked, and cut-line launch gate decisions so product gates cannot remain vague planning branches. `release-proof.ts` defines public distribution release-state evidence for package readiness, publication, registry discoverability, proof gaps, and authority non-claims. `x402-protected-tool-acceptance.ts` defines the production acceptance matrix for the first protected-tool product path as a release-admission contract, not policy or gateway behavior. +`boundary-manifest.ts` defines the shared surface boundary table consumed by +architecture tests. `service-workflow-lifecycle-projections.ts` maps Passport, +ServiceWorkflowAdmission, ServiceWorkflowHandle, Clearance, Outcome, and +AuthorityCertificate to pre-contract context or existing lifecycle entries +without creating a protocol primitive. `activation-gate.ts` defines the +evidence-scoped activation verdict report, required success criteria, and +blocking anti-patterns used to decide whether local proof can unblock later +operated-surface work. `product-launch-gate-resolution.ts` defines selected, +raised-bar, blocked, and cut-line launch gate decisions so product gates cannot +remain vague planning branches. `release-proof.ts` defines public distribution +release-state evidence for package readiness, publication, registry +discoverability, proof gaps, and authority non-claims. +`x402-protected-tool-acceptance.ts` defines the production acceptance matrix for +the first protected-tool product path as a release-admission contract, not +policy or gateway behavior. ## Failure and scale posture diff --git a/src/surfaces/boundary-manifest.ts b/src/surfaces/boundary-manifest.ts index 6d28124..25f1f29 100644 --- a/src/surfaces/boundary-manifest.ts +++ b/src/surfaces/boundary-manifest.ts @@ -68,7 +68,7 @@ export const surfaceAuthorityPostures = [ "evidence_only", "setup_only", "transport_only", - "policy_authority", + "policy_transition_transport", ] as const; export type SurfaceAuthorityPosture = (typeof surfaceAuthorityPostures)[number]; @@ -298,7 +298,7 @@ export const surfaceBoundaryManifest = { status: "active", plane: "operator", custodyRole: "control_plane", - authorityPosture: "policy_authority", + authorityPosture: "policy_transition_transport", sourceRoots: ["src/sdk/surface-clients/policy-client.ts", "src/sdk/surface-clients/transport.ts"], allowedRouteFamilies: ["policy_decision_write"], forbiddenRouteFamilies: [ @@ -361,7 +361,7 @@ export const surfaceBoundaryManifest = { rawInternalRecordIncluded: false, receiptExportCreated: false, }, - claimBoundaryLabels: [...sharedClaimBoundaries, "policy_authority_is_not_gateway_execution"], + claimBoundaryLabels: [...sharedClaimBoundaries, "policy_transition_transport_is_not_gateway_execution"], }, "sdk.adapter": { id: "sdk.adapter", diff --git a/src/surfaces/index.ts b/src/surfaces/index.ts index dabb697..d9d184f 100644 --- a/src/surfaces/index.ts +++ b/src/surfaces/index.ts @@ -5,4 +5,5 @@ export * from "./product-launch-gate-resolution"; export * from "./proof-packets"; export * from "./release-proof"; export * from "./service-workflow-admission"; +export * from "./service-workflow-lifecycle-projections"; export * from "./x402-protected-tool-acceptance"; diff --git a/src/surfaces/service-workflow-lifecycle-projections/index.ts b/src/surfaces/service-workflow-lifecycle-projections/index.ts new file mode 100644 index 0000000..34b7ebe --- /dev/null +++ b/src/surfaces/service-workflow-lifecycle-projections/index.ts @@ -0,0 +1,218 @@ +import { + actionAttemptLifecycleEntry, + type ActionAttemptLifecycleEntry, + type ActionAttemptLifecycleKey, +} from "../../protocol/areas/action-attempt-lifecycle"; +import type { ProtocolTransitionId, TransitionOutcomeClass } from "../../protocol/navigation"; + +export const serviceWorkflowCorrelationFieldNames = [ + "passportPackageDigest", + "passportPresentationId", + "admissionId", + "serviceWorkflowHandleId", + "serviceWorkflowHandleDigest", +] as const; + +export type ServiceWorkflowCorrelationFieldName = (typeof serviceWorkflowCorrelationFieldNames)[number]; + +export type ServiceWorkflowCorrelationFieldBoundary = { + readonly fieldName: ServiceWorkflowCorrelationFieldName; + readonly allowedUse: string; + readonly forbiddenInterpretation: string; + readonly createsAuthority: false; +}; + +export const serviceWorkflowCorrelationFieldBoundaries = [ + { + fieldName: "passportPackageDigest", + allowedUse: "content-addressed correlation with the evidence bundle the agent presented", + forbiddenInterpretation: "identity, trust, permission, or reusable auth", + createsAuthority: false, + }, + { + fieldName: "passportPresentationId", + allowedUse: "unique correlation for one service intake or presentation event", + forbiddenInterpretation: "principal approval, spend approval, or gateway admission", + createsAuthority: false, + }, + { + fieldName: "admissionId", + allowedUse: "service-side readback reference for accepted, refused, stale, proof-gap, or quarantined intake", + forbiddenInterpretation: "policy decision, greenlight, gateway check, receipt, or mutation permission", + createsAuthority: false, + }, + { + fieldName: "serviceWorkflowHandleId", + allowedUse: "workflow context correlation for later proposal/readback", + forbiddenInterpretation: "bearer token, tool permission, retry permission, credential, or payment approval", + createsAuthority: false, + }, + { + fieldName: "serviceWorkflowHandleDigest", + allowedUse: "content-addressed reconstruction reference for the non-authority handle", + forbiddenInterpretation: "proof of authorization, proof of gateway acceptance, or proof of execution", + createsAuthority: false, + }, +] as const satisfies readonly ServiceWorkflowCorrelationFieldBoundary[]; + +export const serviceWorkflowProjectionKinds = [ + "passport", + "service_workflow_admission", + "service_workflow_handle", + "clearance", + "outcome", + "authority_certificate", +] as const; + +export type ServiceWorkflowProjectionKind = (typeof serviceWorkflowProjectionKinds)[number]; + +export type ServiceWorkflowProjection = { + readonly projectionKind: ServiceWorkflowProjectionKind; + readonly productNoun: string; + readonly sourceAuthorityStage: + | "pre_contract_evidence_context" + | "fresh_protected_action_path" + | "terminal_readback" + | "terminal_evidence_projection"; + readonly allowedUse: string; + readonly forbiddenInterpretations: readonly string[]; + readonly createsAuthority: false; + readonly lifecycleKeys: readonly ActionAttemptLifecycleKey[]; + readonly preContractContextRefs: readonly string[]; +}; + +const noLifecycleKeys = [] as const satisfies readonly ActionAttemptLifecycleKey[]; + +export const serviceWorkflowLifecycleProjections = [ + { + projectionKind: "passport", + productNoun: "Passport", + sourceAuthorityStage: "pre_contract_evidence_context", + allowedUse: "present an evidence package for service intake and reconstruction", + forbiddenInterpretations: ["identity", "trust", "permission", "spend approval", "signer access", "reusable auth"], + createsAuthority: false, + lifecycleKeys: noLifecycleKeys, + preContractContextRefs: [ + "participant_identity_binding:evidence_only", + "gateway_custody_packet:evidence_only", + "protected_path_posture:evidence_only", + ], + }, + { + projectionKind: "service_workflow_admission", + productNoun: "ServiceWorkflowAdmission", + sourceAuthorityStage: "pre_contract_evidence_context", + allowedUse: "record service-side accepted, refused, stale, proof-gap, or quarantined intake readback", + forbiddenInterpretations: [ + "policy decision", + "greenlight", + "gateway check", + "receipt", + "certificate", + "mutation permission", + ], + createsAuthority: false, + lifecycleKeys: noLifecycleKeys, + preContractContextRefs: ["passportPackageDigest", "passportPresentationId", "admissionId"], + }, + { + projectionKind: "service_workflow_handle", + productNoun: "ServiceWorkflowHandle", + sourceAuthorityStage: "pre_contract_evidence_context", + allowedUse: "carry correlation and readback context into later fresh proposals", + forbiddenInterpretations: [ + "badge-as-bearer-token", + "tool permission", + "retry permission", + "x402 payment approval", + "auth.md credential", + "gateway pass", + ], + createsAuthority: false, + lifecycleKeys: noLifecycleKeys, + preContractContextRefs: ["serviceWorkflowHandleId", "serviceWorkflowHandleDigest"], + }, + { + projectionKind: "clearance", + productNoun: "Clearance", + sourceAuthorityStage: "fresh_protected_action_path", + allowedUse: "name the fresh exact protected-action path for one event", + forbiddenInterpretations: ["workflow-level permission", "reusable auth", "aggregate spend approval"], + createsAuthority: false, + lifecycleKeys: [ + "proposeActionContract:recorded", + "proposeActionContract:refusal", + "proposeActionContract:conflict", + "evaluatePolicy:greenlight", + "evaluatePolicy:refusal", + "evaluatePolicy:review_required", + "evaluatePolicy:proof_gap", + "evaluatePolicy:conflict", + "gatewayCheck:recorded", + "gatewayCheck:proof_gap", + "gatewayCheck:replay_refusal", + "gatewayCheck:conflict", + ], + preContractContextRefs: [], + }, + { + projectionKind: "outcome", + productNoun: "Outcome", + sourceAuthorityStage: "terminal_readback", + allowedUse: "read receipt, refusal, replay refusal, proof gap, downstream uncertainty, or recovery posture", + forbiddenInterpretations: [ + "downstream business success", + "future permission", + "new greenlight", + "receipt substitute", + ], + createsAuthority: false, + lifecycleKeys: [ + "evaluatePolicy:refusal", + "evaluatePolicy:proof_gap", + "gatewayCheck:recorded", + "gatewayCheck:proof_gap", + "gatewayCheck:replay_refusal", + "gatewayCheck:conflict", + "reconcileSurfaceOperation:recorded", + "reconcileSurfaceOperation:proof_gap", + "reconcileSurfaceOperation:recovery", + "createReceiptExport:exported", + "createReceiptExport:refusal", + "createRecoveryRecommendation:recovery", + "createRecoveryRecommendation:refusal", + ], + preContractContextRefs: [], + }, + { + projectionKind: "authority_certificate", + productNoun: "AuthorityCertificate", + sourceAuthorityStage: "terminal_evidence_projection", + allowedUse: "sign existing terminal evidence for one event", + forbiddenInterpretations: ["permission", "identity", "settlement", "hosted trust", "reusable auth"], + createsAuthority: false, + lifecycleKeys: ["createAuthorityCertificate:exported"], + preContractContextRefs: [], + }, +] as const satisfies readonly ServiceWorkflowProjection[]; + +export const forbiddenServiceWorkflowAuthorityNouns = ["Badge"] as const; + +export function serviceWorkflowProjectionByKind( + projectionKind: ServiceWorkflowProjectionKind, +): ServiceWorkflowProjection { + const projection = serviceWorkflowLifecycleProjections.find((entry) => entry.projectionKind === projectionKind); + if (!projection) throw new Error(`Unknown service workflow projection kind: ${projectionKind}`); + return projection; +} + +export function serviceWorkflowLifecycleEntriesFor( + projectionKind: ServiceWorkflowProjectionKind, +): ActionAttemptLifecycleEntry[] { + return serviceWorkflowProjectionByKind(projectionKind).lifecycleKeys.map(actionAttemptLifecycleEntryForKey); +} + +function actionAttemptLifecycleEntryForKey(key: ActionAttemptLifecycleKey): ActionAttemptLifecycleEntry { + const [transitionId, outcomeClass] = key.split(":") as [ProtocolTransitionId, TransitionOutcomeClass]; + return actionAttemptLifecycleEntry(transitionId, outcomeClass); +} diff --git a/test/architecture/claim-boundary.test.ts b/test/architecture/claim-boundary.test.ts index eaeb940..37f9134 100644 --- a/test/architecture/claim-boundary.test.ts +++ b/test/architecture/claim-boundary.test.ts @@ -101,6 +101,7 @@ describe("claim boundary", () => { const protocolArchitecture = readFileSync("docs/internal/protocol-kernel-architecture.md", "utf8"); const protocolLayman = readFileSync("docs/internal/protocol-layman.md", "utf8"); const protocolNotes = readFileSync("docs/internal/protocol-notes.md", "utf8"); + const serviceWorkflowStory = readFileSync("docs/internal/service-workflow-story.md", "utf8"); const x402Walkthrough = readFileSync("examples/x402-protected-spend/README.md", "utf8"); const httpLane = readFileSync("src/http/LANE.md", "utf8"); const runtimeLane = readFileSync("src/runtime/LANE.md", "utf8"); @@ -145,6 +146,28 @@ describe("claim boundary", () => { /npm package creates hosted enforcement/i, ], }, + { + label: "projection over one authority spine", + sources: [ + { name: "README.md", text: readme }, + { name: "STRUCTURE.md", text: structure }, + { name: "docs/internal/decisions.md", text: decisions }, + { name: "docs/internal/protocol-notes.md", text: protocolNotes }, + { name: "docs/internal/service-workflow-story.md", text: serviceWorkflowStory }, + { name: "src/surfaces/LANE.md", text: readFileSync("src/surfaces/LANE.md", "utf8") }, + ], + requiredPatterns: [ + /projection\/readback/i, + /protocol\s+(?:authority spine|authority state machine|kernel)/i, + /without creating authority|not create authority|does not create/i, + ], + forbiddenPatterns: [ + /product (?:truth|authority) lane (?:owns|creates|authorizes)/i, + /creates? (?:a )?peer product truth lane/i, + /product surface (?:creates|mints|issues) authority/i, + /role-scoped protocol transition clients? (?:are|become) product authority surfaces/i, + ], + }, { label: "category boundary", sources: canonicalSources, diff --git a/test/architecture/service-workflow-lifecycle-projection.test.ts b/test/architecture/service-workflow-lifecycle-projection.test.ts new file mode 100644 index 0000000..bce2dc6 --- /dev/null +++ b/test/architecture/service-workflow-lifecycle-projection.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, it } from "bun:test"; +import { readFileSync } from "node:fs"; +import { + actionAttemptLifecycleEntry, + type ActionAttemptLifecycleKey, +} from "../../src/protocol/areas/action-attempt-lifecycle"; +import type { ProtocolTransitionId, TransitionOutcomeClass } from "../../src/protocol/navigation"; +import { + forbiddenServiceWorkflowAuthorityNouns, + serviceWorkflowCorrelationFieldBoundaries, + serviceWorkflowCorrelationFieldNames, + serviceWorkflowLifecycleEntriesFor, + serviceWorkflowLifecycleProjections, + serviceWorkflowProjectionKinds, +} from "../../src/surfaces/service-workflow-lifecycle-projections"; + +describe("service workflow lifecycle projections", () => { + it("defines friendly product nouns as projections over the existing authority spine", () => { + expect(serviceWorkflowLifecycleProjections.map((entry) => entry.projectionKind)).toEqual([ + ...serviceWorkflowProjectionKinds, + ]); + + const violations: string[] = []; + for (const projection of serviceWorkflowLifecycleProjections) { + if (projection.createsAuthority !== false) { + violations.push(`${projection.productNoun} creates authority`); + } + if (projection.allowedUse.length === 0) { + violations.push(`${projection.productNoun} lacks allowed use`); + } + const forbiddenInterpretations: readonly string[] = projection.forbiddenInterpretations; + if (forbiddenInterpretations.length === 0) { + violations.push(`${projection.productNoun} lacks forbidden interpretations`); + } + for (const key of projection.lifecycleKeys) { + expectLifecycleKeyExists(key); + } + expect(serviceWorkflowLifecycleEntriesFor(projection.projectionKind).length).toBe( + projection.lifecycleKeys.length, + ); + } + + expect(violations.sort()).toEqual([]); + }); + + it("keeps passport, admission, and handle identifiers as correlation only", () => { + expect(serviceWorkflowCorrelationFieldBoundaries.map((entry) => entry.fieldName)).toEqual([ + ...serviceWorkflowCorrelationFieldNames, + ]); + + for (const field of serviceWorkflowCorrelationFieldBoundaries) { + expect(field.createsAuthority).toBe(false); + expect(field.allowedUse).toMatch(/correlation|reconstruction|readback|intake/); + expect(field.forbiddenInterpretation).toMatch(/authority|auth|permission|approval|gateway|identity|execution/); + } + }); + + it("maps clearance, outcome, and certificate to lifecycle entries without creating a protocol primitive", () => { + expect(serviceWorkflowLifecycleEntriesFor("clearance").map((entry) => entry.state)).toEqual( + expect.arrayContaining(["contract_proposed", "policy_greenlit", "gateway_admitted", "gateway_replayed"]), + ); + expect(serviceWorkflowLifecycleEntriesFor("outcome").map((entry) => entry.terminalOutcome)).toEqual( + expect.arrayContaining(["receipt", "refusal", "proof_gap", "projection", "recovery"]), + ); + expect(serviceWorkflowLifecycleEntriesFor("authority_certificate")).toEqual([ + expect.objectContaining({ + state: "authority_certificate_exported", + authorityEffect: "evidence_only", + terminalOutcome: "projection", + }), + ]); + + const protocolFiles = [ + "src/protocol/areas/index.ts", + "src/protocol/public/index.ts", + "src/index.ts", + "package.json", + ]; + for (const file of protocolFiles) { + const text = readFileSync(file, "utf8"); + expect(text).not.toMatch(/ServiceWorkflowLifecycleProjection|serviceWorkflowLifecycleProjections/); + expect(text).not.toMatch(/\bPassport\b|\bBadge\b/); + } + }); + + it("keeps badge language out of service workflow authority nouns", () => { + expect([...forbiddenServiceWorkflowAuthorityNouns]).toEqual(["Badge"]); + const projectionText = JSON.stringify(serviceWorkflowLifecycleProjections); + + expect(projectionText).not.toMatch(/\bBadge\b/); + }); +}); + +function expectLifecycleKeyExists(key: ActionAttemptLifecycleKey): void { + const [transitionId, outcomeClass] = key.split(":") as [ProtocolTransitionId, TransitionOutcomeClass]; + expect(actionAttemptLifecycleEntry(transitionId, outcomeClass)).toBeDefined(); +} diff --git a/test/architecture/surface-boundary-posture.test.ts b/test/architecture/surface-boundary-posture.test.ts index 7cb8196..d8a31b4 100644 --- a/test/architecture/surface-boundary-posture.test.ts +++ b/test/architecture/surface-boundary-posture.test.ts @@ -48,7 +48,7 @@ const modelOrOperatorSurfaces: readonly SurfaceId[] = [ "x402.protected_tool", ]; -const authoritySurfaces: readonly SurfaceId[] = ["sdk.policy"]; +const roleScopedTransitionClients: readonly SurfaceId[] = ["sdk.policy"]; describe("surface boundary posture", () => { it("defines one complete manifest entry for each planned product surface", () => { @@ -88,12 +88,12 @@ describe("surface boundary posture", () => { expect(violations.sort()).toEqual([]); }); - it("keeps explicit authority surfaces narrow and named", () => { + it("keeps role-scoped transition clients narrow and named without making them product authority surfaces", () => { const violations: string[] = []; - for (const id of authoritySurfaces) { + for (const id of roleScopedTransitionClients) { const boundary = boundaryFor(id); - if (boundary.authorityPosture !== "policy_authority") { - violations.push(`${id} is not marked policy authority`); + if (boundary.authorityPosture !== "policy_transition_transport") { + violations.push(`${id} is not marked as policy transition transport`); } if (!boundary.allowedRouteFamilies.includes("policy_decision_write")) { violations.push(`${id} cannot write policy decisions`); @@ -105,8 +105,12 @@ describe("surface boundary posture", () => { if (boundary.claimBoundaryLabels.includes("runtime_evidence_is_not_authority")) { violations.push(`${id} is mislabeled as runtime proposal surface`); } + if (!boundary.claimBoundaryLabels.includes("policy_transition_transport_is_not_gateway_execution")) { + violations.push(`${id} does not say policy transition transport is not gateway execution`); + } } + expect(JSON.stringify(surfaceBoundaryManifest)).not.toContain("policy_authority"); expect(violations.sort()).toEqual([]); }); diff --git a/test/runtime/runtime-ingress.test.ts b/test/runtime/runtime-ingress.test.ts index 185e5f5..d58ef0f 100644 --- a/test/runtime/runtime-ingress.test.ts +++ b/test/runtime/runtime-ingress.test.ts @@ -19,6 +19,7 @@ import { } from "../../src/runtime"; import { runtimeIngressFamilyRegistry } from "../../src/runtime/ingress/registry"; import { futureIso, makeKernelFixture, registerFixtureObjects } from "../support/fixtures"; +import { authMdRuntimeConfig, authMdRuntimeDispatch, installedAuthMdKernel } from "../support/auth-md-flow"; import { packageInstallRuntimeConfig } from "../support/package-install-flow"; const x402Digest = `sha256:${"9".repeat(64)}` as const; @@ -439,13 +440,13 @@ describe("runtime ingress adapter", () => { await expectNoRuntimeAuthorityRecords(fixture.store); }); - it("retains mixed-family grammar while routing each dispatch through its family config", async () => { - const { fixture, x402RuntimeConfig, x402Proposal } = await installedMixedIngressFixture(); + it("retains mixed-family grammar only when every dispatch config shares one execution envelope", async () => { + const { fixture, packageRuntimeConfig, x402RuntimeConfig, x402Proposal } = await installedMixedIngressFixture(); const result = await proposeRuntimeIngressActionContracts( fixture.kernel, { - packageInstall: packageInstallRuntimeConfig(fixture), + packageInstall: packageRuntimeConfig, x402Payment: x402RuntimeConfig, }, { @@ -477,6 +478,89 @@ describe("runtime ingress adapter", () => { await expectNoRuntimeAuthorityRecords(fixture.store); }); + it("rejects mixed-family dispatch blocks with different envelopes before recording runtime evidence", async () => { + const { fixture, packageRuntimeConfig, x402RuntimeConfig, x402Proposal } = await installedMixedIngressFixture(); + + await expect( + proposeRuntimeIngressActionContracts( + fixture.kernel, + { + packageInstall: { ...packageRuntimeConfig, operatingEnvelopeId: "env_different_runtime_block" }, + x402Payment: x402RuntimeConfig, + }, + { + principalIntentRef: "intent:install package and fetch paid context through mismatched envelopes", + generatedCodeOrSpecRef: "runtime:dispatch-block-mixed-envelope-mismatch", + dispatchBoundaryRef: "dispatch-boundary:mixed-envelope-mismatch", + dispatches: [ + { + dispatchKind: "wrapped_package_install", + dispatchRef: "dispatch:package-install:mixed-mismatch", + package: "hono", + versionRange: "^4.12.19", + }, + x402Dispatch( + x402Proposal, + "dispatch:x402-payment:mixed-mismatch", + upstreamX402DispatchBinding(x402Proposal), + ), + ], + }, + ), + ).rejects.toThrow("Runtime ingress mixed-family dispatch block requires one same-envelope projection."); + + expect(await recordCount(fixture.store, "runtime_execution")).toBe(0); + expect(await recordCount(fixture.store, "generated_execution_graph")).toBe(0); + expect(await recordCount(fixture.store, "action_contract")).toBe(0); + await expectNoRuntimeAuthorityRecords(fixture.store); + }); + + it("refuses x402 plus auth.md composition with separate envelopes instead of creating composite authority", async () => { + const authFixture = await installedAuthMdKernel(); + const x402Proposal = await compileX402InstallProposal(validX402InstallInput()); + const x402Records = requireX402Records(x402Proposal); + await authFixture.kernel.putCatalogObject({ objectType: "tool_capability", payload: x402Records.toolCapability }); + await authFixture.kernel.putCatalogObject({ objectType: "action_type", payload: x402Records.actionType }); + await authFixture.kernel.putCatalogObject({ + objectType: "gateway_registry_entry", + payload: x402Records.gatewayRegistryEntry, + }); + await authFixture.kernel.putCatalogObject({ + objectType: "operating_envelope", + payload: x402Records.operatingEnvelope, + }); + const x402CredentialRef = await registerX402WalletCredentialRef(authFixture.kernel, x402Proposal, x402Records); + const x402AuthorityRef = await registerX402DelegatedAuthorityRef(authFixture.kernel, x402Proposal, x402Records); + + await expect( + proposeRuntimeIngressActionContracts( + authFixture.kernel, + { + authMdProtectedApiCall: authMdRuntimeConfig(authFixture), + x402Payment: x402RuntimeConfigFor(x402Proposal, x402Records, x402CredentialRef, x402AuthorityRef), + }, + { + principalIntentRef: "intent:pay and call credentialed API through one generated block", + generatedCodeOrSpecRef: "runtime:dispatch-block-x402-auth-md-composite", + dispatchBoundaryRef: "dispatch-boundary:x402-auth-md-composite", + dispatches: [ + x402Dispatch( + x402Proposal, + "dispatch:x402-payment:auth-md-composite", + upstreamX402DispatchBinding(x402Proposal), + ), + authMdRuntimeDispatch(authFixture, "dispatch:auth-md:composite"), + ], + }, + ), + ).rejects.toThrow("Runtime ingress mixed-family dispatch block requires one same-envelope projection."); + + expect(await recordCount(authFixture.store, "runtime_execution")).toBe(0); + expect(await recordCount(authFixture.store, "generated_execution_graph")).toBe(0); + expect(await recordCount(authFixture.store, "action_contract")).toBe(0); + await expectNoRuntimeAuthorityRecords(authFixture.store); + }); + it("propagates x402 body and provider posture into the exact runtime contract", async () => { const { fixture, runtimeConfig, proposal } = await installedX402IngressFixture(); @@ -1087,38 +1171,68 @@ async function installedMixedIngressFixture() { }); await fixture.kernel.putCatalogObject({ objectType: "operating_envelope", payload: x402Records.operatingEnvelope }); const x402CredentialRef = await registerX402WalletCredentialRef(fixture.kernel, x402Proposal, x402Records); - const x402AuthorityRef = await registerX402DelegatedAuthorityRef(fixture.kernel, x402Proposal, x402Records); + const mixedEnvelope = { + ...fixture.envelope, + envelopeId: "env_mixed_runtime_ingress", + objectiveRef: "intent:install package and fetch paid context", + allowedActionClasses: ["package.install", "x402_payment.exact"], + allowedGateways: [fixture.gateway.gatewayId, x402Records.gatewayRegistryEntry.gatewayId], + allowedResources: ["npm:hono", x402Proposal.resourceRef], + evidenceRequirements: ["package_lock_diff", "x402_payment_required"], + }; + await fixture.kernel.putCatalogObject({ objectType: "operating_envelope", payload: mixedEnvelope }); + const x402AuthorityRef = await registerX402DelegatedAuthorityRef(fixture.kernel, x402Proposal, { + ...x402Records, + operatingEnvelope: mixedEnvelope, + }); + const packageRuntimeConfig = { + ...packageInstallRuntimeConfig(fixture), + operatingEnvelopeId: mixedEnvelope.envelopeId, + }; return { fixture, x402Proposal, + packageRuntimeConfig, x402RuntimeConfig: { - tenantId: x402Proposal.tenantId, - organizationId: x402Proposal.organizationId, - principalId: x402Records.operatingEnvelope.principalId, - agentId: x402Records.operatingEnvelope.agentId, - runId: "run_demo", - runtimeAdapterId: x402Records.toolCapability.runtimeAdapterId, - operatingEnvelopeId: x402Records.operatingEnvelope.envelopeId, - toolCatalogRef: `${x402Records.toolCapability.toolCatalogId}@${x402Records.toolCapability.toolCatalogVersion}`, - actionCatalogRef: `${x402Records.actionType.actionCatalogId}@${x402Records.actionType.actionCatalogVersion}`, - gatewayRegistryRef: `gateway_registry@${x402Records.gatewayRegistryEntry.gatewayRegistryVersion}`, - gatewayReadinessRef: "handshake://local/x402/gateway-readiness.json", - gatewayReadinessDigest: x402Digest, - policyVersionRef: `${x402Proposal.policyPackRef}@${x402Proposal.policyPackVersion}`, - policyVersionDigest: x402Digest, - toolCapabilityId: x402Records.toolCapability.toolCapabilityId, - actionTypeId: x402Records.actionType.actionTypeId, - gatewayRegistryEntryId: x402Records.gatewayRegistryEntry.gatewayRegistryEntryId, - gatewayId: x402Records.gatewayRegistryEntry.gatewayId, - gatewayCredentialBinding: x402WalletGatewayCredentialBindingFor(x402CredentialRef), - delegatedAuthorityBinding: x402DelegatedSpendAuthorityBindingFor(x402AuthorityRef), - maxAtomicAmountPerCall: x402Proposal.spendBounds.maxAtomicAmountPerCall, - contractExpiresAt: futureIso(), - signingSecret: "test-secret", + ...x402RuntimeConfigFor(x402Proposal, x402Records, x402CredentialRef, x402AuthorityRef), + operatingEnvelopeId: mixedEnvelope.envelopeId, }, }; } +function x402RuntimeConfigFor( + proposal: X402InstallProposal, + records: NonNullable, + credentialRef: GatewayCredentialRef, + authorityRef: DelegatedAuthorityRef, +) { + return { + tenantId: proposal.tenantId, + organizationId: proposal.organizationId, + principalId: records.operatingEnvelope.principalId, + agentId: records.operatingEnvelope.agentId, + runId: "run_demo", + runtimeAdapterId: records.toolCapability.runtimeAdapterId, + operatingEnvelopeId: records.operatingEnvelope.envelopeId, + toolCatalogRef: `${records.toolCapability.toolCatalogId}@${records.toolCapability.toolCatalogVersion}`, + actionCatalogRef: `${records.actionType.actionCatalogId}@${records.actionType.actionCatalogVersion}`, + gatewayRegistryRef: `gateway_registry@${records.gatewayRegistryEntry.gatewayRegistryVersion}`, + gatewayReadinessRef: "handshake://local/x402/gateway-readiness.json", + gatewayReadinessDigest: x402Digest, + policyVersionRef: `${proposal.policyPackRef}@${proposal.policyPackVersion}`, + policyVersionDigest: x402Digest, + toolCapabilityId: records.toolCapability.toolCapabilityId, + actionTypeId: records.actionType.actionTypeId, + gatewayRegistryEntryId: records.gatewayRegistryEntry.gatewayRegistryEntryId, + gatewayId: records.gatewayRegistryEntry.gatewayId, + gatewayCredentialBinding: x402WalletGatewayCredentialBindingFor(credentialRef), + delegatedAuthorityBinding: x402DelegatedSpendAuthorityBindingFor(authorityRef), + maxAtomicAmountPerCall: proposal.spendBounds.maxAtomicAmountPerCall, + contractExpiresAt: futureIso(), + signingSecret: "test-secret", + }; +} + type WrappedX402Dispatch = Extract; function x402Dispatch( From a878798488cf5cc2bad6d4be949a3b9a35c50f0d Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 19:49:59 +0800 Subject: [PATCH 011/144] Record architecture closeout evidence --- .../git-checkpoints.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md index 5f69f06..74d1b03 100644 --- a/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md +++ b/.planning/macro-plan/runs/20260525T110908Z-architectural-north-star/git-checkpoints.md @@ -10,7 +10,8 @@ evidence so the architecture correction remains reconstructable. | Commit | Purpose | | --- | --- | | `bdcec05` | Reset architecture macro plan around projection-over-spine north star. | -| pending | Commit implementation of projection map, docs, runtime gate, tests, and validation evidence. | +| `c8db729` | Implement projection map, docs, runtime same-envelope guard, tests, and validation evidence. | +| pending | Record closeout evidence after implementation commit. | ## Working Tree Notes From 4b5ae7754fa37a2a1a92892adadf09c6e26bcba8 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 20:01:21 +0800 Subject: [PATCH 012/144] Split proof packet surface modules --- src/surfaces/LANE.md | 6 +- src/surfaces/proof-packets.ts | 1035 ----------------- .../clean-installed-activation.ts | 90 ++ .../proof-packets/codex-host-activation.ts | 181 +++ src/surfaces/proof-packets/codex-toml.ts | 201 ++++ .../proof-packets/distribution-provenance.ts | 180 +++ src/surfaces/proof-packets/index.ts | 7 + .../proof-packets/live-x402-requirement.ts | 117 ++ .../proof-packets/product-completion.ts | 217 ++++ src/surfaces/proof-packets/shared.ts | 56 + 10 files changed, 1054 insertions(+), 1036 deletions(-) delete mode 100644 src/surfaces/proof-packets.ts create mode 100644 src/surfaces/proof-packets/clean-installed-activation.ts create mode 100644 src/surfaces/proof-packets/codex-host-activation.ts create mode 100644 src/surfaces/proof-packets/codex-toml.ts create mode 100644 src/surfaces/proof-packets/distribution-provenance.ts create mode 100644 src/surfaces/proof-packets/index.ts create mode 100644 src/surfaces/proof-packets/live-x402-requirement.ts create mode 100644 src/surfaces/proof-packets/product-completion.ts create mode 100644 src/surfaces/proof-packets/shared.ts diff --git a/src/surfaces/LANE.md b/src/surfaces/LANE.md index 62fa641..8da7ab7 100644 --- a/src/surfaces/LANE.md +++ b/src/surfaces/LANE.md @@ -38,7 +38,11 @@ release-state evidence for package readiness, publication, registry discoverability, proof gaps, and authority non-claims. `x402-protected-tool-acceptance.ts` defines the production acceptance matrix for the first protected-tool product path as a release-admission contract, not -policy or gateway behavior. +policy or gateway behavior. `proof-packets/` owns focused readback packet +projectors for clean installed activation, Codex host activation, distribution +provenance, live x402 requirement readback, and product-completion closeout; the +folder keeps each packet family local while preserving the single projection +seam consumed by tests and scripts. ## Failure and scale posture diff --git a/src/surfaces/proof-packets.ts b/src/surfaces/proof-packets.ts deleted file mode 100644 index 585c80a..0000000 --- a/src/surfaces/proof-packets.ts +++ /dev/null @@ -1,1035 +0,0 @@ -import { Buffer } from "node:buffer"; -import { createHash } from "node:crypto"; -import { isPaymentRequiredV2, validatePaymentRequired } from "@x402/core/schemas"; - -export const PROOF_PACKET_VERSION = "proof-packets.v0.1" as const; - -export type ProofGap = { - readonly reasonCode: string; - readonly nonClaim: string; -}; - -export type NonAuthorityBoundary = { - readonly createsAuthority: false; - readonly createsPolicyDecision: false; - readonly createsGreenlight: false; - readonly performsGatewayCheck: false; - readonly performsMutation: false; -}; - -export const nonAuthorityBoundary: NonAuthorityBoundary = { - createsAuthority: false, - createsPolicyDecision: false, - createsGreenlight: false, - performsGatewayCheck: false, - performsMutation: false, -}; - -export type CleanInstalledActivationProofInput = { - readonly generatedAt: string; - readonly package: { - readonly name: string; - readonly version: string; - readonly packedFile: string; - readonly localArtifactPath: string | null; - readonly tarballSha256: string; - readonly tarballSizeBytes: number; - readonly npmIntegrity: string | null; - readonly npmShasum: string | null; - readonly fileCount: number | null; - }; - readonly requiredInstalledSurfaces: { - readonly bins: readonly string[]; - readonly exports: readonly string[]; - readonly protectedToolExports: readonly string[]; - }; - readonly activationEvidence: { - readonly facadeImportSource: string; - readonly runtimeDispatchPrepared: boolean; - readonly gatewayAdmissionStatus: string; - readonly downstreamOutcomeStatus: string; - readonly policyDecision: string; - readonly gateDecision: string; - readonly changedParameterDecision: string; - readonly replayDecision: string; - readonly signerInvocationsAfterGatewayAdmission: number; - readonly signerInvocationsAfterReplay: number; - readonly hostileGeneratedExecutionCaseIds: readonly string[]; - readonly rawCredentialMaterialVisible: boolean; - readonly outputRefs: readonly string[]; - }; - readonly commandRefs: readonly string[]; -}; - -export type CleanInstalledActivationProof = ReturnType; - -export function projectCleanInstalledActivationProof(input: CleanInstalledActivationProofInput) { - return { - proofKind: "clean_installed_activation_proof" as const, - proofVersion: PROOF_PACKET_VERSION, - generatedAt: input.generatedAt, - status: "local_activation_passed" as const, - scope: - "Pinned local packed artifact activation for the x402 protected-tool proposal/evidence surface. This is not live host activation.", - package: input.package, - requiredInstalledSurfaces: input.requiredInstalledSurfaces, - activationEvidence: input.activationEvidence, - commandRefs: input.commandRefs, - evidenceRefs: [ - `package:${input.package.name}@${input.package.version}:tarball-sha256:${input.package.tarballSha256}`, - "evidence:clean-installed-import:x402-protected-tool", - "evidence:clean-installed-demo:x402-protected-spend", - ...input.activationEvidence.outputRefs, - ], - authorityBoundary: { - ...nonAuthorityBoundary, - resolvesCredential: false as const, - invokesSigner: false as const, - createsPaymentPayload: false as const, - configuresLiveHost: false as const, - provesMcpRegistryDiscoverability: false as const, - provesPublicNpmCurrentSurface: false as const, - provesCustomerGatewayCustody: false as const, - provesLivePaidExecution: false as const, - }, - proofGaps: [ - gap( - "live_codex_host_not_configured_by_clean_install_check", - "Clean installed activation does not prove live Codex host configuration or host-origin tool invocation.", - ), - gap( - "mcp_registry_discoverability_not_checked_by_clean_install_check", - "Clean installed activation does not prove MCP Registry acceptance or lookup.", - ), - gap( - "public_npm_current_surface_not_checked_by_clean_install_check", - "Clean installed activation uses a local packed artifact and does not prove that the current surface is published.", - ), - gap( - "customer_gateway_live_payment_not_checked_by_clean_install_check", - "Clean installed activation does not exercise a funded customer-gateway-held signer or live x402 paid retry.", - ), - ], - nextMechanism: "Configure a live Codex MCP host against this exact artifact only after explicit approval.", - }; -} - -export type CodexHostActivationReadbackInput = { - readonly generatedAt: string; - readonly commandRefs: readonly string[]; - readonly configPath: string; - readonly configExists: boolean; - readonly configSha256: string | null; - readonly configText?: string; - readonly observedMcpServers?: readonly string[]; - readonly expectedServer?: CodexHostExpectedServer; - readonly hostToolInvocation?: CodexHostToolInvocationReadback; - readonly expectedArtifact: { - readonly path: string; - readonly exists: boolean; - readonly sha256: string | null; - readonly sizeBytes: number | null; - } | null; -}; - -export type CodexHostExpectedServer = { - readonly name: string; - readonly command: string; - readonly args: readonly string[]; - readonly executablePath: string; - readonly artifactSha256: string; -}; - -export type CodexMcpServerRecord = { - readonly name: string; - readonly command: string | null; - readonly args: readonly string[] | null; - readonly startupTimeoutSec: number | null; - readonly envKeys: readonly string[]; -}; - -export type CodexHostToolInvocationReadback = { - readonly proofRef: string; - readonly toolVisible: boolean; - readonly toolCallAttempted: boolean; - readonly outcome: string; - readonly nonAuthorityClaims: readonly string[]; -}; - -export type CodexHostActivationReadback = ReturnType; - -export function projectCodexHostActivationReadback(input: CodexHostActivationReadbackInput) { - const serverRecords = parseCodexMcpServerRecords(input.configText ?? ""); - const observedMcpServers = [...(input.observedMcpServers ?? serverRecords.map((server) => server.name))].sort(); - const targetServerName = input.expectedServer?.name ?? "handshake_x402"; - const targetServer = serverRecords.find((server) => server.name === targetServerName) ?? null; - const targetPresent = observedMcpServers.includes(targetServerName); - const expectedServerMatches = input.expectedServer - ? targetServer !== null && - targetServer.command === input.expectedServer.command && - arrayEquals(targetServer.args ?? [], input.expectedServer.args) - : targetPresent; - const hostToolInvocationObserved = - expectedServerMatches && - input.hostToolInvocation?.toolVisible === true && - input.hostToolInvocation.toolCallAttempted === true; - const status = targetPresent - ? hostToolInvocationObserved - ? ("host_tool_invocation_observed" as const) - : expectedServerMatches - ? ("configured_unverified" as const) - : ("blocked" as const) - : ("blocked" as const); - - return { - proofKind: "codex_host_activation_readback" as const, - proofVersion: PROOF_PACKET_VERSION, - generatedAt: input.generatedAt, - status, - scope: "Read-only Codex-local MCP host configuration readback for the Handshake x402 proposal/evidence server.", - config: { - path: input.configPath, - exists: input.configExists, - sha256: input.configSha256, - observedMcpServers, - targetServerName, - targetPresent, - targetServer, - expectedServer: input.expectedServer ?? null, - expectedServerMatches, - hostToolInvocation: input.hostToolInvocation ?? null, - hostToolInvocationObserved, - }, - expectedArtifact: input.expectedArtifact, - commandRefs: input.commandRefs, - evidenceRefs: codexEvidenceRefs({ - configSha256: input.configSha256, - expectedArtifactSha256: input.expectedArtifact?.sha256 ?? null, - targetPresent, - }), - authorityBoundary: { - ...nonAuthorityBoundary, - resolvesCredential: false as const, - invokesSigner: false as const, - createsPaymentPayload: false as const, - configuresLiveHost: false as const, - observesHostToolInvocation: hostToolInvocationObserved, - provesHostWideContainment: false as const, - provesMcpRegistryDiscoverability: false as const, - provesCustomerGatewayCustody: false as const, - provesLivePaidExecution: false as const, - }, - proofGaps: codexProofGaps(input, targetPresent, hostToolInvocationObserved), - nextMechanism: hostToolInvocationObserved - ? "Move to public distribution/provenance; Codex-local host invocation does not prove registry discovery, customer gateway custody, or live paid execution." - : targetPresent - ? "Exercise `handshake.actions.x402_payment.propose` through the configured Codex host and capture a host-origin transcript." - : "Add `mcp_servers.handshake_x402` to Codex config against the pinned artifact after explicit approval.", - }; -} - -export function parseCodexMcpServerNames(configText: string): string[] { - return parseCodexMcpServerRecords(configText).map((server) => server.name); -} - -export function parseCodexMcpServerRecords(configText: string): CodexMcpServerRecord[] { - const sections = parseTomlSections(configText); - return sections - .filter((section) => section.kind === "mcp_server") - .map((section) => ({ - name: section.name, - command: parseTomlStringField(section.body, "command"), - args: parseTomlStringArrayField(section.body, "args"), - startupTimeoutSec: parseTomlNumberField(section.body, "startup_timeout_sec"), - envKeys: parseCodexMcpServerEnvKeys(sections, section.name), - })) - .sort((left, right) => left.name.localeCompare(right.name)); -} - -export function buildCodexMcpServerTomlBlock(input: { - readonly name: string; - readonly command: string; - readonly args: readonly string[]; - readonly startupTimeoutSec?: number; -}): string { - const startupTimeoutSec = input.startupTimeoutSec ?? 120; - return [ - `[mcp_servers.${input.name}]`, - `command = ${tomlString(input.command)}`, - `args = [${input.args.map(tomlString).join(", ")}]`, - `startup_timeout_sec = ${startupTimeoutSec}`, - "", - ].join("\n"); -} - -export function upsertCodexMcpServerToml(input: { - readonly existingToml: string; - readonly serverName: string; - readonly serverBlockToml: string; -}) { - const newline = input.existingToml.includes("\r\n") ? "\r\n" : "\n"; - const sourceLines = input.existingToml.split(/\r?\n/u); - const retainedLines: string[] = []; - let skippingTargetSection = false; - - for (const line of sourceLines) { - const header = parseTomlHeader(line); - if (header) { - skippingTargetSection = isCodexMcpServerHeader(header, input.serverName); - } - if (!skippingTargetSection) retainedLines.push(line); - } - - const insertIndex = lastMcpSectionEndIndex(retainedLines); - const blockLines = input.serverBlockToml.trimEnd().split(/\r?\n/u); - const before = retainedLines.slice(0, insertIndex); - const after = retainedLines.slice(insertIndex); - const nextLines = [...trimTrailingBlankLines(before), "", ...blockLines, "", ...trimLeadingBlankLines(after)]; - const nextToml = `${nextLines.join(newline).replace(/\n{4,}/gu, `${newline}${newline}${newline}`)}${newline}`; - - return { - changed: nextToml !== input.existingToml, - toml: nextToml, - }; -} - -export type DistributionProvenanceReadbackInput = { - readonly generatedAt: string; - readonly localPackage: { - readonly name: string; - readonly version: string; - readonly mcpName: string; - readonly serverJsonName: string; - readonly serverJsonVersion: string; - readonly exports: readonly string[]; - }; - readonly npmLatest: { - readonly url: string; - readonly status: number | null; - readonly version: string | null; - readonly tarball: string | null; - readonly integrity: string | null; - readonly shasum: string | null; - readonly signatureCount: number; - readonly fileCount: number | null; - readonly exports: readonly string[]; - }; - readonly mcpRegistry: { - readonly lookupUrl: string; - readonly lookupStatus: number | null; - readonly lookupProblemTitle: string | null; - readonly searchUrl: string; - readonly searchStatus: number | null; - readonly searchCount: number | null; - }; - readonly publishAttempt?: DistributionPublishAttemptReadback; - readonly evidenceRefs: readonly string[]; - readonly commandRefs: readonly string[]; -}; - -export type DistributionProvenanceReadback = ReturnType; - -export type DistributionPublishAttemptReadback = { - readonly attempted: boolean; - readonly commandRef: string; - readonly status: "not_attempted" | "failed" | "succeeded"; - readonly provenanceRequested: boolean; - readonly provenanceSupported: boolean | null; - readonly errorCode: string | null; - readonly errorMessage: string | null; - readonly evidenceRef: string | null; -}; - -export function projectDistributionProvenanceReadback(input: DistributionProvenanceReadbackInput) { - const localExports = [...input.localPackage.exports].sort(); - const publishedExports = [...input.npmLatest.exports].sort(); - const missingLocalExports = localExports.filter((entry) => !publishedExports.includes(entry)); - const extraPublishedExports = publishedExports.filter((entry) => !localExports.includes(entry)); - const npmLatestMatchesLocalVersion = input.npmLatest.version === input.localPackage.version; - const currentSurfacePublished = - input.npmLatest.status === 200 && npmLatestMatchesLocalVersion && missingLocalExports.length === 0; - const mcpRegistryAccepted = input.mcpRegistry.lookupStatus === 200; - const mcpRegistryDiscoverable = - mcpRegistryAccepted && input.mcpRegistry.searchCount !== null && input.mcpRegistry.searchCount > 0; - const status = currentSurfacePublished && mcpRegistryDiscoverable ? "registry_discoverable" : "blocked"; - - return { - proofKind: "distribution_provenance_readback" as const, - proofVersion: PROOF_PACKET_VERSION, - generatedAt: input.generatedAt, - status, - scope: - "Public npm and MCP Registry readback for the current local package surface. Publication and registry discovery are distribution facts only.", - localPackage: { - ...input.localPackage, - exports: localExports, - }, - npmLatest: { - ...input.npmLatest, - exports: publishedExports, - missingLocalExports, - extraPublishedExports, - currentSurfacePublished, - }, - mcpRegistry: { - ...input.mcpRegistry, - accepted: mcpRegistryAccepted, - discoverable: mcpRegistryDiscoverable, - }, - publishAttempt: input.publishAttempt ?? null, - commandRefs: input.commandRefs, - evidenceRefs: input.evidenceRefs, - authorityBoundary: { - ...nonAuthorityBoundary, - holdsCustody: false as const, - hostsOperation: false as const, - certifiesMarketplace: false as const, - managesSettlement: false as const, - managesPayment: false as const, - establishesTrust: false as const, - enforcesHostWidePolicy: false as const, - }, - proofGaps: distributionProofGaps({ - npmLatestStatus: input.npmLatest.status, - npmLatestMatchesLocalVersion, - missingLocalExports, - currentSurfacePublished, - mcpRegistryAccepted, - mcpRegistryDiscoverable, - publishAttempt: input.publishAttempt ?? null, - }), - nextMechanism: currentSurfacePublished - ? "Submit and verify MCP Registry publication for the current package version." - : "Publish a new package version containing the current local export surface, then rerun npm and MCP Registry readback.", - }; -} - -export type LiveX402RequirementReadbackInput = { - readonly generatedAt: string; - readonly commandRefs: readonly string[]; - readonly request: { - readonly method: string; - readonly url: string; - readonly responseStatus: number; - readonly providerEnvironmentPosture: "live"; - readonly headersEvidenceRef: string; - }; - readonly paymentRequiredHeader: string; - readonly selectedPaymentRequirementIndex: number; - readonly customerGatewayCustody: { - readonly present: boolean; - readonly proofRef: string | null; - readonly digest: `sha256:${string}` | null; - }; -}; - -export type LiveX402RequirementReadback = ReturnType; - -export function projectLiveX402RequirementReadback(input: LiveX402RequirementReadbackInput) { - const paymentRequired = validatePaymentRequired( - JSON.parse(Buffer.from(input.paymentRequiredHeader, "base64").toString("utf8")), - ); - if (!isPaymentRequiredV2(paymentRequired)) { - throw new Error("Only x402 v2 PAYMENT-REQUIRED evidence is supported."); - } - const selectedPaymentRequirement = paymentRequired.accepts[input.selectedPaymentRequirementIndex]; - if (!selectedPaymentRequirement) throw new Error("Selected x402 payment requirement index is outside accepts."); - if (selectedPaymentRequirement.scheme !== "exact") { - throw new Error("The live x402 first wedge only admits exact requirements."); - } - const status = - input.request.responseStatus === 402 && input.customerGatewayCustody.present - ? ("ready_for_gateway_signed_retry" as const) - : ("blocked" as const); - - return { - proofKind: "live_x402_requirement_readback" as const, - proofVersion: PROOF_PACKET_VERSION, - generatedAt: input.generatedAt, - status, - scope: - "Live x402 Payment Required challenge readback for one buyer-side exact protected action. This is not payment execution.", - request: input.request, - paymentRequired: { - x402Version: paymentRequired.x402Version, - resource: paymentRequired.resource, - acceptsCount: paymentRequired.accepts.length, - selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, - selectedPaymentRequirement, - selectedPaymentRequirementDigest: stableDigest({ - paymentRequired, - selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, - selectedPaymentRequirement, - }), - }, - customerGatewayCustody: input.customerGatewayCustody, - commandRefs: input.commandRefs, - evidenceRefs: [ - input.request.headersEvidenceRef, - `selected-payment-requirement:${stableDigest({ - paymentRequired, - selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, - selectedPaymentRequirement, - })}`, - ], - authorityBoundary: { - ...nonAuthorityBoundary, - resolvesCredential: false as const, - invokesSigner: false as const, - createsPaymentPayload: false as const, - provesCustomerGatewayCustody: input.customerGatewayCustody.present, - provesLivePaidExecution: false as const, - provesSettlementFinality: false as const, - provesProviderCustody: false as const, - certifiesMarketplace: false as const, - }, - proofGaps: liveX402ProofGaps({ - responseStatus: input.request.responseStatus, - custodyPresent: input.customerGatewayCustody.present, - }), - nextMechanism: input.customerGatewayCustody.present - ? "Create one exact x402 action contract from the selected requirement and run a post-VerifiedGatewayCheck signed retry." - : "Attach a funded customer-gateway custody packet before any live signed retry can be attempted.", - }; -} - -export type ProductCompletionGateId = - | "codex_local_host_activation" - | "public_distribution_and_registry" - | "customer_gateway_live_x402_paid_proof" - | "auth_md_x402_admission_packet"; - -export type ProductCompletionGateStatus = "completed" | "hard_blocked" | "incomplete"; - -export type ProductCompletionReadbackInput = { - readonly generatedAt: string; - readonly commandRefs: readonly string[]; - readonly qualityGate: { - readonly command: string; - readonly passed: boolean; - readonly evidenceRef: string; - }; - readonly gates: { - readonly codexLocalHostActivation: { - readonly status: CodexHostActivationReadback["status"]; - readonly artifactVersion: string; - readonly artifactSha256: string | null; - readonly observesHostToolInvocation: boolean; - readonly authorityCreated: boolean; - readonly evidenceRefs: readonly string[]; - }; - readonly publicDistributionAndRegistry: { - readonly status: DistributionProvenanceReadback["status"]; - readonly localVersion: string; - readonly npmLatestVersion: string | null; - readonly currentSurfacePublished: boolean; - readonly mcpRegistryAccepted: boolean; - readonly mcpRegistryDiscoverable: boolean; - readonly provenanceAttempted: boolean; - readonly provenanceSupported: boolean | null; - readonly proofGapReasonCodes: readonly string[]; - readonly evidenceRefs: readonly string[]; - }; - readonly customerGatewayLiveX402PaidProof: { - readonly status: LiveX402RequirementReadback["status"]; - readonly customerGatewayCustodyPresent: boolean; - readonly livePaidRetryPerformed: boolean; - readonly terminalReadbackPresent: boolean; - readonly signerInvocationPosture: "post_gateway_check_only" | "not_observed" | "unsafe_or_unknown"; - readonly proofGapReasonCodes: readonly string[]; - readonly evidenceRefs: readonly string[]; - }; - readonly authMdX402AdmissionPacket: { - readonly packetVersion: "v0"; - readonly packetProjectorPresent: boolean; - readonly refusalFirstTestsPassed: boolean; - readonly redactedReadbackTestsPassed: boolean; - readonly createsAuthority: boolean; - readonly evidenceRefs: readonly string[]; - }; - }; -}; - -export type ProductCompletionReadback = ReturnType; - -export function projectProductCompletionReadback(input: ProductCompletionReadbackInput) { - const gateResults = [ - productCompletionGateResult({ - gateId: "codex_local_host_activation", - title: "Codex-local runtime activation from pinned current-surface artifact", - completed: - input.gates.codexLocalHostActivation.status === "host_tool_invocation_observed" && - input.gates.codexLocalHostActivation.observesHostToolInvocation && - !input.gates.codexLocalHostActivation.authorityCreated, - hardBlocked: false, - blockers: [], - evidenceRefs: input.gates.codexLocalHostActivation.evidenceRefs, - }), - productCompletionGateResult({ - gateId: "public_distribution_and_registry", - title: "Public package distribution, provenance posture, and MCP Registry lookup", - completed: input.gates.publicDistributionAndRegistry.status === "registry_discoverable", - hardBlocked: - !input.gates.publicDistributionAndRegistry.currentSurfacePublished && - input.gates.publicDistributionAndRegistry.provenanceAttempted && - input.gates.publicDistributionAndRegistry.provenanceSupported === false && - !input.gates.publicDistributionAndRegistry.mcpRegistryDiscoverable, - blockers: input.gates.publicDistributionAndRegistry.proofGapReasonCodes, - evidenceRefs: input.gates.publicDistributionAndRegistry.evidenceRefs, - }), - productCompletionGateResult({ - gateId: "customer_gateway_live_x402_paid_proof", - title: "Customer-gateway-held live x402 paid proof through Handshake", - completed: - input.gates.customerGatewayLiveX402PaidProof.customerGatewayCustodyPresent && - input.gates.customerGatewayLiveX402PaidProof.livePaidRetryPerformed && - input.gates.customerGatewayLiveX402PaidProof.terminalReadbackPresent && - input.gates.customerGatewayLiveX402PaidProof.signerInvocationPosture === "post_gateway_check_only", - hardBlocked: - !input.gates.customerGatewayLiveX402PaidProof.customerGatewayCustodyPresent && - input.gates.customerGatewayLiveX402PaidProof.proofGapReasonCodes.includes( - "customer_gateway_custody_packet_absent", - ), - blockers: input.gates.customerGatewayLiveX402PaidProof.proofGapReasonCodes, - evidenceRefs: input.gates.customerGatewayLiveX402PaidProof.evidenceRefs, - }), - productCompletionGateResult({ - gateId: "auth_md_x402_admission_packet", - title: "auth.md+x402 admission packet v0 with refusal tests and redacted readback", - completed: - input.gates.authMdX402AdmissionPacket.packetProjectorPresent && - input.gates.authMdX402AdmissionPacket.refusalFirstTestsPassed && - input.gates.authMdX402AdmissionPacket.redactedReadbackTestsPassed && - !input.gates.authMdX402AdmissionPacket.createsAuthority, - hardBlocked: false, - blockers: [], - evidenceRefs: input.gates.authMdX402AdmissionPacket.evidenceRefs, - }), - ]; - const incompleteGateIds = gateResults - .filter((result) => result.status !== "completed" && result.status !== "hard_blocked") - .map((result) => result.gateId); - const hardBlockedGateIds = gateResults - .filter((result) => result.status === "hard_blocked") - .map((result) => result.gateId); - const overclaimViolations = productCompletionOverclaimViolations(input); - const status = - input.qualityGate.passed && incompleteGateIds.length === 0 && overclaimViolations.length === 0 - ? hardBlockedGateIds.length === 0 - ? ("completed" as const) - : ("closed_with_hard_blocks" as const) - : ("incomplete" as const); - - return { - proofKind: "product_completion_readback" as const, - proofVersion: PROOF_PACKET_VERSION, - generatedAt: input.generatedAt, - status, - scope: - "Aggregate source-owned closeout readback for the four product gates. This object audits evidence posture only; it creates no authority.", - qualityGate: input.qualityGate, - gates: gateResults, - incompleteGateIds, - hardBlockedGateIds, - overclaimViolations, - commandRefs: input.commandRefs, - evidenceRefs: [input.qualityGate.evidenceRef, ...gateResults.flatMap((result) => result.evidenceRefs)], - authorityBoundary: { - ...nonAuthorityBoundary, - createsRelease: false as const, - publishesPackage: false as const, - registersMcpServer: false as const, - configuresHost: false as const, - resolvesCredential: false as const, - invokesSigner: false as const, - createsPaymentPayload: false as const, - createsPaymentSignature: false as const, - exportsReceipt: false as const, - hostsOperation: false as const, - certifiesMarketplace: false as const, - }, - nextMechanism: - status === "completed" - ? "Move from local/product-surface closeout to hosted operation design." - : hardBlockedGateIds.includes("public_distribution_and_registry") - ? "Resolve public distribution: publish the current package with provenance support or explicitly accept the no-provenance release risk, then verify npm and MCP Registry readback." - : "Resolve the remaining incomplete gate with source-owned evidence before claiming product closeout.", - }; -} - -function codexEvidenceRefs(input: { - readonly configSha256: string | null; - readonly expectedArtifactSha256: string | null; - readonly targetPresent: boolean; -}): string[] { - const refs = []; - if (input.configSha256) refs.push(`codex-config:sha256:${input.configSha256}`); - if (input.expectedArtifactSha256) refs.push(`expected-artifact:sha256:${input.expectedArtifactSha256}`); - refs.push( - input.targetPresent - ? "codex-config:mcp-server:handshake_x402:present" - : "codex-config:mcp-server:handshake_x402:absent", - ); - return refs; -} - -function codexProofGaps( - input: CodexHostActivationReadbackInput, - targetPresent: boolean, - hostToolInvocationObserved: boolean, -): ProofGap[] { - const gaps: ProofGap[] = []; - const targetServer = parseCodexMcpServerRecords(input.configText ?? "").find( - (server) => server.name === (input.expectedServer?.name ?? "handshake_x402"), - ); - const expectedServerMatches = input.expectedServer - ? targetServer !== undefined && - targetServer.command === input.expectedServer.command && - arrayEquals(targetServer.args ?? [], input.expectedServer.args) - : targetPresent; - if (!input.configExists) { - gaps.push( - gap( - "codex_config_not_found", - "Codex-local host activation cannot be claimed without readable host configuration.", - ), - ); - } - if (input.expectedArtifact && !input.expectedArtifact.exists) { - gaps.push( - gap( - "expected_activation_artifact_not_found", - "Codex-local host activation cannot be pinned to a missing local artifact.", - ), - ); - } - if (!targetPresent) { - gaps.push( - gap( - "codex_handshake_x402_mcp_server_absent", - "Codex-local host activation is not configured while `mcp_servers.handshake_x402` is absent.", - ), - ); - } - if (targetPresent && !expectedServerMatches) { - gaps.push( - gap( - "codex_handshake_x402_mcp_server_config_mismatch", - "Codex-local host activation cannot be pinned while the configured command or args differ from the expected artifact-derived executable.", - ), - ); - } - if (!hostToolInvocationObserved) { - gaps.push( - gap( - "host_origin_tool_invocation_not_exercised", - "Config readback does not prove `handshake.actions.x402_payment.propose` was invoked through the live host.", - ), - ); - } - return gaps; -} - -function distributionProofGaps(input: { - readonly npmLatestStatus: number | null; - readonly npmLatestMatchesLocalVersion: boolean; - readonly missingLocalExports: readonly string[]; - readonly currentSurfacePublished: boolean; - readonly mcpRegistryAccepted: boolean; - readonly mcpRegistryDiscoverable: boolean; - readonly publishAttempt: DistributionPublishAttemptReadback | null; -}): ProofGap[] { - const gaps: ProofGap[] = []; - if (input.npmLatestStatus !== 200) { - gaps.push( - gap( - "npm_latest_readback_failed", - "Current package distribution cannot be claimed without npm registry readback.", - ), - ); - } - if (input.npmLatestStatus === 200 && !input.npmLatestMatchesLocalVersion) { - gaps.push( - gap("npm_latest_version_does_not_match_local", "The local package version is not the public latest version."), - ); - } - if (input.missingLocalExports.length > 0) { - gaps.push( - gap( - "npm_latest_missing_current_local_exports", - `Public npm latest does not include current local exports: ${input.missingLocalExports.join(", ")}.`, - ), - ); - } - if (!input.currentSurfacePublished) { - gaps.push( - gap( - "current_surface_not_publicly_published", - "Public npm availability does not yet prove the current local product surface.", - ), - ); - } - if (!input.mcpRegistryAccepted) { - gaps.push( - gap("mcp_registry_lookup_not_accepted", "MCP Registry direct lookup does not return the Handshake server."), - ); - } - if (!input.mcpRegistryDiscoverable) { - gaps.push( - gap( - "mcp_registry_discoverability_not_verified", - "MCP Registry search/discovery does not prove the Handshake server is discoverable.", - ), - ); - } - if ( - input.publishAttempt?.attempted === true && - input.publishAttempt.provenanceRequested && - input.publishAttempt.status === "failed" && - input.publishAttempt.provenanceSupported === false - ) { - gaps.push( - gap( - "npm_provenance_generation_unsupported", - "npm rejected trusted provenance generation in this local provider context; publishing without provenance requires explicit release-risk acceptance.", - ), - ); - } - return gaps; -} - -function liveX402ProofGaps(input: { readonly responseStatus: number; readonly custodyPresent: boolean }): ProofGap[] { - const gaps: ProofGap[] = []; - if (input.responseStatus !== 402) { - gaps.push( - gap( - "live_x402_payment_required_not_observed", - "The live endpoint did not return HTTP 402 in the captured response.", - ), - ); - } - if (!input.custodyPresent) { - gaps.push( - gap( - "customer_gateway_custody_packet_absent", - "A live 402 challenge does not prove customer-gateway-held signer custody.", - ), - ); - } - gaps.push(gap("live_paid_retry_not_performed", "No post-VerifiedGatewayCheck live x402 signed retry was performed.")); - gaps.push( - gap( - "settlement_finality_not_proven", - "A challenge readback does not prove settlement finality or downstream business success.", - ), - ); - return gaps; -} - -function productCompletionGateResult(input: { - readonly gateId: ProductCompletionGateId; - readonly title: string; - readonly completed: boolean; - readonly hardBlocked: boolean; - readonly blockers: readonly string[]; - readonly evidenceRefs: readonly string[]; -}) { - const status: ProductCompletionGateStatus = input.completed - ? "completed" - : input.hardBlocked - ? "hard_blocked" - : "incomplete"; - return { - gateId: input.gateId, - title: input.title, - status, - blockers: [...input.blockers].sort(), - evidenceRefs: [...input.evidenceRefs], - }; -} - -function productCompletionOverclaimViolations(input: ProductCompletionReadbackInput): string[] { - const violations: string[] = []; - if (input.gates.codexLocalHostActivation.authorityCreated) { - violations.push("codex_host_activation_claims_authority"); - } - if (input.gates.publicDistributionAndRegistry.status === "registry_discoverable") { - if ( - !input.gates.publicDistributionAndRegistry.currentSurfacePublished || - !input.gates.publicDistributionAndRegistry.mcpRegistryAccepted || - !input.gates.publicDistributionAndRegistry.mcpRegistryDiscoverable - ) { - violations.push("distribution_status_exceeds_public_readback"); - } - } - if ( - input.gates.customerGatewayLiveX402PaidProof.livePaidRetryPerformed && - input.gates.customerGatewayLiveX402PaidProof.signerInvocationPosture !== "post_gateway_check_only" - ) { - violations.push("live_paid_retry_without_post_gateway_signer_posture"); - } - if (input.gates.authMdX402AdmissionPacket.createsAuthority) { - violations.push("auth_md_x402_packet_claims_authority"); - } - if (!input.qualityGate.passed) violations.push("quality_gate_not_passing"); - return violations.sort(); -} - -function gap(reasonCode: string, nonClaim: string): ProofGap { - return { reasonCode, nonClaim }; -} - -type TomlSection = { - readonly name: string; - readonly kind: "mcp_server" | "mcp_server_env" | "other"; - readonly body: readonly string[]; -}; - -function parseTomlSections(configText: string): TomlSection[] { - const sections: TomlSection[] = []; - let current: { name: string; kind: TomlSection["kind"]; body: string[] } | null = null; - for (const line of configText.split(/\r?\n/u)) { - const header = parseTomlHeader(line); - if (header) { - if (current) sections.push(current); - current = { - name: header.name, - kind: header.kind, - body: [], - }; - continue; - } - if (current) current.body.push(line); - } - if (current) sections.push(current); - return sections; -} - -function parseTomlHeader(line: string): { readonly name: string; readonly kind: TomlSection["kind"] } | null { - const trimmed = line.trim(); - const mcpServer = /^\[mcp_servers\.([^\].\n]+)\]$/u.exec(trimmed); - if (mcpServer?.[1]) return { name: mcpServer[1], kind: "mcp_server" }; - const mcpServerEnv = /^\[mcp_servers\.([^\].\n]+)\.env\]$/u.exec(trimmed); - if (mcpServerEnv?.[1]) return { name: mcpServerEnv[1], kind: "mcp_server_env" }; - if (/^\[.+\]$/u.test(trimmed)) return { name: trimmed, kind: "other" }; - return null; -} - -function parseCodexMcpServerEnvKeys(sections: readonly TomlSection[], serverName: string): string[] { - return sections - .filter((section) => section.kind === "mcp_server_env" && section.name === serverName) - .flatMap((section) => - section.body.flatMap((line) => { - const match = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/u.exec(line); - return match?.[1] ? [match[1]] : []; - }), - ) - .sort(); -} - -function parseTomlStringField(lines: readonly string[], key: string): string | null { - const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*(".*")\\s*$`, "u"); - for (const line of lines) { - const match = pattern.exec(line); - if (!match?.[1]) continue; - try { - const value = JSON.parse(match[1]); - return typeof value === "string" ? value : null; - } catch { - return null; - } - } - return null; -} - -function parseTomlStringArrayField(lines: readonly string[], key: string): string[] | null { - const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*(\\[.*\\])\\s*$`, "u"); - for (const line of lines) { - const match = pattern.exec(line); - if (!match?.[1]) continue; - try { - const value = JSON.parse(match[1]); - return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : null; - } catch { - return null; - } - } - return null; -} - -function parseTomlNumberField(lines: readonly string[], key: string): number | null { - const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*([0-9]+)\\s*$`, "u"); - for (const line of lines) { - const match = pattern.exec(line); - if (!match?.[1]) continue; - const value = Number.parseInt(match[1], 10); - return Number.isFinite(value) ? value : null; - } - return null; -} - -function lastMcpSectionEndIndex(lines: readonly string[]): number { - let lastMcpHeaderIndex = -1; - lines.forEach((line, index) => { - const header = parseTomlHeader(line); - if (header?.kind === "mcp_server" || header?.kind === "mcp_server_env") lastMcpHeaderIndex = index; - }); - if (lastMcpHeaderIndex === -1) { - const firstSectionIndex = lines.findIndex((line) => parseTomlHeader(line) !== null); - return firstSectionIndex === -1 ? lines.length : firstSectionIndex; - } - let index = lastMcpHeaderIndex + 1; - while (index < lines.length && !parseTomlHeader(lines[index] ?? "")) index += 1; - return index; -} - -function isCodexMcpServerHeader( - header: { readonly name: string; readonly kind: TomlSection["kind"] }, - serverName: string, -) { - return (header.kind === "mcp_server" || header.kind === "mcp_server_env") && header.name === serverName; -} - -function trimTrailingBlankLines(lines: readonly string[]): string[] { - const output = [...lines]; - while (output.length > 0 && output.at(-1)?.trim() === "") output.pop(); - return output; -} - -function trimLeadingBlankLines(lines: readonly string[]): string[] { - const output = [...lines]; - while (output.length > 0 && output[0]?.trim() === "") output.shift(); - return output; -} - -function tomlString(value: string): string { - return JSON.stringify(value); -} - -function arrayEquals(left: readonly string[], right: readonly string[]): boolean { - return left.length === right.length && left.every((entry, index) => entry === right[index]); -} - -function escapeRegExp(value: string): string { - return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"); -} - -function stableDigest(value: unknown): `sha256:${string}` { - return `sha256:${sha256Text(stableStringify(value))}`; -} - -function sha256Text(value: string): string { - return createHash("sha256").update(value).digest("hex"); -} - -function stableStringify(value: unknown): string { - if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`; - if (value && typeof value === "object") { - const record = value as Record; - return `{${Object.keys(record) - .sort() - .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`) - .join(",")}}`; - } - return JSON.stringify(value) ?? "null"; -} diff --git a/src/surfaces/proof-packets/clean-installed-activation.ts b/src/surfaces/proof-packets/clean-installed-activation.ts new file mode 100644 index 0000000..944c342 --- /dev/null +++ b/src/surfaces/proof-packets/clean-installed-activation.ts @@ -0,0 +1,90 @@ +import { gap, nonAuthorityBoundary, PROOF_PACKET_VERSION } from "./shared"; + +export type CleanInstalledActivationProofInput = { + readonly generatedAt: string; + readonly package: { + readonly name: string; + readonly version: string; + readonly packedFile: string; + readonly localArtifactPath: string | null; + readonly tarballSha256: string; + readonly tarballSizeBytes: number; + readonly npmIntegrity: string | null; + readonly npmShasum: string | null; + readonly fileCount: number | null; + }; + readonly requiredInstalledSurfaces: { + readonly bins: readonly string[]; + readonly exports: readonly string[]; + readonly protectedToolExports: readonly string[]; + }; + readonly activationEvidence: { + readonly facadeImportSource: string; + readonly runtimeDispatchPrepared: boolean; + readonly gatewayAdmissionStatus: string; + readonly downstreamOutcomeStatus: string; + readonly policyDecision: string; + readonly gateDecision: string; + readonly changedParameterDecision: string; + readonly replayDecision: string; + readonly signerInvocationsAfterGatewayAdmission: number; + readonly signerInvocationsAfterReplay: number; + readonly hostileGeneratedExecutionCaseIds: readonly string[]; + readonly rawCredentialMaterialVisible: boolean; + readonly outputRefs: readonly string[]; + }; + readonly commandRefs: readonly string[]; +}; + +export type CleanInstalledActivationProof = ReturnType; + +export function projectCleanInstalledActivationProof(input: CleanInstalledActivationProofInput) { + return { + proofKind: "clean_installed_activation_proof" as const, + proofVersion: PROOF_PACKET_VERSION, + generatedAt: input.generatedAt, + status: "local_activation_passed" as const, + scope: + "Pinned local packed artifact activation for the x402 protected-tool proposal/evidence surface. This is not live host activation.", + package: input.package, + requiredInstalledSurfaces: input.requiredInstalledSurfaces, + activationEvidence: input.activationEvidence, + commandRefs: input.commandRefs, + evidenceRefs: [ + `package:${input.package.name}@${input.package.version}:tarball-sha256:${input.package.tarballSha256}`, + "evidence:clean-installed-import:x402-protected-tool", + "evidence:clean-installed-demo:x402-protected-spend", + ...input.activationEvidence.outputRefs, + ], + authorityBoundary: { + ...nonAuthorityBoundary, + resolvesCredential: false as const, + invokesSigner: false as const, + createsPaymentPayload: false as const, + configuresLiveHost: false as const, + provesMcpRegistryDiscoverability: false as const, + provesPublicNpmCurrentSurface: false as const, + provesCustomerGatewayCustody: false as const, + provesLivePaidExecution: false as const, + }, + proofGaps: [ + gap( + "live_codex_host_not_configured_by_clean_install_check", + "Clean installed activation does not prove live Codex host configuration or host-origin tool invocation.", + ), + gap( + "mcp_registry_discoverability_not_checked_by_clean_install_check", + "Clean installed activation does not prove MCP Registry acceptance or lookup.", + ), + gap( + "public_npm_current_surface_not_checked_by_clean_install_check", + "Clean installed activation uses a local packed artifact and does not prove that the current surface is published.", + ), + gap( + "customer_gateway_live_payment_not_checked_by_clean_install_check", + "Clean installed activation does not exercise a funded customer-gateway-held signer or live x402 paid retry.", + ), + ], + nextMechanism: "Configure a live Codex MCP host against this exact artifact only after explicit approval.", + }; +} diff --git a/src/surfaces/proof-packets/codex-host-activation.ts b/src/surfaces/proof-packets/codex-host-activation.ts new file mode 100644 index 0000000..8de6c7c --- /dev/null +++ b/src/surfaces/proof-packets/codex-host-activation.ts @@ -0,0 +1,181 @@ +import { parseCodexMcpServerRecords } from "./codex-toml"; +import { arrayEquals, gap, nonAuthorityBoundary, PROOF_PACKET_VERSION, type ProofGap } from "./shared"; + +export type CodexHostActivationReadbackInput = { + readonly generatedAt: string; + readonly commandRefs: readonly string[]; + readonly configPath: string; + readonly configExists: boolean; + readonly configSha256: string | null; + readonly configText?: string; + readonly observedMcpServers?: readonly string[]; + readonly expectedServer?: CodexHostExpectedServer; + readonly hostToolInvocation?: CodexHostToolInvocationReadback; + readonly expectedArtifact: { + readonly path: string; + readonly exists: boolean; + readonly sha256: string | null; + readonly sizeBytes: number | null; + } | null; +}; + +export type CodexHostExpectedServer = { + readonly name: string; + readonly command: string; + readonly args: readonly string[]; + readonly executablePath: string; + readonly artifactSha256: string; +}; + +export type CodexHostToolInvocationReadback = { + readonly proofRef: string; + readonly toolVisible: boolean; + readonly toolCallAttempted: boolean; + readonly outcome: string; + readonly nonAuthorityClaims: readonly string[]; +}; + +export type CodexHostActivationReadback = ReturnType; + +export function projectCodexHostActivationReadback(input: CodexHostActivationReadbackInput) { + const serverRecords = parseCodexMcpServerRecords(input.configText ?? ""); + const observedMcpServers = [...(input.observedMcpServers ?? serverRecords.map((server) => server.name))].sort(); + const targetServerName = input.expectedServer?.name ?? "handshake_x402"; + const targetServer = serverRecords.find((server) => server.name === targetServerName) ?? null; + const targetPresent = observedMcpServers.includes(targetServerName); + const expectedServerMatches = input.expectedServer + ? targetServer !== null && + targetServer.command === input.expectedServer.command && + arrayEquals(targetServer.args ?? [], input.expectedServer.args) + : targetPresent; + const hostToolInvocationObserved = + expectedServerMatches && + input.hostToolInvocation?.toolVisible === true && + input.hostToolInvocation.toolCallAttempted === true; + const status = targetPresent + ? hostToolInvocationObserved + ? ("host_tool_invocation_observed" as const) + : expectedServerMatches + ? ("configured_unverified" as const) + : ("blocked" as const) + : ("blocked" as const); + + return { + proofKind: "codex_host_activation_readback" as const, + proofVersion: PROOF_PACKET_VERSION, + generatedAt: input.generatedAt, + status, + scope: "Read-only Codex-local MCP host configuration readback for the Handshake x402 proposal/evidence server.", + config: { + path: input.configPath, + exists: input.configExists, + sha256: input.configSha256, + observedMcpServers, + targetServerName, + targetPresent, + targetServer, + expectedServer: input.expectedServer ?? null, + expectedServerMatches, + hostToolInvocation: input.hostToolInvocation ?? null, + hostToolInvocationObserved, + }, + expectedArtifact: input.expectedArtifact, + commandRefs: input.commandRefs, + evidenceRefs: codexEvidenceRefs({ + configSha256: input.configSha256, + expectedArtifactSha256: input.expectedArtifact?.sha256 ?? null, + targetPresent, + }), + authorityBoundary: { + ...nonAuthorityBoundary, + resolvesCredential: false as const, + invokesSigner: false as const, + createsPaymentPayload: false as const, + configuresLiveHost: false as const, + observesHostToolInvocation: hostToolInvocationObserved, + provesHostWideContainment: false as const, + provesMcpRegistryDiscoverability: false as const, + provesCustomerGatewayCustody: false as const, + provesLivePaidExecution: false as const, + }, + proofGaps: codexProofGaps(input, targetPresent, hostToolInvocationObserved), + nextMechanism: hostToolInvocationObserved + ? "Move to public distribution/provenance; Codex-local host invocation does not prove registry discovery, customer gateway custody, or live paid execution." + : targetPresent + ? "Exercise `handshake.actions.x402_payment.propose` through the configured Codex host and capture a host-origin transcript." + : "Add `mcp_servers.handshake_x402` to Codex config against the pinned artifact after explicit approval.", + }; +} + +function codexEvidenceRefs(input: { + readonly configSha256: string | null; + readonly expectedArtifactSha256: string | null; + readonly targetPresent: boolean; +}): string[] { + const refs = []; + if (input.configSha256) refs.push(`codex-config:sha256:${input.configSha256}`); + if (input.expectedArtifactSha256) refs.push(`expected-artifact:sha256:${input.expectedArtifactSha256}`); + refs.push( + input.targetPresent + ? "codex-config:mcp-server:handshake_x402:present" + : "codex-config:mcp-server:handshake_x402:absent", + ); + return refs; +} + +function codexProofGaps( + input: CodexHostActivationReadbackInput, + targetPresent: boolean, + hostToolInvocationObserved: boolean, +): ProofGap[] { + const gaps: ProofGap[] = []; + const targetServer = parseCodexMcpServerRecords(input.configText ?? "").find( + (server) => server.name === (input.expectedServer?.name ?? "handshake_x402"), + ); + const expectedServerMatches = input.expectedServer + ? targetServer !== undefined && + targetServer.command === input.expectedServer.command && + arrayEquals(targetServer.args ?? [], input.expectedServer.args) + : targetPresent; + if (!input.configExists) { + gaps.push( + gap( + "codex_config_not_found", + "Codex-local host activation cannot be claimed without readable host configuration.", + ), + ); + } + if (input.expectedArtifact && !input.expectedArtifact.exists) { + gaps.push( + gap( + "expected_activation_artifact_not_found", + "Codex-local host activation cannot be pinned to a missing local artifact.", + ), + ); + } + if (!targetPresent) { + gaps.push( + gap( + "codex_handshake_x402_mcp_server_absent", + "Codex-local host activation is not configured while `mcp_servers.handshake_x402` is absent.", + ), + ); + } + if (targetPresent && !expectedServerMatches) { + gaps.push( + gap( + "codex_handshake_x402_mcp_server_config_mismatch", + "Codex-local host activation cannot be pinned while the configured command or args differ from the expected artifact-derived executable.", + ), + ); + } + if (!hostToolInvocationObserved) { + gaps.push( + gap( + "host_origin_tool_invocation_not_exercised", + "Config readback does not prove `handshake.actions.x402_payment.propose` was invoked through the live host.", + ), + ); + } + return gaps; +} diff --git a/src/surfaces/proof-packets/codex-toml.ts b/src/surfaces/proof-packets/codex-toml.ts new file mode 100644 index 0000000..542574e --- /dev/null +++ b/src/surfaces/proof-packets/codex-toml.ts @@ -0,0 +1,201 @@ +import { escapeRegExp } from "./shared"; + +export type CodexMcpServerRecord = { + readonly name: string; + readonly command: string | null; + readonly args: readonly string[] | null; + readonly startupTimeoutSec: number | null; + readonly envKeys: readonly string[]; +}; + +type TomlSection = { + readonly name: string; + readonly kind: "mcp_server" | "mcp_server_env" | "other"; + readonly body: readonly string[]; +}; + +export function parseCodexMcpServerNames(configText: string): string[] { + return parseCodexMcpServerRecords(configText).map((server) => server.name); +} + +export function parseCodexMcpServerRecords(configText: string): CodexMcpServerRecord[] { + const sections = parseTomlSections(configText); + return sections + .filter((section) => section.kind === "mcp_server") + .map((section) => ({ + name: section.name, + command: parseTomlStringField(section.body, "command"), + args: parseTomlStringArrayField(section.body, "args"), + startupTimeoutSec: parseTomlNumberField(section.body, "startup_timeout_sec"), + envKeys: parseCodexMcpServerEnvKeys(sections, section.name), + })) + .sort((left, right) => left.name.localeCompare(right.name)); +} + +export function buildCodexMcpServerTomlBlock(input: { + readonly name: string; + readonly command: string; + readonly args: readonly string[]; + readonly startupTimeoutSec?: number; +}): string { + const startupTimeoutSec = input.startupTimeoutSec ?? 120; + return [ + `[mcp_servers.${input.name}]`, + `command = ${tomlString(input.command)}`, + `args = [${input.args.map(tomlString).join(", ")}]`, + `startup_timeout_sec = ${startupTimeoutSec}`, + "", + ].join("\n"); +} + +export function upsertCodexMcpServerToml(input: { + readonly existingToml: string; + readonly serverName: string; + readonly serverBlockToml: string; +}) { + const newline = input.existingToml.includes("\r\n") ? "\r\n" : "\n"; + const sourceLines = input.existingToml.split(/\r?\n/u); + const retainedLines: string[] = []; + let skippingTargetSection = false; + + for (const line of sourceLines) { + const header = parseTomlHeader(line); + if (header) { + skippingTargetSection = isCodexMcpServerHeader(header, input.serverName); + } + if (!skippingTargetSection) retainedLines.push(line); + } + + const insertIndex = lastMcpSectionEndIndex(retainedLines); + const blockLines = input.serverBlockToml.trimEnd().split(/\r?\n/u); + const before = retainedLines.slice(0, insertIndex); + const after = retainedLines.slice(insertIndex); + const nextLines = [...trimTrailingBlankLines(before), "", ...blockLines, "", ...trimLeadingBlankLines(after)]; + const nextToml = `${nextLines.join(newline).replace(/\n{4,}/gu, `${newline}${newline}${newline}`)}${newline}`; + + return { + changed: nextToml !== input.existingToml, + toml: nextToml, + }; +} + +function parseTomlSections(configText: string): TomlSection[] { + const sections: TomlSection[] = []; + let current: { name: string; kind: TomlSection["kind"]; body: string[] } | null = null; + for (const line of configText.split(/\r?\n/u)) { + const header = parseTomlHeader(line); + if (header) { + if (current) sections.push(current); + current = { + name: header.name, + kind: header.kind, + body: [], + }; + continue; + } + if (current) current.body.push(line); + } + if (current) sections.push(current); + return sections; +} + +function parseTomlHeader(line: string): { readonly name: string; readonly kind: TomlSection["kind"] } | null { + const trimmed = line.trim(); + const mcpServer = /^\[mcp_servers\.([^\].\n]+)\]$/u.exec(trimmed); + if (mcpServer?.[1]) return { name: mcpServer[1], kind: "mcp_server" }; + const mcpServerEnv = /^\[mcp_servers\.([^\].\n]+)\.env\]$/u.exec(trimmed); + if (mcpServerEnv?.[1]) return { name: mcpServerEnv[1], kind: "mcp_server_env" }; + if (/^\[.+\]$/u.test(trimmed)) return { name: trimmed, kind: "other" }; + return null; +} + +function parseCodexMcpServerEnvKeys(sections: readonly TomlSection[], serverName: string): string[] { + return sections + .filter((section) => section.kind === "mcp_server_env" && section.name === serverName) + .flatMap((section) => + section.body.flatMap((line) => { + const match = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/u.exec(line); + return match?.[1] ? [match[1]] : []; + }), + ) + .sort(); +} + +function parseTomlStringField(lines: readonly string[], key: string): string | null { + const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*(".*")\\s*$`, "u"); + for (const line of lines) { + const match = pattern.exec(line); + if (!match?.[1]) continue; + try { + const value = JSON.parse(match[1]); + return typeof value === "string" ? value : null; + } catch { + return null; + } + } + return null; +} + +function parseTomlStringArrayField(lines: readonly string[], key: string): string[] | null { + const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*(\\[.*\\])\\s*$`, "u"); + for (const line of lines) { + const match = pattern.exec(line); + if (!match?.[1]) continue; + try { + const value = JSON.parse(match[1]); + return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : null; + } catch { + return null; + } + } + return null; +} + +function parseTomlNumberField(lines: readonly string[], key: string): number | null { + const pattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*([0-9]+)\\s*$`, "u"); + for (const line of lines) { + const match = pattern.exec(line); + if (!match?.[1]) continue; + const value = Number.parseInt(match[1], 10); + return Number.isFinite(value) ? value : null; + } + return null; +} + +function lastMcpSectionEndIndex(lines: readonly string[]): number { + let lastMcpHeaderIndex = -1; + lines.forEach((line, index) => { + const header = parseTomlHeader(line); + if (header?.kind === "mcp_server" || header?.kind === "mcp_server_env") lastMcpHeaderIndex = index; + }); + if (lastMcpHeaderIndex === -1) { + const firstSectionIndex = lines.findIndex((line) => parseTomlHeader(line) !== null); + return firstSectionIndex === -1 ? lines.length : firstSectionIndex; + } + let index = lastMcpHeaderIndex + 1; + while (index < lines.length && !parseTomlHeader(lines[index] ?? "")) index += 1; + return index; +} + +function isCodexMcpServerHeader( + header: { readonly name: string; readonly kind: TomlSection["kind"] }, + serverName: string, +) { + return (header.kind === "mcp_server" || header.kind === "mcp_server_env") && header.name === serverName; +} + +function trimTrailingBlankLines(lines: readonly string[]): string[] { + const output = [...lines]; + while (output.length > 0 && output.at(-1)?.trim() === "") output.pop(); + return output; +} + +function trimLeadingBlankLines(lines: readonly string[]): string[] { + const output = [...lines]; + while (output.length > 0 && output[0]?.trim() === "") output.shift(); + return output; +} + +function tomlString(value: string): string { + return JSON.stringify(value); +} diff --git a/src/surfaces/proof-packets/distribution-provenance.ts b/src/surfaces/proof-packets/distribution-provenance.ts new file mode 100644 index 0000000..94dc77b --- /dev/null +++ b/src/surfaces/proof-packets/distribution-provenance.ts @@ -0,0 +1,180 @@ +import { gap, nonAuthorityBoundary, PROOF_PACKET_VERSION, type ProofGap } from "./shared"; + +export type DistributionProvenanceReadbackInput = { + readonly generatedAt: string; + readonly localPackage: { + readonly name: string; + readonly version: string; + readonly mcpName: string; + readonly serverJsonName: string; + readonly serverJsonVersion: string; + readonly exports: readonly string[]; + }; + readonly npmLatest: { + readonly url: string; + readonly status: number | null; + readonly version: string | null; + readonly tarball: string | null; + readonly integrity: string | null; + readonly shasum: string | null; + readonly signatureCount: number; + readonly fileCount: number | null; + readonly exports: readonly string[]; + }; + readonly mcpRegistry: { + readonly lookupUrl: string; + readonly lookupStatus: number | null; + readonly lookupProblemTitle: string | null; + readonly searchUrl: string; + readonly searchStatus: number | null; + readonly searchCount: number | null; + }; + readonly publishAttempt?: DistributionPublishAttemptReadback; + readonly evidenceRefs: readonly string[]; + readonly commandRefs: readonly string[]; +}; + +export type DistributionProvenanceReadback = ReturnType; + +export type DistributionPublishAttemptReadback = { + readonly attempted: boolean; + readonly commandRef: string; + readonly status: "not_attempted" | "failed" | "succeeded"; + readonly provenanceRequested: boolean; + readonly provenanceSupported: boolean | null; + readonly errorCode: string | null; + readonly errorMessage: string | null; + readonly evidenceRef: string | null; +}; + +export function projectDistributionProvenanceReadback(input: DistributionProvenanceReadbackInput) { + const localExports = [...input.localPackage.exports].sort(); + const publishedExports = [...input.npmLatest.exports].sort(); + const missingLocalExports = localExports.filter((entry) => !publishedExports.includes(entry)); + const extraPublishedExports = publishedExports.filter((entry) => !localExports.includes(entry)); + const npmLatestMatchesLocalVersion = input.npmLatest.version === input.localPackage.version; + const currentSurfacePublished = + input.npmLatest.status === 200 && npmLatestMatchesLocalVersion && missingLocalExports.length === 0; + const mcpRegistryAccepted = input.mcpRegistry.lookupStatus === 200; + const mcpRegistryDiscoverable = + mcpRegistryAccepted && input.mcpRegistry.searchCount !== null && input.mcpRegistry.searchCount > 0; + const status = currentSurfacePublished && mcpRegistryDiscoverable ? "registry_discoverable" : "blocked"; + + return { + proofKind: "distribution_provenance_readback" as const, + proofVersion: PROOF_PACKET_VERSION, + generatedAt: input.generatedAt, + status, + scope: + "Public npm and MCP Registry readback for the current local package surface. Publication and registry discovery are distribution facts only.", + localPackage: { + ...input.localPackage, + exports: localExports, + }, + npmLatest: { + ...input.npmLatest, + exports: publishedExports, + missingLocalExports, + extraPublishedExports, + currentSurfacePublished, + }, + mcpRegistry: { + ...input.mcpRegistry, + accepted: mcpRegistryAccepted, + discoverable: mcpRegistryDiscoverable, + }, + publishAttempt: input.publishAttempt ?? null, + commandRefs: input.commandRefs, + evidenceRefs: input.evidenceRefs, + authorityBoundary: { + ...nonAuthorityBoundary, + holdsCustody: false as const, + hostsOperation: false as const, + certifiesMarketplace: false as const, + managesSettlement: false as const, + managesPayment: false as const, + establishesTrust: false as const, + enforcesHostWidePolicy: false as const, + }, + proofGaps: distributionProofGaps({ + npmLatestStatus: input.npmLatest.status, + npmLatestMatchesLocalVersion, + missingLocalExports, + currentSurfacePublished, + mcpRegistryAccepted, + mcpRegistryDiscoverable, + publishAttempt: input.publishAttempt ?? null, + }), + nextMechanism: currentSurfacePublished + ? "Submit and verify MCP Registry publication for the current package version." + : "Publish a new package version containing the current local export surface, then rerun npm and MCP Registry readback.", + }; +} + +function distributionProofGaps(input: { + readonly npmLatestStatus: number | null; + readonly npmLatestMatchesLocalVersion: boolean; + readonly missingLocalExports: readonly string[]; + readonly currentSurfacePublished: boolean; + readonly mcpRegistryAccepted: boolean; + readonly mcpRegistryDiscoverable: boolean; + readonly publishAttempt: DistributionPublishAttemptReadback | null; +}): ProofGap[] { + const gaps: ProofGap[] = []; + if (input.npmLatestStatus !== 200) { + gaps.push( + gap( + "npm_latest_readback_failed", + "Current package distribution cannot be claimed without npm registry readback.", + ), + ); + } + if (input.npmLatestStatus === 200 && !input.npmLatestMatchesLocalVersion) { + gaps.push( + gap("npm_latest_version_does_not_match_local", "The local package version is not the public latest version."), + ); + } + if (input.missingLocalExports.length > 0) { + gaps.push( + gap( + "npm_latest_missing_current_local_exports", + `Public npm latest does not include current local exports: ${input.missingLocalExports.join(", ")}.`, + ), + ); + } + if (!input.currentSurfacePublished) { + gaps.push( + gap( + "current_surface_not_publicly_published", + "Public npm availability does not yet prove the current local product surface.", + ), + ); + } + if (!input.mcpRegistryAccepted) { + gaps.push( + gap("mcp_registry_lookup_not_accepted", "MCP Registry direct lookup does not return the Handshake server."), + ); + } + if (!input.mcpRegistryDiscoverable) { + gaps.push( + gap( + "mcp_registry_discoverability_not_verified", + "MCP Registry search/discovery does not prove the Handshake server is discoverable.", + ), + ); + } + if ( + input.publishAttempt?.attempted === true && + input.publishAttempt.provenanceRequested && + input.publishAttempt.status === "failed" && + input.publishAttempt.provenanceSupported === false + ) { + gaps.push( + gap( + "npm_provenance_generation_unsupported", + "npm rejected trusted provenance generation in this local provider context; publishing without provenance requires explicit release-risk acceptance.", + ), + ); + } + return gaps; +} diff --git a/src/surfaces/proof-packets/index.ts b/src/surfaces/proof-packets/index.ts new file mode 100644 index 0000000..235f0c0 --- /dev/null +++ b/src/surfaces/proof-packets/index.ts @@ -0,0 +1,7 @@ +export * from "./clean-installed-activation"; +export * from "./codex-host-activation"; +export * from "./codex-toml"; +export * from "./distribution-provenance"; +export * from "./live-x402-requirement"; +export * from "./product-completion"; +export * from "./shared"; diff --git a/src/surfaces/proof-packets/live-x402-requirement.ts b/src/surfaces/proof-packets/live-x402-requirement.ts new file mode 100644 index 0000000..6306917 --- /dev/null +++ b/src/surfaces/proof-packets/live-x402-requirement.ts @@ -0,0 +1,117 @@ +import { Buffer } from "node:buffer"; +import { isPaymentRequiredV2, validatePaymentRequired } from "@x402/core/schemas"; +import { gap, nonAuthorityBoundary, PROOF_PACKET_VERSION, stableDigest, type ProofGap } from "./shared"; + +export type LiveX402RequirementReadbackInput = { + readonly generatedAt: string; + readonly commandRefs: readonly string[]; + readonly request: { + readonly method: string; + readonly url: string; + readonly responseStatus: number; + readonly providerEnvironmentPosture: "live"; + readonly headersEvidenceRef: string; + }; + readonly paymentRequiredHeader: string; + readonly selectedPaymentRequirementIndex: number; + readonly customerGatewayCustody: { + readonly present: boolean; + readonly proofRef: string | null; + readonly digest: `sha256:${string}` | null; + }; +}; + +export type LiveX402RequirementReadback = ReturnType; + +export function projectLiveX402RequirementReadback(input: LiveX402RequirementReadbackInput) { + const paymentRequired = validatePaymentRequired( + JSON.parse(Buffer.from(input.paymentRequiredHeader, "base64").toString("utf8")), + ); + if (!isPaymentRequiredV2(paymentRequired)) { + throw new Error("Only x402 v2 PAYMENT-REQUIRED evidence is supported."); + } + const selectedPaymentRequirement = paymentRequired.accepts[input.selectedPaymentRequirementIndex]; + if (!selectedPaymentRequirement) throw new Error("Selected x402 payment requirement index is outside accepts."); + if (selectedPaymentRequirement.scheme !== "exact") { + throw new Error("The live x402 first wedge only admits exact requirements."); + } + const status = + input.request.responseStatus === 402 && input.customerGatewayCustody.present + ? ("ready_for_gateway_signed_retry" as const) + : ("blocked" as const); + const selectedPaymentRequirementDigest = stableDigest({ + paymentRequired, + selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, + selectedPaymentRequirement, + }); + + return { + proofKind: "live_x402_requirement_readback" as const, + proofVersion: PROOF_PACKET_VERSION, + generatedAt: input.generatedAt, + status, + scope: + "Live x402 Payment Required challenge readback for one buyer-side exact protected action. This is not payment execution.", + request: input.request, + paymentRequired: { + x402Version: paymentRequired.x402Version, + resource: paymentRequired.resource, + acceptsCount: paymentRequired.accepts.length, + selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, + selectedPaymentRequirement, + selectedPaymentRequirementDigest, + }, + customerGatewayCustody: input.customerGatewayCustody, + commandRefs: input.commandRefs, + evidenceRefs: [ + input.request.headersEvidenceRef, + `selected-payment-requirement:${selectedPaymentRequirementDigest}`, + ], + authorityBoundary: { + ...nonAuthorityBoundary, + resolvesCredential: false as const, + invokesSigner: false as const, + createsPaymentPayload: false as const, + provesCustomerGatewayCustody: input.customerGatewayCustody.present, + provesLivePaidExecution: false as const, + provesSettlementFinality: false as const, + provesProviderCustody: false as const, + certifiesMarketplace: false as const, + }, + proofGaps: liveX402ProofGaps({ + responseStatus: input.request.responseStatus, + custodyPresent: input.customerGatewayCustody.present, + }), + nextMechanism: input.customerGatewayCustody.present + ? "Create one exact x402 action contract from the selected requirement and run a post-VerifiedGatewayCheck signed retry." + : "Attach a funded customer-gateway custody packet before any live signed retry can be attempted.", + }; +} + +function liveX402ProofGaps(input: { readonly responseStatus: number; readonly custodyPresent: boolean }): ProofGap[] { + const gaps: ProofGap[] = []; + if (input.responseStatus !== 402) { + gaps.push( + gap( + "live_x402_payment_required_not_observed", + "The live endpoint did not return HTTP 402 in the captured response.", + ), + ); + } + if (!input.custodyPresent) { + gaps.push( + gap( + "customer_gateway_custody_packet_absent", + "A live 402 challenge does not prove customer-gateway-held signer custody.", + ), + ); + } + gaps.push(gap("live_paid_retry_not_performed", "No post-VerifiedGatewayCheck live x402 signed retry was performed.")); + gaps.push( + gap( + "settlement_finality_not_proven", + "A challenge readback does not prove settlement finality or downstream business success.", + ), + ); + return gaps; +} diff --git a/src/surfaces/proof-packets/product-completion.ts b/src/surfaces/proof-packets/product-completion.ts new file mode 100644 index 0000000..a4b151a --- /dev/null +++ b/src/surfaces/proof-packets/product-completion.ts @@ -0,0 +1,217 @@ +import type { CodexHostActivationReadback } from "./codex-host-activation"; +import type { DistributionProvenanceReadback } from "./distribution-provenance"; +import type { LiveX402RequirementReadback } from "./live-x402-requirement"; +import { nonAuthorityBoundary, PROOF_PACKET_VERSION } from "./shared"; + +export type ProductCompletionGateId = + | "codex_local_host_activation" + | "public_distribution_and_registry" + | "customer_gateway_live_x402_paid_proof" + | "auth_md_x402_admission_packet"; + +export type ProductCompletionGateStatus = "completed" | "hard_blocked" | "incomplete"; + +export type ProductCompletionReadbackInput = { + readonly generatedAt: string; + readonly commandRefs: readonly string[]; + readonly qualityGate: { + readonly command: string; + readonly passed: boolean; + readonly evidenceRef: string; + }; + readonly gates: { + readonly codexLocalHostActivation: { + readonly status: CodexHostActivationReadback["status"]; + readonly artifactVersion: string; + readonly artifactSha256: string | null; + readonly observesHostToolInvocation: boolean; + readonly authorityCreated: boolean; + readonly evidenceRefs: readonly string[]; + }; + readonly publicDistributionAndRegistry: { + readonly status: DistributionProvenanceReadback["status"]; + readonly localVersion: string; + readonly npmLatestVersion: string | null; + readonly currentSurfacePublished: boolean; + readonly mcpRegistryAccepted: boolean; + readonly mcpRegistryDiscoverable: boolean; + readonly provenanceAttempted: boolean; + readonly provenanceSupported: boolean | null; + readonly proofGapReasonCodes: readonly string[]; + readonly evidenceRefs: readonly string[]; + }; + readonly customerGatewayLiveX402PaidProof: { + readonly status: LiveX402RequirementReadback["status"]; + readonly customerGatewayCustodyPresent: boolean; + readonly livePaidRetryPerformed: boolean; + readonly terminalReadbackPresent: boolean; + readonly signerInvocationPosture: "post_gateway_check_only" | "not_observed" | "unsafe_or_unknown"; + readonly proofGapReasonCodes: readonly string[]; + readonly evidenceRefs: readonly string[]; + }; + readonly authMdX402AdmissionPacket: { + readonly packetVersion: "v0"; + readonly packetProjectorPresent: boolean; + readonly refusalFirstTestsPassed: boolean; + readonly redactedReadbackTestsPassed: boolean; + readonly createsAuthority: boolean; + readonly evidenceRefs: readonly string[]; + }; + }; +}; + +export type ProductCompletionReadback = ReturnType; + +export function projectProductCompletionReadback(input: ProductCompletionReadbackInput) { + const gateResults = [ + productCompletionGateResult({ + gateId: "codex_local_host_activation", + title: "Codex-local runtime activation from pinned current-surface artifact", + completed: + input.gates.codexLocalHostActivation.status === "host_tool_invocation_observed" && + input.gates.codexLocalHostActivation.observesHostToolInvocation && + !input.gates.codexLocalHostActivation.authorityCreated, + hardBlocked: false, + blockers: [], + evidenceRefs: input.gates.codexLocalHostActivation.evidenceRefs, + }), + productCompletionGateResult({ + gateId: "public_distribution_and_registry", + title: "Public package distribution, provenance posture, and MCP Registry lookup", + completed: input.gates.publicDistributionAndRegistry.status === "registry_discoverable", + hardBlocked: + !input.gates.publicDistributionAndRegistry.currentSurfacePublished && + input.gates.publicDistributionAndRegistry.provenanceAttempted && + input.gates.publicDistributionAndRegistry.provenanceSupported === false && + !input.gates.publicDistributionAndRegistry.mcpRegistryDiscoverable, + blockers: input.gates.publicDistributionAndRegistry.proofGapReasonCodes, + evidenceRefs: input.gates.publicDistributionAndRegistry.evidenceRefs, + }), + productCompletionGateResult({ + gateId: "customer_gateway_live_x402_paid_proof", + title: "Customer-gateway-held live x402 paid proof through Handshake", + completed: + input.gates.customerGatewayLiveX402PaidProof.customerGatewayCustodyPresent && + input.gates.customerGatewayLiveX402PaidProof.livePaidRetryPerformed && + input.gates.customerGatewayLiveX402PaidProof.terminalReadbackPresent && + input.gates.customerGatewayLiveX402PaidProof.signerInvocationPosture === "post_gateway_check_only", + hardBlocked: + !input.gates.customerGatewayLiveX402PaidProof.customerGatewayCustodyPresent && + input.gates.customerGatewayLiveX402PaidProof.proofGapReasonCodes.includes( + "customer_gateway_custody_packet_absent", + ), + blockers: input.gates.customerGatewayLiveX402PaidProof.proofGapReasonCodes, + evidenceRefs: input.gates.customerGatewayLiveX402PaidProof.evidenceRefs, + }), + productCompletionGateResult({ + gateId: "auth_md_x402_admission_packet", + title: "auth.md+x402 admission packet v0 with refusal tests and redacted readback", + completed: + input.gates.authMdX402AdmissionPacket.packetProjectorPresent && + input.gates.authMdX402AdmissionPacket.refusalFirstTestsPassed && + input.gates.authMdX402AdmissionPacket.redactedReadbackTestsPassed && + !input.gates.authMdX402AdmissionPacket.createsAuthority, + hardBlocked: false, + blockers: [], + evidenceRefs: input.gates.authMdX402AdmissionPacket.evidenceRefs, + }), + ]; + const incompleteGateIds = gateResults + .filter((result) => result.status !== "completed" && result.status !== "hard_blocked") + .map((result) => result.gateId); + const hardBlockedGateIds = gateResults + .filter((result) => result.status === "hard_blocked") + .map((result) => result.gateId); + const overclaimViolations = productCompletionOverclaimViolations(input); + const status = + input.qualityGate.passed && incompleteGateIds.length === 0 && overclaimViolations.length === 0 + ? hardBlockedGateIds.length === 0 + ? ("completed" as const) + : ("closed_with_hard_blocks" as const) + : ("incomplete" as const); + + return { + proofKind: "product_completion_readback" as const, + proofVersion: PROOF_PACKET_VERSION, + generatedAt: input.generatedAt, + status, + scope: + "Aggregate source-owned closeout readback for the four product gates. This object audits evidence posture only; it creates no authority.", + qualityGate: input.qualityGate, + gates: gateResults, + incompleteGateIds, + hardBlockedGateIds, + overclaimViolations, + commandRefs: input.commandRefs, + evidenceRefs: [input.qualityGate.evidenceRef, ...gateResults.flatMap((result) => result.evidenceRefs)], + authorityBoundary: { + ...nonAuthorityBoundary, + createsRelease: false as const, + publishesPackage: false as const, + registersMcpServer: false as const, + configuresHost: false as const, + resolvesCredential: false as const, + invokesSigner: false as const, + createsPaymentPayload: false as const, + createsPaymentSignature: false as const, + exportsReceipt: false as const, + hostsOperation: false as const, + certifiesMarketplace: false as const, + }, + nextMechanism: + status === "completed" + ? "Move from local/product-surface closeout to hosted operation design." + : hardBlockedGateIds.includes("public_distribution_and_registry") + ? "Resolve public distribution: publish the current package with provenance support or explicitly accept the no-provenance release risk, then verify npm and MCP Registry readback." + : "Resolve the remaining incomplete gate with source-owned evidence before claiming product closeout.", + }; +} + +function productCompletionGateResult(input: { + readonly gateId: ProductCompletionGateId; + readonly title: string; + readonly completed: boolean; + readonly hardBlocked: boolean; + readonly blockers: readonly string[]; + readonly evidenceRefs: readonly string[]; +}) { + const status: ProductCompletionGateStatus = input.completed + ? "completed" + : input.hardBlocked + ? "hard_blocked" + : "incomplete"; + return { + gateId: input.gateId, + title: input.title, + status, + blockers: [...input.blockers].sort(), + evidenceRefs: [...input.evidenceRefs], + }; +} + +function productCompletionOverclaimViolations(input: ProductCompletionReadbackInput): string[] { + const violations: string[] = []; + if (input.gates.codexLocalHostActivation.authorityCreated) { + violations.push("codex_host_activation_claims_authority"); + } + if (input.gates.publicDistributionAndRegistry.status === "registry_discoverable") { + if ( + !input.gates.publicDistributionAndRegistry.currentSurfacePublished || + !input.gates.publicDistributionAndRegistry.mcpRegistryAccepted || + !input.gates.publicDistributionAndRegistry.mcpRegistryDiscoverable + ) { + violations.push("distribution_status_exceeds_public_readback"); + } + } + if ( + input.gates.customerGatewayLiveX402PaidProof.livePaidRetryPerformed && + input.gates.customerGatewayLiveX402PaidProof.signerInvocationPosture !== "post_gateway_check_only" + ) { + violations.push("live_paid_retry_without_post_gateway_signer_posture"); + } + if (input.gates.authMdX402AdmissionPacket.createsAuthority) { + violations.push("auth_md_x402_packet_claims_authority"); + } + if (!input.qualityGate.passed) violations.push("quality_gate_not_passing"); + return violations.sort(); +} diff --git a/src/surfaces/proof-packets/shared.ts b/src/surfaces/proof-packets/shared.ts new file mode 100644 index 0000000..2b38dee --- /dev/null +++ b/src/surfaces/proof-packets/shared.ts @@ -0,0 +1,56 @@ +import { createHash } from "node:crypto"; + +export const PROOF_PACKET_VERSION = "proof-packets.v0.1" as const; + +export type ProofGap = { + readonly reasonCode: string; + readonly nonClaim: string; +}; + +export type NonAuthorityBoundary = { + readonly createsAuthority: false; + readonly createsPolicyDecision: false; + readonly createsGreenlight: false; + readonly performsGatewayCheck: false; + readonly performsMutation: false; +}; + +export const nonAuthorityBoundary: NonAuthorityBoundary = { + createsAuthority: false, + createsPolicyDecision: false, + createsGreenlight: false, + performsGatewayCheck: false, + performsMutation: false, +}; + +export function gap(reasonCode: string, nonClaim: string): ProofGap { + return { reasonCode, nonClaim }; +} + +export function arrayEquals(left: readonly string[], right: readonly string[]): boolean { + return left.length === right.length && left.every((entry, index) => entry === right[index]); +} + +export function escapeRegExp(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"); +} + +export function stableDigest(value: unknown): `sha256:${string}` { + return `sha256:${sha256Text(stableStringify(value))}`; +} + +function sha256Text(value: string): string { + return createHash("sha256").update(value).digest("hex"); +} + +function stableStringify(value: unknown): string { + if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`; + if (value && typeof value === "object") { + const record = value as Record; + return `{${Object.keys(record) + .sort() + .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`) + .join(",")}}`; + } + return JSON.stringify(value) ?? "null"; +} From 91d03831ffcff17d68e0f98496e5cff456382cec Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 20:02:00 +0800 Subject: [PATCH 013/144] Remove stale planning archives --- .../PLAN.md | 69 --- .../VALIDATION.md | 72 --- .../ASSUMPTIONS.md | 17 - .../CONTEXT.md | 89 --- .../DECISIONS.md | 46 -- .../2026-05-24-concerns-elimination/PLAN.md | 253 --------- .../2026-05-24-concerns-elimination/RISKS.md | 35 -- .../TASKS.jsonl | 19 - .../VALIDATION.md | 176 ------ .../input.md | 138 ----- .../raw/ADOPTION.md | 152 ----- .../raw/ARCH.md | 227 -------- .../raw/EXECUTION.md | 211 ------- .../raw/RISK.md | 75 --- .../raw/STRATEGY.md | 112 ---- .../synthesis.md | 58 -- .../2026-05-24-tier2-macro-closeout/AUDIT.md | 111 ---- .../GSD-REMAP.md | 91 --- .../2026-05-24-tier2-macro-closeout/REVIEW.md | 134 ----- .../VALIDATION.md | 63 --- .../claim-boundary-cleanup/ASSUMPTIONS.md | 14 - .../claim-boundary-cleanup/CONTEXT.md | 89 --- .../claim-boundary-cleanup/DECISIONS.md | 45 -- .../claim-boundary-cleanup/PLAN.md | 354 ------------ .../claim-boundary-cleanup/RISKS.md | 103 ---- .../claim-boundary-cleanup/TASKS.jsonl | 11 - .../claim-boundary-cleanup/VALIDATION.md | 126 ----- .../input.md | 148 ----- .../raw/ADOPTION.md | 207 ------- .../raw/ARCH.md | 141 ----- .../raw/EXECUTION.md | 423 -------------- .../raw/RISK.md | 417 -------------- .../raw/STRATEGY.md | 121 ---- .../synthesis.md | 96 ---- .../ASSUMPTIONS.md | 39 -- .../CONTEXT.md | 34 -- .../DECISIONS.md | 71 --- .../concrete-adapter-pack-expansion/PLAN.md | 306 ---------- .../concrete-adapter-pack-expansion/RISKS.md | 16 - .../TASKS.jsonl | 12 - .../VALIDATION.md | 65 --- .../input.md | 107 ---- .../raw/ADOPTION.md | 142 ----- .../raw/ARCH.md | 228 -------- .../raw/EXECUTION.md | 186 ------- .../raw/RISK.md | 104 ---- .../raw/STRATEGY.md | 111 ---- .../synthesis.md | 127 ----- .../ASSUMPTIONS.md | 16 - .../CONTEXT.md | 67 --- .../DECISIONS.md | 87 --- .../PLAN.md | 441 --------------- .../RISKS.md | 43 -- .../TASKS.jsonl | 10 - .../VALIDATION.md | 104 ---- .../input.md | 178 ------ .../raw/ADOPTION.md | 196 ------- .../raw/ARCH.md | 400 -------------- .../raw/EXECUTION.md | 522 ------------------ .../raw/RISK.md | 142 ----- .../raw/STRATEGY.md | 338 ------------ .../synthesis.md | 54 -- .../ASSUMPTIONS.md | 35 -- .../host-specific-bypass-harnesses/CONTEXT.md | 105 ---- .../DECISIONS.md | 98 ---- .../host-specific-bypass-harnesses/PLAN.md | 326 ----------- .../host-specific-bypass-harnesses/RISKS.md | 67 --- .../TASKS.jsonl | 11 - .../VALIDATION.md | 93 ---- .../input.md | 100 ---- .../raw/ADOPTION.md | 176 ------ .../raw/ARCH.md | 230 -------- .../raw/EXECUTION.md | 259 --------- .../raw/RISK.md | 72 --- .../raw/STRATEGY.md | 82 --- .../synthesis.md | 119 ---- .../ASSUMPTIONS.md | 41 -- .../CONTEXT.md | 29 - .../DECISIONS.md | 37 -- .../PLAN.md | 303 ---------- .../RISKS.md | 18 - .../TASKS.jsonl | 12 - .../VALIDATION.md | 62 --- .../input.md | 156 ------ .../raw/ADOPTION.md | 217 -------- .../raw/ARCH.md | 205 ------- .../raw/EXECUTION.md | 370 ------------- .../raw/RISK.md | 88 --- .../raw/STRATEGY.md | 139 ----- .../synthesis.md | 68 --- .../ASSUMPTIONS.md | 51 -- .../CONTEXT.md | 67 --- .../DECISIONS.md | 47 -- .../public-distribution-publication/PLAN.md | 296 ---------- .../public-distribution-publication/RISKS.md | 18 - .../TASKS.jsonl | 12 - .../VALIDATION.md | 97 ---- .../input.md | 153 ----- .../raw/ADOPTION.md | 211 ------- .../raw/ARCH.md | 201 ------- .../raw/EXECUTION.md | 303 ---------- .../raw/RISK.md | 30 - .../raw/STRATEGY.md | 177 ------ .../synthesis.md | 122 ---- .../ASSUMPTIONS.md | 35 -- .../terminal-verifier-trust-plane/CONTEXT.md | 63 --- .../DECISIONS.md | 29 - .../terminal-verifier-trust-plane/PLAN.md | 301 ---------- .../terminal-verifier-trust-plane/RISKS.md | 43 -- .../terminal-verifier-trust-plane/TASKS.jsonl | 11 - .../VALIDATION.md | 73 --- .../input.md | 144 ----- .../raw/ADOPTION.md | 244 -------- .../raw/ARCH.md | 186 ------- .../raw/EXECUTION.md | 284 ---------- .../raw/RISK.md | 104 ---- .../raw/STRATEGY.md | 145 ----- .../synthesis.md | 75 --- .planning/tier2/00-canon-alignment.md | 127 ----- .planning/tier2/01-source-study.md | 157 ------ .planning/tier2/02-users-and-tier-pathway.md | 258 --------- .planning/tier2/03-x402-architecture.md | 205 ------- .planning/tier2/04-spec-and-doubt-review.md | 195 ------- .planning/tier2/README.md | 144 ----- .../tier2/surfaces/10-agent-proof-slice.md | 519 ----------------- 125 files changed, 17234 deletions(-) delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/AUDIT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/GSD-REMAP.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/REVIEW.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/synthesis.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/ASSUMPTIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/CONTEXT.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/DECISIONS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/PLAN.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/RISKS.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/TASKS.jsonl delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/VALIDATION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/input.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ADOPTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ARCH.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/EXECUTION.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/RISK.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/STRATEGY.md delete mode 100644 .planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/synthesis.md delete mode 100644 .planning/tier2/00-canon-alignment.md delete mode 100644 .planning/tier2/01-source-study.md delete mode 100644 .planning/tier2/02-users-and-tier-pathway.md delete mode 100644 .planning/tier2/03-x402-architecture.md delete mode 100644 .planning/tier2/04-spec-and-doubt-review.md delete mode 100644 .planning/tier2/README.md delete mode 100644 .planning/tier2/surfaces/10-agent-proof-slice.md diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/PLAN.md deleted file mode 100644 index 5dc4109..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/PLAN.md +++ /dev/null @@ -1,69 +0,0 @@ -# CLI/MCP Publish Readiness Plan - -## Goal - -Bring the CLI and MCP Tier 2 surfaces to publishable package posture without reopening the Tier 1 kernel or implying that CLI/MCP authorize, gate, mutate, certify, settle, or host anything. - -## External Source Inputs - -- npm package metadata: `private: true` blocks publication, `bin` entries become PATH-installed executables, and package files must be verified through dry-run packaging. -- MCP Registry package rules: npm packages use `registryType: "npm"` in `server.json`, the official registry points to public npm artifacts, and `package.json#mcpName` must match `server.json#name`. -- MCP TypeScript SDK posture: stdio is the right local process transport for local MCP integrations, and the official client/server SDK can exercise tools/resources over stdio. -- MCP security posture: local MCP servers are local code execution surfaces, so the exact command must be inspectable and the server must avoid token passthrough, hosted auth claims, raw credential material, and ambient authority. - -## Success Criteria - -- `package.json` is publishable and no longer marked private. -- Node users import bundled ESM from `dist`; Bun local development can still use source through the `bun` export condition. -- `handshake` is a bundled Node CLI that emits the existing false-authority JSON envelope. -- `handshake-mcp` is a bundled Node stdio MCP server that exposes only the x402 proposal/evidence tool/resource surface. -- The package-name bin `handshake-protocol-kernel` points to the MCP server so npm/MCP package installation has a server-shaped default executable. -- `server.json` and `package.json#mcpName` are synchronized for MCP Registry publication. -- Package checks prove the npm dry-run includes source, generated types, bundled JS, bins, MCP metadata, and compact canon while excluding `.planning`, tests, scratch, old docs trees, and workspace junk. -- Published entrypoint checks spawn the actual package bins with Node and exercise CLI schema plus MCP stdio list/read/call through the official MCP client SDK. -- Claims remain explicit: CLI and MCP are evidence/proposal posture only, with no policy decision, greenlight, gateway check, mutation, receipt export, authority certificate minting, hosted operation, provider custody, settlement, broad MCP protection, or clearing-house posture. - -## Non-Goals - -- No hosted control plane. -- No hosted MCP server or process supervisor. -- No provider custody, wallet custody, signer export, payment settlement, facilitator operation, seller middleware, aggregate spend ledger, marketplace, certification, or cross-org trust. -- No new authority routes or Tier 1 schema changes. -- No CLI mutation command, gateway runner, receipt exporter, raw record dump, or certificate minter. -- No broad MCP/browser/shell/network/package-manager/cloud/repo interception claim. - -## Mechanism - -1. Package boundary - - Remove `private: true`. - - Add `license: "UNLICENSED"` until the owner chooses an open-source license. - - Add `bin` entries for `handshake`, `handshake-mcp`, and `handshake-protocol-kernel`. - - Add `./cli` and `./mcp` subpaths without exporting them from package root. - -2. Build boundary - - Keep declarations from `tsc`. - - Add `scripts/build-package-bundles.mjs` to bundle public imports and bins with `bun build --target=node --format=esm`. - - Keep thin Node shebang wrappers under `bin/`. - -3. MCP registry boundary - - Add `server.json` for `io.github.joelchan/handshake-protocol-kernel`. - - Keep server description negative about authority, gateway checks, mutations, receipt export, certificates, provider custody, hosted operation, and broad MCP protection. - -4. Verification boundary - - Extend package surface tests and dry-run checks. - - Add `scripts/check-published-entrypoints.mjs` to run `node bin/handshake schema` and connect to `node bin/handshake-mcp` using the official MCP client SDK. - - Keep architecture tests proving CLI/MCP stay off root and away from policy/gateway/signer/receipt/certificate authority. - -## Closeout Gates - -```bash -npm run test -- test/architecture/claim-boundary.test.ts test/architecture/package-surface.test.ts test/architecture/root-exports.test.ts -npm run pack:check -npm run quality:claims -npm run quality:architecture -npm run check:repo -``` - -## Residual External Action - -Actual publication still requires owner-held external credentials: npm login/publish and MCP Registry namespace authentication. Source publish-readiness means the artifact is shaped, tested, and claim-bounded for those actions; it does not mean the package was published during this goal. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/VALIDATION.md deleted file mode 100644 index 086d6a8..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-cli-mcp-publish-readiness/cli-mcp-publish-readiness-20260524T010000Z/VALIDATION.md +++ /dev/null @@ -1,72 +0,0 @@ -# CLI/MCP Publish Readiness Validation - -Status: closed source-owned implementation validation. - -## Scope - -This validation covers the publish-readiness goal for the Tier 2 CLI and MCP -surfaces only. It does not close hosted operation, provider custody, gateway -operation, receipt export, authority certificate minting, broad MCP protection, -SDK distribution, marketplace/certification, or cross-org trust. - -## External Inputs Applied - -- npm package metadata and bin behavior: package publication requires the package - not be private, package bins are installed as command executables, and the - package payload must be inspected by dry-run packaging. -- MCP Registry package metadata: `server.json` names the MCP server, - `package.json#mcpName` matches that server name, and the package entry points - to an npm stdio transport. -- MCP SDK and transport posture: the local MCP server is exercised by the - official MCP TypeScript client over stdio. -- MCP security posture: the server remains local code execution posture and - therefore exposes only proposal/evidence tools/resources, with no token, - credential, mutation, gateway, or hosted authority path. - -## Requirement-by-Requirement Audit - -| Requirement | Result | Evidence | -| --- | --- | --- | -| Publishable package metadata | Pass | `package.json` has no `private: true`, has package description/license/keywords/engines, and exposes only explicit package subpaths. | -| CLI package command | Pass | `bin/handshake` is a Node wrapper for bundled `dist/bin/handshake.mjs`; `node bin/handshake schema` is exercised by `scripts/check-published-entrypoints.mjs`. | -| MCP package command | Pass | `bin/handshake-mcp` and package-name bin `handshake-protocol-kernel` point to bundled MCP stdio server code. | -| MCP Registry metadata | Pass | `server.json#name`, `package.json#mcpName`, npm package identifier, version, and stdio transport are synchronized by tests and package-entrypoint check. | -| Root export boundary | Pass | CLI and MCP are available only through explicit `./cli` and `./mcp` package subpaths and stay off the package root. | -| Authority boundary | Pass | CLI/MCP command tests, claim tests, and posture tests forbid policy, greenlight, gateway check, mutation, receipt export, certificate minting, raw records, signer custody, and credential material. | -| Package payload | Pass | `npm run pack:check` confirms package dry-run includes bins, source, generated declarations, bundled JS, MCP metadata, README/QUALITY/STRUCTURE, and compact internal docs while excluding `.planning`, tests, scratch, and old docs trees. | -| Published entrypoint smoke | Pass | `scripts/check-published-entrypoints.mjs` spawns actual Node package bins, runs CLI schema, connects to MCP stdio through the official MCP client SDK, lists tools, reads metadata, calls the x402 proposal tool, and checks false-authority fields. | -| npm publish dry-run | Pass | `npm publish --dry-run --access public --cache /tmp/handshake-npm-cache` exits 0, includes 541 files, and reports the publish action as a dry run. | -| Demo evidence | Pass | `npm run demo:mcp-transcript` regenerates the source-owned MCP transcript; `npm run demo:self-hosted` passes `aps_x402_exact_path`, `cli_readbacks`, `mcp_reference_transcript`, and `mcp_stdio_process`. | - -## Gates Run - -```bash -npm run demo:mcp-transcript -npm run demo:self-hosted -npm run pack:check -npm publish --dry-run --access public --cache /tmp/handshake-npm-cache -npm run quality:claims -npm run quality:architecture -npm run check:repo -``` - -Observed closeout: - -- `npm run quality:claims`: 4 pass, 0 fail. -- `npm run quality:architecture`: 61 pass, 0 fail. -- `npm run check:repo`: 448 pass, 0 fail; package surface check passed with 541 files. -- `npm publish --dry-run --access public --cache /tmp/handshake-npm-cache`: dry-run publish of `handshake-protocol-kernel@0.2.4` succeeded with 541 files. - -## Publish Boundary - -The source artifact is publish-ready under the Tier 2 boundary. Actual external -publication still requires owner-held credentials for npm and MCP Registry -namespace authentication. That external account action is not performed by this -validation and does not create a Handshake authority claim. - -## Residual Product Boundary - -CLI/MCP are now publishable proposal/evidence surfaces. They are not execution -gates. The next product mechanism must remain adapter/runtime hardening or -operator adoption over this package boundary, not a claim that MCP or CLI -itself enforces protected mutations. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/ASSUMPTIONS.md deleted file mode 100644 index b4fe64b..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/ASSUMPTIONS.md +++ /dev/null @@ -1,17 +0,0 @@ -# Assumptions - -| ID | Assumption | Confidence | Evidence | Invalidation Trigger | -| --- | --- | --- | --- | --- | -| A1 | Tier 1 protocol/kernel primitives remain stable and should not be reopened for this concern-elimination work. | High | User constraint and raw perspectives agree that Tier 2 surfaces strengthen around the kernel. | A source task requires new protocol semantics rather than new adapter/runtime/MCP refusal behavior. | -| A2 | Runtime posture propagation is the nearest defect and must be fixed before registry extraction. | High | `RuntimeIngressObservedDispatchSchema` accepts posture fields while `x402PaymentAttemptForDispatch()` omits them. | A failing test shows another path creates authority before this bug can be exercised. | -| A3 | Runtime may record proposal/refusal evidence but must not issue policy, greenlights, gateway checks, mutations, receipts, receipt exports, signer evidence, or authority certificates. | High | `src/runtime/LANE.md` and user constraints. | Runtime lane contract is explicitly changed by the user and enforced in canon. | -| A4 | MCP can require explicit request-body and provider-environment posture fields instead of defaulting omitted fields to local safe posture. | Medium | Strict schema already rejects unknown fields and raw perspectives prefer explicit posture. | Existing external MCP callers must remain backwards compatible under a declared compatibility contract. If so, omission must still refuse or remain non-contractable. | -| A5 | Direct x402 adapter refusal reason codes are sufficient for runtime/MCP parity. | High | Existing `x402PaymentAttemptRefusalReasonCodes()` covers amount, official evidence, body posture, digest mismatch, and provider environment. | New source checks reveal missing reason codes for a posture case that can reach contract proposal. | -| A6 | Adding posture/ref to idempotency material is acceptable for new proposals and must not rewrite historical receipts. | High | Raw perspectives identify deterministic binding drift; old evidence remains reconstructable by stored records. | A package or replay contract requires stable legacy idempotency keys for active persisted records. | -| A7 | Local sandbox evidence is useful only as local/reference downstream fixture observation. | High | `sandbox-http.ts`, x402 demo, and perspectives all classify it as non-authority. | A separate seller/facilitator adapter with settlement proof is implemented and tested. | -| A8 | Session/day/review spend fields remain metadata until a reservation ledger exists. | High | `spendWindowEnforcementStatus: "not_enforced_local_metadata"` is present in source/tests and concerns. | A ledger phase introduces tenant/org/principal/agent/action/resource/window reservations with conflict and recovery evidence. | -| A9 | Signer custody remains local/reference or fixture-gateway evidence only. | High | Current wallet gateway uses injected signer after `VerifiedGatewayCheck`; no provider/vault lifecycle exists. | A real provider custody resolver with rotation, revocation, failure, and redaction tests lands. | -| A10 | Host-wide interception cannot be claimed from runtime/MCP evidence alone. | High | Runtime/MCP lanes are proposal/evidence only and no host-specific harness exists. | A concrete browser/shell/package/cloud/repo/MCP host harness with bypass probes is added. | -| A11 | Projection scale/redaction can be improved without claiming hosted audit/search. | Medium | Current store/projection boundaries can add scoped reads and redaction tests. | The implementation would require product or hosted architecture choices not in this macro. | -| A12 | Package/public readiness can be validated only through build, pack, and entrypoint smoke gates, not through dirty TypeScript source alone. | High | `pack:check` rebuilds and runs package surface scripts. | The repository removes bundled package artifacts and publishes directly from source under a new process. | -| A13 | `.planning/` must remain scratch even when it contains accurate concern maps. | High | User constraints and canon state `.planning/` is not repo-facing truth. | A user explicitly promotes a planning artifact into canonical docs after source validation. | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/CONTEXT.md deleted file mode 100644 index 53b03af..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/CONTEXT.md +++ /dev/null @@ -1,89 +0,0 @@ -# Macro Context - -## Target - -Create an executable implementation plan that eliminates the current `.planning/codebase/CONCERNS.md` concern set through source mechanisms, tests, and gates, not documentation-only closure. - -## Run - -- Run id: `concerns-elimination-20260524T044836Z` -- Date: 2026-05-24 -- Role: CHAIR synthesis -- Output scope: `.planning/macro/*` and `.planning/macro/runs/concerns-elimination-20260524T044836Z/synthesis.md` - -## Invariant - -No consequential autonomous action executes outside declared bounds, and divergent behavior must be haltable, isolatable, and reconstructable. - -## Canon - -Canonical repo truth lives in: - -- `AGENTS.md` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-notes.md` - -`.planning/` is scratch. It can identify concerns and implementation order, but it must not become a package surface, exported symbol, script name, CI name, public docs authority, or implementation namespace. - -## Input Packet - -The chair read: - -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/input.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/STRATEGY.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/ARCH.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/EXECUTION.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/RISK.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/ADOPTION.md` -- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/plan-contract.md` - -The chair also performed a narrow source check against `.planning/codebase/CONCERNS.md`, `package.json`, `src/runtime/ingress/index.ts`, `src/mcp/x402-proposal.ts`, `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/adapters/x402-payment/action-proposal.ts`, `src/adapters/x402-payment/sandbox-http.ts`, and `src/protocol/evidence-projections/projections.ts`. - -## Current Dirty Worktree From Input Packet - -These files were observed dirty before planning and are treated as current worktree state to validate, not as committed proof: - -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-notes.md` -- `examples/x402-protected-spend/README.md` -- `examples/x402-protected-spend/run.ts` -- `src/adapters/x402-payment/action-proposal.ts` -- `src/adapters/x402-payment/index.ts` -- `src/adapters/x402-payment/upstream-evidence.ts` -- `src/adapters/x402-payment/wallet-gateway.ts` -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/foundation/reason-codes.ts` -- `src/runtime/ingress/index.ts` -- `test/adapters/x402-payment-action-proposal.test.ts` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/product/x402-protected-spend-demo-report.test.ts` -- `src/adapters/x402-payment/sandbox-http.ts` - -## Source Observations - -- Runtime schema already accepts x402 body/provider posture fields, but `x402PaymentAttemptForDispatch()` does not forward `intendedRequestBodyPosture`, `providerEnvironmentPosture`, or `providerEnvironmentRef`. -- Direct x402 adapter parameters include body/provider posture, but idempotency material currently needs explicit posture/ref binding to prevent equivalence drift. -- MCP x402 proposal schema has `intendedRequestBodyDigest` but lacks explicit body posture and provider-environment posture/ref. -- MCP lane documentation forbids policy, gateway, signer, storage, receipt, all-role SDK, and certificate authority imports. -- Runtime lane documentation says runtime may observe and propose, but must not issue policy, greenlights, gateway checks, receipts, mutation attempts, provider enforcement, or production proof. -- Local x402 sandbox already has refusal reason codes for missing signature evidence, wrong header, non-reference environment, and ambiguous body posture, but it needs a stronger typed evidence boundary to prevent settlement/facilitator/custody overread. -- Projection redaction is pattern-based and must be hardened before hosted/provider claims. -- `package.json` already has `quality:claims`, `quality:architecture`, `quality:storage`, `pack:check`, `demo:aps`, `demo:mcp-transcript`, and `check:repo` gates. - -## Required Implementation Order - -1. Runtime posture propagation and pre-contract refusal. -2. MCP posture parity while staying proposal/evidence only. -3. Local sandbox signed-retry evidence boundary. -4. Runtime family registry/refactor hardening. -5. x402 future-surface, spend metadata, custody, and host-bypass guardrails. -6. Evidence projection scale/redaction mechanisms. -7. Package, `.planning`, demo, and closeout gates. - -No user-owned decision blocks starting this plan. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/DECISIONS.md deleted file mode 100644 index 0495b7a..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/DECISIONS.md +++ /dev/null @@ -1,46 +0,0 @@ -# Decisions - -## Accepted - -- D1: Runtime x402 posture propagation is first. The plan starts with failing runtime tests and a source patch to forward body/provider posture into the x402 attempt. -- D2: Runtime refusal must be pre-contract. Unsupported, omitted, external, live, or unknown x402 posture cannot produce an `ActionContract`. -- D3: Direct x402 idempotency material must include request-body posture, provider-environment posture, and provider-environment ref for new proposals. -- D4: MCP posture parity is second. MCP must carry or refuse the same posture boundary as the direct adapter/runtime path while staying proposal/evidence only. -- D5: MCP schema should require explicit posture fields. Missing posture is schema-invalid or structured pre-contract refusal, never silent local-reference defaulting. -- D6: Sandbox signed retry is local/reference downstream fixture evidence only. It is not settlement, facilitator operation, seller middleware, provider custody, gateway authority, or mutation proof. -- D7: Runtime family registry extraction waits until posture propagation tests pass. The refactor is a hardening phase, not the first fix. -- D8: Spend-window controls remain metadata in this macro. Guard the claim instead of building a partial ledger. -- D9: Custody, hosted verifier, host-wide interception, publication, and broad x402 surfaces are future cuts with tests and claim gates. -- D10: Package/public readiness requires `npm run pack:check`; dirty source and checked-in `dist/` are not proof by themselves. - -## Rejected - -- R1: Do not close concerns through docs-only or copy-only edits. -- R2: Do not make runtime/MCP import wallet gateway, signer, storage, policy, gateway, receipt, all-role SDK, or certificate authority code to achieve parity. -- R3: Do not add a runtime-side aggregate spend sum as a substitute for a real reservation ledger. -- R4: Do not use the sandbox signed retry as evidence of seller middleware, facilitator operation, settlement finality, provider custody, or live paid HTTP operation. -- R5: Do not broaden `x402_payment.exact` to `upto`, batch settlement, lifecycle hooks, signed offers, signed receipts, MCP auto-pay, or seller/facilitator surfaces. -- R6: Do not treat runtime/MCP bypass posture as broad host interception. -- R7: Do not claim npm/MCP Registry publication from source-owned package gates. - -## Deferred - -- F1: Aggregate spend reservation ledger with tenant/org/principal/agent/action/resource/window keys, conflicts, recovery, D1 persistence, and receipt evidence. -- F2: Provider/customer custody with vault resolver, rotation, revocation, gateway failure, and provider-specific redaction tests. -- F3: Hosted verifier with JWKS, revocation, cross-org trust, retention, and operational deployment proof. -- F4: Host-specific bypass interception for browser, shell, package manager, cloud API, repo, network, database, and sibling MCP tools. -- F5: Seller middleware, facilitator operation, settlement finality, and broader x402 action classes. -- F6: Actual npm and MCP Registry publication with owner-held credentials. -- F7: Dedicated support-bundle expansion beyond existing non-authority diagnostic surfaces. - -## User-Owned - -No user-owned decision blocks the implementation plan. - -Future user-owned choices: - -- Whether to fund the aggregate spend ledger. -- Which live custody provider or vault should be first. -- Which host/runtime deserves first real bypass-interception proof. -- Whether and when to publish to npm or MCP Registry with owner credentials. -- Whether to broaden x402 beyond exact buyer-side payment after the first wedge survives closeout. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/PLAN.md deleted file mode 100644 index a28d1f5..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/PLAN.md +++ /dev/null @@ -1,253 +0,0 @@ -# Plan - -## Goal - -Invariant at stake: no x402 proposal surface may create a cleaner contract than the protected path actually observed, and no evidence surface may imply authority, custody, settlement, hosted operation, broad interception, or aggregate spend enforcement that the gateway does not enforce. - -Eliminate the current codebase concerns by strengthening source mechanisms, regression tests, and closeout gates. The plan preserves the Tier 1 kernel as stable protocol meaning, strengthens Tier 2 surfaces around it, keeps runtime/MCP/CLI proposal or evidence only, and keeps x402 as the exact buyer-side first wedge unless future work is explicitly cut. - -## Non-Goals - -- Do not redesign Tier 1 protocol primitives, state machines, canonicalization, or receipt meaning. -- Do not move policy decisions, greenlights, gateway checks, mutation attempts, receipts, receipt export, signer custody, or authority certificate minting into runtime, MCP, CLI, demos, or review output. -- Do not implement an aggregate spend reservation ledger in this macro. -- Do not claim provider/customer custody, live provider operation, hosted verifier, JWKS/revocation, marketplace, certification, or clearing-house readiness. -- Do not claim seller middleware, facilitator operation, settlement finality, signed offers, signed receipts, `upto`, batch settlement, lifecycle hooks, or MCP auto-pay. -- Do not claim broad host interception across browser, shell, package manager, cloud API, network, database, repo, sibling MCP, or unwrapped tools. -- Do not treat `.planning/` as canon or close concerns through documentation-only edits. -- Do not claim npm or MCP Registry publication; package validation stops at source-owned build, pack, and entrypoint smoke gates. - -## Source Boundary - -Canonical repo truth remains `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, and `docs/internal/*`. `.planning/` is scratch and may guide implementation only when reconciled against source and tests. - -This plan was synthesized from: - -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/input.md` -- raw STRATEGY, ARCH, EXECUTION, RISK, and ADOPTION perspective outputs for the same run -- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/plan-contract.md` -- `.planning/codebase/CONCERNS.md` -- narrow source checks of the named runtime, MCP, x402 adapter, sandbox, projection, lane, package, and test files - -The dirty worktree listed in the input packet is current state, not validated closure and not something this plan assumes should be reverted. - -## Current State - -The nearest proven bug is runtime x402 posture loss. `RuntimeIngressObservedDispatchSchema` accepts `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`, but `x402PaymentAttemptForDispatch()` forwards only `intendedRequestBodyDigest` and `selectedHeadersDigest`. `X402PaymentAttemptSchema` then defaults missing posture to `no_body` and `local_reference_sandbox`, which can turn observed unsupported, omitted, external, live, or unknown posture into a contractable local-reference attempt. - -The MCP x402 proposal schema currently lacks `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`. `x402Parameters()` and `deriveMcpX402IdempotencyKey()` therefore cannot bind the same request/body/provider boundary as the direct adapter path. MCP is still proposal/evidence only, but its proposal shape can teach weaker semantics. - -The x402 sandbox is a local/reference fixture. It can emit official-shaped payment-required evidence and observe one signed retry after gateway-created signature evidence. Existing fields such as `authorityCreated: false` are necessary but not enough to prevent seller middleware, facilitator settlement, or payment-finality overread. - -Runtime ingress is still a monolithic cross-family module. That is a real maintainability risk, but refactoring it before the posture bug is fixed can preserve the bug behind a cleaner abstraction. - -Spend session/day/review controls are metadata only. Signer custody is local/reference or fixture-gateway evidence only. Runtime/MCP bypass evidence is scoped observed evidence only. Evidence projections and D1 reads are good local diagnostic proof, not hosted evidence-scale proof. Package surfaces are publishable only after build/pack gates. - -## Target State - -Runtime x402 dispatches either bind exact observed body/provider posture into the resulting candidate parameters and idempotency material or refuse before any action contract is proposed. Refusals preserve runtime/graph evidence where possible, but create no authority-bearing records. - -MCP x402 proposals require explicit request-body and provider-environment posture. Accepted MCP proposals bind the posture fields into parameters, non-secret summaries, tool-call drafts, compile-intent candidate material, and idempotency derivation. Unsupported, omitted, external, live, or unknown posture returns structured non-authority refusal or schema failure before runtime-client contract proposal. - -Sandbox challenge and signed-retry evidence carries an explicit local/reference downstream-fixture boundary. Signed retry evidence is post-gate observation only, with no seller middleware, facilitator operation, settlement finality, provider custody, or authority claim. - -Runtime family proposal code sits behind a source-owned family registry after the hotfix, so new families cannot silently drop refusal-critical fields. The registry remains proposal-only and cannot import or issue policy, greenlight, gateway, mutation, receipt, storage, signer, or certificate authority. - -Future surfaces are guarded by source-owned conformance, claim, package, and architecture tests. Ledger, live custody, hosted verifier, host-wide interception, seller/facilitator operation, registry publication, and broader x402 compatibility stay explicit cuts until separate phases implement them fully. - -## Assumptions - -- No user-owned decision blocks implementation of runtime posture propagation, MCP posture parity, sandbox evidence boundaries, registry hardening, and cut-line guards. -- The current dirty files are live worktree state to validate, not a baseline to revert. -- Existing Tier 1 primitives and reason-code registry can represent these refusals without introducing new kernel concepts. -- MCP schema strictness can require explicit posture fields; omitted posture is not silently normalized to safe local posture. -- Aggregate spend controls remain metadata until a real reservation ledger is designed and implemented. -- Provider/customer custody, hosted verifier, and host-wide interception cannot be validated from current source and must remain future cuts. - -## Decisions - -- Fix the runtime posture propagation defect first, before runtime registry extraction. -- Reuse direct adapter x402 refusal semantics for runtime and MCP parity; do not fork a weaker MCP-specific contract model. -- Require explicit MCP request-body and provider-environment posture fields. Missing posture is schema-invalid or structured pre-contract refusal, never silent local-reference defaulting. -- Add posture fields to x402 idempotency material so equivalent-looking contracts cannot hide different body/provider posture. -- Treat the local x402 sandbox as downstream local/reference fixture evidence only. -- Extract runtime ingress family adapters only after the posture hotfix is covered by tests. -- Keep spend windows, custody, hosted verifier, host interception, facilitator/seller middleware, and publication as cut/future items with guards, not partial implementation inside this macro. - -## Phases - -Phase 1: Runtime x402 posture propagation and refusal boundary. - -Implement failing tests first in `test/runtime/runtime-ingress.test.ts` and `test/adapters/x402-payment-action-proposal.test.ts`. Patch `src/runtime/ingress/index.ts` so `x402PaymentAttemptForDispatch()` forwards `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`. Patch `src/adapters/x402-payment/action-proposal.ts` so direct x402 idempotency material includes request-body posture, provider-environment posture, and provider-environment ref. If runtime currently throws before recording refusal, add a narrow source-owned preflight/refusal helper so unsupported posture becomes `one_or_more_dispatches_refused` without an action contract. - -Acceptance: - -- Unsupported/omitted body posture and external/live/unknown provider posture refuse before action-contract proposal. -- Digest-bound local-reference posture binds posture, body digest, provider posture/ref, selected headers digest, and official evidence fields into candidate parameters. -- Refused runtime cases create no policy decision, greenlight, gateway check, mutation attempt, receipt, receipt export, or authority certificate. - -Phase 2: MCP x402 posture parity while staying proposal/evidence only. - -Patch `src/mcp/x402-proposal.ts` to require `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and nullable `providerEnvironmentRef`. Add MCP-local pre-contract refusal or schema failure for omitted, unsupported, external, live, and unknown posture before runtime-client proposal calls. Bind accepted posture fields into `x402Parameters()`, tool-call draft parameters, non-secret summaries, compile-intent candidate parameters, and `deriveMcpX402IdempotencyKey()`. Update MCP schema fixtures, reference transcript, stdio process smoke, and `scripts/check-published-entrypoints.mjs`. - -Acceptance: - -- MCP cannot propose a weaker x402 contract than the direct adapter/runtime path. -- MCP outputs retain `authorityCreated: false`, `greenlightCreated: false`, `gatewayCheckPerformed: false`, `mutationAttempted: false`, `receiptExportCreated: false`, and `authorityCertificateMinted: false`. -- MCP imports remain inside the lane boundary and do not pull adapter, wallet, signer, storage, policy, gateway, receipt, all-role SDK, or certificate authority code. - -Phase 3: Local sandbox evidence boundary. - -Patch `src/adapters/x402-payment/sandbox-http.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, `src/protocol/evidence-projections/projections.ts`, and the x402 demo/report tests so challenge and signed-retry outputs carry an explicit evidence boundary: local/reference fixture scope, post-gate signed retry observation, not settlement finality, not seller middleware, not facilitator operation, not provider custody, and not authority. Keep signed retry recording gated on gateway-created signature evidence, local-reference provider posture, and non-ambiguous body posture. - -Acceptance: - -- Sandbox challenge and retry evidence cannot be serialized as settlement, seller middleware, facilitator operation, provider custody, or authority. -- Replay, missing signature evidence, wrong signature header, non-reference provider posture, and ambiguous body posture do not increment signed retry counts. -- Demo reports keep `x402_paid_http_call.exact` as buyer-readable proof-object language only, not an action catalog entry. - -Phase 4: Runtime ingress registry/refactor hardening. - -After Phase 1 passes, extract runtime family conversion into a source-owned registry under `src/runtime/ingress/` while preserving `proposeRuntimeIngressActionContracts()` behavior. The registry should own per-family dispatch coverage, config requirements, compile-input construction, preflight refusal reason codes, signing secret selection, grammar version, and raw-bypass reason codes. It must not own authority. - -Acceptance: - -- Package install, auth.md protected API call, and x402 runtime cases pass unchanged through the registry. -- Every supported dispatch kind maps to exactly one family adapter. -- Missing family config fails closed. -- Architecture tests forbid registry imports of policy, greenlight, gateway, storage implementation, mutation, receipt, signer, or certificate authority code. - -Phase 5: x402 cut-line guards for spend, custody, host bypass, and future surfaces. - -Patch conformance, install proposal, bypass probe, demo, and claim tests so unsupported x402 surfaces remain explicit source-owned cuts. Keep session/day/review bounds under `spendWindowEnforcementStatus: "not_enforced_local_metadata"`. Distinguish fixture gateway custody from provider/customer custody. Keep runtime/MCP bypass posture scoped and non-host-wide. - -Acceptance: - -- `upto`, batch settlement, lifecycle hooks, MCP auto-pay, signed offers, signed receipts, seller middleware, facilitator operation, aggregate spend ledger, live custody, hosted verifier, host-wide interception, and registry publication are classified as unsupported/future unless separate source mechanisms exist. -- Spend-window metadata never enters action-contract bounds as enforced aggregate control. -- Claims tests fail on broader x402 compatibility, custody, hosted, settlement, host-wide interception, or aggregate-spend enforcement language. - -Phase 6: Evidence projection scale and redaction mechanisms. - -Patch `src/protocol/store/port.ts`, memory/D1 storage, `migrations/0001_protocol_kernel.sql`, `src/protocol/evidence-projections/assembly.ts`, and `src/protocol/evidence-projections/projections.ts` only to the extent needed for source-owned scale/redaction concerns. Add contract/action/run-scoped store reads and batched stream-event range reads before any hosted evidence-scale claim. Strengthen projection redaction toward typed allowlists and deny-by-default handling for credential-shaped provider refs. - -Acceptance: - -- Projection assembly no longer depends on broad tenant/org scans for contract-scoped envelopes once hosted-scale language is allowed. -- D1 and memory store contracts remain equivalent. -- Provider-format fuzz tests prove raw signer refs, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, vault paths, secret refs, facilitator secrets, and auth.md credential material do not project. - -Phase 7: Package, `.planning`, demo, and closeout gates. - -Update package smoke fixtures and architecture guards after source behavior stabilizes. Keep `.planning/` out of package files, exports, scripts, CI names, README command sections, and canonical docs except as scratch-boundary language. Regenerate demo outputs only after source and tests pass. Run package and full-repo gates before calling concerns closed. - -Acceptance: - -- `npm run pack:check` proves build output, package files, and published entrypoint smoke match the final source schema. -- `npm run quality:claims` and `npm run quality:architecture` fail on claim broadening or lane-boundary drift. -- `npm run check:repo` passes on the worktree intended for closeout. - -## Task Graph - -```text -macro-001 -> macro-002 -> macro-003 -> macro-004 -macro-004 -> macro-005 -> macro-006 -> macro-007 -macro-004 -> macro-008 -> macro-009 -> macro-010 -macro-004 -> macro-011 -> macro-012 -> macro-013 -macro-004 -> macro-014 -> macro-015 -macro-010 -> macro-016 -> macro-017 -macro-007 -> macro-018 -macro-015 -> macro-019 -macro-013 -> macro-019 -macro-017 -> macro-019 -macro-018 -> macro-019 -``` - -Critical path: runtime posture failing tests, runtime propagation/refusal, direct idempotency binding, focused runtime gate, MCP schema/parity, MCP smoke/package fixture update, package/planning drift gate, full closeout. - -Parallel work after Phase 1 stabilizes: sandbox evidence boundary, x402 future-surface cut-line guards, evidence redaction/scale tests, and runtime registry test scaffolding. - -## Risks And Mitigations - -- P0: Runtime defaulting can create a weaker contract than observed. Mitigation: forward posture fields and refuse unsupported/live/unknown before action contract; gate with runtime and adapter tests. -- P0: MCP can teach weaker x402 semantics. Mitigation: strict posture schema, MCP preflight refusal, idempotency binding, stdio/package smoke updates, and MCP lane architecture tests. -- P0: Sandbox evidence can be overread as settlement or facilitator operation. Mitigation: explicit typed local/reference evidence boundary, projection labels, product tests, and claim gates. -- P0: Signer custody can leak into runtime/MCP/CLI or become a live custody claim. Mitigation: forbidden import/export tests, redaction tests, fixture-vs-live custody labels, and future custody cut. -- P1: Registry refactor can preserve the same posture bug. Mitigation: sequence refactor after focused runtime gate and require per-family parity tests. -- P1: Spend-window metadata can become fake aggregate enforcement. Mitigation: keep metadata label visible and fail claims until a real ledger exists. -- P1: Projection redaction can miss provider credential formats. Mitigation: typed allowlist direction plus fuzz fixtures. -- P1: Package artifacts can drift from dirty source. Mitigation: `pack:check` and published entrypoint smoke are closeout gates. -- P2: `.planning` scratch can become canon. Mitigation: package/architecture/claim guards and source-boundary language. - -## Validation Gates - -Focused runtime posture gate: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts -npm run check:types -``` - -Focused MCP posture gate: - -```bash -npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts test/architecture/mcp-surface-posture.test.ts -npm run check:types -``` - -Sandbox and x402 boundary gate: - -```bash -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts -npm run demo:aps -``` - -Runtime registry gate: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts test/protocol/generated-execution-graph.test.ts -npm run quality:architecture -``` - -Evidence projection/storage gate: - -```bash -npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts -npm run quality:storage -``` - -Claim, package, and full closeout gate: - -```bash -npm run demo:mcp-transcript -npm run quality:claims -npm run quality:architecture -npm run pack:check -npm run check:repo -``` - -## Cut Lines - -- Ledger: session/day/review spend control remains metadata until a D1-backed reservation ledger with conflict, recovery, and receipt semantics exists. -- Custody: local signer and fixture gateway proof do not prove provider custody, customer custody, vault rotation, revocation, resolver failure, or hosted signer operation. -- Hosted verifier: local terminal certificate verification does not prove hosted verifier, JWKS, revocation, cross-org trust, marketplace, certification, or clearing-house operation. -- Host interception: runtime/MCP bypass evidence does not prove browser, shell, package-manager, cloud API, network, database, repo, or sibling tool interception. -- x402 breadth: `x402_payment.exact` remains buyer-side exact per-call payment signature evidence; no `upto`, batch, lifecycle, seller, facilitator, settlement, signed offer, signed receipt, or MCP auto-pay support. -- Publication: package readiness is build/pack/entrypoint smoke only; real npm/MCP Registry publication requires external owner credentials. -- `.planning`: planning artifacts can guide work but cannot become package surface, exported names, public command names, CI names, canonical docs, or claim authority. - -## Rollback / Stop Conditions - -- Stop if runtime or MCP unsupported, omitted, external, live, or unknown posture reaches `action_contract_proposed`. -- Stop if runtime or MCP creates policy decision, greenlight, gateway check, mutation attempt, receipt, receipt export, signer evidence, or authority certificate. -- Stop if sandbox evidence serializes as seller middleware, facilitator operation, settlement finality, provider custody, or authority. -- Stop if `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, bearer tokens, vault paths, provider secrets, or raw signer refs leak into MCP, CLI, demo, package smoke, or projection output. -- Stop if aggregate session/day/review spend language appears as enforced without a real reservation ledger. -- Stop if registry extraction changes package/auth.md/x402 runtime behavior outside the intended family boundary. -- Stop if source changes weaken Tier 1 protocol/kernel semantics or move authority into runtime, MCP, CLI, demos, or review output. -- Stop if package smoke does not exercise the final MCP schema after posture fields are added. -- Stop if `.planning/` appears in package files or becomes repo-facing canon. - -## Smallest Next Action - -Add the failing runtime regression in `test/runtime/runtime-ingress.test.ts`: a wrapped x402 dispatch with `intendedRequestBodyPosture: "unsupported"`, `providerEnvironmentPosture: "live"`, and a live provider ref must return `one_or_more_dispatches_refused`, include `x402_request_body_posture_unsupported` and `x402_provider_environment_not_sandboxed`, and create no action contract or authority-bearing records. Then patch `x402PaymentAttemptForDispatch()` to forward posture fields and update x402 idempotency material. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/RISKS.md deleted file mode 100644 index 2d53592..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/RISKS.md +++ /dev/null @@ -1,35 +0,0 @@ -# Risks - -## P0 - -| ID | Risk | Failure Mode | Mitigation | Gate | -| --- | --- | --- | --- | --- | -| P0-R1 | Runtime x402 posture defaulting | Runtime observes unsupported/live posture but omits it before `X402PaymentAttemptSchema`, which defaults into contractable local posture. | Forward posture fields, bind idempotency, and refuse pre-contract. | `npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts` | -| P0-R2 | MCP posture gap | MCP can submit/propose a weaker x402 candidate than the direct adapter would accept. | Add strict posture schema, pre-contract refusal, parameter/idempotency binding, and MCP smoke updates. | `npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts` | -| P0-R3 | Sandbox evidence overread | Local signed retry appears to prove seller middleware, facilitator settlement, payment finality, provider custody, or authority. | Add typed local/reference evidence boundary and projection/demo claim guards. | `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts` | -| P0-R4 | Signer custody leakage | Runtime/MCP/CLI/package output exposes signer material or implies provider/customer custody. | Forbidden imports/exports, redaction tests, fixture-vs-live custody labels. | `npm run test -- test/architecture/import-posture.test.ts test/adapters/x402-wallet-gateway.test.ts test/protocol/evidence-projections.test.ts` | -| P0-R5 | Authority moves into proposal surfaces | Runtime/MCP/CLI creates policy, greenlight, gateway, mutation, receipt, receipt export, signer, or certificate evidence. | Lane architecture tests and explicit non-authority flags. | `npm run quality:architecture` | - -## P1 - -| ID | Risk | Failure Mode | Mitigation | Gate | -| --- | --- | --- | --- | --- | -| P1-R1 | Registry refactor preserves bug | Family adapter abstraction repeats posture dropping across a cleaner boundary. | Refactor only after Phase 1 tests pass; add dispatch-kind coverage and parity tests. | `npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts` | -| P1-R2 | Spend metadata becomes fake budget enforcement | Session/day/review fields are read as enforced aggregate controls. | Keep `not_enforced_local_metadata` visible and fail broad claims until ledger exists. | `npm run test -- test/adapters/x402-install-proposal.test.ts test/architecture/claim-boundary.test.ts` | -| P1-R3 | Redaction misses provider credential formats | Pattern-based redaction misses raw provider/vault/signer material. | Move toward typed allowlists and add provider-format fuzz fixtures. | `npm run test -- test/protocol/evidence-projections.test.ts` | -| P1-R4 | D1/projection scale gets overclaimed | Tenant/org scans and per-offset reads are mistaken for hosted evidence readiness. | Add scoped reads/range reads before hosted audit/search claims. | `npm run quality:storage` | -| P1-R5 | Package drift | Source schema changes but `dist`, bin smoke, or package metadata lag. | Make `pack:check` and published-entrypoint smoke mandatory closeout. | `npm run pack:check` | -| P1-R6 | Future x402 surfaces sneak into first wedge | Unsupported variants are accepted as extensions of `x402_payment.exact`. | Conformance classifications and hostile upstream fixtures. | `npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts` | - -## P2 - -| ID | Risk | Failure Mode | Mitigation | Gate | -| --- | --- | --- | --- | --- | -| P2-R1 | `.planning` scratch becomes canon | Future agents revive stale plan claims from tracked planning maps. | Guard package/docs/scripts/exports against `.planning` authority. | `npm run quality:claims` and `npm run pack:check` | -| P2-R2 | False closeout | Concern marked done without source mechanism, regression test, and gate. | Closure rule: source diff plus focused test plus architecture/claim/package gate. | `npm run check:repo` | -| P2-R3 | Buyer-readable proof label becomes action-class claim | `x402_paid_http_call.exact` is treated as gateway-bound authority. | Keep label report-only until action catalog, compiler, policy, and gateway support it. | `npm run test -- test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts` | -| P2-R4 | Gateway failure evidence too coarse | Redacted diagnostics hide useful failure categories for operations. | Add redacted reason classes only after no-leakage tests. | `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/protocol/evidence-projections.test.ts` | - -## Residual Risk - -Live provider custody, hosted verifier operation, host-wide interception, seller/facilitator settlement, aggregate spend enforcement, and public registry publication remain unvalidated because the mechanisms do not exist in the current source. The correct mitigation is explicit cut-line evidence, not partial claims. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/TASKS.jsonl deleted file mode 100644 index da8a2e3..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/TASKS.jsonl +++ /dev/null @@ -1,19 +0,0 @@ -{"id":"macro-001","priority":"P0","phase":"Phase 1","title":"Add failing runtime x402 posture regression tests","owner":"runtime implementer","rationale":"Runtime currently accepts posture fields but can default them away before x402 proposal; the failure must be visible before the fix.","depends_on":[],"acceptance":["test/runtime/runtime-ingress.test.ts covers unsupported body plus live provider posture returning one_or_more_dispatches_refused","refused runtime case includes x402_request_body_posture_unsupported and x402_provider_environment_not_sandboxed","refused runtime case creates no action_contract, policy_decision, greenlight, gateway_check_attempt, mutation_attempt, receipt, receipt_export, or authority_certificate","supported digest_bound local_reference_sandbox case asserts posture fields survive into candidate parameters"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/adapters/x402-payment-action-proposal.test.ts"],"non_goals":["do not patch source before a failing regression exists","do not test hosted provider custody or aggregate spend enforcement"]} -{"id":"macro-002","priority":"P0","phase":"Phase 1","title":"Forward runtime x402 request and provider posture into adapter attempts","owner":"runtime implementer","rationale":"Observed dispatch posture must become exact adapter input or refuse before contract proposal; omission is compiler overreach.","depends_on":["macro-001"],"acceptance":["src/runtime/ingress/index.ts forwards intendedRequestBodyPosture, providerEnvironmentPosture, and providerEnvironmentRef in x402PaymentAttemptForDispatch","unsupported, omitted, external_sandbox, live, and unknown posture do not default to no_body or local_reference_sandbox","npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts passes"],"candidate_paths":["src/runtime/ingress/index.ts","src/adapters/x402-payment/action-proposal.ts"],"non_goals":["do not extract runtime registry in this task","do not move authority into runtime"]} -{"id":"macro-003","priority":"P0","phase":"Phase 1","title":"Bind x402 posture into direct adapter idempotency material","owner":"x402 adapter implementer","rationale":"Two x402 attempts with different body or provider posture must not share idempotency semantics merely because amount and endpoint match.","depends_on":["macro-001"],"acceptance":["idempotency digest material includes intendedRequestBodyPosture, providerEnvironmentPosture, and providerEnvironmentRef for non-payment-identifier x402 proposals","tests prove idempotency changes when posture or provider ref changes","historical records are not rewritten or claimed equivalent"],"candidate_paths":["src/adapters/x402-payment/action-proposal.ts","test/adapters/x402-payment-action-proposal.test.ts"],"non_goals":["do not change stored historical receipts","do not add a new Tier 1 primitive"]} -{"id":"macro-004","priority":"P0","phase":"Phase 1","title":"Record runtime x402 refusal without authority-bearing records","owner":"runtime implementer","rationale":"A runtime posture refusal should preserve reconstructable proposal evidence without producing an action contract or downstream authority objects.","depends_on":["macro-002","macro-003"],"acceptance":["unsupported runtime x402 posture returns structured refusal outcome instead of unhandled throw","runtime/graph/tool-call evidence remains reconstructable where existing runtime semantics allow","tests assert no policy, greenlight, gateway, mutation, receipt, receipt_export, signer, or certificate records are created","npm run check:types passes"],"candidate_paths":["src/runtime/ingress/index.ts","src/adapters/x402-payment/action-proposal.ts","test/runtime/runtime-ingress.test.ts"],"non_goals":["do not treat refusal evidence as authorization","do not create action_contract for refused x402 attempts"]} -{"id":"macro-005","priority":"P0","phase":"Phase 2","title":"Add explicit MCP x402 body and provider posture schema fields","owner":"mcp implementer","rationale":"MCP cannot be posture-equivalent while its model-facing schema cannot express the direct adapter boundary.","depends_on":["macro-004"],"acceptance":["McpX402PaymentProposalInputSchema requires intendedRequestBodyPosture, providerEnvironmentPosture, and nullable providerEnvironmentRef","schema fixtures reject omitted posture unless an explicit compatibility refusal path is implemented","valid local_reference_sandbox inputs include posture fields","npm run test -- test/mcp/mcp-schema-contract.test.ts passes"],"candidate_paths":["src/mcp/x402-proposal.ts","test/mcp/mcp-schema-contract.test.ts","src/mcp/catalog.ts"],"non_goals":["do not default omitted MCP posture to local_reference_sandbox","do not expose signer or gateway authority through MCP"]} -{"id":"macro-006","priority":"P0","phase":"Phase 2","title":"Implement MCP x402 pre-contract refusal and posture binding","owner":"mcp implementer","rationale":"MCP should either bind the exact posture into a proposal or refuse before runtime-client contract proposal.","depends_on":["macro-005"],"acceptance":["MCP refuses or schema-fails omitted, unsupported, external_sandbox, live, and unknown posture before runtime-client proposeActionContract","accepted MCP proposals bind posture fields into x402Parameters, non-secret summary, tool-call draft, compile-intent candidate parameters, and deriveMcpX402IdempotencyKey","MCP result keeps non-authority flags for refusals and proposals","npm run test -- test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts passes"],"candidate_paths":["src/mcp/x402-proposal.ts","test/mcp/mcp-x402-proposal.test.ts","test/architecture/mcp-surface-posture.test.ts"],"non_goals":["do not import wallet gateway, policy, gateway, storage, receipt, all-role SDK, or certificate code","do not implement MCP auto-pay"]} -{"id":"macro-007","priority":"P0","phase":"Phase 2","title":"Update MCP transcript, stdio, and package smoke fixtures for posture schema","owner":"mcp/package implementer","rationale":"Public MCP/package evidence must exercise the same schema that source now enforces.","depends_on":["macro-006"],"acceptance":["MCP reference transcript includes local no_body success, digest_bound success, unsupported or omitted body refusal, and live or unknown provider refusal","stdio process smoke uses final MCP schema and leaks no PaymentPayload or PAYMENT-SIGNATURE","scripts/check-published-entrypoints.mjs reference MCP input includes posture fields","npm run test -- test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts passes"],"candidate_paths":["examples/mcp-reference-transcript/run.ts","test/mcp/mcp-reference-transcript.test.ts","test/mcp/mcp-stdio-process.test.ts","scripts/check-published-entrypoints.mjs"],"non_goals":["do not claim hosted MCP availability","do not claim sibling MCP interception"]} -{"id":"macro-008","priority":"P0","phase":"Phase 3","title":"Add explicit local/reference sandbox evidence-boundary object","owner":"x402 adapter implementer","rationale":"authorityCreated false is insufficient if signed retry evidence can still be read as settlement or middleware operation.","depends_on":["macro-004"],"acceptance":["sandbox challenge and signed retry outputs carry local_reference fixture scope and non-authority boundary fields","signed retry output explicitly says not settlement finality, not facilitator operation, not seller middleware, and not provider custody","TypeScript types make the boundary visible to demo/projection code"],"candidate_paths":["src/adapters/x402-payment/sandbox-http.ts","src/adapters/x402-payment/wallet-gateway.ts"],"non_goals":["do not implement seller middleware","do not implement facilitator settlement","do not claim live provider operation"]} -{"id":"macro-009","priority":"P0","phase":"Phase 3","title":"Test sandbox retry refusal boundaries and post-gate signing","owner":"x402 test implementer","rationale":"The local sandbox must only observe a signed retry after gateway-created signature evidence and exact local posture.","depends_on":["macro-008"],"acceptance":["missing signature evidence, wrong signature header, non-reference provider posture, ambiguous body posture, and replay do not increment signedRetryCount","official SDK PaymentPayload creation remains after VerifiedGatewayCheck","test output leaks no raw signer, PaymentPayload, or PAYMENT-SIGNATURE material","npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts passes"],"candidate_paths":["test/adapters/x402-wallet-gateway.test.ts","test/integration/x402-d1-http.test.ts","src/adapters/x402-payment/wallet-gateway.ts"],"non_goals":["do not expose payment signature authority to runtime, MCP, CLI, or demos","do not validate real provider custody"]} -{"id":"macro-010","priority":"P0","phase":"Phase 3","title":"Project and report sandbox signed retry as downstream fixture evidence only","owner":"projection/product implementer","rationale":"Adoption surfaces must not launder local retry observation into authority, settlement, custody, or action-catalog breadth.","depends_on":["macro-008","macro-009"],"acceptance":["evidence projections classify x402 local sandbox signed retry as local/reference downstream observation","demo report preserves x402_paid_http_call.exact as buyer-readable proof-object language only","claim tests fail if demo/docs imply settlement, seller middleware, facilitator operation, provider custody, or authority","npm run test -- test/protocol/evidence-projections.test.ts test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts passes"],"candidate_paths":["src/protocol/evidence-projections/projections.ts","examples/x402-protected-spend/run.ts","examples/x402-protected-spend/README.md","test/protocol/evidence-projections.test.ts","test/product/x402-protected-spend-demo-report.test.ts","test/architecture/claim-boundary.test.ts"],"non_goals":["do not create x402_paid_http_call.exact as an action catalog entry","do not claim payment finality"]} -{"id":"macro-011","priority":"P1","phase":"Phase 4","title":"Add runtime family registry coverage tests before extraction","owner":"runtime test implementer","rationale":"The registry is useful only if it prevents field loss and family drift instead of hiding it.","depends_on":["macro-004"],"acceptance":["tests define expected family coverage for package_install, x402_payment, and auth_md protected API dispatches","missing family config fails closed","mixed-family blocks retain existing grammar/version behavior","registry architecture tests forbid authority imports"],"candidate_paths":["test/runtime/runtime-ingress.test.ts","test/runtime/auth-md-candidate-compilation.test.ts","test/runtime/package-install-runtime.test.ts","test/architecture/import-posture.test.ts"],"non_goals":["do not alter public runtime API in the test-only step","do not add a new protected-action family"]} -{"id":"macro-012","priority":"P1","phase":"Phase 4","title":"Extract runtime ingress family adapters behind a proposal-only registry","owner":"runtime implementer","rationale":"Cross-family conversion in one module invites future refusal-field loss as more protected actions are added.","depends_on":["macro-011"],"acceptance":["runtime ingress exposes a family registry with dispatch coverage, config requirement, compile-input construction, preflight refusal, signing secret, grammar version, and raw-bypass hooks","proposeRuntimeIngressActionContracts public behavior remains stable","package install, auth.md, and x402 tests pass through the registry","registry code imports no policy, greenlight, gateway, storage implementation, mutation, receipt, signer, or certificate authority code"],"candidate_paths":["src/runtime/ingress/index.ts","src/runtime/ingress/registry.ts","src/runtime/ingress/families/x402-payment.ts","src/runtime/ingress/families/package-install.ts","src/runtime/ingress/families/auth-md-protected-api-call.ts"],"non_goals":["do not move family semantics into Tier 1 protocol","do not issue authority from runtime"]} -{"id":"macro-013","priority":"P1","phase":"Phase 4","title":"Close runtime registry architecture and regression gates","owner":"architecture reviewer","rationale":"Refactor closure requires proof that boundaries and existing families survived extraction.","depends_on":["macro-012"],"acceptance":["npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts test/protocol/generated-execution-graph.test.ts passes","npm run quality:architecture passes","no package export or lane doc claims runtime authority"],"candidate_paths":["test/architecture/import-posture.test.ts","test/architecture/naming-posture.test.ts","src/runtime/LANE.md"],"non_goals":["do not document registry as gateway enforcement","do not claim host-wide interception"]} -{"id":"macro-014","priority":"P1","phase":"Phase 5","title":"Pin unsupported x402 first-wedge surfaces in conformance tests","owner":"conformance implementer","rationale":"The first wedge must stay exact buyer-side x402_payment.exact unless broader surfaces have source, policy, and gateway support.","depends_on":["macro-004"],"acceptance":["conformance classifies upto, batch settlement, lifecycle hooks, MCP auto-pay, signed offers, signed receipts, seller middleware, facilitator operation, and settlement finality as unsupported or future","hostile upstream fixtures cover unknown extensions, multiple accepts, malformed assets, future versions, and non-exact schemes","npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts passes"],"candidate_paths":["src/adapters/x402-payment/conformance.ts","src/adapters/x402-payment/upstream-evidence.ts","test/conformance/x402-payment-conformance.test.ts","test/conformance/x402-upstream-exact-fixtures.test.ts"],"non_goals":["do not broaden x402_payment.exact","do not implement seller or facilitator adapters"]} -{"id":"macro-015","priority":"P1","phase":"Phase 5","title":"Guard spend metadata, custody labels, and scoped bypass posture","owner":"x402 boundary implementer","rationale":"Metadata-only spend fields, fixture custody, and observed bypass evidence are the easiest surfaces to overclaim.","depends_on":["macro-014"],"acceptance":["spend session/day/review controls remain outside enforced action-contract bounds and retain not_enforced_local_metadata","fixture gateway custody is distinguishable from live provider or customer custody","runtime/MCP bypass evidence remains scoped and non-host-wide","npm run test -- test/adapters/x402-install-proposal.test.ts test/adapters/x402-bypass-probes.test.ts test/architecture/claim-boundary.test.ts passes"],"candidate_paths":["src/adapters/x402-payment/install-proposal.ts","src/adapters/x402-payment/bypass-probes.ts","examples/x402-protected-spend/run.ts","test/adapters/x402-install-proposal.test.ts","test/adapters/x402-bypass-probes.test.ts","test/architecture/claim-boundary.test.ts"],"non_goals":["do not build aggregate spend ledger","do not claim provider custody","do not claim broad host interception"]} -{"id":"macro-016","priority":"P1","phase":"Phase 6","title":"Add projection scale and credential-redaction regression tests","owner":"storage/projection test implementer","rationale":"Hosted evidence and provider custody claims are invalid while projection reads and redaction remain local/denylist-shaped.","depends_on":["macro-010"],"acceptance":["tests cover high unrelated record volume for contract-scoped envelope assembly","tests cover long receipt timelines requiring batched range reads","redaction fuzz covers PaymentPayload, PAYMENT-SIGNATURE, raw signer refs, bearer tokens, vault paths, secret refs, facilitator secrets, and auth.md credential-looking refs","npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts fails before source changes"],"candidate_paths":["test/protocol/evidence-projections.test.ts","test/http/d1-http.test.ts","test/protocol/protocol-store-atomicity-contract.test.ts"],"non_goals":["do not claim hosted audit/search from test scaffolding alone","do not expose raw records through projections"]} -{"id":"macro-017","priority":"P1","phase":"Phase 6","title":"Implement scoped store reads, D1 indexes, range reads, and projection redaction hardening","owner":"storage/projection implementer","rationale":"Projection evidence must be reconstructable and redacted under scale before hosted claims are even considered.","depends_on":["macro-016"],"acceptance":["ProtocolStore exposes contract/action/run-scoped reads needed by envelope assembly","memory and D1 implementations preserve store contract parity","D1 migration adds additive indexes or tables without changing canonical record digests","projection assembly uses scoped methods instead of broad tenant/org scans where scale claims are made","npm run quality:storage passes"],"candidate_paths":["src/protocol/store/port.ts","src/storage/memory/index.ts","src/storage/d1/index.ts","migrations/0001_protocol_kernel.sql","src/protocol/evidence-projections/assembly.ts","src/protocol/evidence-projections/projections.ts"],"non_goals":["do not change protocol record digests","do not implement hosted verifier or retention policy"]} -{"id":"macro-018","priority":"P1","phase":"Phase 7","title":"Update package smoke and planning-drift gates after MCP schema finalization","owner":"package/architecture implementer","rationale":"Package consumers execute built bins and packaged entrypoints, so source-only success is not publish readiness.","depends_on":["macro-007"],"acceptance":["scripts/check-published-entrypoints.mjs uses the final MCP posture schema","package surface checks exclude .planning, tests, workspace junk, raw credential material, PaymentPayload, and PAYMENT-SIGNATURE","architecture tests reject .planning as package/export/script/CI/canonical-doc authority","npm run pack:check passes"],"candidate_paths":["scripts/check-package-surface.mjs","scripts/check-published-entrypoints.mjs","test/architecture/package-surface.test.ts","test/architecture/active-vocabulary.test.ts","test/architecture/claim-boundary.test.ts","package.json"],"non_goals":["do not publish to npm or MCP Registry","do not treat .planning maps as canon"]} -{"id":"macro-019","priority":"P0","phase":"Phase 7","title":"Run final concern-elimination closeout gates","owner":"release captain","rationale":"The concerns are not eliminated until focused gates and full repo gates pass on the intended worktree.","depends_on":["macro-013","macro-015","macro-017","macro-018"],"acceptance":["npm run demo:aps passes and output preserves local/reference non-claims","npm run demo:mcp-transcript passes with posture parity cases","npm run quality:claims passes","npm run quality:architecture passes","npm run pack:check passes","npm run check:repo passes","closeout notes list remaining future cuts rather than claiming them complete"],"candidate_paths":["examples/x402-protected-spend/output/latest.json","examples/x402-protected-spend/output/latest.md","examples/mcp-reference-transcript/output/latest.json",".planning/macro/VALIDATION.md"],"non_goals":["do not commit from this planning task","do not mark ledger, custody, hosted verifier, host interception, seller/facilitator, or publication as complete"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/VALIDATION.md deleted file mode 100644 index 0603b19..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/VALIDATION.md +++ /dev/null @@ -1,176 +0,0 @@ -# Validation - -## Closure Rule - -A concern is not closed unless it has: - -- a source-owned mechanism; -- a focused regression test or conformance test; -- a claim, architecture, storage, package, or full-repo gate that would catch future drift; -- no expansion of Tier 1 primitive meaning; -- no authority moved into runtime, MCP, CLI, demos, or review output. - -## Phase Gates - -### Phase 1: Runtime Posture - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts -npm run check:types -``` - -Proof obligations: - -- Runtime forwards `intendedRequestBodyPosture`, `intendedRequestBodyDigest`, `providerEnvironmentPosture`, and `providerEnvironmentRef`. -- Unsupported/omitted body and external/live/unknown provider posture refuse before action-contract proposal. -- Accepted local-reference/digest-bound posture appears in candidate parameters and idempotency material. -- Refused cases create no policy decision, greenlight, gateway check, mutation attempt, receipt, receipt export, or authority certificate. - -### Phase 2: MCP Posture - -```bash -npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts test/architecture/mcp-surface-posture.test.ts -npm run check:types -``` - -Proof obligations: - -- MCP schema requires explicit request-body and provider-environment posture. -- MCP refuses or schema-fails omitted, unsupported, external, live, and unknown posture before runtime-client proposal. -- Accepted MCP proposals bind posture fields into parameters, non-secret summary, tool-call draft, compile-intent input, and idempotency digest. -- MCP outputs remain non-authority and leak no `PaymentPayload`, `PAYMENT-SIGNATURE`, signer, credential, receipt export, gateway, mutation, or certificate material. - -### Phase 3: Sandbox Boundary - -```bash -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/protocol/evidence-projections.test.ts test/product/x402-protected-spend-demo-report.test.ts -npm run demo:aps -``` - -Proof obligations: - -- Challenge and signed-retry evidence carry local/reference fixture scope and `authorityCreated: false`. -- Signed retry is post-gate downstream observation only. -- Missing signature evidence, wrong signature header, non-reference provider posture, ambiguous body posture, and replay do not create another signed retry. -- Projections and demo output do not claim settlement finality, facilitator operation, seller middleware, provider custody, or authority. - -### Phase 4: Runtime Registry - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts test/protocol/generated-execution-graph.test.ts -npm run quality:architecture -``` - -Proof obligations: - -- Every dispatch kind has exactly one family adapter. -- Missing config fails closed. -- Existing package install, auth.md, and x402 runtime outputs remain behaviorally equivalent except for the intended posture fix. -- Registry code cannot import or issue authority-bearing transitions. - -### Phase 5: Future-Surface Guards - -```bash -npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/adapters/x402-install-proposal.test.ts test/adapters/x402-bypass-probes.test.ts test/architecture/claim-boundary.test.ts -npm run quality:claims -``` - -Proof obligations: - -- Unsupported x402 surfaces stay explicit future cuts. -- Spend session/day/review controls remain `not_enforced_local_metadata`. -- Fixture custody and scoped bypass evidence cannot be serialized as live custody or host-wide interception. -- README/docs/examples fail claims if they imply hosted, provider, broad host, aggregate spend, seller/facilitator, or settlement proof. - -### Phase 6: Projection Scale And Redaction - -```bash -npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts -npm run quality:storage -``` - -Proof obligations: - -- Contract/action/run-scoped store reads and range reads preserve memory/D1 parity. -- Projection assembly does not rely on broad scans when making scale claims. -- Provider-format fuzz cases do not project raw signer refs, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, vault paths, secret refs, facilitator secrets, or auth.md credential material. - -### Phase 7: Package And Closeout - -```bash -npm run demo:mcp-transcript -npm run quality:claims -npm run quality:architecture -npm run pack:check -npm run check:repo -``` - -Proof obligations: - -- Package smoke uses the final MCP posture schema. -- `dist` and bin behavior match source after build. -- `.planning/`, tests, workspace junk, raw credentials, and scratch docs are excluded from package artifacts. -- Full repo check passes on the intended closeout worktree. - -## Commands Not Sufficient Alone - -- `npm run test` without focused posture cases does not prove runtime/MCP x402 parity. -- `npm run demo:aps` does not prove settlement, provider custody, hosted operation, or host interception. -- `npm run pack:check` does not prove publication. -- `npm run quality:claims` does not close a source concern without source tests. - -## Blocked / Future Checks - -- Live provider/customer custody checks are blocked until provider/vault custody code exists. -- Aggregate spend ledger checks are blocked until reservation ledger code exists. -- Hosted verifier, JWKS, revocation, and cross-org trust checks are blocked until hosted verifier code exists. -- Host-wide interception checks are blocked until a concrete host harness exists. -- Seller/facilitator/settlement checks are blocked until those adapters exist. -- Actual npm/MCP Registry publication checks are blocked on owner-held external credentials. - -## Closeout Result: 2026-05-24 - -Executed end-to-end against `macro-001` through `macro-019`. - -Closed source-owned concerns: - -- Runtime x402 posture is explicit in proposal input, candidate parameters, refusal evidence, and idempotency material. -- MCP x402 posture is explicit in schema, reference transcript, idempotency material, and package-entrypoint smoke input. -- Local/reference x402 sandbox retry evidence is labeled downstream fixture evidence only, with no authority, custody, settlement, seller, or facilitator claim. -- Runtime ingress family coverage is behind a proposal-only registry and guarded against authority imports. -- Unsupported x402 surfaces remain explicit future cuts, including settlement finality. -- Evidence projection assembly now uses contract-scoped reads plus store range reads instead of broad tenant/org scans. -- Memory and D1 stores preserve scoped-read and range-read parity, with D1 action-contract side refs and indexes. -- Projection redaction covers raw signer refs, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, vault/Infisical/1Password paths, secret refs, facilitator secrets, and auth.md credential-looking refs. -- Package and architecture gates exclude `.planning/`, tests, workspace junk, raw credential material, `PaymentPayload`, and `PAYMENT-SIGNATURE` from published surfaces. - -Closeout commands run: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts -npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/protocol/evidence-projections.test.ts test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts -npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts test/protocol/generated-execution-graph.test.ts test/architecture/import-posture.test.ts -npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/adapters/x402-install-proposal.test.ts test/adapters/x402-bypass-probes.test.ts test/architecture/claim-boundary.test.ts -npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts -npm run demo:aps -npm run demo:mcp-transcript -npm run quality:storage -npm run quality:claims -npm run quality:architecture -npm run pack:check -npm run check:repo -``` - -Final closeout gate: - -- `npm run check:repo` passed with `471 pass, 0 fail`, package build/surface smoke green, and `git diff --check` green. - -Still future, not claimed: - -- live provider/customer custody; -- aggregate spend-window enforcement; -- hosted verifier/JWKS/revocation/cross-org trust; -- host-wide interception; -- seller middleware, facilitator operation, settlement finality; -- actual npm or MCP Registry publication. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/input.md deleted file mode 100644 index a7f2f10..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/input.md +++ /dev/null @@ -1,138 +0,0 @@ -# Concerns Elimination Macro Plan Input - -Run id: `concerns-elimination-20260524T044836Z` -Date: 2026-05-24 -Requested by: user - -## Target - -Create an executable GSD macro plan to eliminate the current `.planning/codebase/CONCERNS.md` concerns with technical implementation that strengthens Handshake rather than applying documentation-only or assertion-only band-aids. - -## Invariant - -No consequential autonomous action executes outside declared bounds, and divergent behavior must be haltable, isolatable, and reconstructable. - -## User Constraints - -- Plan for implementation, not vague strategy. -- Eliminate concerns by strengthening source mechanisms, tests, and gates. -- Do not weaken or reopen the Tier 1 protocol/kernel. -- Do not expand Tier 2 claims beyond installed, gateway-owned, exact protected paths. -- Keep CLI/MCP proposal/evidence only. -- Keep runtime ingress proposal-only. -- Keep x402 first wedge exact and buyer-side unless a concern explicitly requires a future cut line. -- Preserve existing dirty worktree changes as current state; do not plan by reverting them. -- No band-aids: each phase must include source-owned mechanism, tests, and validation gates. - -## Current Worktree State - -Dirty files observed before planning: - -```text -M README.md -M docs/internal/decisions.md -M docs/internal/protocol-notes.md -M examples/x402-protected-spend/README.md -M examples/x402-protected-spend/run.ts -M src/adapters/x402-payment/action-proposal.ts -M src/adapters/x402-payment/index.ts -M src/adapters/x402-payment/upstream-evidence.ts -M src/adapters/x402-payment/wallet-gateway.ts -M src/protocol/evidence-projections/projections.ts -M src/protocol/foundation/reason-codes.ts -M src/runtime/ingress/index.ts -M test/adapters/x402-payment-action-proposal.test.ts -M test/adapters/x402-wallet-gateway.test.ts -M test/product/x402-protected-spend-demo-report.test.ts -?? src/adapters/x402-payment/sandbox-http.ts -``` - -The map should treat these changes as current live worktree state for planning. The plan must not assume they are already validated or committed. - -## Required Source Packet - -First-pass planners may read: - -- `AGENTS.md` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-notes.md` -- `.planning/codebase/CONCERNS.md` -- `.planning/codebase/ARCHITECTURE.md` -- `.planning/codebase/STRUCTURE.md` -- `.planning/codebase/TESTING.md` -- `.planning/codebase/INTEGRATIONS.md` -- `.planning/codebase/STACK.md` -- `.planning/codebase/CONVENTIONS.md` -- `src/runtime/ingress/index.ts` -- `src/runtime/LANE.md` -- `src/mcp/x402-proposal.ts` -- `src/mcp/LANE.md` -- `src/adapters/x402-payment/action-proposal.ts` -- `src/adapters/x402-payment/upstream-evidence.ts` -- `src/adapters/x402-payment/wallet-gateway.ts` -- `src/adapters/x402-payment/sandbox-http.ts` -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/conformance.ts` -- `src/adapters/x402-payment/bypass-probes.ts` -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/evidence-projections/assembly.ts` -- `src/protocol/store/port.ts` -- `src/storage/d1/index.ts` -- `migrations/0001_protocol_kernel.sql` -- `examples/x402-protected-spend/run.ts` -- `examples/x402-protected-spend/README.md` -- relevant tests under `test/runtime/`, `test/mcp/`, `test/adapters/`, `test/conformance/`, `test/protocol/`, `test/http/`, and `test/architecture/` -- `package.json` -- `scripts/check-package-surface.mjs` -- `scripts/check-published-entrypoints.mjs` - -First-pass planners must not read sibling raw outputs, normalized outputs, or `.planning/macro/PLAN.md`. - -## Concern Groups To Close - -1. Runtime x402 posture propagation: runtime ingress must not default away request-body or provider-environment posture. -2. MCP x402 posture parity: MCP proposals must carry/refuse the same body/environment posture that direct adapter/runtime paths enforce. -3. x402 sandbox/signed retry evidence boundary: local sandbox proof must be impossible to confuse with seller middleware, facilitator settlement, or authority. -4. Runtime ingress family hardcoding: cross-family proposal code needs a stronger source-owned family adapter/registry boundary. -5. x402 first-slice and future-surface guards: unsupported x402 surfaces must stay explicit, tested, and unclaimable. -6. Spend window metadata: aggregate spend/session/day/review controls remain metadata until a real reservation ledger exists. -7. Signer custody and provider custody: local signer proof must not become provider/customer custody claim. -8. Host/bypass posture: runtime/MCP bypass evidence is not broad host interception. -9. Evidence projection scale and redaction: projection assembly and credential redaction need stronger source mechanisms before hosted claims. -10. Publish/package drift: publish-ready package surfaces must stay tied to build/pack/published-entrypoint gates. -11. `.planning` scratch drift: derived maps must not become canon or bypass claim/vocabulary gates. - -## Required Output - -Write a coherent implementation macro plan to: - -- `.planning/macro/PLAN.md` -- `.planning/macro/CONTEXT.md` -- `.planning/macro/ASSUMPTIONS.md` -- `.planning/macro/DECISIONS.md` -- `.planning/macro/RISKS.md` -- `.planning/macro/VALIDATION.md` -- `.planning/macro/TASKS.jsonl` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/synthesis.md` - -Also write raw first-pass outputs under: - -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/STRATEGY.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/ARCH.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/EXECUTION.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/RISK.md` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/raw/ADOPTION.md` - -## Success Criteria - -- Plan has source mechanisms, not documentation-only fixes. -- Plan sequences nearest high-priority defects first: runtime posture propagation, MCP posture parity, and sandbox evidence boundaries. -- Plan explicitly cuts ledger, live custody, host-wide interception, hosted verifier, facilitator/seller middleware, and registry publication unless they are implemented as separate future phases. -- Every task has candidate paths, acceptance tests, and non-goals. -- Validation includes focused tests, architecture/claim gates, package gates, demo regeneration, and full repo check. -- The plan is ready to execute unless a user-owned decision is explicitly identified. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ADOPTION.md deleted file mode 100644 index 1bb845f..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ADOPTION.md +++ /dev/null @@ -1,152 +0,0 @@ -# ADOPTION Perspective - -## Invariant At Stake - -First-use paths must teach the same authority boundary the kernel enforces: runtime, MCP, CLI, demos, support bundles, and docs may propose or display evidence only. They must not imply policy authority, signer custody, gateway checks, mutation execution, receipt export, hosted operation, provider custody, broad host interception, aggregate spend enforcement, or x402 settlement finality. - -## Adoption Path - -1. Fix the mechanism before updating the walkthroughs. - - Runtime x402 ingress must forward `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef` into the x402 attempt and action-contract parameters instead of defaulting them away. - - MCP x402 proposal input must expose the same request-body and provider-environment posture fields, bind them into parameters and idempotency derivation, and refuse unsupported/live/unknown posture as a structured non-authority outcome. - - Demo and docs changes should land only after the focused runtime/MCP tests fail without the source changes and pass with them. - -2. Make the first local success path a narrow activation sequence, not an authority shortcut. - - The first-use guide should preserve this order: `compileX402InstallProposal()` -> catalog/envelope registration -> hostile bypass probes -> `createProtectedPathPosture()` -> runtime proposal -> policy evaluation -> `runX402WalletGateway()` -> redacted evidence projection -> optional terminal certificate after receipt/refusal/proof-gap/replay. - - Add a source-owned activation helper or example-local sequencer only if it reduces ceremony without moving policy, greenlight, signer custody, gateway check, mutation, receipt export, or certificate minting into runtime/MCP/CLI. - - The helper output must include the same non-authority flags used by runtime/MCP/CLI outputs. - -3. Keep MCP and CLI as model/operator evidence surfaces. - - MCP should remain exactly one proposal tool plus read-only resources. It should never become `pay`, `approve`, `gatewayCheck`, `sign`, `receiptExport`, or `certMint`. - - CLI should remain schema/init/doctor/evidence/cert-verify/support/install-health/conformance posture. `support.bundle` can gather debug context, but it must not read raw internal records, spawn mutation commands, include credential material, or claim authority. - - Package docs should teach `handshake` as operator evidence/readiness CLI and `handshake-mcp` as local stdio proposal/evidence server. - -4. Treat demo outputs as adoption contracts. - - `examples/x402-protected-spend/output/latest.json` should keep named phases and include request-body posture, provider-environment posture/ref, gateway check vs downstream status, signed retry as local fixture evidence, replay refusal, non-claims, and missing proof objects. - - `examples/mcp-reference-transcript/output/latest.json` should include posture-parity cases: local no-body success, digest-bound success, omitted/unsupported body refusal, live/unknown/external provider-environment refusal, stale metadata, gateway offline, raw sibling input, replay refusal, and proof gap. - - The demo reports should show `x402_paid_http_call.exact` only as buyer-readable proof-object language, not as an action catalog entry until source, policy, runtime, and gateway all support that action class. - -5. Make packaging a first-use validation step. - - `npm run pack:check` must remain mandatory before publication or registry claims because package consumers use `dist/**` and `bin/**`, not dirty TypeScript source. - - `scripts/check-package-surface.mjs` and `scripts/check-published-entrypoints.mjs` should prove no `.planning/`, tests, workspace junk, raw credentials, `PaymentPayload`, or `PAYMENT-SIGNATURE` leaks into the package or MCP stdio smoke. - - The package docs must keep npm/MCP Registry publication as metadata readiness only until owner credentials actually publish the package and registry namespace. - -## First-Use Checklist - -1. Install and run the full local gate: - - `bun install --frozen-lockfile` - - `npm run check:repo` - -2. Generate the local x402 protected-spend evidence packet: - - `npm run demo:aps` - - Inspect `examples/x402-protected-spend/output/latest.md` and `latest.json` for phases `0_sandbox_payment_required_challenge` through `7_replay_refusal`. - - Confirm runtime records no policy/greenlight/gateway/mutation/receipt/certificate before policy, and the signer is invoked only after `VerifiedGatewayCheck`. - -3. Generate the MCP proposal/evidence transcript: - - `npm run demo:mcp-transcript` - - Confirm MCP outputs carry non-authority flags and posture-parity refusals without creating gateway or mutation records. - -4. Smoke the packaged surfaces: - - `npm run build` - - `node bin/handshake schema` - - `node bin/handshake-mcp` - - `npm run pack:check` - -5. Produce a sanitized support bundle once the bundle mechanism is strengthened: - - Include package version, `server.json`/`package.json#mcpName` sync, command manifest, non-authority flags, focused test results, demo output digests, install-health refs, MCP transcript case list, and redaction summary. - - Exclude raw protocol records, stream events, idempotency internals, raw signer refs, `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, registry credentials, Worker tokens, and `.planning/` scratch. - -## Missing Docs And Examples - -- README quickstart should separate three paths: local kernel proof, package/bin smoke, and MCP proposal/evidence transcript. It should not compress them into "install Handshake and pay safely." -- `examples/x402-protected-spend/README.md` needs a posture matrix: - - `no_body` with null digest: allowed for local/reference exact path. - - `digest_bound` with body digest: allowed only when bound through runtime/MCP and gateway parameters. - - `omitted` or `unsupported`: refusal before contract proposal. - - `local_reference_sandbox`: first-slice provider environment. - - `external_sandbox`, `live`, or `unknown`: refusal until a separate provider/firewall/custody mechanism exists. -- MCP reference transcript needs explicit request-posture and provider-posture examples, not only metadata/install/gateway/idempotency cases. -- CLI support bundle needs an example JSON fixture and a product test proving every field is diagnostic, redacted, and non-authority. -- Package docs need a short "dirty source is not packaged truth" note: `dist/**` is current only after `npm run build`/`pack:check`. -- Spend-window metadata needs one adoption-visible warning in README and demo output: session/day/review bounds are metadata until a reservation ledger exists. -- `.planning` scratch drift needs to stay out of package docs and package files; implementation plans can read `.planning/codebase/CONCERNS.md`, but users must learn canon from README, QUALITY, STRUCTURE, and `docs/internal/*`. - -## Success Metrics - -- A new developer can get from clean checkout to `examples/x402-protected-spend/output/latest.json` in one documented path without touching raw protocol records or all-role SDK clients. -- Runtime x402 posture parity has regression tests proving unsupported body posture and live/unknown/external provider environment refuse without an action contract. -- MCP x402 posture parity has schema, proposal, transcript, and package-entrypoint tests proving the same posture fields are either bound into the proposed contract or refused before authority-shaped output. -- Every first-use output includes `authorityCreated: false`, `greenlightCreated: false`, `gatewayCheckPerformed: false`, `mutationAttempted: false`, `credentialMaterialIncluded: false`, `receiptExportCreated: false`, and `authorityCertificateMinted: false` unless the output is a kernel/gateway evidence object that actually created that object. -- Demo and support outputs include non-claims and missing proof objects for hosted operation, provider custody, aggregate spend enforcement, broad host interception, payment settlement finality, and cross-org certificate trust. -- `npm run pack:check` proves package files and bundled entrypoints match the source boundary; no `.planning/`, tests, deleted doc trees, or workspace junk enter the package. -- `npm run quality:claims` fails if docs or examples teach false authority, broad x402 compatibility, provider custody, hosted operation, MCP auto-pay, facilitator/seller middleware, or spend-window enforcement. - -## Adoption Blockers And Fixes - -1. Runtime x402 posture defaults hide unsafe request/provider posture. - - Blocker: runtime dispatch schemas accept posture fields, but current x402 runtime tests do not prove those fields reach the direct adapter refusal boundary. - - Fix: update runtime x402 dispatch-to-attempt conversion to pass `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`; add tests in `test/runtime/runtime-ingress.test.ts` for unsupported/omitted body and live/unknown/external provider environments producing no `action_contract`. - -2. MCP cannot express the same x402 request/provider posture as direct adapter/runtime paths. - - Blocker: `McpX402PaymentProposalInputSchema`, `x402Parameters()`, and `deriveMcpX402IdempotencyKey()` omit request-body posture and provider-environment posture/ref. - - Fix: add those fields, include them in parameter and idempotency binding, and add MCP proposal/transcript/package smoke cases proving refusal or exact binding. MCP should return structured non-authority outcomes with reason codes instead of letting models infer that missing posture defaults are safe. - -3. Local sandbox signed retry can be misread as seller middleware or settlement. - - Blocker: the sandbox emits official-shaped challenge/retry evidence and can look like real downstream x402 operation to first-time users. - - Fix: make local/reference boundary first-class in demo JSON, support bundle, conformance output, and claim tests. Preserve `authorityCreated: false`, `signedRetryIsAuthority: false`, `downstream fixture only`, and `not settlement finality` in every report. - -4. Activation ceremony is easy to skip. - - Blocker: first-use requires install compilation, record registration, probes, protected-path posture, runtime proposal, policy, gateway, projections, and optional certificate. Users will skip probes or push authority into runtime/MCP unless the sequence is one obvious path. - - Fix: add an activation sequencer or generated checklist that returns refs for each step and refuses to continue when probes/posture are missing. Keep mutation authority in gateway code only. - -5. Support bundles are valuable but dangerous. - - Blocker: a support bundle can become a raw audit dump or leak authority-shaped material. - - Fix: define a support-bundle schema with allowlisted fields only, add product tests for redaction/non-authority flags, and bind the command manifest so the bundle reads projections and generated artifacts, not raw records. - -6. Package readiness can drift from dirty source. - - Blocker: first-use docs mention publishable CLI/MCP surfaces while `dist/**` can lag changed source until build/pack checks run. - - Fix: keep `pack:check` in `check:repo`, add a package smoke section to README, and require demo/support output to report package version plus bundle smoke status as evidence, not publication proof. - -7. Spend-window language invites false adoption expectations. - - Blocker: per-session/day/review fields look like budget enforcement even though only per-call x402 amount is enforced. - - Fix: keep session/day/review values out of action-contract bounds and demo authority claims; report them as `not_enforced_local_metadata` until a reservation ledger exists. - -## Validation Gates - -- Runtime posture gate: - - `npm run test -- test/runtime/runtime-ingress.test.ts` - - Required additions: x402 unsupported/omitted body refusal, live/unknown/external provider-environment refusal, digest-bound binding, and no policy/greenlight/gateway/mutation records. - -- MCP posture gate: - - `npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts` - - Required additions: posture fields in schema, idempotency changes when posture changes, structured refusal cases, and stdio smoke with no signer/payment material leakage. - -- x402 adapter/sandbox gate: - - `npm run test -- test/adapters/x402-payment-action-proposal.test.ts test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts` - - Required assertions: direct adapter and runtime/MCP surfaces agree on request/provider posture; sandbox signed retry stays local/reference and post-gate only. - -- Product/demo gate: - - `npm run demo:aps` - - `npm run demo:mcp-transcript` - - `npm run test -- test/product/x402-protected-spend-demo-report.test.ts test/product/self-hosted-activation.test.ts` - - Required assertions: demo reports include posture fields, non-claims, missing proof objects, support-bundle refs when implemented, and no all-role SDK adoption. - -- CLI/support/package gate: - - `npm run test -- test/architecture/cli-command-posture.test.ts test/architecture/mcp-surface-posture.test.ts test/architecture/package-surface.test.ts test/architecture/surface-boundary-posture.test.ts` - - `npm run pack:check` - - Required assertions: command manifest stays non-authority, support bundle is allowlisted/redacted, package files exclude scratch, and bundled bins run from `dist/**`. - -- Claim/canon gate: - - `npm run quality:claims` - - `npm run quality:architecture` - - Required assertions: no hosted/provider/broad-host/aggregate-spend/facilitator/seller/middleware/cross-org trust claims; `.planning` remains scratch and out of package surface. - -- Full closeout gate: - - `npm run check:repo` - -## Blocked Checks - -- Full validation was not run for this first-pass adoption perspective; implementation has not been changed yet. -- Actual npm publication and MCP Registry namespace publication cannot be validated from source because owner-held registry credentials are external. -- Live provider/customer custody, real vault rotation/revocation, live facilitator/seller middleware, hosted verifier/JWKS/revocation, broad browser/shell/network/MCP host interception, and aggregate spend reservation cannot be checked until those mechanisms exist. -- Sibling raw outputs, normalized outputs, and `.planning/macro/PLAN.md` were intentionally not read, so this perspective does not depend on other macro-planning drafts. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ARCH.md deleted file mode 100644 index 9a5e3bd..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/ARCH.md +++ /dev/null @@ -1,227 +0,0 @@ -# ARCH Perspective - -## Invariant at stake - -Tier 2 proposal and evidence surfaces must not default, omit, or relabel protected-action posture in a way that lets unsupported, live, ambiguous, or bypass-shaped x402 attempts become exact `x402_payment.exact` candidates. Tier 1 protocol meaning stays stable: `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheck`, `Receipt`, `Refusal`, `ProofGap`, and `IsolationState` do not move out of `src/protocol`. - -## Architecture implications - -1. Runtime x402 posture propagation is the first architecture defect to close. - - Current data flow is: - - ```text - RuntimeIngressObservedDispatchSchema - -> x402PaymentAttemptForDispatch() - -> X402PaymentAttemptSchema - -> buildX402PaymentCompileIntentInput() - -> IntentCompilationRecord.candidate.parameters - -> ActionContract.paramsDigest - -> X402WalletGateway observed parameters - ``` - - `src/runtime/ingress/index.ts` accepts `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`, but `x402PaymentAttemptForDispatch()` drops them. `X402PaymentAttemptSchema` then defaults to `no_body` and `local_reference_sandbox`, which can turn an observed live, external, omitted, or unsupported posture into a cleaner proposal than the runtime actually observed. This is compiler overreach by omission. - - Source mechanism: forward the posture fields into the adapter attempt, include posture and provider-environment material in x402 idempotency/canonical parameter material, and add runtime tests proving `unsupported`, `omitted`, `external_sandbox`, `live`, and `unknown` refuse before `ActionContract` proposal where the direct adapter would refuse. - -2. MCP x402 posture parity must be closed without turning MCP into an adapter. - - `src/mcp/x402-proposal.ts` currently carries `intendedRequestBodyDigest` and selected headers, but not `intendedRequestBodyPosture`, `providerEnvironmentPosture`, or `providerEnvironmentRef`. Its `x402Parameters()` and `deriveMcpX402IdempotencyKey()` therefore cannot bind the same posture boundary as `src/adapters/x402-payment/action-proposal.ts`. - - MCP must remain proposal/evidence only. The `src/mcp/LANE.md` and `test/architecture/mcp-surface-posture.test.ts` forbid adapter imports, gateway imports, signer material, and authority-shaped code. Do not fix parity by importing wallet gateway or adapter execution code into MCP. - - Source mechanism: add strict MCP input fields and MCP-local pre-contract posture refusal logic, then test black-box parity against the direct adapter refusal outcomes. Forward accepted posture into tool-call drafts, candidate parameters, non-secret summaries, and the MCP idempotency digest. Output must still report `authorityCreated: false`, `greenlightCreated: false`, `gatewayCheckPerformed: false`, and `mutationAttempted: false`. - -3. The x402 sandbox needs a typed evidence boundary, not friendlier language. - - `src/adapters/x402-payment/sandbox-http.ts` is a local/reference 402 challenge and signed-retry fixture. Its retry is downstream observation after gateway-created signature evidence. It is not seller middleware, facilitator operation, settlement finality, signer custody, or authority. - - Source mechanism: make the local sandbox evidence boundary explicit in code and projections. The signed retry should carry or project a local/reference evidence role such as post-gate signed retry observation, a local provider-environment posture, and non-settlement finality. `authorityCreated: false` is necessary but not sufficient; product and projection tests must make it impossible to read the sandbox retry as facilitator settlement or provider custody. - -4. Runtime ingress family hardcoding should be refactored after the posture hotfix, not before it. - - `src/runtime/ingress/index.ts` is doing orchestration, schemas, family detection, graph-node classification, config selection, compile-input construction, signing-secret selection, and grammar-version selection for package install, x402 payment, and auth.md protected API calls. That increases cross-family drift risk, but the nearest defect is the x402 field drop. - - Source mechanism after the hotfix: introduce a runtime family adapter registry under `src/runtime/ingress/` that owns per-family conversion while the main ingress file owns only block orchestration. The adapter shape should be boring and narrow: - - ```text - familyId - dispatchKinds - requireConfig(config) - buildCompileIntentInput(...) - dispatchSpecificRefusalReasonCodes(...) - signingSecretForDispatch(...) - supportedGrammarVersion - ``` - - Keep the registry inside `src/runtime`; do not move family proposal semantics into `src/protocol`, and do not let runtime issue policy, greenlights, gateway checks, receipts, or mutations. - -5. Spend-window metadata must either stay metadata or become a real reservation ledger. - - `X402SpendBoundsSchema` has session/day/review fields, but the only enforced x402 bound is `maxAtomicAmountPerCall`. This must not be patched with a runtime-side sum or demo assertion. Aggregate spend enforcement would require a real source-owned reservation ledger with tenant/org/principal/agent/action/resource/window keys, reservation states, conflict semantics, recovery evidence, D1/memory implementations, and gateway/policy re-checks. - - For this concern-elimination plan, keep aggregate spend out of the first slice unless a full ledger phase is explicitly chosen. Strengthen the current boundary with source tests that keep `spendWindowEnforcementStatus: "not_enforced_local_metadata"` visible in install proposals, runtime/demo outputs, claim gates, and product reports. - -6. Signer custody and provider custody must remain separated. - - `src/adapters/x402-payment/wallet-gateway.ts` proves the official SDK signer is invoked only after `VerifiedGatewayCheck`, and install/conformance code can require gateway-held or fixture-gateway-held signer posture. That is still local/reference custody, not provider/customer custody or vault lifecycle proof. - - Source mechanism: keep custody status on install/conformance records, forbid raw signer, `PaymentPayload`, and `PAYMENT-SIGNATURE` through CLI/MCP/runtime projections, and require future provider custody to enter through `GatewayCredentialRef` and post-gate `CredentialResolutionEvidence`, not through x402 demo code. - -7. Host and bypass posture is evidence, not broad interception. - - Runtime ingress can refuse observed raw sibling dispatches and MCP can avoid direct payment authority. That does not prove broad browser, shell, package-manager, cloud, repo, or host interception. Do not promote synthetic bypass evidence into host-wide protection. - - Source mechanism: keep bypass posture in conformance and runtime graph evidence; add host-specific probe phases only when there is a concrete host harness. Until then, runtime/MCP outputs must keep saying proposal/evidence only. - -8. Evidence projection scale is a store-port boundary. - - `assembleAgentTransactionEnvelope()` currently scans many object types by tenant/org and filters in memory for one contract. That is acceptable for local foundation, but not for hosted audit/search claims. - - Source mechanism: add contract/action/run-scoped read methods to `ProtocolStore` and implement them in memory and D1 before any hosted evidence-scale claim. Candidate reads include policy decision by contract, latest greenlight by contract, gateway checks by contract, mutation attempts by contract, receipt by action contract, proof gaps by affected contract, refusals by contract, reconciliations by contract, credential-resolution evidence by contract, authority certificates by terminal contract, and recovery records by source contract. D1 needs compatible indexes or side tables; do not solve this in HTTP handlers. - -9. Redaction must move toward typed allowlists for live providers. - - `redactedProjectionRefs()` currently denies many credential-shaped strings by pattern. That is useful but not enough for unknown provider credential formats. Before hosted/provider claims, projection code needs typed evidence-ref allowlists per provider/action family or deny-by-default handling for credential namespaces. Continue to expose opaque refs and digests, not raw material. - -10. Package and planning drift are architecture gates. - - `package.json`, `scripts/check-package-surface.mjs`, and `scripts/check-published-entrypoints.mjs` already make package shape source-owned. Keep `.planning/` excluded from package files and keep `.planning` labels out of source paths, scripts, exports, CI names, and canonical docs. If scratch planning maps stay tracked, add guard tests around what can be promoted to canon rather than treating `.planning/codebase/*` as authority. - -## Boundaries that must not move - -- `src/protocol/areas/*` owns Tier 1 primitive meaning. Do not move x402 request posture, MCP schema convenience, sandbox labels, or runtime family dispatch into protocol primitives unless a real new protocol primitive is being introduced. -- `src/runtime/` may record runtime execution, generated graph evidence, tool-call drafts, intent compilations, action contracts, and refusals. It must not issue policy decisions, greenlights, gateway checks, receipts, authority certificates, or mutation attempts. -- `src/mcp/` may expose proposal/evidence transport only. It must not import adapters, wallet/signing code, storage, protocol kernel internals, gateway transitions, all-role SDK clients, or credential custody surfaces. -- `src/adapters/x402-payment/` owns local/reference x402 upstream evidence, install proposal, conformance, sandbox, and wallet gateway fixtures. It does not define protocol semantics and must not claim live provider custody, seller middleware, facilitator operation, settlement finality, or aggregate spend enforcement. -- `src/protocol/evidence-projections/` owns redacted diagnostic projections. HTTP, SDK, CLI, and MCP may route projections but must not become raw reconstruction or authority surfaces. -- `src/storage/*` owns persistence mechanics. KV remains cache posture only. D1/memory must preserve the same protocol-store contract. -- Canon remains `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, and `docs/internal/*`. `.planning/` is scratch. - -## Files/modules likely touched - -Nearest source fixes: - -- `src/runtime/ingress/index.ts`: forward x402 posture fields; add or prepare family adapter extraction. -- `test/runtime/runtime-ingress.test.ts`: x402 posture propagation/refusal tests; no-authority record-count assertions. -- `src/mcp/x402-proposal.ts`: add request-body and provider-environment posture fields, pre-contract refusal, parameter forwarding, idempotency binding. -- `test/mcp/mcp-schema-contract.test.ts`: schema fixture and catalog metadata update. -- `test/mcp/mcp-x402-proposal.test.ts`: live/unknown/external/omitted/unsupported posture refusal and idempotency/parity tests. -- `scripts/check-published-entrypoints.mjs`: reference MCP proposal input must include new posture fields if schema requires them. - -Sandbox/evidence boundary: - -- `src/adapters/x402-payment/sandbox-http.ts`: explicit local/reference evidence role and retry boundary. -- `src/adapters/x402-payment/wallet-gateway.ts`: ensure retry/sandbox evidence remains post-gate and non-settlement in returned evidence refs. -- `src/protocol/evidence-projections/projections.ts`: classify signed retry as local/reference evidence and settlement-finality-negative. -- `src/adapters/x402-payment/conformance.ts`: classify any new x402 evidence label without authority or settlement finality. -- `test/adapters/x402-wallet-gateway.test.ts`, `test/protocol/evidence-projections.test.ts`, `test/conformance/x402-payment-conformance.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`: boundary assertions. - -Runtime family boundary: - -- `src/runtime/ingress/index.ts` -- possible new files under `src/runtime/ingress/`, for example `registry.ts`, `families/x402-payment.ts`, `families/package-install.ts`, and `families/auth-md-protected-api-call.ts` -- `test/runtime/runtime-ingress.test.ts` -- `test/runtime/auth-md-candidate-compilation.test.ts` -- `test/architecture/import-posture.test.ts` and `test/architecture/naming-posture.test.ts` if folder shape changes - -Spend/custody/bypass claim guards: - -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/conformance.ts` -- `src/adapters/x402-payment/bypass-probes.ts` -- `examples/x402-protected-spend/run.ts` -- `examples/x402-protected-spend/README.md` -- `test/adapters/x402-install-proposal.test.ts` -- `test/adapters/x402-bypass-probes.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/self-hosted-activation-claim-boundary.test.ts` - -Projection scale/redaction if included in the executable plan: - -- `src/protocol/store/port.ts` -- `src/storage/d1/index.ts` -- `src/storage/memory/index.ts` -- `migrations/0001_protocol_kernel.sql` -- `src/protocol/evidence-projections/assembly.ts` -- `src/protocol/evidence-projections/projections.ts` -- `test/protocol/evidence-projections.test.ts` -- `test/protocol/protocol-store-atomicity-contract.test.ts` -- `test/http/d1-http.test.ts` - -Package/planning gates: - -- `package.json` -- `scripts/check-package-surface.mjs` -- `scripts/check-published-entrypoints.mjs` -- `test/architecture/package-surface.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/active-vocabulary.test.ts` - -## Compatibility/migration risks - -- MCP schema changes can break existing callers and packaged smoke fixtures. Prefer a metadata digest/catalog version bump and a backwards-compatible normalization path only when omission truly means legacy `no_body` plus `local_reference_sandbox`; explicit `omitted`, `unsupported`, `external_sandbox`, `live`, or `unknown` must refuse before contract proposal. -- Adding posture fields to idempotency material changes deterministic IDs for new proposals. Do not rewrite old receipts or claim historical equivalence. If needed, version the idempotency material label while keeping prior evidence reconstructable. -- Runtime family extraction can silently change graph-node classification, sequence dependencies, raw sibling refusal, or signing-secret selection. It should happen after the direct posture fix and be guarded by current runtime/auth-md/package-install tests. -- D1 scoped-read migration must be additive. Existing records remain in `protocol_records`; new indexes or side tables must not change canonical record digests. -- Projection redaction tightening can hide refs that current product tests expect. Update tests around roles, not raw strings: credential material stays hidden; opaque refs and digests stay visible where they are safe. -- `dist/` artifacts will drift until `npm run build` or `npm run pack:check` runs. Do not treat checked-in bundles as current proof after source changes. -- Dirty worktree files named in the input packet are current state, not something to revert. The plan must validate them or build on them. - -## Architecture validation gates - -Focused posture gates: - -```bash -npm run test -- test/adapters/x402-payment-action-proposal.test.ts test/runtime/runtime-ingress.test.ts -npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts -``` - -Sandbox and x402 boundary gates: - -```bash -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/product/x402-protected-spend-demo-report.test.ts -npm run demo:aps -``` - -Runtime family/refactor gates: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts test/protocol/generated-execution-graph.test.ts -npm run quality:architecture -``` - -Projection/storage gates if store-port work is included: - -```bash -npm run test -- test/protocol/evidence-projections.test.ts test/protocol/protocol-store-atomicity-contract.test.ts test/http/d1-http.test.ts -npm run quality:storage -``` - -Claim, package, and repo gates: - -```bash -npm run quality:claims -npm run pack:check -npm run check:repo -``` - -Required assertions inside the focused tests: - -- Runtime and MCP refused posture cases create no `policy_decision`, `greenlight`, `gateway_check_attempt`, `mutation_attempt`, `receipt`, or `authority_certificate` records. -- Runtime and MCP accepted local/reference cases bind `intendedRequestBodyPosture`, `intendedRequestBodyDigest`, `providerEnvironmentPosture`, `providerEnvironmentRef`, and selected headers into candidate parameters and params/idempotency material. -- Sandbox signed retry evidence is projected as local/reference downstream observation, not settlement finality, facilitator operation, seller middleware, provider custody, or authority. -- Spend session/day/review fields remain `not_enforced_local_metadata` unless a real reservation ledger is implemented. -- MCP and CLI package entrypoints still emit non-authority flags and leak neither `PaymentPayload` nor `PAYMENT-SIGNATURE`. - -## Blocked checks - -- Not run in this ARCH pass: all tests, demos, package checks, and `check:repo`. This role is assigned a planning output only and file edits outside this raw output are forbidden. -- Not inspected by instruction: sibling raw outputs, normalized outputs, and `.planning/macro/PLAN.md`. -- Live provider/customer custody validation is blocked by absent provider/vault gateway integration and must remain a future cut, not a current x402 claim. -- Broad host/browser/shell/package-manager/cloud/repo interception validation is blocked by absent host-specific harnesses and must remain a future cut. -- Actual npm publication and MCP Registry publication are blocked by external owner credentials; `pack:check` can prove package shape only. - -## Smallest next mechanism to build - -Forward x402 request-body and provider-environment posture through `x402PaymentAttemptForDispatch()`, bind it into x402 candidate/idempotency material, and add runtime refusal tests proving live/unknown/external/unsupported posture cannot produce an `ActionContract`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/EXECUTION.md deleted file mode 100644 index 1a1529a..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/EXECUTION.md +++ /dev/null @@ -1,211 +0,0 @@ -# EXECUTION Perspective - -## Phase Sequence - -Invariant at stake: exact x402 request/body/provider posture must survive runtime and MCP proposal surfaces without creating authority, and local evidence must not be confused with provider enforcement. - -1. **Runtime x402 posture propagation and recorded refusal** - - Source changes: - - `src/runtime/ingress/index.ts`: forward `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef` from `RuntimeIngressObservedDispatchSchema` into the x402 attempt. - - `src/adapters/x402-payment/action-proposal.ts`: expose a non-authority runtime refusal builder or split compile-input construction so runtime ingress can record a graph/tool-call/intent refusal instead of throwing when x402 posture is unsupported. - - `src/adapters/x402-payment/action-proposal.ts`: include body posture and provider-environment posture/ref in x402 idempotency material so the contract key is bound to the same semantics as the params digest. - - Tests: - - `test/runtime/runtime-ingress.test.ts`: add unsupported body/live provider dispatch cases that produce `one_or_more_dispatches_refused`, include `x402_request_body_posture_unsupported` and `x402_provider_environment_not_sandboxed`, create no action contract, and create no policy/greenlight/gateway/mutation/receipt records. - - `test/runtime/runtime-ingress.test.ts`: add supported digest-bound/local-reference case proving the resulting contract parameters preserve body posture, body digest, provider posture, and provider ref. - - `test/adapters/x402-payment-action-proposal.test.ts`: assert x402 idempotency changes when posture/ref changes where the attempt is contractable. - -2. **MCP x402 posture parity** - - Source changes: - - `src/mcp/x402-proposal.ts`: require explicit `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and nullable `providerEnvironmentRef` in `McpX402PaymentProposalInputSchema`. - - `src/mcp/x402-proposal.ts`: preflight MCP proposals through the same x402 refusal semantics as the direct adapter path before any runtime-client call. - - `src/mcp/x402-proposal.ts`: bind the posture fields into `x402Parameters()`, `deriveMcpX402IdempotencyKey()`, tool-call draft parameters, compile-intent candidate parameters, and any execution-block digest material. - - `scripts/check-published-entrypoints.mjs`: update the reference MCP proposal input so package smoke tests exercise the explicit posture schema. - - Tests: - - `test/mcp/mcp-schema-contract.test.ts`: require the new posture fields in `validProposalInput()` and reject omitted posture as invalid input. - - `test/mcp/mcp-x402-proposal.test.ts`: prove `unsupported`, `omitted`, `live`, `unknown`, and `external_sandbox` postures refuse before runtime calls, with non-authority structured outcomes. - - `test/mcp/mcp-x402-proposal.test.ts`: prove supported local/digest-bound posture reaches `compileIntent` with matching parameters and a posture-bound idempotency key. - - `test/mcp/mcp-stdio-process.test.ts` and package smoke path: keep stdio proposal/evidence only. - -3. **x402 local sandbox evidence boundary** - - Source changes: - - `src/adapters/x402-payment/sandbox-http.ts`: add an explicit local/reference evidence-boundary object to challenge and signed-retry outputs: local fixture scope, `authorityCreated: false`, `sellerMiddlewareOperated: false`, `facilitatorSettlementPerformed: false`, and `settlementFinality: "not_settlement_finality"`. - - `src/adapters/x402-payment/sandbox-http.ts`: keep signed retry recording gated on gateway-created signature evidence, local-reference provider posture, and non-ambiguous body posture. - - `src/protocol/evidence-projections/projections.ts`: keep signed retry labels as downstream fixture evidence and forbid facilitator settlement/finality labels for local sandbox refs. - - Tests: - - `test/adapters/x402-wallet-gateway.test.ts`: assert sandbox challenge and signed retry carry the evidence-boundary object and never carry settlement, middleware, or authority fields. - - `test/adapters/x402-wallet-gateway.test.ts`: add refusal cases for missing signature evidence, wrong signature header, non-reference provider posture, and ambiguous body posture with unchanged signed-retry count. - - `test/protocol/evidence-projections.test.ts`: prove `evidence:x402-local-sandbox-signed-retry:*` projects as downstream local fixture evidence, not facilitator settlement or finality. - - `test/product/x402-protected-spend-demo-report.test.ts`: pin buyer-readable report language to local/reference signed retry evidence only. - -4. **Runtime ingress family adapter registry** - - Source changes: - - `src/runtime/ingress/index.ts`: extract family-specific conversion behind a source-owned runtime ingress family registry while preserving the public `proposeRuntimeIngressActionContracts()` API. - - Candidate registry shape: `family`, `dispatchKind` coverage, `requiresConfig`, `buildCompileIntentInput`, `preflightRefusalReasonCodes`, `signingSecret`, `supportedGrammarVersion`, and `rawBypassReasonCodes`. - - Keep runtime ingress proposal-only: registry adapters must not import policy, greenlight, gateway, receipt, storage implementation, or mutation code. - - Tests: - - `test/runtime/runtime-ingress.test.ts`: existing package/x402/auth.md cases must pass through the registry unchanged. - - Add a registry coverage test under `test/runtime/` proving every dispatch kind has exactly one family adapter, missing family config fails closed, and mixed-family blocks retain `runtime-dispatch-mixed-0.1`. - - `test/architecture/import-posture.test.ts`: guard the registry against forbidden authority imports. - -5. **x402 future-surface, spend, custody, and host-bypass guards** - - Source changes: - - `src/adapters/x402-payment/conformance.ts`: keep unsupported x402 surfaces as source-owned cut lines and add explicit future-cut classifications for aggregate spend ledger, provider/customer custody, host-wide interception, facilitator/seller middleware, hosted verifier, and registry publication where they are not already represented. - - `src/adapters/x402-payment/install-proposal.ts`: keep session/day/review controls under `spendWindowEnforcementStatus: "not_enforced_local_metadata"` and prevent them from entering action-contract bounds until a reservation ledger exists. - - `src/adapters/x402-payment/bypass-probes.ts`: keep fixture gateway custody distinct from real gateway custody; host-bypass probes remain scoped evidence, not host-wide interception. - - Tests: - - `test/conformance/x402-payment-conformance.test.ts`: pin every unsupported/future surface to a refusal/cut-line reason code. - - `test/adapters/x402-install-proposal.test.ts`: assert spend-window metadata never appears in contract bounds and cannot be claimed as enforced. - - `test/adapters/x402-bypass-probes.test.ts`: distinguish fixture custody from live provider/customer custody and host-scoped bypass evidence from broad host interception. - - `test/architecture/claim-boundary.test.ts`: keep README/MCP/runtime/doc claims inside exact buyer-side local/reference proof. - -6. **Evidence projection scale and redaction mechanisms** - - Source changes: - - `src/protocol/store/port.ts`: add contract-scoped evidence lookup methods and batched stream-event range reads. - - `src/storage/d1/index.ts` and `migrations/0001_protocol_kernel.sql`: add the D1 indexes/tables needed for contract/action/run scoped projection assembly and receipt timeline range reads. - - `src/protocol/evidence-projections/assembly.ts`: replace broad tenant/org scans with contract-scoped store methods. - - `src/protocol/evidence-projections/projections.ts`: replace regex-only credential hiding with an allowlisted projection-ref policy plus deny patterns for known credential classes. - - Tests: - - `test/protocol/evidence-projections.test.ts`: add provider-format redaction fuzz cases for token, bearer, vault, infisical, raw signature, payment payload, facilitator secret, and auth.md credential refs. - - `test/http/d1-http.test.ts`: add D1 fixtures proving projection assembly uses scoped indexes and timeline range reads under high unrelated record volume. - - `test/protocol/protocol-store-atomicity-contract.test.ts`: pin memory/D1 parity for new store methods and conflict behavior. - -7. **Publish/package and `.planning` scratch drift gates** - - Source changes: - - `scripts/check-package-surface.mjs`: keep `.planning`, tests, local metadata, and generated scratch out of publish dry-run artifacts. - - `scripts/check-published-entrypoints.mjs`: keep CLI/MCP smoke outputs non-authority and synchronized with the new MCP posture schema. - - Architecture tests: add an active guard that `.planning` paths cannot appear in package exports, package files, package scripts, CI names, README command sections, or canonical docs except as scratch-boundary language. - - Tests: - - `test/architecture/package-surface.test.ts`: pin packable files and `check:repo` -> `pack:check`. - - `test/architecture/active-vocabulary.test.ts` and `test/architecture/claim-boundary.test.ts`: reject source/package/README claims that promote `.planning` maps to canon. - - `npm run pack:check`: mandatory before any publish-ready or registry-ready claim. - -## Task Graph - -```text -T1 runtime-failing-tests - -> T2 runtime-x402-preflight-refusal-builder - -> T3 runtime-forward-posture-fields - -> T4 runtime-idempotency-posture-binding - -> T5 runtime-focused-gate - -T6 mcp-schema-failing-tests - depends on T2 - -> T7 mcp-explicit-posture-schema - -> T8 mcp-preflight-refusal-and-binding - -> T9 mcp-stdio-and-package-smoke-update - -T10 sandbox-boundary-tests - -> T11 sandbox-boundary-source-object - -> T12 projection-signed-retry-label-guard - -> T13 product-demo-boundary-gate - -T14 runtime-registry-tests - depends on T5 - -> T15 runtime-family-registry-refactor - -> T16 runtime-registry-architecture-gate - -T17 x402-cutline-tests - -> T18 conformance-future-surface-cutlines - -> T19 spend-metadata-and-custody-guards - -T20 projection-scale-redaction-tests - -> T21 store-port-scoped-methods - -> T22 d1-index-and-range-read-implementation - -> T23 projection-assembly-refactor - -> T24 redaction-policy-hardening - -T25 package-planning-drift-tests - depends on T7 - -> T26 package-smoke-and-planning-guard-updates -``` - -## Dependency Map - -- Phase 1 blocks Phase 2 because MCP parity should reuse the same x402 posture refusal semantics rather than inventing a second refusal table. -- Phase 1 blocks Phase 4 because extracting the runtime registry before fixing x402 posture can preserve the bug behind cleaner structure. -- Phase 2 blocks package smoke updates because `scripts/check-published-entrypoints.mjs` must use the final MCP schema. -- Phase 3 can run after Phase 1 starts; it shares x402 posture vocabulary but does not depend on the MCP bridge. -- Phase 5 can run in parallel with Phase 3 once the direct/runtime posture semantics are stable. -- Phase 6 is independent of runtime/MCP behavior except for evidence labels; start after Phase 3 if signed-retry projection labels change. -- Phase 7 depends on Phase 2 for MCP smoke inputs and should close last so package gates reflect the final public surface. - -## Critical Path - -```text -T1 -> T2 -> T3 -> T4 -> T5 -> T6 -> T7 -> T8 -> T9 -> T25 -> T26 -> full validation -``` - -This is the critical path because runtime posture propagation is the known high-priority defect, MCP parity must not fork the semantics, and package/public smoke gates must reflect the final MCP input contract. - -## Parallelizable Work - -- Sandbox boundary work (`T10`-`T13`) can proceed while MCP parity is implemented, as long as it keeps the same posture enum values. -- x402 cut-line/conformance work (`T17`-`T19`) can proceed after the direct adapter refusal table is settled. -- Evidence projection scale/redaction work (`T20`-`T24`) can proceed independently, with one coordination point on signed-retry evidence labels from Phase 3. -- Package/planning drift tests (`T25`) can be drafted early, but the package smoke implementation (`T26`) must wait for MCP schema finalization. - -## First Executable Step - -Add a failing regression test to `test/runtime/runtime-ingress.test.ts`: - -- Create a `wrapped_x402_payment` dispatch with `intendedRequestBodyPosture: "unsupported"`, `providerEnvironmentPosture: "live"`, and `providerEnvironmentRef: "provider-environment:x402-live"`. -- Expect `proposeRuntimeIngressActionContracts()` to return `one_or_more_dispatches_refused`. -- Expect response and proposal reason codes to include `x402_request_body_posture_unsupported` and `x402_provider_environment_not_sandboxed`. -- Expect zero `action_contract`, `policy_decision`, `greenlight`, `gateway_check_attempt`, `mutation_attempt`, and `receipt` records. -- Expect runtime and generated graph evidence to be recorded, with the x402 dispatch node classified non-contractable instead of throwing. - -Only after that test fails for the right reason, patch `src/runtime/ingress/index.ts` and `src/adapters/x402-payment/action-proposal.ts`. - -## Validation Gates - -Focused gates after Phase 1: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts -npm run check:types -``` - -Focused gates after Phase 2: - -```bash -npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/mcp/mcp-reference-transcript.test.ts test/mcp/mcp-stdio-process.test.ts -npm run check:types -``` - -Focused gates after Phase 3 and Phase 5: - -```bash -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/product/x402-protected-spend-demo-report.test.ts -npm run quality:claims -``` - -Focused gates after Phase 4: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts -npm run quality:architecture -``` - -Focused gates after Phase 6: - -```bash -npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts -npm run quality:storage -``` - -Final gates: - -```bash -npm run demo:aps -npm run quality:claims -npm run quality:architecture -npm run pack:check -npm run check:repo -``` - -## Blocked Checks - -- No user-owned product decision blocks execution; the current concern packet already cuts ledger, live custody, host-wide interception, hosted verifier, facilitator/seller middleware, and registry publication from this macro plan. -- External publication checks remain blocked on owner-held npm/MCP Registry credentials, so validation must stop at `npm run pack:check` and source-owned package smoke tests. -- Live provider/customer custody tests remain blocked until a real provider/vault custody integration is introduced; current work can only add fixture-vs-live cut-line tests. -- Broad host interception checks remain blocked until a specific host adapter/browser/shell/package-manager/cloud integration is in scope; current work can only preserve runtime/MCP bypass evidence as scoped, non-host-wide evidence. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/RISK.md deleted file mode 100644 index ef394b7..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/RISK.md +++ /dev/null @@ -1,75 +0,0 @@ -# RISK Perspective: Concerns Elimination - -## Invariant At Stake - -No consequential autonomous action executes outside declared bounds, and divergent behavior must be haltable, isolatable, and reconstructable. - -The current danger is false closure: runtime/MCP proposal surfaces can look aligned with the x402 adapter while dropping refusal-critical posture, sandbox evidence can be mistaken for seller/facilitator authority, and package/docs gates can make publish or hosted claims before source mechanisms exist. - -## P0 Risk Register - -| ID | Risk | Failure mode | Mitigation or cut line | Required validation gate | -| --- | --- | --- | --- | --- | -| P0-R1 | Runtime x402 posture defaulting creates weaker contracts than the direct adapter. | `RuntimeIngressObservedDispatchSchema` accepts `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`, but `x402PaymentAttemptForDispatch()` currently omits them. Unsupported body posture or live/unknown provider posture can default to `no_body` and `local_reference_sandbox` before proposal. | Propagate the three fields into `X402PaymentAttempt`; add a shared x402 posture fixture/helper so runtime tests and adapter tests assert the same refusal codes. Cut line: runtime ingress cannot be described as an official x402 proposal path until unsupported/live/unknown dispatches refuse before contract proposal. | `npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts`; assertions: no `intent_compilation`, `action_contract`, `greenlight`, or `gateway_check_attempt` on unsupported/live posture. | -| P0-R2 | MCP x402 proposal schema cannot express the same request/provider refusal boundary. | `McpX402PaymentProposalInputSchema`, `x402Parameters()`, and `deriveMcpX402IdempotencyKey()` omit request-body posture and provider-environment posture. A model-facing MCP proposal can produce a weaker candidate than the adapter would accept. | Add `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef` to the strict MCP schema; forward them into candidate parameters, tool-call drafts, non-secret summaries, and idempotency digest material; preflight refuse omitted/unsupported/live/unknown before runtime calls. Cut line: MCP stays proposal/evidence only and cannot be called "parity" until these fields are contract-bound. | `npm run test -- test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts`; pack smoke must update its reference proposal input. | -| P0-R3 | Local sandbox signed retry evidence is confused with seller middleware, facilitator settlement, or authority. | `createLocalX402PaidHttpSandbox()` emits official-shaped 402 challenge evidence and signed retry observation. Even with `authorityCreated: false`, product/demo text can launder it into payment finality or facilitator operation. | Keep sandbox evidence under explicit local/reference types and refs; keep `authorityCreated: false` on challenge and retry; classify signed retry as downstream fixture observation after `VerifiedGatewayCheck`, not policy, greenlight, gateway check, settlement, or signing authority. Cut line: no seller middleware, facilitator operation, settlement finality, or live paid HTTP claim without separate adapter and tests. | `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts`. | -| P0-R4 | Signer custody leaks into runtime/MCP/CLI or becomes a live provider custody claim. | `createOfficialExactX402SigningSurface()` uses an injected `ClientEvmSigner`; this proves gateway-side fixture/local signing after a passed gate, not provider vault lifecycle, customer custody, rotation, or revocation. | Keep signer factory out of adapter barrels and public root/runtime/MCP/CLI exports; enforce gateway-held or fixture-gateway-held signer posture in install/conformance; redact `PaymentPayload`, `PAYMENT-SIGNATURE`, raw private keys, and signer refs in projections and demos. Cut line: no live/provider/customer custody claim without provider-specific custody resolver, rotation/revocation tests, and gateway failure tests. | `npm run test -- test/architecture/import-posture.test.ts test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts test/protocol/evidence-projections.test.ts`. | -| P0-R5 | Runtime/MCP bypass evidence is overclaimed as host-wide interception. | Runtime ingress records observed/synthetic bypass-shaped evidence, and MCP rejects authority-shaped inputs. Neither proves browser, shell, package manager, cloud, network, repo, or sibling MCP interception in a real host. | Keep bypass posture as observed evidence only. Require host-specific bypass probes and installed gateway-owned credentials before claiming protection for any host. Cut line: broad MCP/runtime/browser/shell/network/package protection remains future work. | `npm run quality:claims`; `npm run test -- test/runtime/runtime-ingress.test.ts test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts`. | - -## P1 Risk Register - -| ID | Risk | Failure mode | Mitigation or cut line | Required validation gate | -| --- | --- | --- | --- | --- | -| P1-R1 | Runtime ingress family hardcoding causes cross-family refusal drift. | `src/runtime/ingress/index.ts` owns multiple family schemas, conversion functions, graph nodes, and dispatch classifiers. New families can miss refusal fields or inherit x402 defaults. | Introduce a source-owned family adapter/registry interface for dispatch schema, attempt conversion, graph node metadata, refusal preflight, and signing-secret lookup. Migrate one family at a time with no public claim expansion. Cut line: no new protected-action family through the monolithic switch after the registry exists. | `npm run test -- test/runtime/runtime-ingress.test.ts test/runtime/auth-md-candidate-compilation.test.ts test/runtime/package-install-runtime.test.ts`; `npm run quality:architecture`. | -| P1-R2 | Spend windows are metadata but get read as aggregate enforcement. | `X402SpendBoundsSchema` carries session/day/review fields with `spendWindowEnforcementStatus: "not_enforced_local_metadata"`; changed-amount retries can create separate per-call contracts. | Either implement a reservation ledger keyed by tenant/org/principal/agent/action/resource/window with conflict semantics and recovery evidence, or keep all aggregate spend copy/tests as non-claims. Cut line: no session/day/review enforcement claim until the ledger is source-owned and D1-backed. | Current cut-line gate: `npm run test -- test/runtime/runtime-ingress.test.ts test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts`. Future ledger gate must add D1 atomicity and conflict tests. | -| P1-R3 | Evidence redaction is denylist-shaped and can miss provider credential formats. | `redactedProjectionRefs()` filters raw-looking refs by regex. Unknown vault/provider formats can pass into contract/envelope projections. | Move live-provider projections toward allowlisted typed refs and digests; add provider-format fuzz fixtures for secret refs, payment signatures, bearer tokens, vault paths, and x402 payload terms. Cut line: no hosted audit/search or provider-custody evidence claim while redaction depends only on generic patterns. | `npm run test -- test/protocol/evidence-projections.test.ts test/http/http.test.ts test/integration/auth-md-receipt-reconstruction.test.ts`; add fuzz tests before any live-provider phase closes. | -| P1-R4 | D1/projection assembly does tenant/org scans and per-offset receipt reads. | `assembleAgentTransactionEnvelope()` calls broad `listRecordsByType()` for many object types, and receipt timeline reads load stream events one offset at a time. Hosted evidence reads will degrade or time out under real volume. | Add contract/action/run-scoped store methods, D1 indexes, and batched stream-event range reads. Keep current projections as local diagnostic reads until this lands. Cut line: no hosted audit/search, high-volume evidence, or customer dashboard claim. | `npm run quality:storage`; add scale fixtures around `assembleAgentTransactionEnvelope()` and receipt timeline reads before hosted claims. | -| P1-R5 | Publish/package drift ships stale bundles or stale MCP schema. | Dirty source can change runtime/MCP/x402 behavior while `dist/**`, bin smoke inputs, or package metadata lag behind. | Treat `npm run pack:check` as mandatory for publish readiness; update package entrypoint smoke inputs when MCP schema changes; fail if `.planning/`, tests, or scratch docs enter packed files. Cut line: no npm/MCP Registry/public install claim from source-only changes. | `npm run pack:check`; `node scripts/check-package-surface.mjs`; `node scripts/check-published-entrypoints.mjs`; `npm run check:repo`. | -| P1-R6 | x402 future surfaces sneak into `x402_payment.exact`. | `upto`, batch settlement, signed offers/receipts, lifecycle hooks, seller middleware, facilitator operation, and MCP auto-pay can be mistaken as extensions of the first wedge. | Keep `classifyX402FirstWedgeSurface()` as the source-owned cut line; add hostile/future upstream fixtures for unknown extensions, multiple accepts, non-exact schemes, malformed assets, and facilitator-shaped labels. Cut line: create new action classes only after policy/gateway/receipt support exists. | `npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/architecture/claim-boundary.test.ts`. | - -## P2 Risk Register - -| ID | Risk | Failure mode | Mitigation or cut line | Required validation gate | -| --- | --- | --- | --- | --- | -| P2-R1 | `.planning` scratch drift becomes repo canon. | Derived maps and macro outputs can be treated as source truth by future agents, reviving stale Tier 2 labels or overbroad claims. | Add/keep source-owned docs stating `.planning/` is scratch; ensure package surface excludes `.planning/`; do not create scripts, exports, CI names, or README sections from planning labels. Cut line: promote only source-backed decisions into `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, or `docs/internal/*`. | `npm run quality:claims`; `npm run pack:check`; add an architecture guard if README/package/scripts begin referencing `.planning` as canon. | -| P2-R2 | False completion through doc-only concern closure. | A plan can mark concerns closed after copy edits while source still defaults, overclaims, or leaks evidence. | Closure rule: every concern needs one source mechanism, one focused regression test, and one architecture/claim/package gate. Documentation can only follow source behavior. Cut line: if a concern has no source diff or test diff, it remains open. | Closeout must include focused tests plus `npm run quality:claims`, `npm run quality:architecture`, `npm run pack:check`, and `npm run check:repo`. | -| P2-R3 | Demo output normalizes non-authority proof-object language. | Buyer-readable `x402_paid_http_call.exact` can be mistaken as an action catalog entry, and report output can imply hosted/live provider behavior. | Keep buyer-readable names explicitly non-authority and backed by actual `x402_payment.exact` action-contract fields; product tests must assert local/reference labels, gateway holder, non-claims, and absent raw signer terms. Cut line: no new proof-object label until action catalog, compiler, policy, and gateway expose a matching action class. | `npm run demo:aps`; `npm run test -- test/product/x402-protected-spend-demo-report.test.ts test/architecture/claim-boundary.test.ts`. | -| P2-R4 | Gateway failure evidence remains too coarse for operations. | `runX402WalletGateway()` collapses signing failures to digest-only diagnostics, hiding selected-requirement drift versus SDK/signer/provider failure. | Add redacted failure reason codes without exposing signer material, `PaymentPayload`, or `PAYMENT-SIGNATURE`. Cut line: coarse failure classification is acceptable for local foundation, but not for hosted operations/support claims. | `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/protocol/evidence-projections.test.ts`. | - -## Validation Gates - -Minimum implementation gate for this concerns-elimination plan: - -1. Focused P0 regression gate: - `npm run test -- test/runtime/runtime-ingress.test.ts test/mcp/mcp-schema-contract.test.ts test/mcp/mcp-x402-proposal.test.ts test/adapters/x402-payment-action-proposal.test.ts test/adapters/x402-wallet-gateway.test.ts` -2. x402 future-surface and bypass gate: - `npm run test -- test/conformance/x402-payment-conformance.test.ts test/conformance/x402-upstream-exact-fixtures.test.ts test/adapters/x402-bypass-probes.test.ts` -3. Evidence/redaction/storage gate: - `npm run quality:storage` -4. Claim and architecture gate: - `npm run quality:claims && npm run quality:architecture` -5. Publish drift gate: - `npm run pack:check` -6. Final closeout gate: - `npm run check:repo` - -No concern is closed unless the focused gate and the final closeout gate both pass on the dirty worktree state being shipped. - -## Rollback And Stop Conditions - -- Stop if runtime or MCP unsupported/live/unknown posture still reaches `action_contract_proposed`. -- Stop if any runtime or MCP test creates `policy_decision`, `greenlight`, `gateway_check_attempt`, `mutation_attempt`, `receipt`, or `authority_certificate`. -- Stop if sandbox evidence introduces `authorityCreated: true`, settlement finality, seller middleware, facilitator operation, or live provider language. -- Stop if signer, `PaymentPayload`, raw private key, `PAYMENT-SIGNATURE`, bearer token, vault path, or provider secret material appears in MCP/CLI/demo/projection serialized output. -- Stop if aggregate spend/session/day/review language appears without a D1-backed reservation ledger. -- Stop if D1/projection changes rely on broader tenant/org scans for a hosted claim. -- Stop if package entrypoint smoke does not exercise the final MCP schema after posture fields are added. -- Stop if `.planning/` becomes a package file, public docs authority source, script name, CI name, exported symbol, or README claim source. -- Roll back claim text, not source guardrails, when source mechanisms pass but product copy overstates the installed boundary. -- Roll back implementation if it weakens Tier 1 protocol/kernel invariants or moves authority into runtime, MCP, CLI, demos, or review output. - -## Blocked Checks - -- No validation commands were run in this raw risk pass; this file is a planning artifact only. -- Sibling raw outputs, normalized outputs, and `.planning/macro/PLAN.md` were intentionally not read, so cross-perspective conflicts are unchecked here. -- Live provider custody, hosted verifier, npm publication, MCP Registry publication, facilitator/seller middleware, aggregate spend ledger, and host-wide interception cannot be validated from current source because those mechanisms are not implemented. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/STRATEGY.md deleted file mode 100644 index 3161ca4..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/raw/STRATEGY.md +++ /dev/null @@ -1,112 +0,0 @@ -# STRATEGY - -## Invariant At Stake - -Runtime and MCP proposal surfaces must not make weaker x402 contracts than the direct adapter path, and the local buyer-side `x402_payment.exact` proof must not get broadened into ledger, custody, hosted, facilitator, seller, host-interception, or registry-publication claims. - -## Recommended Macro Shape - -1. Close the proposal correctness defects first. - - Fix runtime x402 posture propagation before any broader cleanup. `src/runtime/ingress/index.ts` already accepts `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`; the builder must pass them into `X402PaymentAttempt` so direct adapter refusals survive runtime ingress. - - Add runtime tests proving unsupported/omitted request-body posture, missing digest for digest-bound bodies, no-body/body-digest mismatch, and live/unknown/external provider posture refuse before action-contract proposal, with zero policy, greenlight, gateway, mutation, receipt, or certificate records. - -2. Bring MCP to parity while keeping it proposal/evidence only. - - Add the same body and provider-environment posture fields to `McpX402PaymentProposalInputSchema`. - - Bind those fields into MCP x402 parameters and idempotency material. - - Refuse live/unknown/unsupported posture before runtime-client calls where possible; otherwise prove the runtime/direct adapter path refuses before contract proposal. - - Preserve `generatedExecutionGraphPosture: "not_exposed_by_role_scoped_runtime_surface"` and all non-authority flags. - -3. Harden the local x402 sandbox evidence boundary. - - Treat `src/adapters/x402-payment/sandbox-http.ts` as local/reference fixture evidence only. - - Keep challenge and signed retry outputs explicitly `authorityCreated: false`. - - Make signed retry evidence impossible to read as seller middleware, facilitator settlement, provider custody, or payment finality. - - Keep official SDK `PaymentPayload` and `PAYMENT-SIGNATURE` creation behind `VerifiedGatewayCheck` in the wallet gateway. - -4. Convert first-wedge cut lines into source-owned guards. - - Keep `x402_payment.exact` as one buyer-side, per-call, local/reference path. - - Unsupported x402 surfaces stay classified through conformance code and tests: `upto`, batch settlement, lifecycle hooks, MCP auto-pay, signed offers, signed receipts, seller middleware, and facilitator operation. - - Keep `x402_paid_http_call.exact` buyer-readable only until the action catalog, compiler, policy, and gateway expose it as a real action class. - - Spend-window session/day/review fields remain metadata. Do not build a partial ledger in this macro. - -5. Only then reduce runtime ingress family hardcoding. - - Introduce a source-owned proposal-family adapter or registry boundary for runtime ingress. - - The registry may normalize dispatch families into candidate proposal inputs; it must not issue policy decisions, greenlights, gateway checks, receipts, mutations, or authority certificates. - - This phase should prevent future family additions from silently dropping refusal-critical fields. - -6. Close evidence, package, and planning drift with gates. - - Evidence projection work should add real redaction and scale mechanisms only where needed: contract-scoped store reads, D1 indexes/range reads, and provider-format redaction fuzzing. Do not claim hosted audit/search from projection cleanup. - - Package drift closes through `pack:check`, package-surface checks, and published-entrypoint smoke tests after source changes. - - `.planning` drift closes through architecture gates that keep `.planning` scratch out of package files, public scripts, canonical docs, exported names, and claim/vocabulary authority. - -## What To Cut - -- Cut aggregate spend ledger implementation from this macro. Keep spend windows unclaimable metadata until a dedicated reservation ledger phase defines tenant/org/principal/agent/action/resource/time-window keys, reservation state, conflicts, recovery, and receipts. -- Cut live provider/customer custody. Local signer proof and fixture gateway custody do not prove provider vault custody, customer wallet custody, rotation, revocation, or resolver failure semantics. -- Cut seller middleware, facilitator operation, settlement finality, signed offers, signed receipts, `upto`, and batch settlement. -- Cut host-wide interception claims for MCP, browser, shell, package manager, cloud API, network, repo, database, and sibling tools. -- Cut hosted verifier, JWKS/revocation, cross-org trust, marketplace, certification, and clearing-house claims. -- Cut npm/MCP Registry publication claims. Source can prove package shape; owner-held registry credentials and real publication are outside this repo. -- Cut any plan step that moves policy, greenlight, gateway check, mutation, signer custody, receipt export, or certificate minting into CLI, MCP, or runtime ingress. - -## User-Owned Decisions - -No user-owned decision is required to start the concern-elimination macro. - -Future decisions that remain deliberately outside this macro: - -- Whether to fund a real aggregate spend reservation ledger. -- Which provider custody target should become the first live custody adapter. -- Which host/runtime deserves real bypass-interception proof first. -- Whether and when to publish to npm or the MCP Registry with owner credentials. - -## Six-Month Regret Scenario - -The bad outcome is a clean-looking x402 demo that quietly taught the market the wrong product: runtime or MCP accepted live/unknown provider posture, defaulted it into local sandbox semantics, and emitted action-contract proposals that the direct adapter would have refused. A pilot then retries multiple changed-amount payments under metadata-only session/day limits, reads local signed retry evidence as settlement, and assumes MCP/runtime protected the host. Six months later the receipt trail is internally consistent but strategically useless because it proves proposal ceremony, not gateway-enforced custody, ledger control, settlement, or host interception. - -The second regret is over-abstracting runtime ingress before fixing dropped fields. A family registry that preserves the same posture loss just makes the bug easier to repeat across auth.md, package install, repo write, and future adapters. - -## Smallest Strategically Valid First Move - -Patch `x402PaymentAttemptForDispatch()` in `src/runtime/ingress/index.ts` to forward: - -- `intendedRequestBodyPosture` -- `intendedRequestBodyDigest` -- `providerEnvironmentPosture` -- `providerEnvironmentRef` - -Then add focused regression tests in `test/runtime/runtime-ingress.test.ts` proving a wrapped x402 dispatch with unsupported request-body posture or live/unknown provider posture refuses before action-contract proposal and creates no authority-bearing records. - -That first move is strategically valid because it closes an actual proposal-boundary defect while preserving the Tier 1 kernel and keeping runtime proposal-only. - -## Validation Gates - -- Runtime posture propagation: - - `npm run test -- test/runtime/runtime-ingress.test.ts test/adapters/x402-payment-action-proposal.test.ts` - - Gate must prove runtime x402 parity with direct adapter refusal semantics. - -- MCP posture parity: - - `npm run test -- test/mcp/mcp-x402-proposal.test.ts test/architecture/mcp-surface-posture.test.ts` - - Gate must prove MCP remains proposal/evidence only and cannot create policy, greenlight, gateway check, mutation, receipt export, signer custody, or authority certificate evidence. - -- x402 sandbox and first-wedge cut lines: - - `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/integration/x402-d1-http.test.ts test/product/x402-protected-spend-demo-report.test.ts` - - `npm run test -- test/conformance/x402-upstream-exact-fixtures.test.ts test/conformance/x402-payment-conformance.test.ts` - - Gate must preserve local/reference labels, `authorityCreated: false`, post-gate signing, unsupported-surface classification, replay refusal, and no settlement/facilitator/seller/custody claims. - -- Evidence projection and storage hardening: - - `npm run test -- test/protocol/evidence-projections.test.ts test/http/d1-http.test.ts test/protocol/protocol-store-atomicity-contract.test.ts` - - Gate must prove redaction and reconstruction behavior without hosted audit/search claims. - -- Claim, architecture, package, and full repo: - - `npm run quality:claims` - - `npm run quality:architecture` - - `npm run demo:aps` - - `npm run pack:check` - - `npm run check:repo` - - Gate must fail on claim broadening, source/package drift, stale package entrypoints, and dirty whitespace. - -## Blocked Checks - -- Did not read sibling raw outputs, normalized outputs, or `.planning/macro/PLAN.md` by instruction. -- Did not run validation commands; this STRATEGY pass is a raw first-pass planning artifact, not an implementation pass. -- Did not inspect files outside the input packet's allowed source set. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/synthesis.md deleted file mode 100644 index d96d18e..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-concerns-elimination/concerns-elimination-20260524T044836Z/synthesis.md +++ /dev/null @@ -1,58 +0,0 @@ -# Chair Synthesis - -## Invariant At Stake - -No x402 proposal surface may create a cleaner contract than the protected path actually observed, and no evidence surface may imply authority, custody, settlement, hosted operation, broad interception, or aggregate spend enforcement that the gateway does not enforce. - -## Synthesis - -The five perspectives converged on the same sequence. The immediate implementation work is not a registry refactor, package cleanup, or docs correction. The first defect is runtime posture loss: the runtime schema accepts `intendedRequestBodyPosture`, `providerEnvironmentPosture`, and `providerEnvironmentRef`, but `x402PaymentAttemptForDispatch()` drops them before the direct adapter boundary. That can turn unsupported or live posture into default local-reference posture. This is compiler overreach by omission. - -The second defect is MCP posture parity. MCP is proposal/evidence only, but its model-facing x402 proposal schema currently cannot express the same body/provider boundary as the direct adapter. MCP must either bind explicit posture into a proposed contract or refuse before proposal. It must not solve parity by importing adapter execution, wallet, signer, storage, policy, gateway, receipt, all-role SDK, or certificate authority code. - -The third defect is evidence interpretation. The local x402 sandbox is useful because it shows a post-gate signed retry can be observed in a local/reference fixture. It is dangerous if the resulting evidence reads like seller middleware, facilitator operation, settlement finality, provider custody, or authority. The fix is a typed local/reference evidence boundary plus projection/demo tests, not friendlier copy. - -Only after those nearest defects are covered should runtime ingress be extracted behind a family registry. The registry is a hardening step to prevent future field loss; if done first, it can preserve the current bug in a cleaner shape. - -The rest of the concern set is not implementation-by-half. Spend ledger, provider/customer custody, hosted verifier, host-wide interception, seller/facilitator operation, settlement, and public registry publication are explicit cuts. This macro should add source-owned guards that keep those surfaces unclaimable, not partial substitutes. - -## Chosen Phase Order - -1. Runtime x402 posture propagation and pre-contract refusal. -2. MCP x402 posture parity while staying proposal/evidence only. -3. Local sandbox evidence boundary. -4. Runtime ingress family registry/refactor hardening. -5. x402 future-surface, spend metadata, custody, and host-bypass guards. -6. Evidence projection scale and redaction mechanisms. -7. Package, `.planning`, demo, and closeout gates. - -## Reconciled Differences - -- Some raw outputs mention no `intent_compilation` record on posture refusal, while others allow a refused compile-intent record. The synthesis requires no action contract or authority-bearing records. If the existing protocol path records a refused intent compilation, it must be explicitly non-authority and reconstructable. -- Some raw outputs suggest backwards-compatible MCP normalization. The synthesis chooses strict explicit posture fields. If compatibility is later required, omitted posture must still fail closed as schema invalid or structured pre-contract refusal. -- Evidence projection scale is included after x402 boundary phases, but it remains a mechanism for local reconstruction and future readiness. It does not authorize hosted audit/search claims. - -## Outputs Written - -- `.planning/macro/PLAN.md` -- `.planning/macro/CONTEXT.md` -- `.planning/macro/ASSUMPTIONS.md` -- `.planning/macro/DECISIONS.md` -- `.planning/macro/RISKS.md` -- `.planning/macro/VALIDATION.md` -- `.planning/macro/TASKS.jsonl` -- `.planning/macro/runs/concerns-elimination-20260524T044836Z/synthesis.md` - -## Blocked Checks - -- No implementation validation commands were run; this chair task writes planning artifacts only. -- Live provider/customer custody remains blocked by absent provider/vault custody mechanism. -- Aggregate spend enforcement remains blocked by absent reservation ledger. -- Hosted verifier/JWKS/revocation/cross-org trust remains blocked by absent hosted verifier mechanism. -- Broad host/browser/shell/package/cloud/repo/MCP interception remains blocked by absent host-specific harnesses. -- Seller middleware, facilitator operation, settlement finality, signed offers, signed receipts, `upto`, and batch settlement remain blocked by absent action classes, policy, gateway, and receipt support. -- Actual npm/MCP Registry publication remains blocked by owner-held external credentials. - -## Smallest Next Mechanism - -Add the failing runtime x402 posture regression in `test/runtime/runtime-ingress.test.ts`, then patch `x402PaymentAttemptForDispatch()` to forward posture fields and update x402 idempotency material. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/AUDIT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/AUDIT.md deleted file mode 100644 index c20ad75..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/AUDIT.md +++ /dev/null @@ -1,111 +0,0 @@ -# Tier 2 Macro Closeout Audit - -Date: 2026-05-24 - -Status: passed for repo-owned source closeout; external owner-held publication -and production-hosted proofs remain explicit proof gaps. - -## Invariant At Stake - -No consequential automated action may be represented as protected unless it is -reduced to an exact action contract, evaluated by policy, bound to a one-use -greenlight, checked by a gateway before consequence, and reconstructable as a -receipt, refusal, proof gap, or terminal certificate. - -The seven macro plans are closed only at the source-owned scope proven by the -current repo. They do not claim production hosted readiness, provider custody, -actual npm publication, MCP Registry discoverability, settlement, payment -management, certification, package safety, or host-wide containment. - -## Scope - -Closed macro folders: - -- `claim-boundary-cleanup` -- `customer-owned-gateway-custody-proof` -- `terminal-verifier-trust-plane` -- `hosted-admission-redacted-evidence-plane` -- `concrete-adapter-pack-expansion` -- `host-specific-bypass-harnesses` -- `public-distribution-publication` - -Still active and not closed by this audit: - -- `.planning/macro/active/x402-product-evaluation-20260524` - -## Commit Mapping - -| Macro plan | Closeout commit(s) | Evidence summary | -| --- | --- | --- | -| Claim boundary cleanup | `286ea47` | Canonical docs and package metadata now frame Handshake as protected action infrastructure for automated decision making; claim guards reject engineering-agent-only and x402/payment overclaims. | -| Customer-owned gateway custody proof | `0d6cbcf` | `GatewayCustodyProofPacket`, `CredentialResolutionEvidence`, transition/navigation/object registry coverage, and redaction tests landed. | -| Terminal verifier trust plane | `b4c5229`, `3752733` | Issuer/key/status models, verifier key-set projection, JWKS projection, structured verification response, CLI parity, and hosted verifier read routes landed. | -| Hosted admission and redacted evidence plane | `5a257df`, `9718905` | Hosted verifier/read routes, deployment-mode admission config, tenant/read-role split, raw-read posture, and readiness projection landed. | -| Concrete adapter pack expansion | `15c2eee` | Package-install material adapter pack, evidence report, lifecycle-script posture, proof gaps, gateway observed-parameter validation, and conformance coverage landed. | -| Host-specific bypass harnesses | `7760654` | Local package-manager host fixture, raw sibling posture, freshness, proof-packet/report, and host-specific non-claims landed. | -| Public distribution and publication | `b3635c5` | `PackageReleaseProof`, release states, authority non-claims, package metadata guard, and release proof readiness check landed. | - -## Requirements Audit - -| Requirement | Status | Source evidence | Residual proof gap | -| --- | --- | --- | --- | -| Correct category boundary | Passed | `README.md`, `AGENTS.md`, `docs/internal/decisions.md`, `test/architecture/claim-boundary.test.ts`, `package.json` | None for repo wording. | -| x402 exact per-call remains first wedge | Passed | `README.md`, `docs/internal/protocol-notes.md`, `test/conformance/x402-payment-conformance.test.ts`, `test/conformance/x402-upstream-exact-fixtures.test.ts` | Broad x402 surfaces remain future cuts. | -| No payment-management, settlement, marketplace, or custody overclaim | Passed | `test/architecture/claim-boundary.test.ts`, `scripts/check-release-proof.mjs`, `src/surfaces/release-proof.ts` | Actual external payment/provider operations not implemented or claimed. | -| Custody proof packet binds gateway custody evidence | Passed | `src/protocol/areas/credential-custody/`, `test/protocol/credential-custody.test.ts`, `test/protocol/evidence-projections.test.ts` | Provider-specific/customer deployment proof remains external. | -| Credential resolution is post-gate evidence | Passed | `recordCredentialResolutionEvidence`, `test/protocol/credential-custody.test.ts`, adapter gateway tests | None for source path. | -| Terminal certificate verification is structured evidence | Passed | `src/protocol/areas/authority-certificate/`, `test/protocol/authority-certificate.test.ts`, `src/cli/certificate.ts` | Cross-org trust publication and live revocation operations remain future work. | -| Hosted admission is deny-by-default and tenant-scoped | Passed | `src/http/admission/hosted-admission-config.ts`, `src/http/admission/hosted-caller-identity.ts`, `test/http/http.test.ts` | Production deployment posture remains unproven. | -| Hosted reads are redacted and read-entitled | Passed | `src/http/handlers/evidence-read.ts`, `src/http/handlers/internal-record-read.ts`, `test/http/http.test.ts` | Compliance-grade audit/export program remains future work. | -| Package-install adapter pack proves one exact install attempt | Passed | `src/adapters/package-install/adapter-pack.ts`, `test/adapters/package-install-adapter-pack.test.ts`, `test/integration/package-install-end-to-end.test.ts` | Real external package safety/provenance certification is not claimed. | -| Lifecycle scripts blocked or proof-gapped | Passed | `src/adapters/package-install/adapter-pack.ts`, `src/adapters/package-install/gateway.ts`, adapter-pack and gateway tests | Separately contracted lifecycle script action not implemented. | -| Host-specific bypass harness is narrow | Passed | `src/adapters/package-install/host-harness.ts`, `src/adapters/protected-path-probes/host-fixture.ts`, `test/adapters/package-install-host-harness.test.ts` | Additional hosts and ongoing freshness automation remain future work. | -| Public release states are separated | Passed | `src/surfaces/release-proof.ts`, `test/architecture/package-release-proof.test.ts`, `scripts/check-release-proof.mjs` | Actual npm publish, clean install from public artifact, MCP Registry acceptance, and discoverability are external proof gaps. | - -## Integration Audit - -The implemented chain is internally coherent: - -```text -claim boundary --> custody proof packet --> terminal verifier structure --> hosted read/admission posture --> package-install adapter pack --> host-specific bypass harness --> release-state proof -``` - -No slice creates an alternate authority path. Runtime ingress, MCP, CLI, -hosted verifier/readiness, release proof, and package-install reports remain -proposal/evidence/read/metadata surfaces. The gateway check remains the -pre-consequence enforcement point. - -## Gate Evidence - -Final closeout commands run after the seven implementation commits: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Observed result: - -- `quality:claims`: 4 pass, 0 fail. -- `quality:architecture`: 63 pass, 0 fail. -- `format:check`: passed. -- `check:repo`: 495 pass, 0 fail; package surface check passed with 563 files; - release proof readiness check passed; `git diff --check` passed. - -## Verdict - -Passed for repo-owned source closeout. The seven macro plans should no longer -live under `.planning/macro/active/`. - -Do not collapse the residual proof gaps into success language. Publication, -production hosted operation, provider custody, cross-org trust, package safety, -and host-wide containment remain unclaimed until future source and external -evidence prove them. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/GSD-REMAP.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/GSD-REMAP.md deleted file mode 100644 index 8bba70c..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/GSD-REMAP.md +++ /dev/null @@ -1,91 +0,0 @@ -# GSD Remap: Tier 2 Macro Closeout - -Date: 2026-05-24 - -## Mapper Runtime - -`gsd-sdk query init.map-codebase` reported that mapper agents were not -installed in this checkout. This remap was performed inline and written to the -existing `.planning/codebase/` scratch documents. - -## Remapped Documents - -Updated scratch maps: - -- `.planning/codebase/STACK.md` -- `.planning/codebase/ARCHITECTURE.md` -- `.planning/codebase/INTEGRATIONS.md` -- `.planning/codebase/STRUCTURE.md` -- `.planning/codebase/CONVENTIONS.md` -- `.planning/codebase/TESTING.md` -- `.planning/codebase/CONCERNS.md` - -Key correction: older map entries that described runtime/MCP x402 posture -propagation as current bugs are now stale. Current source includes the posture -fields in both runtime ingress and MCP proposal schema. - -## Current Source Map Delta - -New or materially expanded source areas: - -- `src/protocol/areas/credential-custody/`: gateway custody proof packets and - post-gate credential resolution evidence. -- `src/protocol/areas/authority-certificate/`: structured terminal verifier - response, issuer/key/status posture, verifier key-set projection, and JWKS - projection. -- `src/http/admission/`: hosted deployment-mode admission and caller identity - posture. -- `src/http/handlers/verifier.ts`: non-mutating hosted verifier routes. -- `src/http/handlers/hosted-readiness.ts`: hosted readiness reporting without - secret values or mutation authority. -- `src/adapters/package-install/adapter-pack.ts`: package-install material - adapter-pack evidence/report projection. -- `src/adapters/package-install/host-harness.ts` and - `src/adapters/protected-path-probes/host-fixture.ts`: named local host bypass - harness and proof-packet posture. -- `src/surfaces/release-proof.ts`: publication release-state proof and - non-authority boundary. -- `scripts/check-release-proof.mjs`: publication claim/readiness guard. - -## Active Planning State After Closeout - -Implemented bundle: - -- `.planning/macro/implemented/2026-05-24-tier2-macro-closeout/` - -Remaining active macro folder: - -- `.planning/macro/active/x402-product-evaluation-20260524` - -The remaining active folder was not one of the seven macro plans implemented in -this closeout and must not be archived by association. - -## Practical Next Map Queries - -Use this remap to route future work: - -- Custody or secret-boundary work: start in - `src/protocol/areas/credential-custody/` and - `test/protocol/credential-custody.test.ts`. -- Terminal verification work: start in - `src/protocol/areas/authority-certificate/`, `src/http/handlers/verifier.ts`, - and `test/protocol/authority-certificate.test.ts`. -- Hosted admission/read work: start in `src/http/admission/`, - `src/http/handlers/evidence-read.ts`, `src/http/handlers/internal-record-read.ts`, - `src/http/handlers/hosted-readiness.ts`, and `test/http/http.test.ts`. -- Package-install adapter work: start in - `src/adapters/package-install/adapter-pack.ts`, - `src/adapters/package-install/gateway.ts`, and - `test/adapters/package-install-adapter-pack.test.ts`. -- Host bypass work: start in `src/adapters/protected-path-probes/`, - `src/adapters/package-install/host-harness.ts`, and - `test/adapters/package-install-host-harness.test.ts`. -- Publication readiness work: start in `src/surfaces/release-proof.ts`, - `scripts/check-release-proof.mjs`, and - `test/architecture/package-release-proof.test.ts`. - -## Remap Verdict - -The current codebase map now matches the source-closed seven-plan stack. It -still treats `.planning/` as scratch and names external proof gaps instead of -turning them into product claims. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/REVIEW.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/REVIEW.md deleted file mode 100644 index a6c4750..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/REVIEW.md +++ /dev/null @@ -1,134 +0,0 @@ -# Tier 2 Macro Closeout Review - -Date: 2026-05-24 - -## Review Posture - -This is a source-closeout review of the seven macro implementation commits, not -a release approval for external npm/MCP publication or production hosted -operation. - -Reviewed axes: - -- correctness against the seven macro plans; -- authority-boundary preservation; -- security and redaction posture; -- architecture/import posture; -- test and gate credibility; -- residual proof gaps. - -## Findings - -No blocking findings were found in the closeout state. - -## Important Residual Risks - -### External publication remains a proof gap - -`PackageReleaseProof` correctly separates `ready_to_publish`, -`actually_published`, and `registry_discoverable`, but the repo has not -performed npm publish, post-publish clean install from the public artifact, MCP -Registry submission, or registry discoverability verification. This is not a -source bug; it is an external release-operator boundary. - -Required discipline: do not say "published" or "registry discoverable" until -the proof state advances with external evidence. - -### Hosted readiness is not production hosted operation - -Hosted admission, read-role separation, raw-read posture, and readiness reports -exist. They prove source-level local foundation behavior and configured posture, -not production operation, remote D1/KV proof, live revocation authority, abuse -control, or cross-org trust. - -Required discipline: keep "hosted" wording bound to admission/readiness and -evidence projections unless deployment evidence exists. - -### Package-install material evidence is not package safety - -The package-install adapter pack records material evidence, lifecycle-script -posture, proof gaps, exact contract binding, and gateway observed-parameter -validation. It does not prove package code is benign, replace npm audit, or -verify Bun provenance. - -Required discipline: preserve the report non-claims in future adapter pack -work. - -### Host-specific harness is not host-wide containment - -The host bypass harness proves one named local package-manager environment and -named raw sibling candidates at a freshness state. It does not prove generic -browser, shell, network, MCP, package-manager ecosystem, or runtime sandbox -containment. - -Required discipline: every new host claim needs its own manifest, probe list, -freshness, raw sibling posture, and proof-packet evidence. - -## Architecture Review - -The implementation preserves the core boundary: - -- Protocol primitives stay under `src/protocol/`. -- Runtime ingress remains observer/compiler/proposal posture. -- MCP remains proposal/evidence/read-only. -- CLI remains evidence/local readiness/readback. -- Hosted verifier/readiness routes are non-mutating. -- Release proof records publication evidence states, not authority. -- Adapter reports are reconstruction/evidence projections, not enforcement. - -The main architectural watch item is runtime ingress size. It is still the -largest cross-family conversion module. Current tests and the runtime registry -keep it proposal-only, so this is not a closeout blocker. The next family beyond -package install should trigger a narrow extraction before the module becomes a -god registry. - -## Security Review - -Redaction and custody posture improved: - -- Custody proof packets reject raw credential-looking material. -- Credential resolution evidence is post-gate. -- Evidence projections redact signer/payment/auth material. -- Hosted reads hide cross-tenant existence and gate raw records by posture. -- Verifier/JWKS projection exposes public key material only. - -Residual security boundaries are explicit: - -- no provider/customer custody proof from local fixtures; -- no live secret manager/vault provider integration; -- no production hosted trust or revocation distribution; -- no package safety guarantee; -- no host-wide bypass containment. - -## Test Review - -The final gate is credible because it includes: - -- full TypeScript checking; -- ESLint; -- Prettier; -- all Bun tests; -- package build and surface checks; -- published-entrypoint smoke checks; -- release proof readiness checks; -- whitespace diff check. - -Focused tests cover the new slices: - -- custody: `test/protocol/credential-custody.test.ts`; -- verifier: `test/protocol/authority-certificate.test.ts`, `test/http/http.test.ts`; -- hosted: `test/http/http.test.ts`, `test/sdk/role-clients.test.ts`; -- adapter pack: `test/adapters/package-install-adapter-pack.test.ts`; -- bypass harness: `test/adapters/package-install-host-harness.test.ts`; -- publication states: `test/architecture/package-release-proof.test.ts`; -- claims: `test/architecture/claim-boundary.test.ts`. - -## Review Verdict - -Keep. The seven-plan source stack is coherent, guarded, and narrow enough. - -Do not broaden it in closeout language. The next useful review is a -buyer-facing proof-path read: one concrete protected action from proposal to -contract, policy, one-use greenlight, gateway check, custody proof, receipt or -proof gap, terminal certificate, hosted redacted read, bypass posture, and -release metadata. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/VALIDATION.md deleted file mode 100644 index ceaeae4..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/VALIDATION.md +++ /dev/null @@ -1,63 +0,0 @@ -# Closeout Validation - -Date: 2026-05-24 - -## Commands - -Final gate commands from the implementation closeout: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Planning closeout/remap must rerun at least: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -## Source-Closeout Results - -- `npm run quality:claims`: passed. -- `npm run quality:architecture`: passed. -- `npm run format:check`: passed. -- `npm run check:repo`: passed with 495 tests, 0 failures, package surface check - with 563 files, and release proof readiness check. - -## Planning-Closeout Rerun Results - -- `npm run format:check`: passed after the GSD remap/audit/review artifacts. -- `npm run quality:claims`: passed with 4 tests, 0 failures. -- `npm run quality:architecture`: passed with 63 tests, 0 failures. -- `npm run check:repo`: passed with 495 tests, 0 failures, package surface - check with 563 files, and release proof readiness check. -- `git diff --staged --check`: passed after force-adding ignored closeout - artifacts. - -## Closeout-Specific Checks - -- The seven implemented macro folders have moved under this implemented bundle. -- `.planning/macro/active/x402-product-evaluation-20260524` remains active. -- `.planning/codebase/CONCERNS.md` no longer lists closed runtime/MCP x402 - posture propagation issues as active bugs. -- The audit and review documents distinguish source-closed implementation from - external proof gaps. - -## Non-Claims Preserved - -- No actual npm publication claimed. -- No MCP Registry discoverability claimed. -- No production hosted operation claimed. -- No provider/customer custody claimed from local fixture evidence. -- No cross-org AuthorityCertificate trust claimed. -- No settlement, payment management, seller middleware, facilitator operation, - marketplace, or certification claimed. -- No package safety, npm audit replacement, Bun provenance verification, or - broad supply-chain security claimed. -- No host-wide containment or generic runtime/MCP/CLI enforcement claimed. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/ASSUMPTIONS.md deleted file mode 100644 index c970c4f..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/ASSUMPTIONS.md +++ /dev/null @@ -1,14 +0,0 @@ -# Assumptions - -| ID | Assumption | Confidence | Evidence | Invalidation Trigger | -| --- | --- | --- | --- | --- | -| A1 | The user correction is authoritative: Handshake is protected actions for automated decision making. | High | Immutable input packet and all raw perspectives converge. | User chooses a different category phrase before implementation. | -| A2 | Tier 1 protocol/kernel meaning is stable and must not change in this cleanup. | High | Input constraints and protocol definition already support protected action control. | A strengthened claim guard cannot pass without a protocol behavior change. That should stop the slice. | -| A3 | x402 exact per-call protected action is the current first wedge. | High | README, x402 walkthrough, product report test, and perspectives all point to the official buyer-side `x402_payment.exact` path. | Source evidence proves the x402 path is not the narrowest executable wedge. | -| A4 | Aggregate payment-budget management is intentionally outside current remit. | High | Input explicitly requires replacing spend-ledger-required wording with out-of-remit posture. | User asks to plan spend-budget management as a separate capability. | -| A5 | Engineering-agent workflows remain useful adoption context and threat model. | High | Current canon and examples are built around generated execution and engineering-agent mutation surfaces. | Implementation removes all engineering-agent references and loses first-use clarity. | -| A6 | `not_enforced_local_metadata` may remain only as local metadata. | Medium | Raw perspectives agree; current source uses local spend-window status language. | Search finds the marker used as a product-scope enforcement promise. | -| A7 | Current x402 proof is local/reference evidence, not live custody or hosted operation. | High | README, protocol definition, x402 walkthrough, and report tests state local/reference boundaries. | Future implementation adds real customer/provider gateway custody and verifies it. | -| A8 | Claim guards should use named high-authority surfaces, not unbounded regex sprawl. | High | Maintainability requirement and existing `claim-boundary.test.ts` structure. | Guard coverage cannot express the boundary without a broader source-owned vocabulary mechanism. | -| A9 | External verification is out of scope for this cleanup. | High | Input says do not browse by default and mark external claims out of scope. | A future implementation adds positive external x402, legal, registry, JWKS, npm, or Cloudflare claims. | -| A10 | `.planning/codebase/CONCERNS.md` is scratch risk evidence, not canon. | High | README and decisions canon say `.planning/` is scratch. | User explicitly promotes a planning artifact into repo canon. | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/CONTEXT.md deleted file mode 100644 index a250009..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/CONTEXT.md +++ /dev/null @@ -1,89 +0,0 @@ -# Context - -## Target - -Plan critical-path item 0 from `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md`: Claim Boundary Cleanup. - -The cleanup must make eliminated items intentional product boundaries before new capability work. The user correction is controlling: Handshake is protected actions for automated decision making, not just engineering agents. x402 is the first wedge. - -## Source Packet - -Immutable packet: - -- `.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md` - -Raw perspectives: - -- `raw/STRATEGY.md` -- `raw/ARCH.md` -- `raw/EXECUTION.md` -- `raw/RISK.md` -- `raw/ADOPTION.md` - -Contract: - -- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/plan-contract.md` - -Allowed source checks used during synthesis: - -- `AGENTS.md` -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `test/architecture/claim-boundary.test.ts` -- `test/product/x402-protected-spend-demo-report.test.ts` -- `examples/x402-protected-spend/README.md` -- `examples/x402-protected-spend/run.ts` -- `examples/self-hosted-activation/README.md` -- `src/*/LANE.md` files named by the input packet -- `.planning/codebase/CONCERNS.md` as scratch risk evidence only - -No archive macro runs or external sources were read. - -## Current State - -Canonical docs and current README still contain category-level engineering-agent language. The protocol definition is safer: it already describes Handshake as a protocol kernel for protected action control and names the gateway as the pre-consequence enforcement point. - -x402 is already source-backed as the first narrow proof wedge. It is one buyer-side `x402_payment.exact` per-call path with local/reference sandbox evidence, gateway-held signer use after `VerifiedGatewayCheck`, replay refusal, and redacted report output. The repo also contains explicit non-claims for broad x402 compatibility, provider custody, hosted operation, facilitator/seller operation, settlement, marketplace/certification, and broad MCP/runtime control. - -The main contradiction is claim residue around aggregate spend. `README.md` still says session/day/review spend windows are metadata until a ledger exists, and the current product report test still expects `spend reservation ledger` in `missingProofObjects`. For this cleanup, that should become an explicit non-remit: aggregate payment-budget management is intentionally outside current scope. - -`test/architecture/claim-boundary.test.ts` already guards several claim surfaces, but it does not yet force the corrected category or prevent engineering-agent-only product definition. It should be strengthened, not replaced with a broad unstructured grep. - -## Relevant Canon - -Repo truth lives in: - -- `AGENTS.md` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` - -Operational behavior is guarded by: - -- `package.json` -- `.github/workflows/check.yml` -- `test/architecture/*` -- `src/*/LANE.md` - -`.planning/` is scratch. It can record this run and identify drift, but it must not become source, script, CI, package, or public API truth. - -## Synthesis Position - -The plan is a test-led claim cleanup: - -1. Inventory and phrase table. -2. Strengthen claim guards. -3. Rewrite canonical category language. -4. Clean x402 report/walkthrough wording. -5. Align lane manifests if needed. -6. Clean active scratch drift. -7. Run focused and full validation gates. - -No capability work is planned in this slice. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/DECISIONS.md deleted file mode 100644 index 09177d7..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/DECISIONS.md +++ /dev/null @@ -1,45 +0,0 @@ -# Decisions - -## Accepted - -- Use "protected actions for automated decision making" as the category phrase for this cleanup. -- Keep Tier 1 protocol meaning stable. The cleanup changes claims, examples, report wording, and tests, not protocol authority behavior. -- Treat engineering-agent workflows as adoption context and generated-execution stress case, not category boundary. -- Treat x402 as the first official buyer-side exact per-call protected-action wedge. -- Keep `x402_payment.exact` as the protected action class. Treat `x402_paid_http_call.exact` as buyer-readable report language only. -- Replace product-scope "spend reservation ledger required before claim" language with "aggregate payment-budget management intentionally out of current remit." -- Preserve customer-owned gateway custody as the future enforcement model while denying current provider/customer custody claims from local fixtures. -- Strengthen source-owned claim guards before or alongside prose changes. -- Use a small, named claim-surface list and grouped assertions. Avoid god files, regex sprawl, pass-through abstractions, and broad unstructured repo scans. - -## Rejected - -- Engineering agents as the product category. -- x402 as the protocol definition. -- Payment management, balances, aggregate spend windows, reservations, settlement, seller middleware, facilitator operation, or Handshake-held payment custody in this slice. -- Hosted operation, hosted trust, hosted verifier, live JWKS/revocation, marketplace/certification, clearing-house readiness, or cross-org certificate trust in this slice. -- Broad runtime, MCP, CLI, browser, shell, network, package-manager, cloud, repo, or database control claims. -- Treating runtime/MCP/CLI/SDK/review/report/certificate surfaces as authority surfaces. -- Implementing capability to make stale claims true. -- Promoting `.planning/` scratch into repo-facing source truth. - -## Deferred - -- Customer-owned gateway custody proof packets. -- Terminal verifier trust plane, JWKS/revocation, and portable verification. -- Hosted admission and redacted evidence plane. -- Additional protected-action packs beyond x402 exact per-call. -- Host-specific bypass harnesses for browser, shell, package manager, cloud, repo, database, or broad MCP/runtime surfaces. -- Public npm/MCP Registry publication proof and external package provenance claims. -- External x402 compatibility, legal, payment-regulatory, Cloudflare, or standards claims. -- Whether `test/architecture/active-vocabulary.test.ts` should join the cleanup. It was not in the chair's allowed source read, so implementation should verify it during inventory if needed. - -## User-Owned Decisions - -No P1 user-owned decision blocks execution of this cleanup plan. - -Potential future user decisions before capability expansion: - -- Which second protected-action pack follows x402 after claim cleanup. -- Whether the long-run clearing-house thesis should be captured in strategy docs outside this current repo. -- Whether active `.planning/codebase/CONCERNS.md` should be cleaned in the same implementation slice or left as stale scratch evidence with the active macro plan overriding it. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/PLAN.md deleted file mode 100644 index 27b3f03..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/PLAN.md +++ /dev/null @@ -1,354 +0,0 @@ -# Plan - -## Goal - -Create an executable implementation plan for claim-boundary cleanup before new capability work. - -The future implementation must make the eliminated items intentional product boundaries, not pending promises. It must correct the category boundary to protected actions for automated decision making, preserve Tier 1 protocol meaning, and keep x402 as the first official buyer-side exact per-call protected-action wedge. - -The invariant at stake: public repo language must not create authority that the gateway does not enforce. - -## Non-Goals - -- No Tier 1 protocol or schema redesign. -- No new authority, policy, gateway, greenlight, receipt, storage, or x402 signing behavior. -- No aggregate payment-budget management, spend reservation ledger, balances, settlement, seller middleware, facilitator operation, or payment-management product. -- No Handshake-held wallet, signer, provider, or customer custody claim. -- No hosted operation, hosted trust, hosted verifier, live JWKS/revocation, marketplace, certification, clearing-house readiness, or cross-org certificate trust claim. -- No broad runtime, MCP, CLI, browser, shell, network, package-manager, cloud, repo, or database control claim. -- No broad x402 compatibility claim. The current wedge is one official buyer-side `x402_payment.exact` per-call path. -- No public package, MCP Registry, Cloudflare, legal, or payment-regulatory claim unless a later slice explicitly performs external verification. - -## Source Boundary - -Used inputs: - -- `.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md` -- Raw perspective outputs under `.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/` -- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/plan-contract.md` -- The allowed source files named in the input packet where needed to resolve conflicts. - -Not used: - -- No archived macro runs. -- No external browsing. -- No source files outside the allowed packet. - -Source priority for implementation: - -1. User correction in the immutable input packet. -2. Current canonical docs and tests. -3. Current `.planning` active run evidence. -4. Derived `.planning/codebase/*` maps as scratch risk context only. - -## Current State - -The protocol spine is already broader than the stale product language. `docs/internal/protocol-definition.md` defines protected action control: exact action contract, policy decision, one-use greenlight, gateway check before mutation, and receipt/refusal/proof-gap evidence. - -The category language is stale in high-authority docs. `AGENTS.md`, `README.md`, and `docs/internal/decisions.md` still define Handshake around engineering agents in places. That makes an adoption context look like the product boundary. - -x402 is the strongest current wedge but has claim residue. The repo already presents one official buyer-side exact per-call x402 path with gateway-held signing after `VerifiedGatewayCheck`, replay refusal, local/reference evidence, and non-claims. But `README.md`, `.planning/codebase/CONCERNS.md`, and `test/product/x402-protected-spend-demo-report.test.ts` still preserve "spend reservation ledger" / "metadata until a ledger exists" posture that can read as pending aggregate payment-budget management. - -Current guards exist but are not strict enough for the corrected category. `test/architecture/claim-boundary.test.ts` already checks runtime/MCP/conformance/x402 non-authority language and public entrypoint separation. `test/product/x402-protected-spend-demo-report.test.ts` already checks the local APS report boundary, redaction, role clients, replay refusal, and non-claims. These gates must be strengthened; they were not run during this planning-only synthesis. - -`.planning/` contains useful drift evidence but is not repo truth. `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` already says per-call x402 exact authorization is immediate posture and aggregate payment-budget management is not the product. `.planning/codebase/CONCERNS.md` still includes a derived spend-ledger fix path; implementation must treat that as stale risk evidence unless intentionally updated as scratch. - -## Target State - -Canonical repo truth reads as: - -```text -Handshake protects consequential actions from automated decision systems by reducing each protected action attempt to an exact, policy-evaluated, gateway-bound action contract before consequence. -``` - -The hierarchy is explicit: - -```text -category: protected actions for automated decision making -primitive: exact contract -> policy -> one-use greenlight -> gateway check -> receipt/refusal/proof gap -first wedge: one buyer-side x402_payment.exact per-call protected action -current adoption context: automated engineering/runtime workflows and generated execution -local proof boundary: local/reference only unless a customer-owned gateway owns the credential and checks the exact greenlight -``` - -Engineering-agent workflows remain useful as a generated-execution stress case and adoption context. They do not define the category. - -x402 remains one protected-action pack. It proves the spine; it does not define the protocol, broad payment management, settlement, seller/facilitator operation, provider/customer custody, marketplace/certification, or broad x402 compatibility. - -Aggregate payment-budget management is explicitly out of current remit. `not_enforced_local_metadata` may remain only when attached to local metadata and surrounded by wording that denies enforcement and budget-management claims. - -Claim guards fail if canon, examples, generated reports, or lane manifests imply broader authority than the source enforces. - -## Assumptions - -- The user correction is authoritative: Handshake is protected actions for automated decision making, not just engineering agents. -- Tier 1 protocol/kernel meaning is stable and must not be changed by this cleanup. -- x402 exact per-call protected action remains the first wedge unless future source evidence proves a narrower sequence is required. -- Existing current x402 proof is local/reference evidence, not live provider/customer custody or hosted operation. -- `.planning/` is scratch; active planning outputs may guide work but must not become repo-facing source paths, scripts, package names, or canonical docs. -- External standards, package publication, registry, legal, payment-regulatory, Cloudflare, JWKS, and live x402 compatibility claims are out of scope for this slice. - -## Decisions - -- Adopt "protected actions for automated decision making" as the category phrase for this cleanup. -- Keep engineering-agent language only where it is adoption context, generated-execution threat model, or a current local proof context. -- Treat x402 as the first official buyer-side exact per-call protected-action wedge. -- Keep `x402_payment.exact` as the protected action class. Keep `x402_paid_http_call.exact` as buyer-readable report language only unless a future source change adds a matching action catalog, compiler, policy, and gateway class. -- Replace product-scope "spend reservation ledger required before claim" language with "aggregate payment-budget management intentionally out of current remit." -- Keep customer-owned gateway custody as the future enforcement model, while stating that local x402 proof does not prove provider/customer custody today. -- Use source-owned claim guards over a small named surface set. Avoid broad random regex scans, god tests, pass-through abstractions, and spaghetti conditional exceptions. - -## Phases - -### Phase 0 - Claim Inventory And Phrase Table - -Build a small implementation inventory before edits. - -Classify each relevant phrase in `AGENTS.md`, `README.md`, `docs/internal/*`, x402 examples, the APS report generator, lane manifests, and active planning scratch as one of: - -- category claim; -- first wedge claim; -- current adoption context; -- local/reference evidence only; -- explicit non-claim or cut line; -- stale scratch evidence. - -Closeout evidence: an implementation note or PR description table. Do not add a new repo-facing canon file for the inventory. - -### Phase 1 - Test-First Claim Guards - -Strengthen guards before rewriting docs. - -Update `test/architecture/claim-boundary.test.ts` with a named surface map and grouped assertions: - -- category boundary assertions for canonical docs; -- x402 wedge assertions; -- payment-management non-claim assertions; -- runtime/MCP/CLI/SDK/lane non-authority assertions; -- custody, hosted, marketplace/certification, clearing-house, and cross-org trust non-claims. - -Update `test/product/x402-protected-spend-demo-report.test.ts` so the APS report no longer requires `spend reservation ledger` as a missing proof object. It should require aggregate payment-budget management to be absent from current authority or explicitly listed as out of current remit. - -Maintainability rule: use named surfaces and grouped helpers inside the test, or split into focused architecture tests if the file becomes a god file. Do not add repo-wide grep sprawl with opaque exceptions. - -Closeout evidence: focused tests initially fail on stale wording, then pass after phases 2-4. - -### Phase 2 - Canonical Category Rewrite - -Patch canonical docs after guards define the failure. - -Candidate paths: - -- `AGENTS.md` -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` - -Required changes: - -- top-level category becomes protected actions for automated decision making; -- engineering-agent language moves to adoption context or generated-execution threat model; -- first wedge language becomes x402 exact per-call protected action; -- Tier 1 protocol object meanings remain unchanged; -- "No adapter family defines the protocol" remains visible; -- receipts, terminal certificates, and reports do not become permission, identity, settlement, certification, hosted trust, or downstream business success. - -Closeout evidence: category guard passes without protocol behavior changes. - -### Phase 3 - x402 Report And Walkthrough Cleanup - -Patch the first wedge without broadening it. - -Candidate paths: - -- `examples/x402-protected-spend/README.md` -- `examples/x402-protected-spend/run.ts` -- `examples/self-hosted-activation/README.md` -- `test/product/x402-protected-spend-demo-report.test.ts` - -Required changes: - -- scope the walkthrough to one buyer-side `x402_payment.exact` per-call protected action; -- label `x402_paid_http_call.exact` as buyer-readable report language only; -- replace product-scope spend-ledger wording with aggregate payment-budget management out of current remit; -- keep `not_enforced_local_metadata` only as local metadata; -- preserve signer invocation only after `VerifiedGatewayCheck`; -- preserve replay refusal before signer reuse; -- preserve local/reference downstream fixture wording; -- add or preserve support/debug payload redaction boundaries for payment-sensitive material. - -Closeout evidence: `npm run demo:aps` regenerates report output and the product report test passes. - -### Phase 4 - Lane And Surface Boundary Alignment - -Patch only lane wording that reintroduces stale category or authority drift. - -Candidate paths: - -- `src/runtime/LANE.md` -- `src/mcp/LANE.md` -- `src/cli/LANE.md` -- `src/sdk/LANE.md` -- `src/adapters/LANE.md` -- `src/conformance/LANE.md` - -Required posture: - -- runtime proposes and records evidence only; -- MCP proposes and displays evidence only; -- CLI reads/renders local evidence only; -- SDK role clients stay role-scoped for walkthroughs; -- adapters are protected-action packs and mutate only after verified gateway checks; -- conformance is reference posture, not certification or standards compliance. - -Closeout evidence: import posture, root exports, and claim-boundary tests stay green. - -### Phase 5 - Active Scratch Register Cleanup - -Patch active planning scratch only where it would mislead future agents. - -Candidate paths: - -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `.planning/codebase/CONCERNS.md` only if the executor decides tracked scratch drift must be corrected in the same slice. - -Required posture: - -- category uses protected actions for automated decision making; -- x402 exact per-call remains the first wedge; -- aggregate payment-budget management is intentionally out of current remit; -- old spend-ledger fix advice is stale derived evidence unless rewritten. - -Closeout evidence: active scratch no longer contradicts canonical docs. Do not reference `.planning` from repo-facing source, package scripts, CI, README sections, or exported symbols. - -### Phase 6 - Validation And Closeout - -Run focused gates first, then full repo gate last. - -Required closeout ordering: - -1. `npm run quality:claims` -2. `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts` -3. `npm run demo:aps` if `examples/x402-protected-spend/run.ts` changed -4. `npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts` if lane/package surfaces changed -5. `npm run quality:architecture` -6. `npm run format:check` -7. `npm run check:repo` - -Closeout evidence: command output plus a diff summary proving no protocol behavior changed. - -## Task Graph - -```text -macro-001 claim inventory - -> macro-002 architecture claim guards - -> macro-003 x402 report claim guards - -macro-002 architecture claim guards - -> macro-004 canonical category rewrite - -> macro-006 lane boundary alignment - -macro-003 x402 report claim guards - -> macro-005 x402 report and walkthrough cleanup - -macro-004 canonical category rewrite - -> macro-007 active scratch cleanup - -> macro-008 focused claim validation - -macro-005 x402 report and walkthrough cleanup - -> macro-008 focused claim validation - -> macro-009 APS demo validation - -macro-006 lane boundary alignment - -> macro-010 architecture posture validation - -macro-007 active scratch cleanup - -> macro-008 focused claim validation - -macro-008 focused claim validation -macro-009 APS demo validation -macro-010 architecture posture validation - -> macro-011 full repo closeout -``` - -Critical path: - -```text -inventory -> guard old failures -> canon rewrite -> x402 report cleanup -> active scratch cleanup -> focused gates -> check:repo -``` - -Parallelizable after inventory: - -- architecture claim guards and x402 report claim guards; -- canonical docs and lane manifest wording once phrase table is stable; -- x402 report cleanup independently of lane wording; -- active scratch cleanup after canonical phrasing is settled. - -## Risks And Mitigations - -- P0: Category boundary remains engineering-agent-only. Mitigation: positive category guard plus bounded-context allowance for engineering-agent examples. -- P0: x402 becomes payment management. Mitigation: explicit non-remit language and product report guard that rejects spend-ledger-as-promise wording. -- P0: Docs create authority without gateway enforcement. Mitigation: every protected claim must bind to exact contract, one-use greenlight, customer-owned gateway check before consequence, and receipt/refusal/proof-gap evidence. -- P0: Claim guards are too narrow or brittle. Mitigation: named source surfaces, grouped high-risk boundaries, required positive language plus forbidden overclaims; avoid whole-repo regex sprawl. -- P1: x402 becomes protocol definition. Mitigation: keep adapter/action-pack discipline and "No adapter family defines the protocol." -- P1: Customer-owned gateway custody gets erased while removing custody overclaims. Mitigation: use three states: local/reference fixture now, customer-owned gateway custody future enforcement model, Handshake-held custody out of remit. -- P1: Local sandbox evidence reads as seller/facilitator/settlement operation. Mitigation: report and tests keep local downstream fixture evidence separate from authority and downstream success. -- P1: Runtime/MCP/CLI surfaces launder authority. Mitigation: lane wording and import/export tests keep them proposal/evidence/read-only. -- P2: `.planning` scratch becomes canon again. Mitigation: support docs and plan state that scratch is coordination evidence only. -- P2: `x402_paid_http_call.exact` reads as an action catalog class. Mitigation: report test labels it buyer-readable only. - -## Validation Gates - -Existing source-present guards, not re-run during synthesis: - -- `test/architecture/claim-boundary.test.ts` currently checks public entrypoint separation and several runtime/MCP/x402 non-claims. -- `test/product/x402-protected-spend-demo-report.test.ts` currently executes the demo report and checks local/reference x402 authority boundaries, role clients, replay refusal, and redaction. - -Planned strengthened gates: - -- Category gate: canonical docs must state protected actions for automated decision making and must not define Handshake as engineering-agent-only. -- Adoption-context gate: engineering-agent references must be explicitly adoption context, generated-execution stress case, or current local proof context. -- x402 wedge gate: x402 is one official buyer-side exact per-call protected-action pack, not the protocol definition or broad x402 compatibility. -- Payment non-remit gate: aggregate payment-budget management is intentionally outside current remit; no spend ledger is required to make current per-call x402 claim honest. -- Local metadata gate: `not_enforced_local_metadata` appears only as local metadata and never as disabled enforcement. -- Surface authority gate: runtime, MCP, CLI, SDK, review, reports, and terminal certificates cannot create policy, greenlights, gateway checks, mutation authority, receipt export, signer authority, or certification trust. -- Redaction gate: docs and report do not ask users to share `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, signer refs, raw store records, role-token maps, gateway credentials, or raw payment material. -- Full closeout gate: `npm run check:repo` after focused gates. - -Performance and scale posture: - -- This slice should not affect runtime performance because it is docs, examples, and tests only. -- Claim guard scans should use a fixed, named set of high-authority files, not unbounded repo traversal. -- Demo regeneration is acceptable as a product proof gate; it must remain deterministic and local. - -## Cut Lines - -Stop or split into a separate capability plan if implementation requires: - -- protocol schema or state-machine changes; -- gateway, policy, greenlight, storage, receipt, x402 signing, or terminal certificate behavior changes; -- aggregate spend enforcement, spend windows, balance tracking, settlement, seller/facilitator roles, or payment management; -- new hosted routes, verifier operation, JWKS/revocation, org auth, retention, or audit search; -- package publication, registry publication, Cloudflare deployment, legal/payment/regulatory claims, or external x402 compatibility claims; -- new public exports, package scripts, source directories, MCP tools, CLI mutation commands, or SDK authority clients; -- broad runtime/MCP/browser/shell/network/package-manager protection claims without host-specific bypass harnesses. - -## Rollback / Stop Conditions - -Rollback should be mechanical: revert the docs, example, report, and test guard changes from the implementation slice. No migrations, package export changes, source behavior changes, or generated distribution dependency should be necessary. - -Stop immediately if: - -- a claim can be made true only by changing Tier 1 protocol meaning; -- a test failure suggests implementing a spend ledger instead of narrowing the claim; -- a local/reference fixture is being described as live provider/customer custody; -- a report or terminal certificate is treated as permission, identity, settlement, certification, or hosted trust; -- any positive external claim is added without explicit verification; -- broad runtime/MCP/CLI/browser/shell/network/package-manager control language appears outside an explicit non-claim. - -## Smallest Next Action - -Add the failing claim-boundary guard first: update `test/architecture/claim-boundary.test.ts` so canonical docs fail when they define Handshake as engineering-agent-only and fail when aggregate payment-budget management is treated as a pending spend-ledger promise instead of intentionally out of current remit. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/RISKS.md deleted file mode 100644 index 957b3aa..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/RISKS.md +++ /dev/null @@ -1,103 +0,0 @@ -# Risks - -## P0 - -### R1 - Category Boundary Remains Wrong - -Risk: Canon still defines Handshake as engineering-agent infrastructure. Future plans then treat one adoption context as the whole category. - -Mitigation: Add a positive category guard and rewrite canon to protected actions for automated decision making. Allow engineering-agent language only as adoption context, generated-execution stress case, or local proof context. - -Validation: `test/architecture/claim-boundary.test.ts` fails on engineering-agent-only product definitions. - -### R2 - x402 Becomes Payment Management - -Risk: Spend-ledger wording implies aggregate budget management is pending rather than out of remit. - -Mitigation: Replace product-scope ledger-required phrasing with aggregate payment-budget management intentionally out of current remit. Keep x402 per-call exact only. - -Validation: Product report test rejects `spend reservation ledger` as a current missing proof promise and requires explicit non-remit posture where aggregate spend is discussed. - -### R3 - Docs Create Authority Without Gateway Enforcement - -Risk: Broadened "protected" language claims control where no gateway owns the mutation credential and checks the exact greenlight. - -Mitigation: Bind every protected claim to exact contract, one-use greenlight, gateway check before consequence, and receipt/refusal/proof-gap evidence. - -Validation: Claim guards scan named canon and lane manifests for hosted, custody, broad runtime, and certification overclaims. - -### R4 - Guard Coverage Is Cosmetic - -Risk: Tests pin a few phrases but miss high-risk claim surfaces, or become brittle exact-copy tests that discourage accurate wording. - -Mitigation: Use a named surface map with grouped semantic assertions and forbidden overclaim patterns. Keep exact strings only for contract terms such as `x402_payment.exact`, `not_enforced_local_metadata`, `VerifiedGatewayCheck`, and "proposal/evidence only". - -Validation: Focused tests fail on known stale category and spend-ledger language before cleanup. - -## P1 - -### R5 - x402 Defines The Protocol - -Risk: Correcting engineering-agent drift overcorrects into payment-protocol positioning. - -Mitigation: Keep the hierarchy visible: category, primitive, first wedge, adoption context, local proof boundary. Preserve "No adapter family defines the protocol." - -Validation: Claim guard requires first-wedge wording and rejects broad x402 compatibility. - -### R6 - Customer-Owned Gateway Custody Gets Cut Too Far - -Risk: Removing custody overclaims also removes the future enforcement model. - -Mitigation: Use three states: local/reference fixture now, customer-owned gateway custody future enforcement model, Handshake-held custody out of remit. - -Validation: Docs keep current non-claim and future boundary in separate language. - -### R7 - Local Sandbox Evidence Reads As Seller/Facilitator/Settlement - -Risk: Local 402 challenge and signed retry evidence get mistaken for seller middleware, facilitator operation, or settlement finality. - -Mitigation: Keep local/reference downstream fixture labels and post-gateway observation wording. Maintain report booleans for settlement/facilitator/seller/provider custody false. - -Validation: `test/product/x402-protected-spend-demo-report.test.ts` continues asserting local sandbox non-claims. - -### R8 - Runtime/MCP/CLI Surfaces Launder Authority - -Risk: Automated-decision language makes proposal/evidence/read surfaces sound like control planes. - -Mitigation: Lane manifests must say these surfaces do not evaluate policy, issue greenlights, perform gateway checks, mutate, export receipts, invoke signers, or mint certificates. - -Validation: Claim-boundary, import-posture, and root-export tests stay green. - -### R9 - Redaction And Support Language Overclaims Privacy Or Audit Readiness - -Risk: Support/debug docs imply hosted audit, privacy, compliance, retention, or provider secret lifecycle proof. - -Mitigation: Add support payload allowlist and forbidden payment/credential field list if first-use docs are touched. - -Validation: Claim guards reject raw credential/payment material in public walkthroughs and report output. - -## P2 - -### R10 - `.planning` Scratch Becomes Canon Again - -Risk: Future agents load stale derived maps and override cleaned canon. - -Mitigation: This plan and support files classify `.planning` as scratch; future implementation may clean active scratch but must not reference it from repo-facing surfaces. - -Validation: No README, source, tests, scripts, exports, or CI names refer to `.planning` as product truth. - -### R11 - Buyer-Readable Report Label Becomes Action Class - -Risk: `x402_paid_http_call.exact` is mistaken for gateway-bound authority. - -Mitigation: Keep it explicitly buyer-readable and non-authority. The protected action remains `x402_payment.exact`. - -Validation: Product report or claim-boundary test asserts the distinction. - -### R12 - Rollback Is Not Mechanical - -Risk: A claim cleanup touches behavior, exports, or migrations and becomes hard to reverse. - -Mitigation: Limit diff to docs, examples, report strings, claim tests, and active scratch. Stop if behavior must change. - -Validation: Closeout diff contains no protocol/gateway/storage/export behavior change unless separately justified by a new plan. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/TASKS.jsonl deleted file mode 100644 index be7826d..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/TASKS.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"id":"macro-001","priority":"P1","phase":"Phase 0","title":"Build claim inventory and phrase table","owner":"implementation lead","rationale":"The cleanup needs exact classification before edits so category, wedge, adoption context, local evidence, and non-claim language do not get blurred.","depends_on":[],"acceptance":["Each relevant claim surface is classified as category, first wedge, adoption context, local/reference evidence, explicit non-claim, or stale scratch evidence.","Inventory names every product-definition use of engineering-agent language and every spend-ledger or aggregate-spend phrase.","Inventory is recorded in the PR description or implementation note, not promoted as new repo canon."],"candidate_paths":["AGENTS.md","README.md","docs/internal/decisions.md","docs/internal/protocol-definition.md","docs/internal/protocol-kernel-architecture.md","docs/internal/protocol-layman.md","docs/internal/protocol-notes.md","examples/x402-protected-spend/README.md","examples/x402-protected-spend/run.ts","examples/self-hosted-activation/README.md","src/runtime/LANE.md","src/mcp/LANE.md","src/cli/LANE.md","src/sdk/LANE.md","src/adapters/LANE.md","src/conformance/LANE.md",".planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md",".planning/codebase/CONCERNS.md"],"non_goals":["No source behavior changes.","No new canonical inventory file.","No archive macro-run reads."]} -{"id":"macro-002","priority":"P1","phase":"Phase 1","title":"Strengthen architecture claim-boundary guards","owner":"test owner","rationale":"Source-owned tests must fail stale category and overclaim language before docs are rewritten.","depends_on":["macro-001"],"acceptance":["Claim guard requires protected actions for automated decision making in canonical product definitions.","Claim guard rejects engineering-agent-only category definitions while allowing engineering-agent adoption-context references.","Claim guard rejects broad x402 compatibility, payment management, settlement, seller/facilitator operation, hosted trust, marketplace/certification, clearing-house readiness, cross-org certificate trust, and broad runtime/MCP/CLI/browser/shell/network/package-manager control unless explicitly non-claims.","Guard uses a small named surface map and grouped assertions, not unbounded regex sprawl."],"candidate_paths":["test/architecture/claim-boundary.test.ts"],"non_goals":["No protocol behavior changes.","No broad repo-wide grep with opaque exceptions.","No new authority surfaces."]} -{"id":"macro-003","priority":"P1","phase":"Phase 1","title":"Strengthen x402 report claim guards","owner":"product proof owner","rationale":"The APS report is buyer-readable and must not imply aggregate payment-budget management or action classes the gateway does not expose.","depends_on":["macro-001"],"acceptance":["Product report test no longer requires spend reservation ledger as a missing proof object for current claims.","Test requires aggregate payment-budget management to be absent from current authority or explicitly out of current remit.","Test keeps not_enforced_local_metadata only as local metadata.","Test keeps x402_paid_http_call.exact classified as buyer-readable report language and x402_payment.exact as the protected action class."],"candidate_paths":["test/product/x402-protected-spend-demo-report.test.ts"],"non_goals":["No aggregate spend ledger implementation.","No new payment or settlement semantics.","No gateway or signer behavior changes."]} -{"id":"macro-004","priority":"P1","phase":"Phase 2","title":"Rewrite canonical category language","owner":"docs/canon owner","rationale":"Durable repo truth must reflect the corrected category while preserving Tier 1 protocol meaning.","depends_on":["macro-002"],"acceptance":["AGENTS.md, README.md, and docs/internal/decisions.md no longer define Handshake as engineering-agent-only.","Canonical docs describe Handshake as protected actions for automated decision making or protected action control.","Engineering-agent references are retained only as adoption context, generated-execution stress case, or current proof context.","No protocol object semantics, public exported symbols, scripts, or source paths are renamed."],"candidate_paths":["AGENTS.md","README.md","docs/internal/decisions.md","docs/internal/protocol-definition.md","docs/internal/protocol-kernel-architecture.md","docs/internal/protocol-layman.md","docs/internal/protocol-notes.md"],"non_goals":["No Tier 1 protocol rewrite.","No product marketing expansion.","No broad automated-decision governance claim."]} -{"id":"macro-005","priority":"P1","phase":"Phase 3","title":"Clean x402 walkthrough and report wording","owner":"example/product proof owner","rationale":"The first wedge must stay exact per-call x402 authorization without payment-management, custody, settlement, or broad compatibility implications.","depends_on":["macro-003"],"acceptance":["x402 walkthrough scopes the proof to one buyer-side x402_payment.exact per-call protected action.","examples/x402-protected-spend/run.ts emits out-of-current-remit aggregate payment-budget posture instead of spend-ledger-required wording.","not_enforced_local_metadata remains only where clearly local metadata.","Report and README preserve local/reference sandbox, gateway-held signer after VerifiedGatewayCheck, replay refusal, proof-gap, and non-claims.","Support/debug language does not request or expose raw payment or credential material."],"candidate_paths":["examples/x402-protected-spend/README.md","examples/x402-protected-spend/run.ts","examples/self-hosted-activation/README.md","test/product/x402-protected-spend-demo-report.test.ts"],"non_goals":["No signer custody change.","No x402 compatibility expansion.","No settlement, facilitator, seller, or hosted operation claim."]} -{"id":"macro-006","priority":"P2","phase":"Phase 4","title":"Align lane manifests with category and non-authority boundaries","owner":"source-boundary owner","rationale":"Lane manifests are local ownership contracts and must not launder proposal/evidence surfaces into authority surfaces.","depends_on":["macro-002","macro-004"],"acceptance":["Runtime lane says runtime proposes and records evidence only.","MCP lane says MCP proposes/displays evidence only and cannot authorize.","CLI and SDK lane wording does not imply signer, gateway, receipt-export, or certificate authority.","Adapter lane preserves protected-action-pack discipline and says no adapter family defines the protocol.","Conformance lane avoids marketplace, certification, or provider-enforcement claims."],"candidate_paths":["src/runtime/LANE.md","src/mcp/LANE.md","src/cli/LANE.md","src/sdk/LANE.md","src/adapters/LANE.md","src/conformance/LANE.md"],"non_goals":["No new MCP tools.","No new CLI commands.","No SDK authority client.","No package export changes."]} -{"id":"macro-007","priority":"P2","phase":"Phase 5","title":"Clean active planning scratch drift","owner":"planning hygiene owner","rationale":"Future agents may reload active scratch; it should not contradict the cleaned canon even though it is not repo truth.","depends_on":["macro-004","macro-005"],"acceptance":[".planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md uses protected actions for automated decision making and keeps x402 exact per-call as first wedge.","Spend-ledger language in active scratch is either removed or clearly marked stale/out of remit.","If .planning/codebase/CONCERNS.md is touched, it is updated as scratch risk evidence only and not promoted to canon."],"candidate_paths":[".planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md",".planning/codebase/CONCERNS.md"],"non_goals":["No archive cleanup.","No repo-facing references to .planning.","No planning taxonomy in source, scripts, CI, README sections, or exports."]} -{"id":"macro-008","priority":"P1","phase":"Phase 6","title":"Run focused claim validation","owner":"implementation lead","rationale":"The slice is not closed until claim guards prove stale category and payment-management wording cannot return.","depends_on":["macro-004","macro-005","macro-007"],"acceptance":["npm run quality:claims passes.","npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts passes.","Failures are fixed by narrowing claims, not by implementing out-of-scope capability."],"candidate_paths":["test/architecture/claim-boundary.test.ts","test/product/x402-protected-spend-demo-report.test.ts"],"non_goals":["No skipped claim tests.","No weakening forbidden-claim assertions to make prose pass."]} -{"id":"macro-009","priority":"P1","phase":"Phase 6","title":"Regenerate and verify APS report if report source changed","owner":"product proof owner","rationale":"The buyer-readable report is an observable contract and must match the narrowed claim boundary.","depends_on":["macro-005"],"acceptance":["npm run demo:aps passes when examples/x402-protected-spend/run.ts changes.","examples/x402-protected-spend/output/latest.md and latest.json preserve exact per-call x402 posture and local/reference non-claims.","Generated report contains no raw credential or payment material."],"candidate_paths":["examples/x402-protected-spend/run.ts","examples/x402-protected-spend/output/latest.md","examples/x402-protected-spend/output/latest.json"],"non_goals":["No hosted provider run.","No external x402 compatibility verification.","No settlement or payment finality proof."]} -{"id":"macro-010","priority":"P2","phase":"Phase 6","title":"Run architecture and package posture validation","owner":"source-boundary owner","rationale":"Claim cleanup must not move public entrypoints or lane authority boundaries.","depends_on":["macro-006"],"acceptance":["npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts passes if lane or package-facing wording changed.","npm run quality:architecture passes.","No new public exports, scripts, package subpaths, or source directories are introduced."],"candidate_paths":["test/architecture/import-posture.test.ts","test/architecture/root-exports.test.ts","src/runtime/LANE.md","src/mcp/LANE.md","src/cli/LANE.md","src/sdk/LANE.md","src/adapters/LANE.md","src/conformance/LANE.md"],"non_goals":["No export changes.","No package publication claim.","No generated dist or publish workflow work unless existing gates require it."]} -{"id":"macro-011","priority":"P1","phase":"Phase 6","title":"Run final format and repo closeout","owner":"implementation lead","rationale":"The future implementation slice should close with normal repo proof, not just focused claim tests.","depends_on":["macro-008","macro-009","macro-010"],"acceptance":["npm run format:check passes.","npm run check:repo passes.","Closeout summary names existing green evidence, changed guard surfaces, blocked external checks, and proof that Tier 1 behavior did not change."],"candidate_paths":["README.md","AGENTS.md","docs/internal/decisions.md","docs/internal/protocol-definition.md","docs/internal/protocol-kernel-architecture.md","docs/internal/protocol-layman.md","docs/internal/protocol-notes.md","test/architecture/claim-boundary.test.ts","test/product/x402-protected-spend-demo-report.test.ts"],"non_goals":["No staging or commit unless separately requested.","No external verification claims.","No capability expansion."]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/VALIDATION.md deleted file mode 100644 index 7171646..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/VALIDATION.md +++ /dev/null @@ -1,126 +0,0 @@ -# Validation - -## Existing Source-Present Checks - -These checks exist in the repo today but were not run during this planning-only synthesis: - -- `test/architecture/claim-boundary.test.ts` checks public entrypoint separation and several current runtime, MCP, conformance, and x402 non-claims. -- `test/product/x402-protected-spend-demo-report.test.ts` executes `examples/x402-protected-spend/run.ts` and checks local APS report boundaries, redaction, replay refusal, role clients, and non-claims. -- `test/architecture/import-posture.test.ts` and `test/architecture/root-exports.test.ts` guard package/lane import and export posture. - -## Planned Guard Additions - -### Category Boundary - -Proof obligation: - -- Canonical docs state protected actions for automated decision making. -- Canonical docs do not define Handshake as engineering-agent-only. -- Engineering-agent references are adoption context, generated-execution threat model, or current local proof context. - -Candidate gate: - -```bash -npm run test -- test/architecture/claim-boundary.test.ts -``` - -### x402 Wedge Boundary - -Proof obligation: - -- x402 is one official buyer-side `x402_payment.exact` per-call protected-action wedge. -- No adapter family defines the protocol. -- `x402_paid_http_call.exact` remains buyer-readable report language only. -- No broad x402 compatibility, `upto`, batch settlement, seller middleware, facilitator operation, or settlement finality claim. - -Candidate gates: - -```bash -npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts -npm run demo:aps -``` - -### Aggregate Payment-Budget Non-Remit - -Proof obligation: - -- Product-scope `spend reservation ledger required before claim` language is removed. -- Aggregate payment-budget management is intentionally out of current remit. -- `not_enforced_local_metadata` appears only as local metadata, not disabled enforcement or a roadmap promise. - -Candidate gate: - -```bash -npm run test -- test/product/x402-protected-spend-demo-report.test.ts -``` - -### Surface Non-Authority - -Proof obligation: - -- Runtime, MCP, CLI, SDK, review, report, and terminal certificate surfaces do not evaluate policy, issue greenlights, check gateways, mutate, export raw receipts, invoke signers, or mint authority. -- Lane manifests do not claim broad runtime, MCP, browser, shell, network, package-manager, cloud, repo, or database protection. - -Candidate gates: - -```bash -npm run test -- test/architecture/claim-boundary.test.ts -npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts -npm run quality:architecture -``` - -### Redaction And Support Payload Boundary - -Proof obligation: - -- Walkthroughs and support language do not request or expose `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, signer refs, raw store records, role-token maps, gateway credentials, or raw payment material. -- Shareable support/debug artifacts are redacted refs, reason codes, request IDs, local report sections, and local certificate verification results. - -Candidate gate: - -```bash -npm run quality:claims -``` - -## Required Closeout Commands - -Run focused gates first: - -```bash -npm run quality:claims -npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts -``` - -Run demo gate if `examples/x402-protected-spend/run.ts` changes: - -```bash -npm run demo:aps -``` - -Run architecture/package posture gates if lane manifests or public docs change: - -```bash -npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts -npm run quality:architecture -``` - -Run final formatting and repo gate: - -```bash -npm run format:check -npm run check:repo -``` - -If implementation touches runtime, MCP, or x402 proposal internals despite the cut line, add: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/mcp/mcp-x402-proposal.test.ts test/adapters/x402-payment-action-proposal.test.ts -``` - -That should be exceptional. A need for those tests means the slice may be drifting from claim cleanup into capability work. - -## Blocked In This Synthesis - -- No tests were run; this chair task was planning-only. -- No external x402, npm, MCP Registry, JWKS, Cloudflare, legal, or payment-regulatory verification was performed. -- Package script definitions were not re-read from `package.json` because the run input provided the command contract and this chair stayed inside the allowed source boundary. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md deleted file mode 100644 index f0bb016..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md +++ /dev/null @@ -1,148 +0,0 @@ -# Macro Plan Input: Claim Boundary Cleanup - -Run ID: `claim-boundary-cleanup-20260524T065926Z` - -## Target - -Create a source-grounded macro plan for critical-path item 0 from `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md`: **Claim Boundary Cleanup**. - -Goal: remove ambiguity before adding new capability. The plan must define the implementation path for making eliminated items intentional product boundaries, not pending promises or roadmap-shaped claims. - -Important correction from the user: Handshake is **not specific to engineering agents**. Handshake is protected actions for automated decision making. The current first wedge is x402 protected actions, and engineering-agent workflows are an adoption context, not the category boundary. The plan must preserve modularity so the protocol can extend beyond the first wedge without turning any wedge into the protocol definition. - -## User Constraints - -- Use `$gsd-macro-plan` as a subagent-first workflow. -- This is planning only. Do not implement source changes under this run. -- Keep Tier 1 protocol/kernel meaning stable. -- Treat protected actions for automated decision making as the product category. -- Treat x402 as the first wedge unless source evidence proves a narrower implementation sequence is required. -- Do not make engineering agents the product boundary; treat them as one current adoption context. -- Do not weaken the Tier 2 x402 exact per-call wedge. -- Preserve customer-owned gateway custody as the future enforcement model. -- Do not turn Handshake into payment management, generic agent governance, hosted observability, settlement, marketplace, certification, or broad runtime control. -- Plans must be executable later: source-owned mechanisms, tests, claim guards, closeout gates, and cut lines. - -## Source Boundary - -Allowed source files for first-pass agents: - -- `AGENTS.md` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` -- `.planning/macro/README.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `.planning/codebase/ARCHITECTURE.md` -- `.planning/codebase/CONCERNS.md` -- `.planning/codebase/CONVENTIONS.md` -- `.planning/codebase/INTEGRATIONS.md` -- `.planning/codebase/STACK.md` -- `.planning/codebase/STRUCTURE.md` -- `.planning/codebase/TESTING.md` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` -- `test/product/x402-protected-spend-demo-report.test.ts` -- `examples/x402-protected-spend/README.md` -- `examples/x402-protected-spend/run.ts` -- `examples/self-hosted-activation/README.md` -- `src/runtime/LANE.md` -- `src/mcp/LANE.md` -- `src/cli/LANE.md` -- `src/sdk/LANE.md` -- `src/adapters/LANE.md` -- `src/conformance/LANE.md` - -Forbidden files for first-pass agents: - -- sibling raw outputs under this run; -- normalized outputs under this run; -- the final `PLAN.md` for this run before chair synthesis; -- unrelated historical `.planning/macro/archive/**` files unless a specific current source file links to them; -- source files not listed above unless the agent first records why the listed source packet is insufficient. - -## Required Output Directory - -All artifacts for this item must stay under: - -```text -.planning/macro/active/claim-boundary-cleanup/ -``` - -First-pass outputs: - -```text -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/STRATEGY.md -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ARCH.md -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/EXECUTION.md -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/RISK.md -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ADOPTION.md -``` - -Chair outputs: - -```text -.planning/macro/active/claim-boundary-cleanup/PLAN.md -.planning/macro/active/claim-boundary-cleanup/CONTEXT.md -.planning/macro/active/claim-boundary-cleanup/ASSUMPTIONS.md -.planning/macro/active/claim-boundary-cleanup/DECISIONS.md -.planning/macro/active/claim-boundary-cleanup/RISKS.md -.planning/macro/active/claim-boundary-cleanup/VALIDATION.md -.planning/macro/active/claim-boundary-cleanup/TASKS.jsonl -.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md -``` - -## Plan Requirements - -The chair plan must include: - -- goal; -- non-goals; -- source boundary; -- current state; -- target state; -- assumptions; -- decisions; -- phases; -- task graph; -- risks and mitigations; -- validation gates; -- cut lines; -- rollback / stop conditions; -- smallest next action. - -The plan must explicitly cover: - -- replacing "spend reservation ledger required before claim" wording with "aggregate payment-budget management intentionally out of current remit" where source evidence supports that cleanup; -- identifying source language that over-constrains Handshake to engineering agents and planning how to restate it as protected actions for automated decision making without overclaiming broad runtime control; -- keeping `not_enforced_local_metadata` only where clearly local metadata; -- adding or strengthening claim guards so docs/examples cannot imply payment management, settlement, seller/facilitator operation, hosted trust, broad x402 compatibility, broad runtime/MCP/CLI/browser/shell/network/package-manager control, marketplace/certification, clearing-house readiness, or cross-org certificate trust; -- preserving per-call x402 exact authorization as the current wedge; -- preserving modular adapter/action-pack discipline so x402 proves the spine but does not define it; -- preserving customer-owned gateway custody, terminal evidence, proposal/evidence surfaces, and one protected-action-pack-at-a-time discipline; -- identifying which checks are already green versus planned; -- identifying what must remain deferred or eliminated. - -## Success Criteria - -- The macro plan is executable as a future implementation slice without altering Tier 1 protocol meaning. -- The plan corrects category language toward protected actions for automated decision making while preserving source-backed boundaries. -- The plan narrows claim language and tests; it does not add authority, custody, payment management, settlement, or hosted operation. -- Each task names source/test/doc candidate paths and closeout evidence. -- `TASKS.jsonl` parses as JSONL. -- Validation gates are specific enough to fail overclaims. -- The plan names antipatterns and stop conditions. - -## External Verification - -This item is mostly repo-claim cleanup. Do not browse by default. If a perspective proposes npm, MCP Registry, JWKS, Cloudflare, x402, or legal/payment-regulatory language as part of this specific slice, it must explicitly mark that as out of scope or require external verification before implementation. - -## 10 Star Product Bar - -Claim cleanup is successful when a sophisticated buyer, maintainer, auditor, or future agent cannot misread local proof lanes as broad product authority or misread the first adoption context as the whole category. Handshake should read as smaller, sharper, and harder to fake: protected actions for automated decision making, proven first through x402 exact per-call authorization, with exact contract, one-use greenlight, gateway check, redacted evidence, proof gap, and terminal evidence only where the source actually enforces them. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ADOPTION.md deleted file mode 100644 index 1592ee0..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ADOPTION.md +++ /dev/null @@ -1,207 +0,0 @@ -# ADOPTION First-Pass Plan: Claim Boundary Cleanup - -## Invariant at stake - -Adoption material must not turn a local proof lane into a product claim. A new user, maintainer, buyer, auditor, or future agent must understand that Handshake is protected actions for automated decision making, currently proven through a narrow x402 exact per-call protected-action wedge. Engineering-agent workflows are an adoption context, not the category boundary. - -If the docs teach "engineering agents" as the product category, the compiler overreaches the principal. If the x402 walkthrough teaches spend budgeting, settlement, hosted trust, seller/facilitator operation, or broad runtime control, the adoption surface is advisory theatre. - -## Source posture used - -Allowed packet read: `.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/input.md`. - -Allowed source files read for this pass included the canonical docs, current macro register, codebase maps, claim-boundary tests, x402 product report test, x402 walkthrough/readme, self-hosted activation readme, and source lane manifests named by the input packet. - -No sibling raw outputs, normalized outputs, or final `PLAN.md` were read. - -## Adoption path - -1. Establish the category vocabulary first. - - Candidate paths: `README.md`, `AGENTS.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`, `docs/internal/protocol-layman.md`. - - Replace top-level "contracted execution infrastructure for engineering agents" posture with "protected actions for automated decision making" or "protocol kernel for protected action control" where the statement defines the product category. - - Preserve engineering-agent examples only where they are explicitly framed as the current adoption context or one generated-execution source. - - Do not change the Tier 1 primitive: exact action contract -> policy decision -> one-use greenlight -> gateway check -> receipt/refusal/proof gap. - -2. Make x402 the first wedge, not the protocol definition. - - Candidate paths: `README.md`, `docs/internal/decisions.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `examples/x402-protected-spend/README.md`, `examples/x402-protected-spend/run.ts`. - - Teach the first-use path as one installed protected action pack: one official buyer-side `x402_payment.exact` per-call attempt. - - Keep `x402_paid_http_call.exact` as buyer-readable report language only unless the action catalog, compiler, policy, and gateway all expose that action class. - - Keep "No adapter family defines the protocol" visible near the first x402 walkthrough. - -3. Reframe aggregate spend as intentionally outside current remit. - - Candidate paths: `README.md`, `examples/x402-protected-spend/run.ts`, `test/architecture/claim-boundary.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`. - - Replace "spend reservation ledger required before claim" and "until a ledger exists" style language with "aggregate payment-budget management is intentionally out of current remit" where the source is describing product scope. - - Keep `not_enforced_local_metadata` only where it labels local metadata and cannot be read as a planned spend-window feature. - - The adoption message should be: Handshake authorizes one exact x402 protected action attempt; it does not manage budgets, reservations, or payment programs. - -4. Turn the first-use path into a claim-boundary walkthrough. - - Candidate paths: `README.md`, `examples/x402-protected-spend/README.md`, `examples/self-hosted-activation/README.md`. - - The first-use path should ask the user to run `npm run demo:aps`, inspect `examples/x402-protected-spend/output/latest.md`, and verify these boundaries: - - 402 challenge evidence exists before authority. - - Runtime proposal creates no policy, greenlight, gateway check, mutation, receipt, or certificate. - - Policy greenlights one exact contract. - - Gateway check precedes signing. - - Signed retry is downstream fixture evidence, not authority. - - Replay refuses before signer reuse. - - Proof gaps remain proof gaps. - - Terminal certificate is local pinned terminal evidence only. - -5. Keep support and debugging redacted from first use. - - Candidate paths: `README.md`, `src/sdk/LANE.md`, `examples/x402-protected-spend/README.md`. - - First-use docs should tell users to share only redacted report refs, reason codes, request identities, projection payloads, and local certificate verification results. - - They must not share `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, signer refs, raw store records, role-token maps, or gateway credentials. - -6. Preserve role-scoped activation ergonomics. - - Candidate paths: `README.md`, `examples/x402-protected-spend/run.ts`, `src/sdk/LANE.md`, `test/product/x402-protected-spend-demo-report.test.ts`. - - Keep first-slice activation on `RuntimeClient` and `EvidenceClient` from `handshake-protocol-kernel/sdk/role-clients`. - - Keep all-role `HandshakeClient` out of product walkthroughs because it teaches a mixed-custody shape. - -## First-use checklist - -For the future implementation slice, first-use docs should let a user complete this exact path: - -1. Read the top-level category: Handshake protects actions for automated decision making through installed gateway-checked paths. -2. Confirm the local setup command: `bun install --frozen-lockfile`. -3. Run the repo gate: `npm run check:repo`. -4. Run the x402 first wedge: `npm run demo:aps`. -5. Open `examples/x402-protected-spend/output/latest.md`. -6. Confirm the report shows the exact action class `x402_payment.exact`, not a generic payment manager. -7. Confirm the report's non-claims include no hosted operation, no provider/customer custody, no aggregate payment-budget management, no settlement finality, no seller/facilitator operation, no broad x402 compatibility, no broad MCP/CLI/browser/shell/network control, no cross-org certificate trust, no marketplace/certification, and no clearing-house readiness. -8. Confirm the gateway/signing section says signer invocation happens only after `VerifiedGatewayCheck`. -9. Confirm replay refusal does not reuse the signer. -10. Confirm support/debugging instructions use redacted refs and reason codes only. - -## Missing docs and examples - -- Missing category correction in top-level canonical language. - - Current issue: `README.md`, `AGENTS.md`, and `docs/internal/decisions.md` still contain category-level engineering-agent language. - - Fix: top-level category should become protected actions for automated decision making; engineering-agent execution remains a current adoption context and generated-execution source. - -- Missing wedge ladder. - - Fix: add a compact ladder in `README.md` and `docs/internal/decisions.md`: - - category: protected actions for automated decision making; - - protocol primitive: exact contract, policy, one-use greenlight, gateway check, receipt/refusal/proof gap; - - first wedge: x402 exact per-call protected action; - - current adoption context: automated engineering/runtime workflows; - - local proof boundary: local/reference only, no hosted/provider/cross-org claims. - -- Missing "how to read the APS report" guide. - - Fix: in `examples/x402-protected-spend/README.md`, explain each report section as adoption evidence: challenge before authority, proposal not permission, gateway check, signed retry evidence, replay refusal, proof gap, terminal certificate, non-claims. - -- Missing aggregate payment-budget cut-line language. - - Current issue: source/test language still treats "spend reservation ledger" as a missing proof object for future aggregate spend enforcement. - - Fix: replace with "aggregate payment-budget management intentionally out of current remit" in docs/report fields where the claim boundary is product scope rather than local metadata. - -- Missing support/debuggability playbook. - - Fix: add a short support section to the x402 walkthrough and/or README that says exactly which redacted artifacts can be shared and which credential/payment fields must never be requested. - -- Missing claim guard for engineering-agent category drift. - - Fix: strengthen `test/architecture/claim-boundary.test.ts` so top-level category statements cannot define Handshake as only engineering-agent infrastructure while still allowing engineering-agent workflows as example/adoption context. - -- Missing claim guard for report proof-object label. - - Fix: strengthen `test/product/x402-protected-spend-demo-report.test.ts` so `x402_paid_http_call.exact` remains classified as buyer-readable report language, not the action catalog class. - -## Success metrics - -- A buyer can state the product category after reading the first screen of `README.md`: protected actions for automated decision making, not generic agent governance and not only engineering agents. -- A developer can run `npm run demo:aps` and identify the exact contract, policy decision, gateway check, signed retry evidence, replay refusal, proof gap posture, and terminal evidence boundary without reading source internals. -- `npm run quality:claims` fails if canonical docs imply payment management, settlement, seller/facilitator operation, hosted trust, broad x402 compatibility, broad runtime/MCP/CLI/browser/shell/network/package-manager control, marketplace/certification, clearing-house readiness, or cross-org certificate trust. -- `test/product/x402-protected-spend-demo-report.test.ts` fails if the report describes aggregate payment-budget management as a near-term missing implementation rather than an intentional current non-remit. -- First-use examples import `RuntimeClient` and `EvidenceClient` from `handshake-protocol-kernel/sdk/role-clients` and do not import `HandshakeClient`. -- Search over canonical docs and walkthroughs finds engineering-agent language only as an adoption context, generated-execution example, or first-wedge operating environment, not as the protocol category. -- Search over x402 walkthrough/report output finds `not_enforced_local_metadata` only next to clearly local metadata, never as enforced spend control. - -## Adoption blockers and fixes - -| Blocker | Adoption failure | Fix | -| --- | --- | --- | -| Engineering-agent language defines the category | Buyers and future implementers think Handshake is a coding-agent tool, not protected actions for automated decision making | Rewrite category claims in canonical docs; add claim guard that allows engineering-agent examples only with context qualifiers | -| x402 first wedge reads like payment management | Users expect budgets, settlement, facilitator/seller roles, or provider custody | Make aggregate payment-budget management an explicit non-remit; keep per-call x402 exact as the only current spend authority | -| "Spend reservation ledger" reads like pending roadmap | Future work drifts into payment-program features just to satisfy an old claim | Replace product-scope occurrences with intentional non-remit language; leave ledger only as local metadata language if needed | -| Report proof object differs from action class | Users think `x402_paid_http_call.exact` is gateway-bound authority | Label it as buyer-readable only and guard action class remains `x402_payment.exact` | -| Self-hosted activation packet composes many surfaces | Users infer MCP/CLI/runtime are mutation or authority surfaces | Put proposal/evidence-only disclaimers directly next to activation commands and artifacts | -| Role-scoped SDK path is easy to bypass | Examples drift back to all-role client ergonomics | Keep product walkthroughs on role clients and assert the example source does not import `HandshakeClient` | -| Support path is underdocumented | Debugging requests may solicit payment signatures, raw records, or credentials | Add a support payload allowlist and forbidden field list to first-use docs | -| Package/registry/readiness language can overclaim availability | Users infer public distribution or endorsement from local metadata | Keep publication/registry claims deferred unless externally verified and owner-held credentials prove publication | - -## Assumptions - -- The user correction overrides stale category wording in current source: Handshake is protected actions for automated decision making. -- x402 remains the first wedge unless later source evidence proves a narrower implementation sequence. -- Tier 1 protocol/kernel meaning remains stable. -- This slice is claim cleanup only. It should not add custody, hosted operation, payment-budget management, settlement, provider integration, or runtime interception. -- Claim-boundary tests are the right enforcement surface for adoption language. -- `.planning/` remains scratch and must not become canonical repo truth. - -## Dependencies - -- Canonical docs: `README.md`, `AGENTS.md`, `docs/internal/decisions.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`. -- Adoption examples: `examples/x402-protected-spend/README.md`, `examples/x402-protected-spend/run.ts`, `examples/self-hosted-activation/README.md`. -- Guard tests: `test/architecture/claim-boundary.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`. -- Lane boundaries: `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/sdk/LANE.md`, `src/adapters/LANE.md`, `src/conformance/LANE.md`. -- Validation commands named by allowed docs: `npm run quality:claims`, `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts`, `npm run check:repo`. - -## Risks - -- Overcorrection risk: replacing engineering-agent category language with "automated decision making" could sound like broad governance unless every occurrence is tied back to installed protected paths. -- Wedge confusion risk: x402 can prove the spine without defining the protocol; docs must keep this hierarchy explicit. -- Payment-regulatory risk: "budget", "reservation", "settlement", "facilitator", "seller", and "clearing house" language can imply payment-management scope. Use non-claim language, not roadmap language. -- Support risk: a user debugging a failed local run may expose credential material unless the docs state a redacted support payload. -- MCP/CLI risk: local proposal/evidence surfaces can look like control surfaces if the first-use path puts them before the x402 authority chain. -- Claim-test brittleness risk: naive regex bans can block valid "engineering-agent adoption context" text. Guards should distinguish category statements from examples. -- External availability risk: publication, MCP Registry, JWKS, provider custody, and x402 legal/payment claims require external verification and are outside this cleanup slice. - -## Validation gates - -Planning gates for the future implementation slice: - -1. Category language gate. - - Search canonical docs and examples for category-level "engineering agents" wording. - - Pass only if engineering-agent references are context/examples, not product boundary. - -2. x402 wedge gate. - - `test/architecture/claim-boundary.test.ts` must keep "No adapter family defines the protocol" and one official buyer-side exact per-call boundary. - - It must reject broad x402 compatibility, facilitator/seller/settlement, hosted trust, and broad runtime claims. - -3. Aggregate payment-budget gate. - - `test/product/x402-protected-spend-demo-report.test.ts` must assert aggregate payment-budget management is outside current remit. - - It must not require a "spend reservation ledger" as a future claim prerequisite unless clearly labeled local metadata and not product scope. - -4. First-use output gate. - - `npm run demo:aps` must produce `examples/x402-protected-spend/output/latest.md` and `.json` with non-claims and missing-proof posture that cannot be read as authority. - -5. Role-client gate. - - Product walkthroughs must use `RuntimeClient` and `EvidenceClient` and must not import `HandshakeClient`. - -6. Support redaction gate. - - Docs must contain a support payload allowlist and forbidden credential/payment fields. - -7. Closeout gate. - - Run: - - `npm run quality:claims` - - `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts` - - `npm run check:repo` - -## Cut lines - -- No hosted operation. -- No payment management. -- No aggregate payment-budget management. -- No settlement or downstream business-success claims. -- No facilitator operation. -- No seller middleware. -- No provider/customer custody claim from local fixtures. -- No broad x402 compatibility. -- No broad MCP, CLI, browser, shell, package-manager, network, cloud, repo, or database control. -- No marketplace, certification, clearing-house, or cross-org trust claim. -- No public package or MCP Registry availability claim without external verification and owner-held publication evidence. -- No review UI, approval, or rendered report as authority unless structurally bound to the exact action contract and enforced at gateway time. -- No mutation, signer access, receipt export, or certificate minting through SDK/MCP/CLI first-use surfaces. - -## Blocked checks - -- Did not run validation commands; this is a planning-only first-pass output. -- Did not verify `package.json` scripts directly because `package.json` was not in the allowed source boundary. Commands were taken from allowed docs. -- Did not externally verify x402, npm, MCP Registry, JWKS, Cloudflare, or legal/payment-regulatory language; the input packet says not to browse by default for this slice. -- Did not inspect source files outside the input packet allowlist, including implementation files referenced by allowed docs. -- Did not inspect sibling raw outputs, normalized outputs, or final `PLAN.md`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ARCH.md deleted file mode 100644 index c0d296c..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/ARCH.md +++ /dev/null @@ -1,141 +0,0 @@ -# ARCH First Pass: Claim Boundary Cleanup - -## Invariant At Stake - -Handshake must not let category language become authority language. The architecture can support protected actions for automated decision making, with x402 as the first wedge, only if repo canon keeps the authority spine stable: - -```text -exact action contract --> policy decision --> one-use greenlight or refusal --> gateway check before mutation --> receipt, refusal, proof gap, or terminal evidence -``` - -If cleanup turns into broad runtime control, payment management, hosted trust, or a protocol rewrite, it weakens the boundary. If cleanup leaves "engineering agents" as the product boundary, the repo misstates the category and will keep producing wedge-shaped strategy errors. - -## Architecture Implications - -- This is a claim and guard migration, not a Tier 1 protocol migration. `docs/internal/protocol-definition.md` already defines the core as "protected action control" and should remain the authority rule source. -- Product category language should move from "contracted execution infrastructure for engineering agents" to protected actions for automated decision making. Engineering-agent workflows remain an adoption context and evidence source, not the protocol boundary. -- x402 should be presented as the current first protected-action wedge: one official buyer-side `x402_payment.exact` per-call path. It must not become the protocol definition. -- Existing protocol participant names such as `agentId`, `AgentTransactionEnvelopeProjection`, runtime evidence, and generated-execution graph should not be renamed in this slice. "Agent" remains a participant/evidence role where source objects already use it; it should stop being the top-level category claim. -- Spend-window language should stop implying a ledger is required before a future claim. Aggregate payment-budget management should be named as intentionally out of current remit. `not_enforced_local_metadata` can remain only when a local metadata field is explicitly non-enforcing. -- The cleanup should strengthen `test/architecture/claim-boundary.test.ts` and `test/product/x402-protected-spend-demo-report.test.ts`, not create new authority surfaces. -- `.planning/codebase/*` identifies current runtime/x402/MCP posture drift, but `.planning/` remains scratch. Durable corrections belong in compact canon docs and tests. - -## Boundaries That Must Not Move - -- `src/protocol/**` remains the only owner of protocol meaning. Do not move product-category text into protocol objects unless the schema truly changes. -- `src/runtime/**` remains proposal/evidence only. It may observe generated decisions and propose candidates; it must not evaluate policy, issue greenlights, gateway-check, receipt, mutate, or sign. -- `src/mcp/**` and `src/cli/**` remain proposal/evidence/operator surfaces only. No mutation, signer, gateway custody, receipt export, hosted operation, or cross-org trust path belongs there. -- `src/adapters/**` remains reference gateway/profile code. Mutation-capable adapters still run only after `VerifiedGatewayCheck`. -- `src/conformance/**` remains reference posture checks, not certification or standards compliance. -- Customer-owned gateway custody remains the future enforcement model. Do not add Handshake-held payment custody, signer custody, balances, settlement, seller middleware, or facilitator operation. -- x402 remains per-call exact authorization only. Do not add aggregate budget management to make old wording true. -- `AuthorityCertificate` remains terminal evidence. Do not claim permission, identity, settlement, marketplace certification, hosted verifier operation, or cross-org trust. - -## Likely Source/Test/Doc Paths - -### Canonical Docs To Update - -- `AGENTS.md`: replace category-level "contracted execution infrastructure for engineering agents" and "first wedge is engineering-agent actions" with protected actions for automated decision making; retain engineering-agent examples as current adoption context and generated-execution pressure case. -- `README.md`: update headline, system-design posture, and x402 demo language so the repo reads as a protected-action kernel with x402 as first wedge. -- `docs/internal/decisions.md`: update "Product Kernel", "Current Bought Product", and "Claims Boundary" so the durable decision is category-first, wedge-second. -- `docs/internal/protocol-definition.md`: likely only small wording cleanup. Preserve "protocol kernel for protected action control" and authority rule exactly. -- `docs/internal/protocol-kernel-architecture.md`: update architecture summary/local establishment wording only where it implies engineering agents define the protocol. -- `docs/internal/protocol-layman.md`: restate "agents will do real work through tools" as one common automated-decision actor, not the category limit. -- `docs/internal/protocol-notes.md`: update "Use case: reduce generated engineering-agent execution..." to protected-action attempts from automated decision systems, with generated engineering-agent execution as current pressure case. -- `examples/x402-protected-spend/README.md`: change scope from "generated engineering-agent execution evidence" to automated decision / generated execution evidence, with engineering-agent workflow as the local demo context if needed. -- `examples/self-hosted-activation/README.md`: likely keep non-claims; check for category drift during implementation. - -### Tests And Guards To Update - -- `test/architecture/claim-boundary.test.ts`: add guard that canon contains protected actions for automated decision making and does not define the product as engineering-agent-only. Also guard against payment management, settlement, seller/facilitator, hosted trust, broad x402 compatibility, broad runtime control, marketplace/certification, and cross-org certificate trust. -- `test/product/x402-protected-spend-demo-report.test.ts`: replace expectation that `missingProofObjects` contains "spend reservation ledger" with wording that marks aggregate payment-budget management out of remit or absent by design. Keep assertions for per-call exact authorization, local/reference sandbox, gateway-held signer, replay refusal, proof gap, and non-claims. -- `test/architecture/import-posture.test.ts`: likely no direct change unless doc cleanup touches lane manifest boundaries. Keep as validation gate. -- `test/architecture/root-exports.test.ts`: likely no direct change. Run to prove claim cleanup did not move public surfaces. - -### Source/Demo Paths Likely Touched By Claim Text - -- `examples/x402-protected-spend/run.ts`: update report strings such as "Premium context for one generated engineering-agent request", missing proof object label "spend reservation ledger", and final local-evidence disclaimer if needed. Do not alter authority flow. -- `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/cli/LANE.md`, `src/sdk/LANE.md`, `src/adapters/LANE.md`, `src/conformance/LANE.md`: only update category wording if a lane describes the product boundary. Keep lane-specific authority owner and forbidden imports stable. - -## Data And Control Flow To Preserve - -```text -automated decision / generated execution evidence --> runtime or MCP proposal surface --> intent compilation --> CandidateAction --> ActionContract --> PolicyDecision --> Greenlight --> GatewayCheck --> x402 wallet gateway creates signature evidence after verified gate --> local/reference signed retry evidence --> Receipt / Refusal / ProofGap / terminal certificate evidence -``` - -The first node can be generalized from "engineering agent" to automated decision making. The rest of the flow must not change in this slice. - -## Compatibility And Migration Risks - -- Category rename risk: a broad text replacement of "agent" would corrupt protocol participant semantics, exported schema names, and tests. The migration must distinguish product-category text from existing participant/evidence object names. -- Demo-contract risk: `examples/x402-protected-spend/run.ts` currently emits buyer-readable report fields consumed by `test/product/x402-protected-spend-demo-report.test.ts`; changing labels without updating assertions will break the product gate. -- Scratch-canon risk: `.planning/codebase/CONCERNS.md` still recommends adding a spend reservation ledger before claiming aggregate spend enforcement. The current run should override that as eliminated scope, but only in the active macro plan; do not promote scratch maps as canon. -- Wedge inversion risk: making x402 the product category would create the same architecture error as engineering-agent-only language. The protocol must remain adapter-pack modular. -- Surface drift risk: updating MCP/CLI/SDK docs for category clarity can accidentally imply those surfaces authorize or protect work. Claim guards must keep non-authority flags explicit. -- External verification risk: no external x402, MCP Registry, npm, JWKS, Cloudflare, or legal/payment claims should be added in this slice. Any such claim must be blocked until separately verified. - -## Architecture Validation Gates - -- `npm run quality:claims` -- `npm run quality:architecture` -- `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts` -- `npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts` -- `npm run format:check` -- Final implementation closeout should run `npm run check:repo` if the slice touches docs, tests, or demo report generation. - -## Assumptions - -- The user correction is authoritative for this plan: protected actions for automated decision making is the category; engineering agents are an adoption context. -- Tier 1 protocol objects and source authority boundaries are stable and should not be renamed in this slice. -- x402 remains the first wedge because the current source packet proves the strongest local/reference path there. -- Aggregate x402 payment-budget management is eliminated from current remit, not deferred as a required future ledger for the current wedge. -- The macro plan will be implemented later; this first pass must not change source beyond this assigned raw output. - -## Dependencies - -- Canon docs must be updated before claim guards can be made strict without producing confusing failures. -- Demo report string changes in `examples/x402-protected-spend/run.ts` and assertion changes in `test/product/x402-protected-spend-demo-report.test.ts` should land together. -- Claim-boundary guards should drive the cleanup so future docs cannot reintroduce engineering-agent-only category language or payment-management claims. -- Architecture and root export tests provide regression proof that the cleanup did not move authority across package/lane boundaries. - -## Risks - -- Over-generalization: "automated decision making" can become generic agent governance if not tied back to protected actions, exact contracts, and gateway checks. -- Under-correction: leaving README/AGENTS/decisions as engineering-agent-first will keep future plans scoped to the wrong market and adoption model. -- Payment-regulatory drift: replacing "spend reservation ledger" poorly can still imply Handshake manages budgets, wallets, or settlement. Use "aggregate payment-budget management intentionally out of current remit" where applicable. -- x402 monopoly drift: x402 proof language can overfit the protocol to payments. Keep "adapter/action pack" and "one protected action pack at a time" discipline visible. -- Evidence theatre: buyer-readable report labels like `x402_paid_http_call.exact` must stay report labels, not action-catalog or gateway-bound authority types unless future source implements them. - -## Cut Lines - -- Do not implement a spend ledger, wallet custody, settlement, facilitator, seller middleware, or hosted verifier in this slice. -- Do not rename exported protocol schemas or root package surfaces to remove "agent" terminology. -- Do not add new public package exports, package scripts, CI names, or source folders. -- Do not modify `src/protocol/**` behavior unless a test proves a claim guard cannot be expressed without a source-owned predicate. -- Do not use `.planning/` files as active repo truth beyond this macro-planning run. -- Do not browse or add external standards claims for x402, MCP Registry, npm, JWKS, Cloudflare, or legal/payment posture. - -## Blocked Checks - -- Could not verify actual current test results because this first-pass role is planning-only and must not run implementation gates. -- Could not inspect unlisted implementation files such as `src/adapters/x402-payment/action-proposal.ts`, `src/adapters/x402-payment/install-proposal.ts`, `src/runtime/ingress/index.ts`, `src/mcp/x402-proposal.ts`, `src/surfaces/boundary-manifest.ts`, or `package.json`; path recommendations come from the allowed source packet and codebase maps. -- Could not confirm whether `not_enforced_local_metadata` appears outside the allowed packet; implementation should search the full repo during the execution slice. -- Could not confirm generated example outputs under `examples/*/output/`; implementation should regenerate affected demos before final claim gates if report text changes. - -## Smallest Next Mechanism To Build - -Strengthen `test/architecture/claim-boundary.test.ts` first so the repo fails when canonical docs define Handshake as engineering-agent-only or imply aggregate payment-budget management, then update canon/docs/demo strings until that guard passes without touching Tier 1 behavior. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/EXECUTION.md deleted file mode 100644 index 0c3e8f1..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/EXECUTION.md +++ /dev/null @@ -1,423 +0,0 @@ -# EXECUTION First Pass: Claim Boundary Cleanup - -## Invariant at stake - -The implementation plan must prevent broad product language from becoming fake authority. Handshake should read as protected actions for automated decision making, proven first through one x402 exact per-call protected action wedge, without changing Tier 1 protocol meaning or implying payment management, hosted operation, provider custody, settlement, broad runtime control, or engineering agents as the category boundary. - -## Execution posture - -- Planning only. No implementation was performed in this pass. -- Source boundary honored: this pass used the immutable input packet and the allowed source files named there. -- `.planning/` is derived scratch. It can guide the cleanup plan, but durable repo truth must land in `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, and `docs/internal/*`. -- Tier 1 protocol/kernel meaning should remain stable. The work is claim, documentation, report, and guard cleanup unless a failing claim guard requires a narrow source-output adjustment. - -## Recommended phase sequence - -### Phase 0: Claim inventory and exact target language - -Purpose: create the edit map before touching source. - -Tasks: - -- Inventory current category claims across `AGENTS.md`, `README.md`, `docs/internal/decisions.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`, `examples/x402-protected-spend/README.md`, `examples/x402-protected-spend/run.ts`, `examples/self-hosted-activation/README.md`, and lane manifests. -- Classify each claim as one of: - - category claim: protected actions for automated decision making; - - first wedge claim: x402 exact per-call protected action; - - current adoption context: engineering-agent workflows/generated execution; - - local/reference evidence only; - - explicit non-claim/cut line. -- Identify every "engineering agents" phrase that currently defines the product rather than describing an adoption context. -- Identify every "spend reservation ledger" or ledger-required-before-claim phrase and decide whether it is: - - authority idempotency ledger language that remains valid; - - aggregate payment-budget management language that should be cut as intentionally out of current remit; - - local metadata language that may keep `not_enforced_local_metadata`. - -Owner: implementation lead. - -Closeout evidence: claim inventory in the implementation PR description or support note, not a new repo-facing canon file. - -### Phase 1: Test-first claim guards - -Purpose: make overclaim failures mechanical before rewriting docs. - -Tasks: - -- Strengthen `test/architecture/claim-boundary.test.ts` to require: - - category wording does not define Handshake as engineering-agent-only; - - canonical docs state protected actions for automated decision making; - - engineering-agent/generated-execution wording is adoption context or runtime evidence context; - - x402 is the first wedge/action pack, not the protocol definition; - - current x402 enforcement is exact per-call only; - - aggregate payment-budget management is intentionally out of current remit; - - docs/examples do not imply payment management, settlement, seller middleware, facilitator operation, hosted trust, provider custody, marketplace/certification, broad runtime control, broad x402 compatibility, or cross-org certificate trust. -- Strengthen `test/product/x402-protected-spend-demo-report.test.ts` to require: - - the buyer-readable report no longer lists "spend reservation ledger" as a missing proof object required before an aggregate spend claim; - - aggregate payment-budget management appears as a non-claim or out-of-remit boundary; - - `not_enforced_local_metadata` is only represented as local metadata, not a deferred promise; - - `x402_paid_http_call.exact` stays a buyer-readable label and not an action catalog authority type; - - x402 report language names automated decision/protected action context without erasing generated execution evidence. -- If the implementation inventory confirms active vocabulary tests scan these surfaces, update `test/architecture/active-vocabulary.test.ts` as a follow-up candidate. This file was not opened in this first-pass source boundary. - -Owner: test owner. - -Dependency: Phase 0 inventory. - -Closeout evidence: initial failing focused test slice, then green after source/doc cleanup. - -### Phase 2: Canonical category rewrite - -Purpose: align durable repo truth to the user correction without expanding authority. - -Tasks: - -- Update `AGENTS.md` category doctrine: - - from "contracted execution infrastructure for engineering agents"; - - to protected actions for automated decision making; - - keep generated engineering-agent execution as the current adoption context and threat model. -- Update `README.md` first screen and system design posture: - - describe this checkout as a TypeScript protocol kernel for protected action control; - - state x402 exact per-call protected action as the current first wedge; - - remove engineering-agent phrasing where it defines category; - - keep runtime/generated execution language where it describes evidence inputs. -- Update `docs/internal/decisions.md`: - - Product Kernel: category becomes protected actions for automated decision making; - - first credible wedge becomes x402 exact per-call protected actions; - - "engineering-agent actions" becomes adoption context / current workflow context; - - first bought product remains narrow only if framed as one automated decision workflow around one protected action, not category. -- Update `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md`, and `docs/internal/protocol-notes.md` only where needed: - - preserve the primitive and authority rule; - - avoid changing protocol object semantics; - - shift use-case phrasing from "generated engineering-agent execution" to "automated decision/runtime generated execution" where it is category-defining; - - keep examples that are explicitly generated execution or coding-agent adoption examples. - -Owner: docs/canon owner. - -Dependencies: Phase 1 claim guard draft. - -Closeout evidence: claim-boundary tests prove the category language cannot regress. - -### Phase 3: x402 protected-action report cleanup - -Purpose: keep the first wedge strong while cutting payment-management implication. - -Tasks: - -- Update `examples/x402-protected-spend/README.md`: - - scope becomes one official buyer-side `x402_payment.exact` protected action attempt from automated/generated execution evidence; - - retain "generated engineering-agent" only as one demo context if needed; - - keep cut lines for no provider custody, no aggregate x402 spend windows, no facilitator/seller/settlement, no broad x402 compatibility. -- Update `examples/x402-protected-spend/run.ts` report fields: - - replace `missingProofObjects` entry `spend reservation ledger` with an out-of-remit/non-claim object such as `aggregate payment-budget management`; - - make `requiredBeforeClaim` stop implying a planned ledger is required for current claim cleanup; - - keep `spendWindowEnforcementStatus: "not_enforced_local_metadata"` only where it describes local metadata; - - keep idempotency wording as authority idempotency only, not payment settlement. -- Update `examples/self-hosted-activation/README.md` if needed: - - self-hosted packet remains local reference evidence; - - no hosted operation, provider/customer custody, cross-org trust, aggregate spend-window enforcement, clearing-house readiness, or broad host protection. - -Owner: example/product proof owner. - -Dependencies: Phase 1 product report assertions. - -Closeout evidence: `test/product/x402-protected-spend-demo-report.test.ts` and `npm run demo:aps` pass. - -### Phase 4: Lane and surface boundary alignment - -Purpose: keep package/lane manifests from reintroducing the old category or surface authority. - -Tasks: - -- Update `src/runtime/LANE.md`: - - runtime proposal evidence supports automated/generated execution; it does not define the category or issue authority. -- Update `src/mcp/LANE.md`, `src/cli/LANE.md`, and `src/sdk/LANE.md` only if current wording implies broad runtime/MCP/CLI control or category ownership. -- Update `src/adapters/LANE.md`: - - adapter proof lanes are protected-action packs; - - x402 is the first wedge/action pack; - - no adapter family defines the protocol. -- Update `src/conformance/LANE.md`: - - conformance verifies narrow adapter/protected-action posture, not certification or provider enforcement. - -Owner: source-boundary owner. - -Dependencies: Phase 2 and Phase 3 wording decisions. - -Closeout evidence: `test/architecture/import-posture.test.ts`, `test/architecture/root-exports.test.ts`, and `test/architecture/claim-boundary.test.ts` pass. - -### Phase 5: Scratch planning register cleanup - -Purpose: stop active planning scratch from teaching future agents the wrong boundary. - -Tasks: - -- Update `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md`: - - vision/category becomes protected actions for automated decision making; - - x402 exact per-call protected action remains first wedge; - - engineering-agent workflows become adoption context, not category; - - Step 0 cleanup says aggregate payment-budget management is intentionally outside current remit, not a missing spend ledger promise. -- Treat `.planning/codebase/CONCERNS.md` as derived scratch. If implementation touches it, revise the "Spend Window Metadata" fix approach from "add a spend reservation ledger before claiming aggregate spend" to "do not claim aggregate payment-budget management in the current remit; keep local metadata only." Do not promote this scratch text to canon. - -Owner: planning hygiene owner. - -Dependencies: Phase 2 canonical wording. - -Closeout evidence: active macro scratch no longer contradicts canon. - -### Phase 6: Validation and closeout - -Purpose: prove the cleanup did not alter authority behavior or package posture. - -Tasks: - -- Run focused claim gates first. -- Run architecture/import/export gates if lane manifests, exports, or package-facing wording changed. -- Run demo/report gate after example report changes. -- Run full repo gate before declaring the slice executable/closed. -- Record any blocked checks with exact command and reason. - -Owner: implementation lead. - -Dependencies: Phases 1-5. - -Closeout evidence: command outputs and no source behavior changes beyond claim/report surfaces unless explicitly justified by test failure. - -## Task graph - -```text -T0 claim_inventory - -> T1 architecture_claim_guard - -> T2 product_report_claim_guard - -T1 architecture_claim_guard - -> T3 canonical_category_rewrite - -> T5 lane_manifest_alignment - -T2 product_report_claim_guard - -> T4 x402_report_cleanup - -T3 canonical_category_rewrite - -> T6 scratch_register_cleanup - -> T8 validation_quality_claims - -T4 x402_report_cleanup - -> T8 validation_quality_claims - -> T9 validation_demo_aps - -T5 lane_manifest_alignment - -> T7 import_export_validation - -T6 scratch_register_cleanup - -> T8 validation_quality_claims - -T7 import_export_validation - -> T10 full_repo_gate - -T8 validation_quality_claims - -> T10 full_repo_gate - -T9 validation_demo_aps - -> T10 full_repo_gate -``` - -Task IDs: - -- T0: build claim inventory and target phrase table. -- T1: strengthen `test/architecture/claim-boundary.test.ts`. -- T2: strengthen `test/product/x402-protected-spend-demo-report.test.ts`. -- T3: rewrite canonical docs. -- T4: rewrite x402 report/example language and report fields. -- T5: align lane manifests. -- T6: align active scratch register. -- T7: run import/export architecture validation. -- T8: run focused claim validation. -- T9: run APS demo/report validation. -- T10: run full repo validation. - -## Dependency map - -| Work item | Depends on | Blocks | -| --- | --- | --- | -| Claim inventory | none | all rewrite tasks | -| Architecture claim guard | claim inventory | canonical docs, lane manifests, scratch cleanup | -| Product report claim guard | claim inventory | x402 report cleanup | -| Canonical category rewrite | architecture guard | scratch cleanup, quality claims | -| x402 report cleanup | product report guard | demo/report validation | -| Lane manifest alignment | architecture guard and canonical phrasing | import/export validation | -| Scratch register cleanup | canonical category rewrite | final closeout | -| Focused validation | docs/examples/tests complete | full repo gate | -| Full repo gate | focused gates green | execution readiness | - -## Critical path - -```text -claim inventory --> claim-boundary tests fail for old category/spend wording --> canonical docs rewrite --> x402 report cleanup --> active scratch register cleanup --> focused claim/product gates --> full repo gate -``` - -The critical path is claim-test-led because this slice is primarily about preventing future overclaims. Editing docs first without a failing guard risks reintroducing the same ambiguity. - -## What can run in parallel - -After T0: - -- T1 and T2 can run in parallel. - -After T1: - -- T3 canonical docs and T5 lane manifests can run in parallel if they share a phrase table. - -After T2: - -- T4 x402 report cleanup can run independently of canonical doc edits. - -After T3: - -- T6 scratch register cleanup can run in parallel with T4/T5 as long as it mirrors canonical wording and does not invent new claims. - -Validation can be staged in parallel only after relevant files settle: - -- `test/architecture/claim-boundary.test.ts` and `test/product/x402-protected-spend-demo-report.test.ts` can run as focused slices. -- Import/export checks can run separately if lane/package surfaces change. -- `npm run check:repo` should remain last. - -## First executable step - -Add failing claim guards before source rewrites: - -```bash -npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts -``` - -Expected initial failure targets: - -- Canonical docs still define Handshake as engineering-agent infrastructure in places. -- Product/demo report still treats `spend reservation ledger` as a missing proof object rather than treating aggregate payment-budget management as intentionally out of remit. - -## Source/test/doc candidate paths - -### Canonical docs - -- `AGENTS.md` -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` - -### Examples and reports - -- `examples/x402-protected-spend/README.md` -- `examples/x402-protected-spend/run.ts` -- `examples/self-hosted-activation/README.md` - -### Architecture/product tests - -- `test/architecture/claim-boundary.test.ts` -- `test/product/x402-protected-spend-demo-report.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` -- `test/architecture/active-vocabulary.test.ts` as a candidate if implementation inventory confirms it scans the relevant terms. It was not opened in this first-pass source boundary. - -### Lane manifests - -- `src/runtime/LANE.md` -- `src/mcp/LANE.md` -- `src/cli/LANE.md` -- `src/sdk/LANE.md` -- `src/adapters/LANE.md` -- `src/conformance/LANE.md` - -### Source candidates only if claim guards require output adjustment - -These were named by allowed codebase maps but not opened directly in this first pass: - -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/action-proposal.ts` -- `src/runtime/ingress/index.ts` -- `src/mcp/x402-proposal.ts` -- `src/surfaces/boundary-manifest.ts` - -Use these only for narrow metadata/output posture fixes. Do not change protocol semantics or add aggregate spend enforcement in this slice. - -### Planning scratch - -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `.planning/codebase/CONCERNS.md` only if the implementation owner decides tracked scratch drift must be corrected. Do not treat it as canon. - -## Validation gates - -Focused gates: - -```bash -npm run quality:claims -npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts -npm run demo:aps -``` - -Architecture/package posture gates: - -```bash -npm run test -- test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts -npm run quality:architecture -``` - -Closeout gates: - -```bash -npm run format:check -npm run check:repo -``` - -If a source-output adjustment touches runtime/MCP/x402 proposal posture, add: - -```bash -npm run test -- test/runtime/runtime-ingress.test.ts test/mcp/mcp-x402-proposal.test.ts test/adapters/x402-payment-action-proposal.test.ts -``` - -## Cut lines - -- Do not change Tier 1 protocol object semantics, authority rule, gateway check semantics, greenlight consumption, idempotency behavior, or receipt/proof-gap semantics. -- Do not implement a spend reservation ledger. -- Do not describe aggregate payment-budget management as a pending near-term promise. -- Do not weaken the x402 exact per-call wedge. -- Do not make x402 the protocol definition. -- Do not make engineering agents the product category boundary. -- Do not add seller middleware, facilitator operation, settlement finality, balances, wallet custody, or payment-management claims. -- Do not add hosted operation, hosted dashboard claims, hosted verifier claims, JWKS/revocation claims, customer/provider custody claims, or cross-org trust claims. -- Do not add broad MCP/CLI/browser/shell/network/package-manager/runtime control claims. -- Do not expose CLI/MCP/runtime policy, greenlight, gateway, mutation, receipt-export, signer, or certificate-minting authority. -- Do not create new package exports, scripts, source directories, or public surfaces for this slice unless a claim guard proves the existing surface is misleading. -- Do not edit sibling raw outputs, normalized outputs, or final `PLAN.md` under this run. - -## Assumptions - -- The user correction is authoritative: Handshake category is protected actions for automated decision making. -- x402 exact per-call protected action is the first wedge for current implementation/product proof. -- Engineering-agent workflows remain important adoption context and threat model, but not the product boundary. -- Current Tier 1 protocol primitives already support the corrected category; the cleanup should not require schema or state-machine changes. -- `not_enforced_local_metadata` can remain when attached to local metadata and explicitly denied as enforcement. -- The current APS report can change wording/report fields without changing the protected action execution path. -- Validation command names are taken from allowed repo docs and codebase testing maps; package script definitions were not independently opened in this first pass. - -## Risks - -- Category over-broadening risk: "automated decision making" can sound like generic governance. Mitigation: always bind the category to protected actions and gateway-enforced consequence. -- Wedge collapse risk: making x402 the first wedge can accidentally make x402 the protocol. Mitigation: keep "adapter/action pack" language and repeat "No adapter family defines the protocol." -- Payment-management drift: ledger wording can make aggregate budgets look like an unfinished feature. Mitigation: move aggregate payment-budget management to explicit out-of-remit/non-claim language. -- Local metadata ambiguity: `not_enforced_local_metadata` can look like disabled enforcement. Mitigation: tests must require it to appear only as metadata and never as claim support. -- Test overfitting risk: exact string assertions can pass while nearby text overclaims. Mitigation: pair required phrases with forbidden regexes and scan all relevant docs/examples/lanes. -- Scratch drift risk: `.planning/codebase/CONCERNS.md` still says "add spend reservation ledger" as a fix approach. Mitigation: either update tracked scratch or record it as stale derived evidence in the final plan. -- Product proof drift: `x402_paid_http_call.exact` buyer-readable label can be mistaken for action catalog authority. Mitigation: product test must keep it explicitly non-authority until source action catalog, compiler, policy, and gateway expose it. -- Hidden implementation creep: touching `run.ts` may tempt changing x402 behavior. Mitigation: product report edits should not change gateway signing, policy, replay, receipt, or proof-gap behavior. - -## Blocked checks - -- Tests were not run in this first-pass planning role. -- External verification was not performed. The input says not to browse by default, and this slice should not add npm, MCP Registry, JWKS, Cloudflare, x402, legal, or payment-regulatory claims. -- Source files outside the allowed first-pass packet were not opened, including implementation internals named by codebase maps. Candidate source paths above need implementation-time verification before edits. -- Sibling raw outputs, normalized outputs, and the final `PLAN.md` for this run were not read. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/RISK.md deleted file mode 100644 index 51b416c..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/RISK.md +++ /dev/null @@ -1,417 +0,0 @@ -# RISK First Pass: Claim Boundary Cleanup - -## Invariant At Stake - -Claim cleanup must not silently change authority. The slice is safe only if it -narrows product language toward protected actions for automated decision making, -keeps x402 as the first protected-action wedge, preserves per-call exact -authorization, and refuses to create new claims about custody, settlement, -hosted operation, broad runtime control, or payment-budget management. - -## Scope Boundary - -This is a planning artifact for a future implementation slice. The future slice -should be docs, examples, and claim guards only unless the chair finds a -source-owned guard that must move with the wording. It must not alter Tier 1 -protocol semantics, gateway authority, policy evaluation, greenlight behavior, -receipt semantics, storage, x402 signing behavior, or adapter execution. - -Source packet evidence used: - -- `README.md` still opens with "contracted execution infrastructure for - engineering agents" and later frames the use case as generated - engineering-agent execution. -- `AGENTS.md` and `docs/internal/decisions.md` still describe the product - kernel or first credible domain in engineering-agent terms. -- `docs/internal/protocol-definition.md` gives the safer canonical primitive: - protected action control, exact action contract, policy decision, one-use - greenlight, gateway check, and receipt/refusal/proof gap. -- `docs/internal/protocol-kernel-architecture.md` and - `docs/internal/protocol-notes.md` already separate runtime evidence from - gateway enforcement and make x402 per-call only. -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` explicitly says aggregate - x402 spend-window enforcement should be eliminated from the near-term remit. -- `.planning/codebase/CONCERNS.md` still contains a derived "Fix approach" that - adds a spend reservation ledger before claiming aggregate spend enforcement; - that conflicts with the run input's correction and must be treated as scratch - risk evidence, not canon. - -## P0 Risk Register - -### P0.1 Category Boundary Remains Wrong - -Risk: If the cleanup leaves the top-level claim as "engineering agents", -Handshake remains scoped to one adoption context instead of the product category: -protected actions for automated decision making. That creates strategy and -architecture drift: future planners may make runtime/agent governance the -product boundary and treat non-engineering protected actions as out-of-scope. - -Mitigation: Update canonical product language in `README.md`, `AGENTS.md`, -`docs/internal/decisions.md`, `docs/internal/protocol-notes.md`, and any example -scope text to say protected actions for automated decision making. Keep -engineering agents only as a current adoption context or generated-execution -risk pattern. Preserve the primitive wording from -`docs/internal/protocol-definition.md`. - -Cut line: Stop the slice if a task claims Handshake provides generic automated -decision governance, generic agent safety, broad runtime control, or category -coverage beyond installed protected paths. - -Validation gate: Claim guard must fail if active canon says "Handshake is -contracted execution infrastructure for engineering agents" as the product -definition. It may allow phrases that explicitly mark engineering agents as a -current adoption context. - -### P0.2 x402 Becomes Payment Management - -Risk: Current sources contain both correct per-call x402 language and residue -that points toward a "spend reservation ledger" as a missing proof object. If -the cleanup keeps that phrasing, the repo still implies aggregate payment-budget -management is pending rather than intentionally outside the current remit. - -Mitigation: Replace "spend reservation ledger required before claim" style -phrasing with "aggregate payment-budget management intentionally out of current -remit". Keep `not_enforced_local_metadata` only where it labels local metadata, -not deferred enforcement. Keep the x402 wedge as one official buyer-side -`x402_payment.exact` per-call path. - -Cut line: No task may add a budget ledger, session/day/review enforcement, -spend reporting, balance tracking, settlement state, seller middleware, or -facilitator operation as part of claim cleanup. - -Validation gate: `test/architecture/claim-boundary.test.ts` and -`test/product/x402-protected-spend-demo-report.test.ts` should fail on -"spend reservation ledger" in active claim surfaces and should require the -intentional-out-of-remit wording where aggregate spend is discussed. - -### P0.3 Docs Create Authority Without Gateway Enforcement - -Risk: Claim cleanup can accidentally polish language into "safe", "trusted", -"controlled", or "protected" claims for paths where no customer-owned gateway -owns the mutation credential and checks the exact greenlight before mutation. -That is advisory, not Handshake. - -Mitigation: Every broadened product phrase must be paired with the installed -path rule: exact contract, one-use greenlight, customer-owned gateway check -before consequence, receipt/refusal/proof gap, and isolation/bypass evidence -where applicable. - -Cut line: Stop if a claim says Handshake protects a path without naming the -gateway enforcement boundary or if it treats runtime, MCP, CLI, SDK, review, -catalog, certificate, or receipt surfaces as authority. - -Validation gate: Claim tests must scan canonical docs and lane manifests for -hosted operation, provider custody, broad MCP/runtime/browser/shell/network -control, marketplace/certification, clearing-house readiness, and certificate -trust language unless paired with explicit non-claims. - -### P0.4 Claim Guards Are Too Narrow - -Risk: Existing `claim-boundary.test.ts` pins important README, x402 walkthrough, -runtime, adapter, conformance, and MCP language, but the source packet shows -category-risk language in `AGENTS.md`, `docs/internal/decisions.md`, -`docs/internal/protocol-notes.md`, and `examples/x402-protected-spend/run.ts`. -A prose cleanup without expanded guards will drift back. - -Mitigation: Expand guard coverage to active canon and generated report source: -`AGENTS.md`, `README.md`, `docs/internal/decisions.md`, -`docs/internal/protocol-definition.md`, -`docs/internal/protocol-kernel-architecture.md`, -`docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`, -`examples/x402-protected-spend/README.md`, -`examples/x402-protected-spend/run.ts`, `examples/self-hosted-activation/README.md`, -and the lane manifests that carry public posture claims. - -Cut line: Do not close the future implementation slice if changed wording is -not guarded by tests. Unguarded prose cleanup is reversible but not durable. - -Validation gate: `npm run quality:claims` plus the focused claim/product test -slice must fail on the old category boundary, payment-management implication, -and broad x402/runtime/hosted/custody claims. - -## P1 Risk Register - -### P1.1 x402 First Wedge Turns Into Protocol Definition - -Risk: The user correction says x402 is the first wedge, not the protocol. If -the plan overcorrects from "engineering agents" into "x402 protected spend", -Handshake becomes a payment protocol instead of a protected-action authority -spine. - -Mitigation: Say the protocol category is protected actions for automated -decision making. Say x402 is the first protected-action pack because it exercises -exact per-call authorization, gateway signer custody, replay refusal, redacted -evidence, and proof gaps. Keep "No adapter family defines the protocol." - -Cut line: Stop if `x402_payment.exact` is described as the general action model, -the protocol definition, broad x402 compatibility, or a settlement/payment -product. - -Validation gate: Claim tests should require "No adapter family defines the -protocol" or equivalent language near first-wedge status. - -### P1.2 Customer-Owned Gateway Custody Gets Cut Too Far - -Risk: Removing provider/customer custody claims can accidentally remove the -future enforcement model. The source needs to say customer-owned gateway custody -is the intended enforcement posture without claiming it is already proven. - -Mitigation: Use three states consistently: local/reference gateway fixture is -proven now; customer-owned gateway custody is future required enforcement model; -Handshake-held payment custody is out of remit. - -Cut line: Do not claim provider/customer custody is landed. Do not remove -customer-owned gateway custody from the future enforcement architecture. - -Validation gate: Canonical docs must include both a current non-claim -("not provider/customer custody") and a future boundary ("customer-owned gateway -custody before live custody claims"). - -### P1.3 Local Sandbox Evidence Gets Read As Seller Or Facilitator Operation - -Risk: The x402 walkthrough and report include local/reference 402 challenge and -signed retry evidence. A buyer can misread that as seller middleware, -facilitator operation, settlement finality, or live provider operation. - -Mitigation: Keep the sandbox labeled as local/reference downstream fixture -evidence. Keep `authorityCreated: false` before policy. Keep signed retry as -post-gateway observation, not authority or settlement. - -Cut line: No claim may say seller middleware, facilitator operation, settlement -finality, payment finality, live provider operation, or merchant fulfillment -unless a future adapter and external verification exist. - -Validation gate: Product report tests should continue checking -`settlementFinalityClaimed: false`, `facilitatorOperationClaimed: false`, -`sellerMiddlewareClaimed: false`, `providerCustodyClaimed: false`, and local -sandbox posture. - -### P1.4 Runtime/MCP/CLI Surfaces Launder Authority - -Risk: Changing category language toward automated decision making can make MCP, -CLI, runtime, SDK, or review surfaces sound like generalized control planes. The -allowed sources repeatedly state these are proposal/evidence/read surfaces only. - -Mitigation: Keep each surface's role explicit: runtime proposes, MCP proposes -and displays evidence, CLI renders local evidence, SDK sends requests and parses -responses. None evaluates policy, creates greenlights, performs gateway checks, -mutates, exports raw receipts, mints authority certificates, or holds signer -material. - -Cut line: No new public route, package subpath, CLI command, MCP tool, or SDK -client should be planned for this slice. Any such work is capability expansion, -not claim cleanup. - -Validation gate: Existing import/root export/surface posture tests should remain -green, and claim guards should fail if these surfaces are described as -authority, execution, custody, or broad host protection. - -### P1.5 Redaction And Privacy Claims Overreach - -Risk: Docs can imply privacy-grade redaction or hosted audit readiness while the -source only proves redacted local projections and known pattern coverage. The -codebase concerns note that unknown provider credential formats need fuzzing -before live provider claims. - -Mitigation: Say redacted evidence projections are local/source-owned and -diagnostic. Avoid privacy, compliance, audit-search, retention, hosted reader -authorization, or provider secret lifecycle claims. - -Cut line: Stop if the plan claims SOC/compliance readiness, hosted audit search, -production privacy posture, retention policy, or provider-grade secret lifecycle -proof. - -Validation gate: Claim tests should forbid raw credential terms in examples and -ensure redacted evidence is not described as hosted compliance evidence. - -### P1.6 External x402 Facts Drift - -Risk: The example source names x402 docs and package versions. This planning -slice is not supposed to browse. If the future implementation changes x402 -compatibility, legal/payment-regulatory language, package version claims, or -facilitator semantics without external verification, it can create false claims. - -Mitigation: Treat external x402 references as existing source basis only. Do not -change external compatibility claims or regulatory/payment language except to -narrow them. Require external verification for any positive new external claim. - -Cut line: No new npm, MCP Registry, JWKS, Cloudflare, x402 compatibility, -payment-regulatory, settlement, facilitator, or custody claim in this slice. - -Validation gate: Chair plan should mark external verification as blocked/out of -scope unless a later implementation explicitly requests it. - -## P2 Risk Register - -### P2.1 Tests Overfit Exact Prose - -Risk: Current claim tests rely on exact phrases. Strengthening guards only with -more literal strings can make future truthful wording changes painful and can -encourage cargo-cult phrasing. - -Mitigation: Use a mix of required semantic phrases and forbidden regex patterns. -Pin high-risk exact phrases only where they are contractual, such as -`not_enforced_local_metadata`, `x402_payment.exact`, `maxUses: 1`, and -"proposal/evidence only". - -Cut line: Do not make tests require every sentence of product copy. - -Validation gate: Tests should fail on old overclaims and forbidden broadened -claims while allowing equivalent narrower wording. - -### P2.2 `.planning/` Scratch Becomes Canon Again - -Risk: The input packet intentionally reads `.planning` files, but repo canon says -`.planning/` is scratch. Derived maps include stale or conflicting improvement -paths. Future agents may reload those maps and override cleaned canon. - -Mitigation: The chair plan should explicitly classify `.planning` inputs as run -evidence and risk context, not source of repo truth. Any durable claim must land -in canonical docs and tests. - -Cut line: Do not promote `.planning/codebase/*` wording into repo-facing docs -without revalidating against active source and tests. - -Validation gate: Support docs should record this assumption, and future -implementation should not reference `.planning` paths from README, source, tests, -scripts, package exports, or CI names. - -### P2.3 Example Report Label Remains Ambiguous - -Risk: `x402_paid_http_call.exact` is a buyer-readable report proof-object label, -while the actual action class is `x402_payment.exact`. Without guard language, -readers can treat the label as an action catalog type or gateway authority class. - -Mitigation: Keep the label explicitly buyer-readable and non-authority until an -action catalog, compiler, policy, and gateway expose that exact action class. - -Cut line: Do not add `x402_paid_http_call.exact` as source action class or -public protocol type in this slice. - -Validation gate: Product report or claim-boundary tests should assert the label -is non-authority language and the protected action remains `x402_payment.exact`. - -### P2.4 Rollback Is Easy But Not Named - -Risk: Claim cleanup is mostly reversible docs/tests work, but without explicit -stop conditions a future implementation can keep pushing after tests reveal -category conflicts. - -Mitigation: Make rollback mechanical: revert docs/examples/test guard changes -from the slice; no migrations, package API changes, data rewrites, or generated -dist dependency should be necessary. - -Cut line: If the future slice needs a migration, route change, storage change, -new package export, or gateway behavior change to make the claims true, stop and -open a separate capability plan. - -Validation gate: Closeout diff should contain only canonical docs, examples, -claim tests, and possibly source-owned guard scripts. No protocol behavior diff. - -## Validation Gates - -Required future closeout gates: - -1. `npm run quality:claims` -2. `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts` -3. `npm run quality:architecture` -4. `npm run format:check` -5. `npm run check:repo` - -Additional focused checks the chair should consider: - -- A grep-style guard that fails on product-definition uses of "engineering - agents" outside explicit adoption-context language. -- A guard that fails on "spend reservation ledger" in active claim surfaces. -- A guard that fails on "x402 compatible", "payment management", "settlement", - "seller middleware", "facilitator operation", "hosted trust", - "cross-org certificate trust", "marketplace", "certification", - "clearing-house", and broad MCP/runtime/browser/shell/network/package-manager - control claims unless explicitly listed as non-claims. -- Regenerate or execute the APS report path only if the implementation changes - `examples/x402-protected-spend/run.ts`; then verify the report still has local - non-claims and no raw credential material. - -## Rollback And Stop Conditions - -Rollback plan: - -- Revert the docs/example/test changes from the claim cleanup slice. -- Do not run migrations. -- Do not change package exports or public APIs. -- Do not change x402 gateway behavior, signer custody, policy, greenlight, - receipt, storage, or adapter semantics. - -Stop conditions: - -- Any task requires changing Tier 1 protocol meaning. -- Any task adds aggregate spend enforcement, budget reservation, payment - management, settlement, balances, seller/facilitator operation, or hosted - payment custody. -- Any task changes gateway, policy, greenlight, receipt, storage, or x402 signing - behavior to make wording true. -- Any task claims broad runtime/MCP/CLI/browser/shell/network/package-manager - protection without a host-specific bypass harness. -- Any task requires external legal/payment-regulatory/x402/JWKS/npm/MCP Registry - claims without external verification. -- Any claim change is not backed by a source-owned guard. - -## Assumptions - -- The input packet correction is authoritative for this run: Handshake is - protected actions for automated decision making; engineering agents are an - adoption context; x402 is the first wedge. -- Tier 1 protocol/kernel semantics are stable and must not be changed by this - plan. -- x402 remains exact per-call buyer-side authorization only in the current - wedge. -- `not_enforced_local_metadata` may remain only as local metadata and must not - imply planned budget enforcement. -- Customer-owned gateway custody remains the future enforcement model, but it is - not currently proven by the local x402 walkthrough. -- `.planning/` files are scratch coordination. They can reveal drift, but they - do not override canonical docs and tests. - -## Dependencies - -- Canonical docs: `AGENTS.md`, `README.md`, `docs/internal/decisions.md`, - `docs/internal/protocol-definition.md`, - `docs/internal/protocol-kernel-architecture.md`, - `docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`. -- Claim tests: `test/architecture/claim-boundary.test.ts`, - `test/product/x402-protected-spend-demo-report.test.ts`, and any existing - active-vocabulary guard if the chair includes it. -- Lane manifests: `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/cli/LANE.md`, - `src/sdk/LANE.md`, `src/adapters/LANE.md`, `src/conformance/LANE.md`. -- Example claim surfaces: `examples/x402-protected-spend/README.md`, - `examples/x402-protected-spend/run.ts`, - `examples/self-hosted-activation/README.md`. -- Existing command contract: `npm run quality:claims`, focused Bun tests, - `npm run quality:architecture`, `npm run format:check`, and - `npm run check:repo`. - -## Antipatterns To Reject - -- Clean proof surface -> first market. -- x402 wedge -> x402 defines Handshake. -- Engineering-agent adoption context -> product category. -- Local/reference fixture -> provider/customer custody. -- Per-call authorization -> aggregate payment-budget management. -- Signed retry evidence -> settlement finality. -- Terminal certificate -> permission, identity, certification, or cross-org - trust. -- MCP/CLI/runtime/SDK proposal or evidence surface -> authority surface. -- Receipt -> downstream business success. -- Claim cleanup -> behavior change. -- `.planning` register -> canonical source truth. - -## Blocked Checks - -- Did not run tests; first-pass planner was asked to read and plan only. -- Did not browse external x402, npm, MCP Registry, JWKS, Cloudflare, or - legal/payment-regulatory sources; the input packet said not to browse by - default and this slice should not make new external claims. -- Did not read source files outside the immutable input packet and the allowed - file list named inside it. -- Did not inspect sibling raw outputs, normalized outputs, or the final plan for - this run. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/STRATEGY.md deleted file mode 100644 index e3a7938..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/raw/STRATEGY.md +++ /dev/null @@ -1,121 +0,0 @@ -# STRATEGY First Pass: Claim Boundary Cleanup - -## Invariant at stake - -Handshake must not let a first wedge, adoption context, demo report, or missing proof object become a product claim. The current strategic invariant is: Handshake is protected actions for automated decision making; x402 exact per-call authorization is the first wedge; engineering agents are one adoption context. - -## Findings - -- The source packet still contains legacy category language. `AGENTS.md`, `README.md`, `docs/internal/decisions.md`, and `docs/internal/protocol-notes.md` describe Handshake as contracted execution infrastructure for engineering agents or generated engineering-agent execution. That is too narrow after the user correction. -- The protocol primitive is already broader than engineering agents. `docs/internal/protocol-definition.md` defines a protocol kernel for protected action control and describes exact `ActionContract`, `PolicyDecision`, one-use `Greenlight`, pre-mutation `GatewayCheck`, and terminal `Receipt` / `Refusal` / `ProofGap` evidence. That is the stable Tier 1 anchor. -- x402 is already the best first wedge in the current source packet. `README.md`, `examples/x402-protected-spend/README.md`, and `test/product/x402-protected-spend-demo-report.test.ts` show one buyer-side `x402_payment.exact` per-call path with gateway-held signing after verified gate, replay refusal, redacted evidence, and local/reference non-claims. -- The strategic risk is not that x402 is too narrow. The risk is that x402 becomes the protocol definition, payment management, settlement, broad x402 compatibility, or a clearing-house claim. -- Existing claim guards are meaningful but incomplete for the corrected category. `test/architecture/claim-boundary.test.ts` guards public entrypoint boundaries, local runtime ingress language, MCP proposal/evidence posture, and several x402 non-claims. It does not yet force the category rewrite away from engineering-agent-only language. -- The "spend reservation ledger" phrase is strategically wrong if treated as a missing requirement before product truth. Aggregate payment-budget management should be marked intentionally out of current remit. Per-call x402 exact authorization must remain in scope. -- `not_enforced_local_metadata` appears in the x402 demo source as spend-window status. That can stay only if the surrounding report treats session/day/review spend windows as local metadata and not as a deferred enforcement promise. -- Package install, repo write, and preview deploy are useful protocol regression/reference lanes, not wedge replacements for this cleanup. Treating package install as the first wedge would reintroduce the old engineering-agent category bias. - -## Recommended macro shape - -1. Re-anchor category language. - - Rewrite canonical product statements from "engineering agents" to "protected actions for automated decision making" where they define Handshake. - - Keep engineering agents as a current adoption context, generated-execution stress case, or local proof lane. - - Do not change Tier 1 protocol object meaning. - -2. Re-state x402 as first protected-action pack. - - Preserve `x402_payment.exact` as one official buyer-side per-call path. - - Keep package install as regression/parity, not first wedge. - - Preserve "No adapter family defines the protocol." - -3. Convert eliminated items into explicit non-goals. - - Replace "spend reservation ledger required before claim" posture with "aggregate payment-budget management intentionally out of current remit." - - Keep settlement, seller middleware, facilitator operation, broad x402 compatibility, payment custody, clearing-house readiness, marketplace/certification, hosted trust, and broad runtime control as cut lines. - -4. Strengthen claim guards. - - Extend `test/architecture/claim-boundary.test.ts` and `test/product/x402-protected-spend-demo-report.test.ts` so the corrected category and x402 non-claims fail if they drift. - - Add explicit forbidden patterns for engineering-agent-only category language in canonical product definitions while allowing bounded adoption-context references. - -5. Close with source-owned verification only. - - Required future gates: `npm run quality:claims`, targeted claim-boundary and x402 report tests, and then broader repo gate if the implementation touches canonical docs or demo output. - - No external verification is needed unless the implementation adds new x402, payment-regulatory, JWKS, MCP Registry, npm, Cloudflare, or legal claims. - -## What to cut - -- Cut engineering agents as the product category. -- Cut "agent auth", "generic agent governance", "runtime control", "hosted observability", and "dashboard over logs" framing. -- Cut any implication that x402 exact per-call proof means aggregate payment-budget management. -- Cut `spend reservation ledger` as a required missing proof object for the current wedge; replace it with an intentional out-of-remit boundary. -- Cut payment management, settlement finality, Handshake-held wallets, seller middleware, facilitator operation, signed-offer flows, batch settlement, `upto` authorization, and clearing-house readiness. -- Cut broad x402 compatibility. The current wedge is official buyer-side `exact` only. -- Cut hosted operation, live provider/customer custody, cross-org certificate trust, live JWKS/revocation, marketplace certification, and provider custody claims from this slice. -- Cut broad MCP/CLI/browser/shell/network/package-manager protection claims. MCP and CLI remain proposal/evidence surfaces. -- Cut any plan that adds capability before the claim boundary is cleaned. - -## What must be decided before execution - -- Exact canonical category phrase: use the user's phrase, "protected actions for automated decision making," unless the chair records a stronger source-backed wording. -- Whether `AGENTS.md` doctrine is in scope for the implementation slice. Strategically it should be, because it currently defines the old category. -- Allowed references to engineering agents: they should remain only as adoption context, generated-execution stress case, or current local proof context. -- Whether the demo report should remove `spend reservation ledger` entirely from `missingProofObjects` or move it to an explicit `outOfRemit` / `nonClaims` field. The strategic preference is explicit out-of-remit, not hidden deletion. -- Whether "APS" remains a buyer-readable label for the x402 report. If kept, it must resolve to x402 exact protected spend and not imply a broader payment product. - -## Six-month regret scenario - -Six months from now, the damaging failure is that the repo reads cleaner but still sells the wrong thing. Buyers see "engineering agents" and treat Handshake as a coding-agent niche. x402 readers see `spend reservation ledger` and assume payment-budget management is on the roadmap. Internal builders then implement hosted dashboards, verifier routes, or package-manager lanes to satisfy implied claims instead of hardening one customer-owned gateway path. The protocol survives in code but the product category drifts into advisory governance and payment theatre. - -## Smallest strategically valid first move - -Patch the canonical claim boundary, not the product surface: update the canonical docs and claim tests so the source must say "protected actions for automated decision making," must say x402 exact per-call authorization is the first wedge, and must fail if it implies aggregate spend management, hosted trust, broad runtime control, or engineering-agent-only category scope. - -## Assumptions - -- Tier 1 protocol meaning is stable and must not be redefined in this macro plan. -- x402 remains the first wedge unless an execution planner finds a source-level blocker. -- The implementation slice is allowed to edit the listed canonical docs, examples, and tests. -- `.planning/` remains scratch; only promoted plan outputs under the active macro directory are durable for this run. -- Existing x402 local/reference proof is sufficient for claim cleanup; external x402 verification is not part of this slice. - -## Dependencies - -- Canonical docs: `AGENTS.md`, `README.md`, `docs/internal/decisions.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`. -- Claim guard tests: `test/architecture/claim-boundary.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`. -- Demo source/report wording: `examples/x402-protected-spend/README.md`, `examples/x402-protected-spend/run.ts`, `examples/self-hosted-activation/README.md`. -- Lane manifests that preserve non-authority posture: `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/cli/LANE.md`, `src/sdk/LANE.md`, `src/adapters/LANE.md`, `src/conformance/LANE.md`. -- Closeout commands named by the input: `npm run quality:claims` and targeted claim/x402 tests. - -## Risks - -- Overcorrection risk: replacing every "engineering agent" phrase would erase the useful current adoption context and generated-code threat model. -- Wedge collapse risk: making x402 the category would turn Handshake into payment infrastructure. -- Scope creep risk: adding hosted, custody, verifier, marketplace, or registry work would violate the claim-cleanup purpose. -- Test theatre risk: banning words without requiring positive category language could produce sterile docs that still fail to explain the product. -- Demo-report drift risk: `missingProofObjects` can imply "pending promise" even when the intended boundary is "not our remit." -- Adoption confusion risk: if engineering-agent examples disappear entirely, the first buyer path loses the concrete stress case that explains why protected actions are needed. - -## Validation gates - -- Positive category gate: canonical product definitions contain protected actions for automated decision making or equivalent chair-approved wording. -- Bounded adoption-context gate: engineering agents appear only as adoption context, generated-execution stress case, or current proof lane, not as the product boundary. -- x402 wedge gate: docs/examples keep one official buyer-side `x402_payment.exact` per-call path as first wedge and reject broad x402 compatibility. -- Non-goal gate: docs/examples/tests reject payment management, aggregate spend enforcement, settlement, seller/facilitator operation, Handshake-held custody, marketplace/certification, clearing-house readiness, hosted trust, and broad runtime control. -- Metadata gate: `not_enforced_local_metadata` remains only where clearly local metadata, not a deferred enforcement claim. -- Authority spine gate: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, and terminal evidence distinctions stay unchanged. -- Closeout gate: future executor runs `npm run quality:claims` and `npm run test -- test/architecture/claim-boundary.test.ts test/product/x402-protected-spend-demo-report.test.ts`. - -## Cut lines - -- No new protocol primitives. -- No new hosted surfaces. -- No new payment, settlement, seller, facilitator, or ledger implementation. -- No new MCP/CLI mutation capability. -- No package publication, registry publication, JWKS, revocation, or Cloudflare deployment work. -- No external legal/payment-regulatory claims. -- No new adapter pack beyond preserving x402 exact and existing regression/reference lanes. -- No claim that local/reference proof equals live provider/customer custody. - -## Blocked checks - -- Did not run tests or commands; this first-pass role is planning-only and wrote only the assigned raw strategy artifact. -- Did not browse or externally verify x402, npm, MCP Registry, JWKS, Cloudflare, or payment/legal claims; external verification is out of scope unless future execution adds such claims. -- Did not inspect sibling raw outputs, normalized outputs, or the final `PLAN.md`. -- Did not read source files outside the immutable packet's allowed source list. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md deleted file mode 100644 index f9e8fc5..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md +++ /dev/null @@ -1,96 +0,0 @@ -# Chair Synthesis - -## Invariant At Stake - -Claim cleanup must not silently create authority. The repo must say protected actions for automated decision making, preserve exact contract -> policy -> one-use greenlight -> gateway check -> receipt/refusal/proof gap, and keep x402 as the first buyer-side exact per-call protected-action wedge. - -## Inputs Read - -- Immutable input packet for `claim-boundary-cleanup-20260524T065926Z`. -- Raw perspective outputs: Strategy, Architecture, Execution, Risk, Adoption. -- Macro plan contract. -- Selected allowed source files to verify current claim/test surfaces. -- Lightweight memory lookup for prior repo-specific x402/Tier discipline. - -No archive macro runs, sibling normalized outputs, or external sources were read. - -## Synthesis - -The perspectives converged on one sequence: - -1. Inventory claims and produce a phrase table. -2. Add or strengthen failing claim guards. -3. Rewrite canonical category language. -4. Clean x402 report and walkthrough wording. -5. Align lane manifests only where they drift. -6. Clean active scratch drift. -7. Run focused claim gates and full repo gate. - -The plan is test-led because prose cleanup alone would be reversible. The durable mechanism is a small, named claim-boundary guard surface covering canonical docs, x402 examples/report output, and lane manifests. - -## Conflicts Resolved - -### Engineering Agents - -Decision: engineering agents are not the product category. They remain as adoption context, generated-execution threat model, and current local proof context. - -Reason: the protocol primitive already supports protected action control, and the user correction is explicit. - -### x402 - -Decision: x402 is the first official buyer-side exact per-call protected-action wedge, not the protocol definition. - -Reason: the source packet proves the x402 path as the strongest current wedge, but broad payment, compatibility, settlement, seller/facilitator, hosted, and marketplace claims are out of scope. - -### Spend Reservation Ledger - -Decision: product-scope spend-ledger-required language should be replaced with aggregate payment-budget management intentionally out of current remit. - -Reason: treating the ledger as missing proof makes payment-budget management look like a pending promise. The current claim is exact per-call authorization only. - -### `.planning` Evidence - -Decision: active `.planning` files can be cleaned as scratch drift but must not become canon. - -Reason: README and decisions docs define `.planning/` as scratch. Durable claims must land in canonical docs and tests. - -### Claim Guards - -Decision: strengthen existing guard surfaces rather than build a new broad vocabulary subsystem. - -Reason: the slice should avoid god files, regex sprawl, pass-through abstractions, and capability expansion. A fixed surface map with grouped assertions is enough for this cleanup. - -## Architecture And Control Flow Preserved - -```text -automated decision / generated execution evidence --> runtime or MCP proposal/evidence surface --> intent compilation --> CandidateAction --> ActionContract --> PolicyDecision --> one-use Greenlight --> GatewayCheck before mutation --> x402 wallet gateway signer use after VerifiedGatewayCheck --> Receipt / Refusal / ProofGap / terminal local evidence -``` - -Only the first node is generalized from engineering-agent-only language to automated decision making. The authority path remains unchanged. - -## Blocked Checks - -- No tests were run; this chair task was planning-only. -- No `npm run quality:claims`, focused tests, demo, or `check:repo` gate was executed. -- No external x402, npm, MCP Registry, JWKS, Cloudflare, legal, or payment-regulatory verification was performed. -- No source implementation files outside the allowed packet were opened. - -## Output Files Written - -- `.planning/macro/active/claim-boundary-cleanup/PLAN.md` -- `.planning/macro/active/claim-boundary-cleanup/CONTEXT.md` -- `.planning/macro/active/claim-boundary-cleanup/ASSUMPTIONS.md` -- `.planning/macro/active/claim-boundary-cleanup/DECISIONS.md` -- `.planning/macro/active/claim-boundary-cleanup/RISKS.md` -- `.planning/macro/active/claim-boundary-cleanup/VALIDATION.md` -- `.planning/macro/active/claim-boundary-cleanup/TASKS.jsonl` -- `.planning/macro/active/claim-boundary-cleanup/runs/claim-boundary-cleanup-20260524T065926Z/synthesis.md` diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/ASSUMPTIONS.md deleted file mode 100644 index 3a8d5c0..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/ASSUMPTIONS.md +++ /dev/null @@ -1,39 +0,0 @@ -# Assumptions - -## Product Assumptions - -- Handshake is protected actions for automated decision making, not engineering-agent-only. -- x402 exact per-call protected action is the first wedge, not the protocol center. -- Package-manager material attestation is the right first adapter expansion because it preserves exactness while moving beyond payment-centered interpretation. -- The buyer-readable value is gating automated dependency actions on exact material evidence, policy, and gateway-bound authority. -- The product must not claim package safety, npm audit replacement, Bun provenance verification, broad supply-chain security, hosted operation, payment management, or broad runtime/MCP/CLI enforcement. - -## Source Assumptions - -- `ProtectedActionAdapterPackSchema` exists and is the right basis for the adapter manifest activation boundary. -- The schema already includes pack id/version, action family, protected surface, parameter schema ref, endpoint evidence schema ref, install compiler ref, policy rule pack ref, gateway observed parameter validator ref, receipt evidence mapper ref, bypass probe kinds, and hostile fixture refs. -- A generic install proposal exists and can be made package-install-specific without broadening authority. -- Package install runtime compiler and gateway tests exist. -- Preview deploy runtime/gateway lanes exist but should remain second. -- Repo write runtime/gateway lanes exist but should remain third. -- Runtime ingress contains cross-family hardcoding risk and must not become a god registry. -- CLI and MCP are proposal/evidence/read-only surfaces. - -## External Assumptions - -- npm provenance and signatures can verify source/build/publisher posture and registry/tarball integrity. -- `npm audit signatures` verifies registry signatures and provenance attestations after `npm install` when used with a supported npm CLI. -- Trusted publishing and provenance depend on external package account, repository, and workflow configuration. -- npm provenance/signature evidence does not prove package code is benign. -- Bun lockfile evidence is local material/reconstruction evidence, not npm provenance verification. - -## Security Assumptions - -- Lifecycle scripts are consequential code execution. -- Lifecycle scripts must default blocked unless separately contracted. -- Raw sibling package-manager invocation is a bypass condition. -- Missing material evidence must be recorded as a proof gap. -- A buyer report is not enforcement. -- Runtime trace is not an action contract. -- Proposal is not permission. -- Evidence preview is not gateway acceptance. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/CONTEXT.md deleted file mode 100644 index b653f6b..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/CONTEXT.md +++ /dev/null @@ -1,34 +0,0 @@ -# Context - -Handshake is protected actions for automated decision making. The next macro item is concrete adapter pack expansion. - -The expansion must not collapse into an engineering-agent-only narrative, payment management, hosted operations, or broad runtime enforcement. x402 remains the first exact per-call protected action wedge, but it is not the protocol center. - -The promoted first adapter pack is package-manager material attestation/package-install. This pack is the best first expansion because it breaks payment-centered interpretation while staying exact: one automated dependency action, one proposed contract, one policy decision, one gateway-bound mutation attempt, one reconstructable receipt. - -The key architectural constraint is that the adapter pack manifest is the activation boundary. Runtime ingress may select compilers, but must not authorize. CLI and MCP may expose proposal, inventory, evidence, and read-only surfaces, but must not be treated as enforcement. - -The package-install pack must prove that the Tier 1 spine generalizes: - -- exact protected action contract; -- atomic policy decision; -- one-use greenlight; -- gateway observed-parameter validation; -- material evidence mapping; -- hostile fixtures; -- bypass posture; -- receipt/refusal/proof-gap reconstruction. - -The product claim is narrow: - -Handshake gates automated dependency actions on exact material evidence, policy, and gateway-bound authority. - -The forbidden claim is broad supply-chain safety. npm provenance/signatures can help verify source/build/publisher posture and registry/tarball integrity. They do not prove package code is benign. Bun lockfile evidence supports local reconstruction and drift detection, not npm provenance verification. - -Expansion order: - -1. package-manager material attestation/package-install; -2. preview deploy; -3. repo write. - -Smallest next mechanism: package-install conformance for one npm install attempt. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/DECISIONS.md deleted file mode 100644 index 4855b12..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/DECISIONS.md +++ /dev/null @@ -1,71 +0,0 @@ -# Decisions - -## D1: Promote Package-Manager Material Attestation First - -Package-manager material attestation/package-install is the first concrete adapter pack expansion. - -Reason: it breaks the payment-centered narrative while keeping the protected action exact, observable, and gateway-bound. - -## D2: Keep x402 As Wedge, Not Center - -x402 remains the first exact per-call protected action wedge. It must not become the center of the protocol or the explanation of all protected actions. - -Reason: Handshake is the control layer for protected actions in automated decision making, not a payment-management system. - -## D3: Expansion Order - -Adapter pack expansion order is: - -1. package install; -2. preview deploy; -3. repo write. - -Reason: package install has enough existing compiler/gateway surface to prove the adapter spine without immediately inheriting deploy or repo-write scope. - -## D4: Manifest Contract Is Activation Boundary - -The adapter pack manifest is the activation boundary. - -Reason: a pack is promotable only when its schemas, compiler, policy rule pack, gateway validator, receipt mapper, bypass probes, and hostile fixtures are declared together. - -## D5: Runtime Ingress Selects, It Does Not Authorize - -Runtime ingress may route to compilers by action family. It must not become the authority holder. - -Reason: authorization belongs to exact contract policy and gateway-bound greenlight enforcement. - -## D6: Use Small Typed Registries - -Use small typed registries for compilers, policy packs, gateway validators, receipt mappers, bypass probes, and hostile fixtures. Do not create one god registry. - -Reason: one central registry invites cross-family shortcut authority and ambient coupling. - -## D7: Gateway Validator Enforces Exact Binding - -The package-install gateway observed-parameter validator is the pre-consequence enforcement point. - -Reason: policy decision without gateway enforcement is advisory, not Handshake. - -## D8: Receipts Record Evidence And Proof Gaps - -The receipt mapper records material evidence, gateway check, execution result, reconstruction material, and proof gaps. - -Reason: missing evidence must survive as missing evidence. It must not be converted into confidence language. - -## D9: Lifecycle Scripts Default Blocked - -Lifecycle scripts are blocked by default unless separately contracted. - -Reason: install scripts are consequential code execution and cannot hide under package-install authority. - -## D10: Bypass Posture Blocks Promotion - -Raw sibling bypass must be detected, isolated, or treated as a stop condition. - -Reason: if generated code can call an unwrapped consequential package-manager tool, the generated code escaped the contract boundary. - -## D11: Reports Must Bind To Exact Contract - -Buyer-readable reports must reference exact contract and receipt evidence. They must not summarize authority in loose prose. - -Reason: otherwise the report becomes review theatre. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/PLAN.md deleted file mode 100644 index 47f9146..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/PLAN.md +++ /dev/null @@ -1,306 +0,0 @@ -# GSD Macro Plan: Concrete Adapter Pack Expansion - -## Goal - -Invariant at stake: adapter pack expansion must prove that protected actions for automated decision making generalize without turning x402, runtime ingress, CLI, MCP, or reports into shortcut authority. - -Build the first concrete adapter pack expansion around package-manager material attestation for one exact package install attempt. The pack must show that Handshake can take an automated dependency action, reduce it to an exact protected action contract, require material evidence, enforce gateway-bound authority, and leave a reconstructable receipt with explicit proof gaps. - -The first wedge is x402 exact per-call protected action. It is not the protocol center. The package-manager adapter pack must preserve the Tier 1 spine while proving that exact per-call authorization can apply to non-payment protected actions. - -## Non-Goals - -- No payment management. -- No hosted operation claim. -- No broad runtime, MCP, or CLI enforcement claim. -- No supply-chain safety claim. -- No npm audit replacement claim. -- No Bun provenance verification claim. -- No claim that provenance, signatures, lockfiles, or attestations prove package code is benign. -- No package install execution outside an exact gateway-bound greenlight. -- No expansion into preview deploy or repo write until the package-install conformance slice closes. -- No god registry that centralizes every family, compiler, policy, validator, mapper, and bypass probe behind ambient runtime ingress authority. - -## Source Boundary - -Canonical source boundaries for this macro plan: - -- `ProtectedActionAdapterPackSchema` is the adapter contract boundary. -- Runtime ingress may select the relevant compiler for an action family. -- Runtime ingress must not authorize protected action execution. -- CLI and MCP may expose proposal, evidence, inventory, or read-only surfaces. -- CLI and MCP must not be described as enforcement points unless a gateway-bound mutation path actually enforces the exact greenlight. -- Gateway observed-parameter validation is the pre-consequence enforcement boundary. -- Receipt evidence mapping is post-decision and post-gateway evidence, not proof that downstream business outcome succeeded. - -The expansion order is: - -1. Package-manager material attestation / package-install adapter pack. -2. Preview deploy adapter pack. -3. Repo write adapter pack. - -## Current State - -Known source state: - -- `ProtectedActionAdapterPackSchema` exists and includes: - - pack id/version; - - action family; - - protected surface; - - parameter schema ref; - - endpoint evidence schema ref; - - install compiler ref; - - policy rule pack ref; - - gateway observed parameter validator ref; - - receipt evidence mapper ref; - - bypass probe kinds; - - hostile fixture refs. -- A generic install proposal exists. -- Package install runtime compiler and gateway tests exist. -- Preview deploy runtime and gateway lanes exist. -- Repo write runtime and gateway lanes exist. -- Runtime ingress has cross-family hardcoding risk and must not become a god registry. -- CLI and MCP are proposal/evidence/read-only surfaces. -- Bun lockfile evidence is available as local material/reconstruction evidence, not npm provenance verification. - -External evidence boundary: - -- npm provenance and signatures can verify source/build/publisher posture and registry/tarball integrity. -- `npm audit signatures` verifies registry signatures and provenance attestations after `npm install` with a supported npm CLI. -- Trusted publishing and provenance depend on external package account, repository, and workflow configuration. -- None of this proves benign package code. - -## Target State - -A concrete package-manager adapter pack exists as the first promoted expansion pack. - -It proves: - -- the manifest is the activation boundary; -- package install is represented as an exact protected action contract; -- runtime ingress selects the package-install compiler but does not authorize execution; -- policy evaluates exact package-manager material evidence requirements; -- gateway observed-parameter validation enforces the exact binding before mutation; -- receipt mapping records: - - proposed action; - - authority binding; - - exact contract; - - material evidence; - - gateway check; - - execution outcome; - - proof gaps; - - reconstruction material; - - bypass posture. -- lifecycle scripts are blocked by default unless separately contracted. -- raw sibling bypass is detected or blocks expansion. -- hostile fixtures prove the pack fails closed under drift, laundering, and bypass attempts. - -The buyer-readable product claim becomes: - -Handshake gates automated dependency actions on exact material evidence, policy, and gateway-bound authority. - -## Assumptions - -- The existing `ProtectedActionAdapterPackSchema` is close enough to freeze as the pack activation boundary, with only narrow additions allowed for conformance. -- The generic install proposal can be canonicalized into a package-install action contract without inventing broad package-manager authority. -- Existing package install runtime compiler and gateway tests can be extended into conformance fixtures. -- npm provenance/signature evidence is optional or gap-recorded when unavailable, not silently treated as satisfied. -- Bun lockfile evidence is useful for reconstruction and drift detection, not provenance verification. -- Lifecycle scripts are consequential execution and require separate contracting. -- Raw package-manager invocation outside the gateway is a bypass condition, not an unsupported happy path. -- Preview deploy and repo write can wait until package-install conformance demonstrates the adapter pattern. - -## Decisions - -1. Promote package-manager material attestation/package-install first. -2. Treat preview deploy as second. -3. Treat repo write as third. -4. Keep x402 as the first exact per-call protected action wedge, not the protocol center. -5. Treat the adapter manifest as the activation boundary. -6. Use small typed registries per concern instead of one god registry. -7. Runtime ingress selects compilers only; it does not authorize. -8. Gateway observed-parameter validator enforces exact binding. -9. Receipt evidence mapper records evidence and proof gaps; it does not certify benign code. -10. Block lifecycle scripts by default unless separately contracted. -11. Treat raw sibling bypass as a stop condition for expansion. -12. Require hostile fixtures before declaring the adapter pack promotable. - -## Phases - -Phase 1: Freeze Adapter Contract - -- Confirm `ProtectedActionAdapterPackSchema` expresses the activation boundary. -- Separate pack identity, action family, protected surface, compiler, policy, gateway validator, evidence mapper, bypass probes, and hostile fixtures. -- Prevent runtime ingress from becoming the authorization registry. -- Define conformance requirements for a promoted adapter pack. - -Phase 2: Canonical Package Install Proposal - -- Canonicalize the generic install proposal into a package-install protected action contract. -- Bind package name, version/range resolution, registry, package manager, lockfile posture, lifecycle script posture, material evidence requirements, and idempotency expectations. -- Preserve uncertainty markers when resolution or evidence cannot be proven before install. - -Phase 3: Gateway Observed-Parameter Validator - -- Implement package-install observed-parameter validation as the enforcement boundary. -- Reject drift between canonical contract and observed install parameters. -- Reject reusable greenlights. -- Reject lifecycle scripts unless separately contracted. -- Reject raw sibling bypass or mark expansion blocked when detection is not available. - -Phase 4: Material Attestation Mapper - -- Map npm provenance/signature evidence, registry/tarball integrity, lockfile material, package manager version, and proof gaps into receipt evidence. -- Keep npm evidence claims narrow. -- Treat Bun lockfile evidence as reconstruction material, not provenance verification. -- Record absent or unverifiable evidence as proof gaps. - -Phase 5: Custody And Bypass Probes - -- Add hostile fixtures for provenance laundering, lockfile drift, lifecycle script execution, registry substitution, tarball mismatch, raw sibling bypass, stale policy, and credential custody ambiguity. -- Expansion cannot pass if bypass posture is unobserved or advisory only. - -Phase 6: Buyer-Readable Report - -- Produce a report format with sections: - - action; - - authority; - - exact contract; - - evidence; - - outcome; - - proof gaps; - - reconstruction. -- Ensure the report does not imply package safety, hosted operation, or broad supply-chain security. - -Phase 7: Conformance And Export - -- Define adapter pack conformance export for the package-install slice. -- Produce a minimal conformance fixture for one npm install attempt. -- Export receipts and reports that reconstruct the chain without relying on chat transcript or runtime trace. - -## Task Graph - -```mermaid -flowchart TD - A["Freeze adapter contract"] --> B["Canonical package-install proposal"] - B --> C["Gateway observed-parameter validator"] - B --> D["Material attestation mapper"] - C --> E["Custody and bypass probes"] - D --> E - E --> F["Buyer-readable report"] - F --> G["Conformance/export"] - G --> H["Promote preview deploy second"] - G --> I["Promote repo write third"] -``` - -Critical path: - -1. Freeze adapter contract. -2. Canonicalize one npm install attempt. -3. Enforce observed-parameter validation. -4. Map material evidence and proof gaps. -5. Pass hostile fixtures. -6. Export receipt/report. - -## Risks And Mitigations - -- Shortcut authority: Runtime ingress, CLI, MCP, or report surfaces may be mistaken for enforcement. - - Mitigation: declare gateway observed-parameter validation as the only pre-consequence enforcement boundary. - -- Provenance laundering: npm provenance may be presented as package safety. - - Mitigation: receipt language must say provenance/signatures verify source/build/publisher posture and integrity, not benign code. - -- Lifecycle script consequence: install scripts can execute code during dependency install. - - Mitigation: lifecycle scripts default blocked unless separately contracted. - -- Lockfile drift: observed install may differ from contract or prior material state. - - Mitigation: gateway validator rejects drift or records proof gap before consequence where rejection is impossible. - -- Raw sibling bypass: generated code may call package-manager tools outside the protected gateway. - - Mitigation: bypass probe required; absence of detection blocks expansion. - -- Runtime/MCP/CLI overclaim: proposal and evidence surfaces may be marketed as enforcement. - - Mitigation: all docs and reports must separate proposal, policy, gateway check, and receipt. - -- Credential custody ambiguity: package registry tokens, CI identities, or local credentials may perform mutation outside the contract. - - Mitigation: adapter pack must name custody boundary and proof gaps. - -- Report theatre: buyer-readable report may summarize rather than bind to exact contract and receipt. - - Mitigation: report must reference exact contract id/hash and receipt evidence ids. - -## Validation Gates - -Gate 1: Adapter Contract Freeze - -- `ProtectedActionAdapterPackSchema` acts as activation boundary. -- No cross-family god registry is introduced. -- Runtime ingress remains compiler selection only. - -Gate 2: Package Install Contract - -- One npm install attempt can be represented as an exact protected action contract. -- Contract includes material evidence expectations and lifecycle script posture. -- Contract does not imply permission. - -Gate 3: Gateway Enforcement - -- Gateway validator rejects observed parameter drift. -- Greenlight is one-use and exact. -- Lifecycle scripts are blocked unless separately contracted. - -Gate 4: Evidence Mapping - -- npm signatures/provenance are recorded only within their real evidentiary scope. -- Bun lockfile evidence is recorded as local reconstruction material only. -- Missing evidence becomes a proof gap. - -Gate 5: Hostile Fixtures - -- Fixtures cover provenance laundering, lockfile drift, lifecycle scripts, registry substitution, tarball mismatch, raw sibling bypass, stale policy, and credential custody ambiguity. -- Any advisory-only bypass posture fails the gate. - -Gate 6: Report And Export - -- Report distinguishes action, authority, exact contract, evidence, outcome, proof gaps, and reconstruction. -- Export reconstructs the chain without trusting the runtime transcript. - -## Cut Lines - -Cut immediately: - -- Any broad supply-chain security claim. -- Any claim that npm provenance proves package safety. -- Any Bun provenance claim. -- Any payment-management framing. -- Any hosted-operation framing. -- Any MCP/CLI/runtime enforcement claim not backed by gateway enforcement. -- Any registry design that turns runtime ingress into authorization. -- Any report section that summarizes authority without exact contract binding. -- Any lifecycle-script allowance without a separate contract. - -Defer: - -- Preview deploy adapter pack. -- Repo write adapter pack. -- Cross-runtime enforcement claims. -- Hosted control plane packaging. -- Buyer dashboard polish. -- Broad adapter marketplace language. - -## Rollback / Stop Conditions - -Stop expansion if: - -- Runtime ingress becomes the authority holder. -- A greenlight can authorize more than one install attempt. -- Gateway observed-parameter validation cannot reject drift. -- Lifecycle scripts can execute under package-install authority without separate contracting. -- Raw sibling package-manager invocation cannot be detected, isolated, or treated as a blocking bypass. -- Receipt cannot distinguish gateway check from downstream install result. -- npm provenance/signature evidence is represented as benign-code proof. -- The report cannot reconstruct exact contract, authority, evidence, outcome, and proof gaps. -- The implementation requires broad CLI/MCP/runtime enforcement claims to sound useful. - -## Smallest Next Action - -Define the package-install conformance fixture for one npm install attempt: exact contract fields, expected npm material evidence, lifecycle script default-block posture, gateway observed parameters, receipt evidence mapping, and hostile drift cases. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/RISKS.md deleted file mode 100644 index 7e97d52..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/RISKS.md +++ /dev/null @@ -1,16 +0,0 @@ -# Risks - -| ID | Risk | Failure Mode | Mitigation | Stop Condition | -| --- | --- | --- | --- | --- | -| R1 | Shortcut authority | Runtime ingress, CLI, MCP, or reports are treated as authorization. | State that only gateway observed-parameter validation enforces before consequence. | Any docs or implementation path claims ingress/CLI/MCP enforcement without gateway binding. | -| R2 | God registry | Cross-family hardcoding becomes one ambient authority registry. | Use small typed registries by concern. | Runtime ingress owns policy, gateway validation, or receipt mapping authority. | -| R3 | Provenance laundering | npm provenance/signatures are described as package safety. | Limit claim to source/build/publisher posture and registry/tarball integrity. | Report claims benign code, safe package, or supply-chain security. | -| R4 | npm audit replacement claim | Adapter sounds like a vulnerability or audit replacement. | Say material attestation complements policy; it is not vulnerability detection. | Product copy claims audit replacement. | -| R5 | Bun provenance confusion | Bun lockfile is treated as npm provenance verification. | Treat Bun lockfile as local reconstruction and drift evidence only. | Receipt says Bun verified npm provenance. | -| R6 | Lifecycle script escape | Package install runs consequential code under install authority. | Block lifecycle scripts by default unless separately contracted. | Lifecycle scripts execute without a separate exact contract. | -| R7 | Lockfile drift | Observed install differs from canonical contract or expected material. | Gateway validator rejects drift or records proof gap before consequence where rejection is impossible. | Drift is accepted silently. | -| R8 | Raw sibling bypass | Generated code invokes package manager outside the gateway. | Require bypass probes and block promotion if bypass posture is advisory only. | Bypass cannot be detected, isolated, or treated as blocking. | -| R9 | Credential custody ambiguity | Registry credentials or CI identity mutate outside declared authority. | Receipt and manifest name custody boundary and proof gaps. | Credential source cannot be reconstructed. | -| R10 | Report theatre | Buyer report summarizes action without exact binding. | Report must include action, authority, exact contract, evidence, outcome, proof gaps, reconstruction. | Report cannot tie back to contract id/hash and receipt evidence. | -| R11 | Stale policy | Gateway check uses a decision made against stale policy or stale contract. | Gateway validator checks exact greenlight binding, one-use state, and policy/contract identity. | Reused or stale greenlight can pass. | -| R12 | Expansion overreach | Preview deploy or repo write borrows package-install authority pattern without hostile fixtures. | Keep expansion order gated by conformance. | Second/third pack starts before package-install conformance closes. | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/TASKS.jsonl deleted file mode 100644 index e5713de..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/TASKS.jsonl +++ /dev/null @@ -1,12 +0,0 @@ -{"id":"CAP-001","priority":"P0","phase":"freeze-adapter-contract","title":"Freeze adapter pack manifest as activation boundary","owner":"architecture","rationale":"Adapter expansion is unsafe unless the manifest declares the exact compiler, policy, gateway validator, receipt mapper, bypass probes, and hostile fixtures required for activation.","depends_on":[],"acceptance":["ProtectedActionAdapterPackSchema is treated as the promoted pack boundary","manifest references remain typed and concern-specific","runtime ingress is not the authority holder"],"candidate_paths":["src/protocol","src/runtime","docs/internal/protocol-notes.md","docs/internal/decisions.md"],"non_goals":["implementation of preview deploy pack","implementation of repo write pack","god registry design"]} -{"id":"CAP-002","priority":"P0","phase":"freeze-adapter-contract","title":"Split adapter registries by concern","owner":"architecture","rationale":"A single registry would invite cross-family shortcut authority and turn runtime ingress into ambient authorization.","depends_on":["CAP-001"],"acceptance":["compiler registry is separate from policy registry","gateway validator registry is separate from receipt mapper registry","bypass probes and hostile fixtures are not hidden behind runtime ingress"],"candidate_paths":["src/runtime","src/policy","src/gateway","src/receipts"],"non_goals":["central control-plane registry","runtime enforcement claim","hosted registry service"]} -{"id":"CAP-003","priority":"P0","phase":"canonical-package-install","title":"Canonicalize one npm install protected action contract","owner":"protocol","rationale":"The smallest proof is one exact npm install attempt reduced from proposal to inspectable contract without granting broad package-manager authority.","depends_on":["CAP-001"],"acceptance":["contract binds package identity, version or resolution posture, registry, package manager, lifecycle-script posture, material evidence expectations, and idempotency key","contract is a proposal, not permission","uncertainty is preserved as uncertainty markers"],"candidate_paths":["src/protocol","src/adapters/package-install","tests"],"non_goals":["package safety scoring","vulnerability audit replacement","general dependency management"]} -{"id":"CAP-004","priority":"P0","phase":"gateway-validator","title":"Implement gateway observed-parameter validator for package install","owner":"gateway","rationale":"Policy without observed-parameter gateway enforcement is advisory, not Handshake.","depends_on":["CAP-003"],"acceptance":["validator rejects drift between contract and observed install parameters","validator enforces exact one-use greenlight binding","validator blocks lifecycle scripts unless separately contracted"],"candidate_paths":["src/gateway","src/adapters/package-install","tests/gateway"],"non_goals":["CLI enforcement","MCP enforcement","runtime trace enforcement"]} -{"id":"CAP-005","priority":"P0","phase":"material-attestation","title":"Map npm signatures and provenance into receipt evidence","owner":"receipts","rationale":"Material evidence must be recorded in its real evidentiary scope without laundering it into package safety.","depends_on":["CAP-003"],"acceptance":["receipt records npm registry signature/provenance status when available","receipt states proof gaps when evidence is absent or unsupported","receipt does not claim benign code or broad supply-chain security"],"candidate_paths":["src/receipts","src/adapters/package-install","docs/internal/protocol-notes.md"],"non_goals":["npm audit replacement","malware detection","package reputation scoring"]} -{"id":"CAP-006","priority":"P1","phase":"material-attestation","title":"Record Bun lockfile as reconstruction evidence only","owner":"receipts","rationale":"Bun lockfile material can help reconstruction and drift analysis, but it is not npm provenance verification.","depends_on":["CAP-005"],"acceptance":["Bun lockfile evidence is labeled as local material or reconstruction evidence","receipt never claims Bun verified npm provenance","lockfile drift produces rejection or proof gap"],"candidate_paths":["src/receipts","src/adapters/package-install","tests/fixtures"],"non_goals":["Bun provenance support","package safety claim","cross-package-manager equivalence claim"]} -{"id":"CAP-007","priority":"P0","phase":"custody-bypass-probes","title":"Add lifecycle-script hostile fixture","owner":"security","rationale":"Lifecycle scripts are consequential code execution and cannot hide inside package-install authority.","depends_on":["CAP-004"],"acceptance":["fixture attempts install with lifecycle script execution","default behavior blocks or refuses without separate contract","receipt records refusal or proof gap accurately"],"candidate_paths":["tests/fixtures/hostile","tests/gateway","src/adapters/package-install"],"non_goals":["supporting lifecycle scripts by default","script sandbox claim","supply-chain safety claim"]} -{"id":"CAP-008","priority":"P0","phase":"custody-bypass-probes","title":"Add raw sibling package-manager bypass fixture","owner":"security","rationale":"If generated code can call an unwrapped package-manager mutation path, the generated code escaped the contract boundary.","depends_on":["CAP-004"],"acceptance":["fixture exercises raw sibling install attempt","system detects, isolates, or marks expansion blocked","docs state advisory-only bypass posture is not promotable"],"candidate_paths":["tests/fixtures/hostile","src/runtime","src/gateway","docs/internal/decisions.md"],"non_goals":["broad host sandbox guarantee","MCP enforcement claim","CLI enforcement claim"]} -{"id":"CAP-009","priority":"P1","phase":"custody-bypass-probes","title":"Add material drift and provenance laundering fixtures","owner":"quality","rationale":"The pack must fail closed when evidence changes, disappears, or is misrepresented.","depends_on":["CAP-005","CAP-006"],"acceptance":["fixtures cover missing provenance, invalid signature, tarball mismatch, registry substitution, and lockfile drift","receipt records proof gaps without confidence language","gateway rejects pre-consequence drift where observable"],"candidate_paths":["tests/fixtures/hostile","tests/receipts","src/adapters/package-install"],"non_goals":["malware judgment","dependency update recommendation","registry trust scoring"]} -{"id":"CAP-010","priority":"P1","phase":"buyer-report","title":"Define buyer-readable protected dependency action report","owner":"product","rationale":"Adoption needs a readable artifact, but the report must bind to exact contract and receipt evidence or it becomes review theatre.","depends_on":["CAP-005","CAP-008","CAP-009"],"acceptance":["report sections are action, authority, exact contract, evidence, outcome, proof gaps, reconstruction","report references exact contract and receipt evidence ids","report excludes package safety and broad supply-chain claims"],"candidate_paths":["docs/internal","src/receipts","src/reports"],"non_goals":["dashboard polish","hosted operations claim","compliance certification"]} -{"id":"CAP-011","priority":"P0","phase":"conformance-export","title":"Create package-install conformance export for one npm install attempt","owner":"quality","rationale":"The first expansion is only real if the whole chain reconstructs from contract to receipt for one concrete attempt.","depends_on":["CAP-004","CAP-005","CAP-008","CAP-010"],"acceptance":["export includes proposal, exact contract, policy decision, gateway check, execution outcome, evidence, proof gaps, and reconstruction material","chain reconstructs without runtime transcript","closeout commands pass"],"candidate_paths":["tests/conformance","docs/internal","src/adapters/package-install"],"non_goals":["preview deploy conformance","repo write conformance","adapter marketplace"]} -{"id":"CAP-012","priority":"P2","phase":"next-pack-readiness","title":"Define promotion checklist for preview deploy and repo write","owner":"architecture","rationale":"Second and third packs must inherit the spine, not shortcut around package-install proof.","depends_on":["CAP-011"],"acceptance":["checklist requires manifest, compiler, policy, gateway validator, receipt mapper, bypass probes, and hostile fixtures","preview deploy remains second and repo write remains third","checklist blocks broad runtime/MCP/CLI enforcement claims"],"candidate_paths":["docs/internal/decisions.md","docs/internal/protocol-notes.md","tests/conformance"],"non_goals":["implementing preview deploy","implementing repo write","broadening protected actions beyond the validated spine"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/VALIDATION.md deleted file mode 100644 index b23bc67..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/VALIDATION.md +++ /dev/null @@ -1,65 +0,0 @@ -# Validation - -## Validation Matrix - -| Gate | Required Evidence | Passing Condition | Failure Means | -| --- | --- | --- | --- | -| Adapter contract freeze | Adapter pack manifest fields and references | Manifest is the activation boundary and no god registry is introduced | Expansion is structurally unsafe | -| Runtime ingress boundary | Runtime ingress routing behavior | Ingress selects compiler only and does not authorize | Shortcut authority | -| Package-install contract | Canonical package-install proposal | One npm install attempt is exact, inspectable, and policy-evaluable | Vague intent laundered into fake precision | -| Policy decision | Policy rule pack result | Decision is greenlight, refusal, review, halt, or quarantine against exact contract | Advisory policy | -| Gateway observed-parameter validation | Observed install parameters | Gateway rejects drift and enforces one-use exact binding | This is advisory, not Handshake | -| Lifecycle script posture | Contract and observed install flags | Lifecycle scripts blocked unless separately contracted | Hidden consequential execution | -| npm material evidence | Signature/provenance/tarball/registry evidence | Evidence recorded within real scope, with proof gaps when absent | Provenance laundering | -| Bun lockfile evidence | Lockfile material and reconstruction notes | Lockfile recorded as local reconstruction/drift evidence only | False provenance claim | -| Receipt mapping | Receipt/refusal/proof-gap output | Receipt distinguishes proposal, policy, gateway check, execution result, proof gaps | Evidence theatre | -| Bypass probes | Hostile fixtures | Raw sibling bypass is detected, isolated, or blocks promotion | Generated code escaped the contract boundary | -| Buyer report | Report artifact | Report sections bind to exact contract and receipt evidence | Review theatre | -| Export conformance | Exported fixture and receipt | Chain reconstructs without runtime transcript | This is not auditable | - -## Hostile Fixture Requirements - -Required hostile fixtures: - -- provenance laundering; -- missing provenance; -- invalid npm registry signature; -- tarball integrity mismatch; -- registry substitution; -- lockfile drift; -- lifecycle script attempt; -- raw sibling package-manager invocation; -- stale policy decision; -- reusable greenlight attempt; -- credential custody ambiguity; -- report/contract mismatch. - -## Closeout Commands - -Run closeout only after implementation work exists. This macro plan itself is planning-only. - -Expected closeout command set: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Focused closeout must also include the existing package-install runtime/gateway test target once its exact project script name is confirmed. - -## Closeout Evidence - -Closeout requires: - -- package-install conformance fixture for one npm install attempt; -- contract canonicalization evidence; -- gateway observed-parameter validation evidence; -- npm material evidence receipt mapping; -- Bun lockfile reconstruction evidence, if Bun material is present; -- explicit proof-gap case; -- lifecycle-script blocked case; -- raw sibling bypass case; -- buyer-readable report bound to exact contract and receipt ids; -- no product claims beyond protected dependency-action gating. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/input.md deleted file mode 100644 index 1a22cdc..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/input.md +++ /dev/null @@ -1,107 +0,0 @@ -# GSD Macro Input: Concrete Adapter Pack Expansion - -Run id: `concrete-adapter-pack-expansion-20260524T082400Z` -Date: 2026-05-24 - -## Hard Frame - -Handshake is protected actions for automated decision making, not an engineering-agent-only product. - -x402 exact per-call protected spend is the first wedge. It must remain one adapter proof pack, not the protocol center and not a payment-management product. - -Concrete adapter pack expansion must prove the Tier 1 spine generalizes: - -```text -exact action contract --> policy decision --> one-use gateway-bound greenlight/refusal --> customer-owned gateway check before mutation --> receipt/refusal/proof gap --> redacted reconstruction -``` - -No new adapter may invent shortcut authority because the mutation seems simpler than x402. - -## Current Source State - -Existing source already contains: - -- `ProtectedActionAdapterPackSchema` in `src/install/protected-action-adapter-pack/index.ts` with pack id/version, action family, protected surface kind, parameter schema ref, endpoint evidence schema ref, install compiler ref, policy rule pack ref, gateway observed parameter validator ref, receipt mapper ref, bypass probe kinds, and hostile fixture refs. -- Generic install proposals in `src/install/install-proposal/index.ts`. -- x402 install proposal and gateway signer path. -- Package install runtime proposal compiler in `src/runtime/package-install/action-proposal.ts`. -- Package install gateway in `src/adapters/package-install/gateway.ts`. -- Preview deploy runtime proposal compiler in `src/runtime/preview-deploy/action-proposal.ts`. -- Preview deploy gateway in `src/adapters/preview-deploy/gateway.ts`. -- Repo write runtime proposal compiler in `src/runtime/repo-write/action-proposal.ts`. -- Repo write gateway in `src/adapters/repo-write/gateway.ts`. -- Tests for package-install gateway, package-install runtime, package-install end-to-end, preview-deploy gateway, repo-write gateway, repo-write D1/HTTP, and support flows. - -Current `.planning/codebase/CONCERNS.md` says: - -- Runtime ingress is a 1,014-line cross-family module hardcoding package install, x402 payment, and auth.md dispatches. -- Each new protected-action family increases risk of missed refusal fields, cross-family parameter drift, and accidental authority language in the public runtime subpath. -- New family conversion should move behind source-owned family adapters or registry. -- Runtime ingress creates proposal evidence only: no policy decisions, greenlights, gateway checks, mutation attempts, receipts, or authority certificates. -- Package install is currently a regression lane until external package-manager material attestation is source-owned and tested. -- Broad runtime/host interception is not proven. - -Current `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` recommends first candidates: - -1. package-manager material attestation, because package install already exists as a regression lane; -2. preview deploy, because it is a common automated/generative execution mutation with visible downstream consequence; -3. repo write with protected branch or release consequence, because it exercises generated-code inspection and gateway path binding. - -Mechanisms required per adapter: - -- install proposal compiler; -- action type and gateway registry entry; -- exact parameter canonicalization; -- gateway observed-parameter validator; -- custody/bypass probes; -- receipt/proof-gap mapper; -- conformance fixture; -- buyer-readable report. - -## External Source Constraints - -For package-manager material attestation: - -- npm provenance lets consumers verify where/how a package was published and validate authorized publisher posture; `npm audit signatures` verifies registry signatures and provenance attestations when dependencies were installed with npm CLI support. -- npm provenance is not proof of benign code; it is a verifiable link to source/build instructions and transparency log evidence. -- npm registry signatures bind package name, version, and tarball integrity. -- Trusted publishing can automatically generate provenance when public packages are published via supported OIDC workflows, but account/repository/workflow correctness remains external configuration. -- Bun creates a `bun.lock` lockfile and recommends committing it; Bun lock evidence is local material evidence, not npm provenance verification by itself. - -Source links used: - -- https://docs.npmjs.com/viewing-package-provenance/ -- https://docs.npmjs.com/about-registry-signatures/ -- https://docs.npmjs.com/generating-provenance-statements/ -- https://docs.npmjs.com/trusted-publishers/ -- https://bun.com/docs/pm/lockfile - -## Planning Question - -Create a macro plan for concrete adapter pack expansion. Decide the first adapter pack to promote, the sequencing for preview deploy and repo write, and the mechanism that keeps adapter packs modular without weakening Tier 1 or making x402 the protocol. - -The likely answer should be: promote package-manager material attestation first, because package install already has runtime/gateway/regression lanes and external provenance standards can be bound as evidence. But challenge that if another candidate is materially stronger. - -## Required Output Properties - -The plan must include: - -- selected first adapter pack and why; -- explicit non-goals and cut lines; -- adapter pack manifest contract; -- parameter canonicalization and observed-parameter validation; -- material/provenance evidence posture; -- gateway custody and bypass probes; -- conformance fixtures; -- runtime/MCP/CLI exposure boundary; -- buyer-readable proof report; -- validation gates and closeout commands; -- architecture/import posture and no-god-registry constraints; -- success criteria and 10-star product bar. - -Do not implement source changes in this run. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ADOPTION.md deleted file mode 100644 index 3c72138..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ADOPTION.md +++ /dev/null @@ -1,142 +0,0 @@ -# ADOPTION Perspective - -## Invariant At Stake - -Mutation authority stays in the gateway. The adapter pack may propose, explain, diagnose, and report, but it must not make CLI/MCP/runtime surfaces feel like enforcement. - -## Recommended First Adapter Pack - -Make the first concrete expansion a Package Install Adapter Pack. - -Do not promote preview deploy and repo write alongside it yet. Package install is narrow enough to prove modularity, evidence capture, lockfile grounding, registry identity checks, replay/idempotency posture, and gateway-bound mutation without implying Handshake controls the whole runtime. - -x402 exact remains the first protected-action wedge. Package install becomes the first buyer-legible adapter proof that the same control primitive generalizes. - -## Operator/Developer Adoption Path - -1. Read-only inventory. - Detect package manager, workspace root, lockfile, package manifests, registry config, and install command posture. - Output what Handshake can observe, not what it can enforce. - -2. Proposal mode. - Agent/runtime/CLI/MCP can propose `package.install` candidates. - Candidate includes package spec, manager, workspace, expected manifest targets, expected lockfile effect, lifecycle-script posture, registry source, and required gateway. - -3. Evidence preview. - Show npm provenance/signature/material identity evidence where available. - Show Bun lockfile as local material evidence. - Say explicitly: provenance/signatures support identity/source/build posture, not package safety. - -4. Gateway-bound greenlight. - Policy evaluates the exact canonical package-install contract. - Gateway verifies one-use greenlight before running the install. - No CLI or MCP command can mutate without the gateway check. - -5. Receipt/report. - Record proposal, canonical contract, policy decision, gateway check, execution result, lockfile/package manifest delta, evidence sources, and proof gaps. - -## Command And Report Affordances - -Developer-facing commands should feel boring and composable: - -```bash -handshake adapters list -handshake adapters inspect package-install -handshake package-install scan -handshake package-install propose bun add zod@3.25.0 -handshake package-install report --latest -handshake package-install diagnose --receipt -``` - -Gateway mutation must be visibly separate: - -```bash -handshake gateway execute -``` - -Avoid commands like: - -```bash -handshake install zod -handshake approve install -handshake run agent safely -``` - -Those blur proposal, approval, and enforcement. - -## Buyer-Readable Proof Report Shape - -A useful report should fit on one page first, with expandable evidence. - -Sections: - -1. Action. - Install package `zod@3.25.0` in workspace `apps/web` using `bun`. - -2. Authority. - Principal, runtime, policy version, greenlight id, gateway id. - State clearly whether the gateway enforced before mutation. - -3. Exact Contract. - Canonical action type, package name/version/range, registry, package manager, workspace, expected manifest/lockfile targets, idempotency key, one-use greenlight binding. - -4. Evidence. - npm provenance/signature status if available, registry metadata captured, Bun lockfile before/after material delta, package manifest delta, lifecycle scripts detected or absent. - -5. Outcome. - Executed, refused, quarantined, halted, or proof gap. - Downstream install success is not the same as package safety. - -6. Proof Gaps. - Missing provenance, unverified signature, registry metadata unavailable, lockfile changed outside expected package closure, lifecycle script posture uncertain. - -7. Reconstruction. - Receipt id, contract hash, greenlight hash, gateway-check record, evidence artifact ids. - -## Error Model - -Errors should name the violated boundary, not just the failed command. - -Examples: - -- `CONTRACT_REQUIRED`: runtime attempted a package mutation without a canonical package-install contract. -- `GREENLIGHT_MISSING`: gateway received a mutation request without an exact one-use greenlight. -- `GREENLIGHT_SCOPE_MISMATCH`: greenlight was for a different package, workspace, manager, registry, or lockfile target. -- `GREENLIGHT_ALREADY_USED`: replayed authority attempt. -- `LOCKFILE_DELTA_UNEXPECTED`: install changed more than the declared dependency closure. -- `PROVENANCE_UNAVAILABLE`: evidence gap, not failure unless policy requires it. -- `LIFECYCLE_SCRIPT_REQUIRES_REVIEW`: package install includes script execution posture that policy will not auto-greenlight. -- `READ_ONLY_SURFACE`: CLI/MCP can propose or report, but cannot mutate. - -## Diagnostics And Anti-Frustration Details - -- Always show the exact field that prevented greenlight. -- Provide a copyable corrected proposal command. -- Distinguish policy refused from gateway could not verify. -- Distinguish package identity evidence missing from package unsafe. -- Show lockfile delta in human terms, not only hash terms. -- Explain why a reused greenlight failed. -- Let teams run read-only scan/report commands without gateway setup. -- Provide fixture/demo mode using known package installs, but label it non-production evidence. -- Keep preview deploy and repo write visible as available lanes, not default promoted adapters. - -## 10-Star Product Bar - -The first adapter pack is excellent when a skeptical engineering lead can say: - -- I can add this to one repo without migrating my runtime. -- I understand exactly which package install was contracted. -- I can see where authority was enforced. -- I can prove CLI/MCP did not hold mutation authority. -- I can reconstruct the action six months later. -- I can explain provenance/signatures without pretending they prove safety. -- I can see lockfile evidence as local material proof. -- I can diagnose refusal without reading source code. -- I can pilot this on package installs before trusting broader protected actions. -- I do not feel sold a universal agent-control platform. - -## Brutal Verdict - -Keep package install as the first adapter pack. Cut simultaneous promotion of preview deploy and repo write. Narrow CLI/MCP to proposal, evidence, diagnostics, and read-only reporting. Buyer trust comes from exact gateway-bound mutation evidence, not from claiming runtime control. - -Smallest next mechanism to build: a package-install proof report schema that binds canonical contract, policy decision, gateway check, lockfile delta, npm provenance/signature evidence, and explicit proof gaps. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ARCH.md deleted file mode 100644 index 7cbb6cf..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/ARCH.md +++ /dev/null @@ -1,228 +0,0 @@ -# ARCHITECTURE Perspective - -## Invariant At Stake - -Adapter expansion must not create shortcut authority. Every adapter can only describe how to compile, canonicalize, validate, map evidence, probe bypass, and test hostile cases for a protected action family. It must never mint permission, widen a greenlight, or treat external provenance as proof of safety. - -## Architectural Plan - -### 1. Adapter-Pack Manifest Contract - -`ProtectedActionAdapterPackSchema` should become the only accepted manifest shape for adapter expansion. - -Each adapter pack should declare: - -- `adapterPackId`: stable, namespaced, versioned identifier. -- `actionFamily`: package install, preview deploy, repo write, etc. -- `supportedRuntimes`: runtime proposal surfaces only, not authority holders. -- `installCompilerRef`: turns runtime intent into proposed contracts. -- `policyPackRef`: family-specific policy rules and refusal reasons. -- `gatewayObservedParameterValidatorRef`: validates actual gateway-side parameters. -- `receiptMapperRef`: maps proposal, policy, gateway, execution, proof-gap, and bypass evidence. -- `bypassProbeRefs`: detects raw or sibling mutation paths. -- `hostileFixtureRefs`: conformance fixtures for overreach, stale policy, replay, parameter drift, and hidden mutation. -- `materialEvidenceFields`: family-specific evidence that may help reconstruction. -- `provenanceEvidenceFields`: attestations such as npm provenance/signatures or Bun lockfile facts. -- `redactionPolicyRef`: field-level reconstruction rules. - -The manifest is not executable authority. It is a signed or hash-addressed declaration of which family-specific components Handshake is allowed to load for proposal and evidence handling. - -### 2. Source Ownership - -Keep adapter ownership split by control primitive, not by runtime. - -Recommended ownership shape: - -- Protocol-owned schemas: canonical action contract, adapter-pack manifest, evidence envelopes, refusal/proof-gap enums. -- Family-owned adapter packs: package install, preview deploy, repo write. -- Runtime-owned proposal compilers: Codex, MCP, CLI, browser, CI, etc. -- Gateway-owned validators: observed parameter validation and greenlight binding. -- Receipt-owned mappers: durable evidence shape and redaction posture. -- Test-owned conformance suites: hostile fixtures and bypass probes. - -Do not let runtime ingress own adapter-family logic. Runtime ingress should select a proposal compiler by declared runtime and action family, then hand the candidate into canonical protocol flow. Cross-family hardcoding in ingress is architectural debt because it makes runtime adapters quietly become policy routers. - -### 3. Registry Shape - -Use small registries with typed refs, not one global registry. - -Required registries: - -- `AdapterPackRegistry`: resolves manifest refs by adapter pack id and version. -- `ActionCatalogRegistry`: maps known consequential action families to schemas. -- `CompilerRegistry`: maps runtime plus action family to proposal compiler. -- `PolicyPackRegistry`: maps action family plus policy version to evaluator. -- `GatewayValidatorRegistry`: maps action family plus gateway id to observed-parameter validator. -- `ReceiptMapperRegistry`: maps action family to evidence mapper. -- `FixtureRegistry`: maps adapter pack to conformance and hostile fixtures. - -Registry lookup must be deterministic and version-pinned. No runtime-selected dynamic imports from model output. No fallback to generic adapter for protected mutations unless the result is refusal or proof gap. - -### 4. Parameter Canonicalization - -Canonicalization is the contract boundary. - -Each adapter pack must define a deterministic canonical parameter shape: - -- normalized package manager command, package names, versions, registry, lockfile intent; -- normalized preview deploy target, project, branch, environment, provider, commit; -- normalized repo write path set, operation type, diff hash, branch, external consequence marker. - -Canonicalization must reject ambiguity. It should not best-guess package aliases, deploy targets, branch names, environment names, or write scopes. - -Canonical output should include: - -- `canonicalActionHash`; -- `protectedSurfaceId`; -- `idempotencyKey`; -- `sequencingDependencies`; -- `materialParameters`; -- `uncertaintyMarkers`; -- `redactionHints`. - -The compiler may produce candidates. The canonicalizer decides whether the candidate is exact enough to evaluate. If not, refusal or review, not permission. - -### 5. Observed-Parameter Validation - -Gateway observed-parameter validation is the adapter's most important expansion point. - -At mutation time, the gateway must compare: - -- canonical contract parameters; -- one-use greenlight binding; -- actual observed gateway parameters; -- policy version; -- adapter pack version; -- gateway registry version; -- isolation state. - -Mismatch means refusal or proof gap, not degraded execution. - -Validation must catch: - -- package manager changed package/version/registry/flags; -- Bun/npm lockfile drift after approval; -- preview deploy target changed branch/environment/provider/project; -- repo write touched paths outside approved diff; -- runtime retried with mutated parameters; -- sibling/raw tool path bypassed the adapter; -- stale review surface approved an older contract. - -A greenlight is valid for exactly one observed mutation attempt. - -### 6. Material And Provenance Evidence Posture - -Material evidence helps reconstruction. It is not authority. - -For package managers, evidence fields may include: - -- npm provenance attestation presence; -- npm signature verification result; -- registry URL; -- resolved package tarball integrity; -- lockfile digest; -- Bun lockfile digest; -- package manager version; -- install command digest; -- dependency graph delta. - -These fields prove what was attempted or observed. They do not prove the code is benign. Treating provenance as safety proof is evidence theatre. - -For preview deploys: - -- provider; -- project; -- environment; -- commit SHA; -- build config digest; -- deployment URL; -- provider request id; -- gateway decision id. - -For repo writes: - -- path allowlist; -- diff hash; -- commit hash if committed; -- working tree state; -- external consequence marker; -- bypass probe result. - -Receipts must distinguish proposal, policy decision, gateway check, execution result, downstream uncertainty, refusal, and proof gap. - -### 7. Conformance Fixtures - -Every adapter pack must ship hostile fixtures before it is accepted. - -Minimum fixture families: - -- overbroad vague intent compiled into excessive scope; -- generated code loop retries after refusal; -- greenlight replay attempt; -- stale policy version at gateway check; -- stale rendered review artifact; -- parameter drift between proposal and gateway; -- hidden secondary mutation; -- raw tool bypass; -- sibling adapter bypass; -- missing material evidence; -- missing provenance evidence; -- provenance present but malicious or unknown package behavior; -- receipt mapper unable to distinguish gateway check from execution result. - -The fixture suite should prove the adapter preserves the global Handshake chain: - -```text -proposal -> canonical contract -> policy -> greenlight/refusal -> gateway check -> receipt/proof gap -> redacted reconstruction -``` - -### 8. Import / Export Posture - -Adapter packs may be imported as declarative manifests plus versioned implementation refs. Import must validate schema, version, fixture coverage, and registry compatibility before activation. - -Export should produce reconstruction bundles: - -- adapter pack manifest digest; -- action contract; -- policy decision; -- gateway check record; -- observed parameters; -- evidence fields; -- redaction map; -- proof gaps; -- bypass probe results. - -Exports must not leak secrets, tokens, raw environment values, or full unredacted lockfile content unless explicitly allowed by redaction policy. CLI and MCP exports remain proposal/evidence only. - -### 9. No-God-Registry Constraints - -Do not build a universal adapter registry that can decide everything. - -Hard constraints: - -- Registry resolves refs; it does not interpret policy. -- Runtime ingress selects compilers; it does not authorize. -- Adapter pack declares family behavior; it does not bypass canonical protocol schemas. -- Policy pack evaluates exact contracts; it does not execute. -- Gateway validator enforces exact binding; it does not infer intent. -- Receipt mapper records evidence; it does not smooth gaps. -- CLI/MCP propose and report evidence; they do not mint greenlights. - -A god registry will become ambient authority with better metadata. Keep registries narrow, typed, version-pinned, and hostile-fixture-gated. - -## Expansion Sequence - -1. Promote adapter-pack manifest contract as the required activation boundary. -2. Split runtime ingress from action-family selection so compilers are looked up by runtime plus action family. -3. Define canonical parameter contracts for package install, preview deploy, and repo write. -4. Add gateway observed-parameter validators for those three families. -5. Attach material/provenance evidence fields without treating them as safety proof. -6. Require hostile fixture suites before any adapter pack is considered conformant. -7. Add redacted reconstruction export for one complete package-install receipt. -8. Only then add more adapter families. - -## Brutal Verdict - -Keep the adapter-pack expansion, but narrow its authority. The adapter pack is not a plugin permission model. It is a constrained evidence-and-contract module that must pass through the same Handshake primitive every time. - -Smallest next mechanism to build: a versioned adapter-pack activation gate that validates manifest refs, fixture coverage, canonical parameter schema, and gateway observed-parameter validator presence before the pack can be used. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/EXECUTION.md deleted file mode 100644 index 1d4b607..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/EXECUTION.md +++ /dev/null @@ -1,186 +0,0 @@ -# EXECUTION Perspective - -## Invariant At Stake - -A concrete adapter may expand Tier 1 only if it preserves exact contract binding: candidate action -> deterministic canonicalization -> policy decision -> one-use gateway check -> receipt/refusal/proof-gap. Anything that adds provenance, reports, or runtime tests without gateway-observed enforcement is advisory, not Handshake. - -## First Adapter Selection - -Select package install adapter first. - -Reason: it already has runtime compiler and gateway test lanes, and the missing piece is sharply bounded: promote material attestation without pretending it proves package safety. That makes it the smallest credible adapter-pack expansion while protecting Tier 1. - -Do not select preview deploy or repo write first. They are more operationally valuable, but their blast radius includes environment drift, downstream platform state, filesystem semantics, and rollback ambiguity. Package install gives the adapter pack a cleaner first conformance surface. - -## Phase 0: Freeze The Adapter Contract - -Tasks: - -1. Define the package-install adapter pack boundary. -2. Confirm action type name, protected surface, gateway registry ownership, and receipt event names. -3. State explicitly that npm signatures/provenance are material evidence, not benignness proof. -4. State Bun lockfile evidence as local material evidence only. -5. Add no new Tier 1 claims unless a gateway check observes and validates the same canonical parameters. - -Validation gate: - -- The adapter pack must be expressible as one action type with one protected mutation path. -- No report or receipt may imply package safety from provenance alone. - -Stop condition: - -- If the existing package install action contract cannot carry install target, package manager, registry source, lockfile/material evidence fields, and idempotency key without widening Tier 1 primitives, stop and redesign the contract shape first. - -## Phase 1: Canonical Package Install Proposal - -Tasks: - -1. Compile package-install proposals into exact candidate actions. -2. Canonicalize package manager, package names, versions/ranges, registry URL, workspace path, lockfile path, install mode, and expected material evidence. -3. Reject dynamic package names, implicit registries, hidden postinstall scope, or unresolved workspace targets as refusal/review candidates. -4. Preserve generated code/spec references as proposal evidence, not permission. - -Validation gate: - -- Golden fixture proves semantically equivalent install proposals produce identical canonical contracts. -- Ambiguous versions, registry aliases, and workspace-relative path drift produce refusal/review outcomes. - -Stop condition: - -- If the compiler converts vague intent like "make tests pass" into package install authority without explicit candidate evidence, stop. The compiler overreached the principal. - -## Phase 2: Gateway Observed Parameter Validator - -Tasks: - -1. Add gateway registry entry for package install. -2. Validate observed gateway parameters against the exact greenlit canonical contract. -3. Enforce one-use greenlight binding. -4. Verify package manager, package spec, registry, workspace path, and idempotency key at the mutation boundary. -5. Record mismatch as refusal or bypass/proof-gap evidence, not a soft warning. - -Validation gate: - -- Gateway tests prove mismatch on package name, version, registry, workspace, or package manager blocks execution. -- Replay of a used greenlight fails. -- Raw/sibling install path is detected or recorded as bypass posture where possible. - -Stop condition: - -- If install can proceed through an unwrapped package-manager path while claiming Handshake enforcement, stop. The generated code escaped the contract boundary. - -## Phase 3: Material Attestation Mapper - -Tasks: - -1. Capture npm provenance/signature verification result when npm is the package manager. -2. Capture `npm audit signatures` result as registry-signature/provenance evidence after install where applicable. -3. Capture Bun lockfile deltas as local material evidence only. -4. Map unavailable, unsupported, failed, or skipped attestation to structured proof gaps. -5. Keep attestation separate from gateway check and downstream install result. - -Validation gate: - -- npm provenance/signature success is recorded as material attestation evidence, not safety approval. -- unsupported package manager or missing registry support records proof gap. -- failed attestation does not get smoothed into generic install failure. - -Stop condition: - -- If receipt language implies "verified package is safe," stop. Provenance does not prove benignness. - -## Phase 4: Custody And Bypass Probes - -Tasks: - -1. Probe whether install occurred through the Handshake-wrapped gateway. -2. Probe for lockfile/package manifest changes that do not match the greenlit contract. -3. Distinguish gateway-observed install, raw install suspicion, postinstall uncertainty, and unsupported custody evidence. -4. Record bypass/proof-gap evidence even when install appears successful. - -Validation gate: - -- Fixture proves manifest or lockfile mutation without matching gateway receipt is recorded as bypass/proof gap. -- Fixture proves install success without material attestation does not erase the proof gap. - -Stop condition: - -- If custody cannot distinguish gateway check from downstream install result, stop. This is evidence theatre. - -## Phase 5: Buyer-Readable Adapter Report - -Tasks: - -1. Generate a compact report for one package install attempt. -2. Include candidate contract, policy result, gateway check, observed install result, material attestation, bypass posture, and proof gaps. -3. Avoid internal planning-stage labels. -4. Make the report reconstructable from receipts, not from runtime logs alone. - -Validation gate: - -- Report can be regenerated from stored evidence. -- Report does not claim benignness, supply-chain safety, or org-wide enforcement beyond the observed attempt. - -Stop condition: - -- If the report is manually assembled from runtime trace instead of receipt evidence, stop. This is not auditable. - -## Phase 6: Conformance And Export Surface - -Tasks: - -1. Add package-install adapter conformance fixture. -2. Add architecture/export tests for action type, gateway registry entry, receipt/proof-gap mapper, and report generator. -3. Add runtime/MCP proposal tests only if this adapter is exposed through runtime/MCP proposal surfaces. -4. Keep preview deploy and repo write untouched except for shared adapter-pack interfaces required by this slice. - -Validation gate: - -- Architecture/export tests prove the adapter pack is wired through declared registries, not ad hoc imports. -- Conformance fixture proves proposal -> canonical contract -> gateway validation -> receipt/report reconstruction. - -## Closeout Commands - -Run only after implementation: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Add focused tests if present: - -```bash -npm test -- package-install -npm test -- adapter -npm test -- gateway -``` - -## Rollback Conditions - -Rollback or stop the slice if: - -1. Tier 1 wording expands from enforced package install attempts to general supply-chain safety. -2. A greenlight can authorize more than one install attempt. -3. Gateway validation does not compare observed parameters to the canonical contract. -4. Provenance/signature evidence is treated as authorization. -5. Receipts collapse gateway check, install result, and attestation into one vague success event. -6. Raw or sibling package-manager bypass is invisible or unrecorded. -7. The adapter requires preview deploy or repo write changes to look complete. - -## Smallest Implementation Slice - -Build only this: - -Package install adapter conformance slice for one npm install attempt: - -1. Action catalog entry. -2. Deterministic canonical package-install contract. -3. Gateway registry entry with observed parameter validator. -4. One-use greenlight enforcement test. -5. Receipt mapper that separates gateway check, install result, npm signature/provenance evidence, and proof gaps. -6. One buyer-readable report generated from the receipt. - -Smallest next mechanism to build: the package-install gateway observed-parameter validator bound to the canonical contract. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/RISK.md deleted file mode 100644 index 8bd5def..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/RISK.md +++ /dev/null @@ -1,104 +0,0 @@ -# RISK Perspective - -## Invariant At Stake - -A new adapter pack must not convert protected actions into polite wrappers. Every package install, preview deploy, and repo write still needs an exact action contract, one-use greenlight, gateway-side check, receipt/refusal/proof-gap evidence, and bypass posture. If the adapter merely proposes or reports, it is advisory, not Handshake. - -## Risk Stance - -First adapter pack should be narrow: package-install, preview-deploy, and repo-write only. - -Do not center x402. Do not claim broad host interception. Do not claim CLI/MCP enforcement unless the gateway actually blocks mutation. CLI/MCP can emit proposals and evidence, but they are not authority holders unless paired with a blocking gateway. - -## Threat Model - -Protected actions: - -- Install or update dependencies. -- Trigger preview deploys. -- Write repo files with consequential downstream effects. -- Invoke CLI/MCP tools that may mutate through sibling paths. -- Use credentials needed by package managers, deploy systems, repos, or cloud APIs. - -Trust boundaries: - -- Agent runtime to Handshake proposal boundary. -- Handshake policy to gateway enforcement boundary. -- Gateway to external system mutation boundary. -- Package manager to registry/provenance/lockfile boundary. -- CLI/MCP adapter to raw host tools boundary. -- Receipt evidence to downstream business-success claims. - -Primary adversary is generated code with loops, retries, stale plans, dynamic tool names, lifecycle script execution, env access, credential leakage, and vague intent compiled into excessive scope. - -## Premortem - -| Risk | Failure Mode | Required Mechanism | -| --- | --- | --- | -| Shortcut authority | Adapter pack treats approved install/deploy/write as reusable permission. | One exact contract per mutation attempt; greenlight nonce bound to adapter, target, args, policy version, idempotency key, and expiry. | -| Supply-chain evidence laundering | npm provenance/signature is shown as proof the package is safe. | Receipt must distinguish registry provenance verified from benign code proven. | -| Package-manager side effects | Install runs lifecycle scripts, postinstall downloads, binary builds, env reads, or transitive mutations. | Package-install contract must declare lifecycle posture: blocked, sandboxed, or explicitly allowed with evidence. | -| Lifecycle scripts | Generated code only installs a package but install executes arbitrary package code. | Default should be ignore-scripts unless lifecycle scripts are separately contracted. | -| Lockfile drift | Lockfile changes differ from proposed dependency delta, or Bun lockfile is treated as npm provenance. | Canonical lockfile diff must be receipted; Bun lockfile proof cannot stand in for npm registry provenance. | -| Raw sibling bypass | Agent calls npm, bun, git, deploy CLI, or MCP raw path outside the adapter. | Explicit bypass tests; isolation state set on detected raw sibling mutation. | -| Runtime/MCP overclaim | CLI/MCP emits proposals/evidence but product claims enforcement. | Label CLI/MCP as proposal/evidence only until paired with a blocking gateway. | -| Credential custody | Adapter holds broad tokens and becomes ambient authority. | Gateway-owned scoped credentials; per-action credential reference; no runtime-held deploy/package/repo mutation secrets. | -| Report theatre | Adapter generates a clean report without proving gateway check or downstream result. | Receipts must separate proposal, policy decision, gateway check, attempted mutation, external response, and proof gap. | -| Import posture | Imported adapter lessons, package attestations, or external claims become canon without enforcement proof. | Imports are advisory notes unless backed by local contract/gateway/receipt fixtures. | - -## Hard Validation Gates - -1. Contract gate. - Each adapter action must canonicalize to a deterministic contract with protected surface, exact target, args, idempotency key, policy version, credential ref, expected evidence, and bypass posture. - -2. One-use greenlight gate. - A greenlight must fail on replay, mutation drift, expired policy, changed args, changed target, changed credential ref, or second use. - -3. Gateway enforcement gate. - Mutation must be impossible without the gateway check. If the raw tool can still mutate the same surface from the same runtime path, the adapter is not enforcement. - -4. Package-install evidence gate. - Package install receipts must separately record registry metadata, signature/provenance status, lockfile delta, lifecycle-script posture, package-manager version, and proof gaps. - -5. Lifecycle gate. - Lifecycle scripts default blocked. Allowing them requires a separate exact contract and evidence record. - -6. Bypass gate. - Tests must attempt raw npm/bun, raw deploy CLI, raw git write, and MCP sibling mutation. Any successful uncontracted mutation sets isolation state and blocks expansion. - -7. Runtime ingress gate. - Runtime family hardcoding must be removed or explicitly bounded. Adapter pack cannot assume one runtime family maps to authority semantics. - -8. Credential gate. - Runtime cannot possess broad mutation credentials. Gateway must hold or broker scoped credentials, and receipts must identify which credential reference was used. - -9. Receipt gate. - Receipts must reconstruct proposal, policy decision, gateway check, external attempt, result, refusal, proof gap, and bypass detection independently of chat logs. - -10. Claim gate. - README/docs/product language must not claim host-wide interception, MCP enforcement, package safety, or x402-centered authority unless implemented and tested. - -## Stop Conditions - -Stop adapter expansion if any of these are true: - -- A greenlight can authorize more than one mutation. -- A raw sibling path can mutate the protected surface. -- CLI/MCP is described as enforcement while only producing proposals or evidence. -- Package install evidence treats provenance, signatures, or lockfiles as proof of benign code. -- Lifecycle scripts can run without a separate contracted decision. -- Runtime ingress logic depends on hardcoded runtime families for authority. -- Gateway check and downstream execution are collapsed into one receipt field. -- Credentials are available to the agent runtime instead of the gateway boundary. -- Docs claim broad host interception before bypass tests prove it. -- x402 becomes the center of the protocol story instead of a protected-spend adapter case. - -## Brutal Verdict - -Keep the adapter pack only if it is framed as three concrete protected-action adapters with blocking gateway checks and hostile bypass tests. - -Cut any marketable language that says adapter support, MCP enforcement, safe installs, or runtime protection without exact gateway blocking. - -Narrow package install hardest. It is the riskiest because package managers execute code, mutate lockfiles, resolve transitive graphs, and produce evidence that is easy to launder into false confidence. - -Smallest next mechanism to build: a package-install contract fixture that records lifecycle posture, registry provenance status, lockfile delta, credential ref, one-use greenlight, gateway check, and explicit proof gaps. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/STRATEGY.md deleted file mode 100644 index 0f65721..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/raw/STRATEGY.md +++ /dev/null @@ -1,111 +0,0 @@ -# STRATEGY Perspective - -## Invariant At Stake - -A protected action must reduce an automated decision into an exact, gateway-checkable contract with reconstructable evidence. The next adapter pack must prove Handshake is not payments, not deploy approvals, not agent auth, and not a hosted workflow product. - -## Choice - -Promote package-manager material attestation first. - -Not package install approval. That is too weak and too engineering-agent-coded. Promote the adapter as material attestation for automated dependency decisions. - -This is the cleanest next proof that the Tier 1 spine generalizes from x402 exact per-call to non-payment protected actions: - -- exact action contract; -- one-use greenlight; -- gateway check before consequence; -- refusal/proof-gap path; -- reconstructable material evidence; -- narrow adapter-owned semantics. - -Preview deploy is useful, but it pulls the product toward hosted operations. Repo write is foundational, but it is too broad and likely to become an intent/compiler swamp before the adapter spine is proven. - -## Strategic Sequencing - -1. Package-manager material attestation. - First promoted adapter pack. Use it to prove Handshake can gate an automated decision based on material evidence rather than payment state. - -2. Preview deploy. - Second. Use it to prove the same spine controls externally visible hosted consequences, but only after the adapter-pack boundary is already clean. - -3. Repo write. - Third. Use it when the compiler/canonicalizer boundary is stronger. Repo write touches too many protected surfaces and will otherwise blur action contract, diff intent, branch policy, CI side effects, and downstream deploy consequence. - -## Product Claim Boundary - -Say: - -> Handshake can gate automated dependency actions on exact package material evidence, policy, and gateway-bound execution authority. - -Do not say: - -- Handshake proves package code is safe. -- Handshake replaces npm audit. -- Handshake guarantees dependency security. -- Handshake verifies Bun provenance. -- Handshake knows whether a package is benign. -- Handshake is package-manager auth. -- Handshake broadly secures software supply chains. - -The exact claim is narrower and stronger: - -> For a declared package-manager action, Handshake records the proposed package mutation, evaluates required material evidence, greenlights or refuses one exact attempt, checks that greenlight at the gateway, and records the resulting evidence or proof gap. - -## 10-Star Bar - -The promoted adapter pack is not 10-star unless it has all of this: - -1. Adapter-owned contract schema. - Package name, version/range, resolved version, registry, package manager, lockfile posture, install command shape, workspace path, expected mutation class, and idempotency key are first-class fields. - -2. Canonicalization before policy. - The same proposed install/update must canonicalize deterministically. No policy decision over raw command strings. - -3. Material evidence model. - npm provenance/signature evidence is represented separately from local lockfile evidence. Bun lockfiles can support local reconstruction, but cannot masquerade as npm provenance verification. - -4. Explicit non-benign-code boundary. - The adapter must state that signatures/provenance/tarball integrity are material posture, not proof of harmless code. - -5. Gateway-side check. - The install path must verify the exact greenlight before mutation. If the runtime compiler proposes but raw install can bypass, that bypass must be recorded or blocked. - -6. Refusal as product output. - Missing signature, unsupported registry, unverifiable package manager, stale lockfile, unresolved package, or mismatched tarball must produce structured refusal or proof gap. - -7. Evidence receipt separation. - Receipt must distinguish proposal, policy decision, gateway check, install execution, signature/provenance verification, lockfile delta, and downstream audit uncertainty. - -8. No god registry. - Runtime ingress must not absorb package-manager semantics. The adapter pack owns package-manager canonicalization and evidence interpretation behind a narrow interface. - -9. Regression lane converted into source-owned adapter. - Existing package install fixtures/tests stop being only regression coverage. They become canonical adapter examples with named doctrine. - -10. Cross-manager honesty. - npm gets provenance/signature verification where supported. Bun gets local lockfile/material evidence only unless an actual provenance verification mechanism is wired. No fake parity. - -## Cut Lines - -Cut package install as permission. The product is not "agent asked to install lodash and user approved." That is approval theatre unless the gateway binds the exact resolved artifact and attempt. - -Cut broad supply-chain security. Handshake does not decide benignness. It controls whether an automated dependency mutation may proceed under declared material evidence requirements. - -Cut Bun provenance claims unless wired to a real verification mechanism. Bun lockfiles are useful reconstruction evidence, not npm provenance attestation. - -Cut runtime-ingress centralization. Runtime ingress should normalize proposal intake and route to adapter packs. It must not become the global registry for every protected action family. - -Cut MCP/CLI as authority surfaces. MCP/CLI can propose, inspect, and emit evidence. They do not become the authority holder unless the gateway check is actually enforced there. - -Cut preview deploy as first generalization proof. It is compelling, but it reinforces hosted operation control. Use it after package-manager attestation proves the spine works on material evidence. - -Cut repo write as first generalization proof. It is too large. Without stronger compiler boundaries, repo write will collapse into vague intent, diff review, branch policy, CI consequence, and deploy adjacency. - -## Brutal Verdict - -Promote package-manager material attestation first. - -It is the smallest adapter pack that breaks the payment-center narrative while preserving exact per-action discipline. It forces Handshake to say what evidence proves, what it does not prove, and where gateway authority actually lives. - -Smallest next mechanism to build: a source-owned package-manager material attestation adapter contract with npm signature/provenance evidence, Bun lockfile-only evidence, structured refusal/proof-gap receipts, and one gateway fixture proving exact greenlight binding before install. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/synthesis.md deleted file mode 100644 index 1d7e51e..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/concrete-adapter-pack-expansion/runs/concrete-adapter-pack-expansion-20260524T082400Z/synthesis.md +++ /dev/null @@ -1,127 +0,0 @@ -# Chair Synthesis: Concrete Adapter Pack Expansion - -## Invariant At Stake - -No consequential automated action executes outside declared bounds, and divergent behavior must be haltable, isolatable, and reconstructable. - -For this macro item, the dangerous failure is expansion theatre: claiming Handshake generalizes beyond x402 while silently replacing exact gateway-bound authority with runtime ingress, CLI/MCP surfaces, reports, npm evidence, or package-manager conventions. - -## Perspective Reconciliation - -### Strategy - -Strategy is right to promote package-manager material attestation first. - -It breaks the payment-centered narrative without broadening into vague platform claims. The claim is narrow and defensible: Handshake gates automated dependency actions on exact material evidence, policy, and gateway-bound authority. - -The strategy boundary is equally important. Do not say package safety. Do not say npm audit replacement. Do not say Bun provenance. Do not say broad supply-chain security. Do not say hosted operation. Do not say MCP/CLI/runtime enforcement. - -### Architecture - -Architecture is right that the manifest contract is the activation boundary. - -The adapter pack is not a folder of helpers. It is a declared activation unit: schemas, compiler, policy rule pack, gateway observed-parameter validator, receipt evidence mapper, bypass probes, hostile fixtures. - -The runtime ingress concern is real. If runtime ingress grows into one cross-family registry that knows every compiler, policy, validator, mapper, and bypass probe, it becomes ambient authority by architecture. Use small typed registries. Runtime ingress selects compilers. It does not authorize. - -### Execution - -Execution is right on phase order: - -1. freeze adapter contract; -2. canonical package install proposal; -3. gateway observed-parameter validator; -4. material attestation mapper; -5. custody/bypass probes; -6. buyer-readable report; -7. conformance/export. - -The smallest useful slice is package-install conformance for one npm install attempt. Anything broader invites unearned claims. - -### Risk - -Risk is right to treat lifecycle scripts, lockfile drift, raw sibling bypass, provenance laundering, credential custody, and report theatre as first-class blockers. - -Lifecycle scripts are the sharp edge. An install that runs scripts is not merely installing material. It is executing code. Default block unless separately contracted. - -Raw sibling bypass is the second sharp edge. If generated code can call `npm`, `bun`, `pnpm`, or another package-manager mutation path outside the gateway, the generated code escaped the contract boundary. Advisory detection is not enough for promotion. - -### Adoption - -Adoption is right that the operator path must be concrete: - -1. scan/inventory; -2. propose; -3. evidence preview; -4. gateway-bound greenlight; -5. receipt/report. - -The commands and UI must not blur proposal, approval, and enforcement. The report must have stable sections: action, authority, exact contract, evidence, outcome, proof gaps, reconstruction. - -The report is useful only if it binds to the exact contract and receipt evidence. Otherwise this is review theatre. - -## 10-Star Bar - -A 10-star version of this macro plan proves the Tier 1 spine outside payments with one exact dependency action. - -It must demonstrate: - -- exact package-install contract; -- policy decision against that exact contract; -- one-use greenlight; -- gateway observed-parameter enforcement; -- lifecycle script default block; -- npm material evidence mapped within true scope; -- Bun lockfile evidence scoped to reconstruction; -- raw sibling bypass detected or promotion blocked; -- hostile fixtures that fail closed; -- receipt that distinguishes proposal, policy, gateway check, downstream install result, and proof gaps; -- buyer-readable report that does not overclaim. - -The 10-star bar is not a beautiful adapter story. It is one reconstructable protected action that cannot be confused with payment management, package safety, supply-chain security, hosted operations, or runtime enforcement. - -## Antipatterns - -### Antipattern: Clean Proof Surface Becomes First Market - -A clean package-install proof surface is not automatically the first market. It is a demo candidate and adapter spine proof. Market merit still requires urgent, budgeted, frequent, expensive pain and a distribution path. - -### Antipattern: npm Evidence Becomes Safety Claim - -npm provenance/signatures help verify source/build/publisher posture and registry/tarball integrity. They do not prove benign code. Calling this package safety is provenance laundering. - -### Antipattern: Bun Lockfile Becomes Provenance - -Bun lockfile material supports local reconstruction and drift evidence. It is not npm provenance verification. - -### Antipattern: Runtime Ingress Becomes Authority - -Runtime ingress selecting a compiler is acceptable. Runtime ingress authorizing a mutation is shortcut authority. - -### Antipattern: CLI/MCP Enforcement Language - -CLI and MCP may propose, display, inventory, and export evidence. Unless they are the gateway-bound mutation path, they are not enforcement. - -### Antipattern: Report Theatre - -A buyer-readable report that summarizes authority without binding to exact contract and receipt evidence is review theatre. - -### Antipattern: Lifecycle Scripts Hidden Under Install - -Lifecycle scripts are consequential execution. They require separate contracting or default blocking. - -### Antipattern: Bypass As Documentation - -Documenting that raw package-manager bypass exists is not enough. Detect it, isolate it, or block promotion. - -## Final Verdict - -Keep and narrow. - -Promote package-manager material attestation/package-install first. It is the right adapter pack because it proves Handshake is about exact protected actions, not payments, while staying small enough to enforce. - -Cut every broad claim around supply-chain security, package safety, hosted operations, payment management, and runtime/MCP/CLI enforcement. - -Do not start preview deploy or repo write promotion until package-install conformance closes for one npm install attempt with hostile fixtures and reconstructable receipt evidence. - -Smallest next mechanism to build: package-install conformance for one npm install attempt, including exact contract, npm material evidence expectations, lifecycle-script default block, gateway observed parameters, receipt mapping, and hostile drift/bypass cases. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/ASSUMPTIONS.md deleted file mode 100644 index d36a022..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/ASSUMPTIONS.md +++ /dev/null @@ -1,16 +0,0 @@ -# Assumptions - -| ID | Assumption | Confidence | Evidence | Invalidation Trigger | -| --- | --- | --- | --- | --- | -| A1 | Tier 1 protocol meaning must stay stable: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, isolation. | High | User constraints and all raw perspectives. | Implementation requires a custody-specific greenlight, approval, or permission object. | -| A2 | Customer-owned gateway custody means the customer/provider gateway owns or resolves the mutation credential; Handshake does not hold it. | High | Input constraints and product canon in raw outputs. | Any source change stores signer material, wallets, bearer tokens, payment credentials, balances, or settlement state in Handshake. | -| A3 | x402 is the first wedge but must not define generic custody proof semantics. | High | User constraints and strategy/execution raw outputs. | Protocol packet fields become x402/payment-specific instead of provider-neutral. | -| A4 | A new packet is needed because extending only existing fields leaves buyer-readable custody proof scattered. | Medium-High | ARCH, STRATEGY, EXECUTION, and ADOPTION raw outputs converge. | Source map shows an existing source-owned object can carry the full chain without overloading semantics. | -| A5 | The packet can be added under credential custody as evidence without creating a second authority plane. | Medium | Existing credential-custody and protected-path primitives appear to own the right boundary. | Object registry, kernel, or public schema ownership prevents additive packet wiring without broad redesign. | -| A6 | Custody proof should be required first for credential-backed protected paths, not every `gateway_checked` path. | High | Strategy raw output warns global requirement could drift Tier 1 meaning. | Implementation proves all gateway-checked paths already have credential backing and can migrate safely. | -| A7 | Fixture/local custody can support regression tests but cannot support provider/customer custody claims. | High | Input constraints and all raw perspectives. | Any docs, examples, or projections describe `fixture_gateway_held` as customer/provider custody. | -| A8 | Credential resolution evidence remains post-gate and cannot become install proof or permission. | High | ARCH, RISK, and ADOPTION raw outputs. | Implementation records credential resolution before a passed gateway check or uses it to authorize policy. | -| A9 | Redacted projections should be allowlist-style for custody fields because provider formats are not verified. | Medium-High | RISK and ADOPTION raw outputs identify pattern-only redaction risk. | Official provider verification and fuzz tests prove safe provider-specific field rendering. | -| A10 | Provider-neutral schema planning can proceed without browsing. | High | Input packet explicitly says do not browse by default. | A named provider/vault/KMS/wallet implementation becomes necessary for the first slice. | -| A11 | Companion files outside the packet may affect object registration, public inputs, projection schemas, and storage. | High | ARCH and EXECUTION raw outputs list unverified source paths. | Phase 0 inspection shows no companion changes are required. | -| A12 | Claim-boundary cleanup remains in force and must be extended, not bypassed. | High | Input references active claim-boundary cleanup and raw outputs rely on claim guards. | Claim tests are stale or do not cover custody proof language. | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/CONTEXT.md deleted file mode 100644 index 9e195ea..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/CONTEXT.md +++ /dev/null @@ -1,67 +0,0 @@ -# Context - -## Target - -Create a source-grounded macro plan for customer-owned gateway custody proof, the critical-path item that proves a protected action path is real because the mutation credential lives behind a customer/provider gateway that enforces the exact greenlight before consequence. - -The intended mechanism is: - -```text -gateway install evidence --> credential ref binding --> protected-path posture --> custody/bypass probe packet --> gateway check binds exact contract --> redacted custody projection -``` - -## Source Packet - -Read inputs: - -- `.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md` -- raw perspective outputs under `.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/` -- `/Users/joelchan/.codex/skills/gsd-macro-plan/references/plan-contract.md` - -The raw outputs independently converged on the same core decision: add a source-owned custody proof packet, but keep it subordinate to existing credential ref, protected-path posture, bypass probe, policy, gateway check, credential resolution, and projection primitives. - -## Current State Summary - -Existing source, as summarized by the raw agents, already has: - -- opaque gateway credential references. -- post-gate credential resolution evidence. -- current protected-path posture with probe coverage and source authority. -- policy-time and gateway-time posture/credential binding checks. -- one-use greenlight and gateway check semantics. -- x402 local/reference signing after `VerifiedGatewayCheck`. -- auth.md lifecycle, revocation, redaction, and post-gate credential resolution patterns. -- redacted projection infrastructure and claim-boundary tests. - -Missing: - -- one typed, source-owned, digest-bound custody packet tying install evidence, credential ref, posture, bypass probes, drift status, redaction status, and claim level. -- policy/gateway refusal rules that require that packet for credential-backed protected paths. -- redacted custody projection that a buyer can inspect without raw record reads or secret exposure. -- claim guards preventing fixture custody from becoming provider/customer custody language. - -## Relevant Canon - -- Handshake is protected actions for automated decision making, not just engineering agents. -- x402 is the first wedge, not the protocol. -- customer-owned gateway custody is the enforcement model. -- Tier 1 protocol meaning remains exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, and isolation. -- `.planning/` is scratch. Durable claims must be source/test/canonical-doc backed before becoming repo-facing truth. - -## Implementation Source Boundary To Verify Later - -The plan cannot be executed until implementation verifies companion ownership for: - -- protocol public schemas and inputs. -- object registry and source-owned object type wiring. -- kernel facade and public exports. -- evidence projection schemas. -- store/memory/D1 persistence and migrations. -- test fixtures and adapter export surfaces. - -Provider-specific vault/KMS/wallet/x402 provider details remain blocked until official source verification. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/DECISIONS.md deleted file mode 100644 index b0ea8b6..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/DECISIONS.md +++ /dev/null @@ -1,87 +0,0 @@ -# Decisions - -## Accepted - -### D1 - Add A Custody Proof Packet As Evidence - -Add `GatewayCustodyProofPacket` or the final source-owned equivalent under `src/protocol/areas/credential-custody/`. - -Justification: existing primitives are necessary but scattered. A buyer-readable customer-owned custody claim needs a digest-bound object that references install evidence, credential ref, protected-path posture, bypass probes, resolver/lease/provider posture, drift status, redaction status, and claim level. - -Boundary: the packet creates no permission. It cannot replace policy, greenlight, gateway check, mutation evidence, credential resolution evidence, or downstream reconciliation. - -### D2 - Extend Existing Authority Bindings - -Extend `GatewayCredentialRef`, `ProtectedPathPosture`, bypass probe inputs, policy input, gateway check evidence, and projections only as needed to bind the packet id/digest and drift status. - -Justification: a new custody authority plane would violate Tier 1 protocol meaning. The gateway check remains the enforcement point before consequence. - -### D3 - Require Packet First For Credential-Backed Protected Paths - -Require custody packet binding first for credential-backed protected paths such as x402 signer custody. Do not make custody proof mandatory for every `gateway_checked` path in this slice. - -Justification: this avoids changing Tier 1 protocol meaning while proving the stronger enforcement story where mutation credential custody is the issue. - -### D4 - x402 Uses The Generic Packet - -x402 install/proposal/gateway paths should bind signer custody through generic `GatewayCredentialRef` plus custody packet digest. - -Justification: x402 is the first wedge but not the protocol. Payment-specific signer fields must not become generic protocol semantics. - -### D5 - Fixture Custody Is Local-Only Evidence - -Introduce or preserve an explicit claim level such as `local_fixture`, `customer_gateway_evidence`, `provider_gateway_evidence`, and `proof_gap`. - -Justification: local fixture keys can test mechanics but cannot prove live customer/provider custody. - -### D6 - Projection Is Redacted And Reconstruction-Oriented - -The buyer-facing artifact is a redacted custody projection over refs/digests/statuses, not raw packet browsing. - -Justification: custody proof must be auditable without exposing signer material, secret paths, payment payloads, bearer tokens, or mutation credentials. - -## Rejected - -### R1 - Only Add More Fields To Existing Records - -Rejected because it leaves custody proof distributed across credential refs, posture, probes, resolution evidence, and projections. That makes customer-owned custody too easy to overclaim and hard to reconstruct. - -### R2 - Add A New Custody Permission Or Greenlight - -Rejected because it creates a second authority plane. The packet is evidence, not permission. - -### R3 - Make x402 Payment Management The Slice - -Rejected because the product primitive is protected-action custody proof. Balances, settlement, payment management, seller/facilitator operation, and aggregate spend ledgers are outside scope. - -### R4 - Claim Live Provider Custody From Fixtures - -Rejected because fixture custody is local/reference evidence only. Live provider/customer custody requires source-owned packet behavior, negative tests, redacted projections, and later official source verification for provider-specific implementation. - -### R5 - Move Enforcement Into Runtime, MCP, CLI, Or SDK Convenience - -Rejected because runtime-facing surfaces can propose and read evidence but cannot own policy decisions, greenlights, gateway checks, credential resolution, receipts, or mutation authority. - -## Deferred - -### F1 - Exact Public Object Registration Pattern - -Deferred until Phase 0 verifies object registry, public schemas, kernel facade, projection schemas, storage, and fixture ownership. - -### F2 - Exact Gateway Check Artifact Shape - -Deferred until schema ownership is verified. Preferred shape is explicit packet refs/digests seen on gateway evidence. Fallback is only acceptable if posture digest deterministically includes packet digest and drift state, with tests proving it. - -### F3 - Provider-Specific Custody Implementations - -Deferred until official source verification for named vault, KMS, wallet, x402 provider, JWKS, Cloudflare, legal, or payment-regulatory details. - -### F4 - Activation Helper Or Buyer Quickstart - -Deferred until the packet, policy/gateway binding, x402 integration, and projection exist. A helper may sequence transitions but cannot move authority into runtime/MCP/SDK. - -## User-Owned - -No P1 user-owned decision blocks the next implementation slice. The plan chooses the packet approach. - -User or maintainer decision may be needed later if Phase 0 reveals a wider public API/storage migration blast radius than expected. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/PLAN.md deleted file mode 100644 index 9f8ac5c..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/PLAN.md +++ /dev/null @@ -1,441 +0,0 @@ -# Plan - -## Goal - -Invariant at stake: a protected action is real only when the mutation credential remains behind a customer/provider gateway boundary, an exact one-use greenlight is checked immediately before consequence, unsafe or drifted custody refuses before mutation, and the surviving evidence is redacted but reconstructable. - -Create an implementation plan for customer-owned gateway custody proof as a source-owned mechanism for protected actions for automated decision making. x402 is the first wedge because paid HTTP makes credential custody concrete, but x402 must not define the protocol. Tier 1 protocol meaning stays stable: exact action contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, and isolation state remain the authority spine. - -The 10-star bar is this: a buyer can see that the automated decision system never received the mutation credential, the customer/provider gateway held or resolved the credential, the exact greenlight was checked immediately before mutation, drift/stale/unsafe custody refused before consequence, and the surviving packet is redacted but reconstructable. - -## Non-Goals - -- No Handshake-held wallets, private keys, bearer tokens, payment credentials, balances, settlement state, or payment-management state. -- No provider/customer custody claim from fixture keys, local sandbox signers, conformance fixtures, or `fixture_gateway_held` posture. -- No live provider custody, named vault/KMS/wallet architecture, JWKS behavior, x402 provider behavior, legal, or payment-regulatory claim until official source verification happens in a later implementation pass. -- No broad x402 compatibility, marketplace, certification, clearing-house readiness, facilitator operation, seller middleware, signed offers, signed receipts, aggregate spend ledgers, or payment settlement. -- No broad runtime, MCP, browser, shell, package-manager, cloud, repo, database, or network control claim. -- No new authority plane. A custody proof packet cannot create permission, mint greenlights, replace policy evaluation, replace the gateway check, or prove downstream business success. -- No raw custody packet read API that exposes secret-bearing provider coordinates, signer material, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, mutation credentials, payment payloads, authorization headers, claim tokens, JWTs, PII, or provider secret paths. -- No planning-stage labels from `.planning/` promoted into source paths, package scripts, CI names, exports, or canonical docs. - -## Source Boundary - -This plan was synthesized from the immutable packet at `.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md`, the five raw perspective outputs under the same run, and the macro plan contract. - -Allowed source paths named in the packet define the evidence boundary for this planning pass. The plan relies on the raw agents' source-grounded findings, especially around: - -- `GatewayCredentialRef`, `CredentialResolutionEvidence`, and credential-custody transitions. -- `ProtectedPathPosture`, source-authority posture, and bypass probe digests. -- policy and gateway transitions that already re-check posture and credential bindings. -- x402 install, wallet-gateway, bypass-probe, and conformance posture. -- auth.md gateway, revocation, bypass, and serialization-redaction learnings. -- evidence projection and claim-boundary tests. - -Companion implementation files outside the first-pass packet must be verified before coding, including protocol public aggregation, object registry, kernel facade, projection schemas, fixtures, storage, and migrations. This plan is executable only after that source map is checked. - -## Current State - -Current source appears to have the authority spine needed for the slice: - -- `GatewayCredentialRef` provides an opaque, provider-neutral credential reference and rejects raw credential-looking material. -- `CredentialResolutionEvidence` is post-gate evidence. It binds exact contract, greenlight, gate attempt, credential ref digest, resolver metadata, request digest, redaction status, and result class after a passed gateway check. -- `ProtectedPathPosture` models current runtime/gateway/action/resource posture, including gateway-checked state, credential custody status, raw sibling status, bypass probe refs/digests, source authority, expiry, and posture digest. -- policy evaluation and gateway check both consult current protected-path posture and gateway credential bindings before authority proceeds. -- gateway artifacts distinguish gateway check from mutation attempt and downstream outcome. -- redacted projections already expose contract, transaction, receipt, install-health, idempotency, and credential evidence without raw credential material. -- x402 proves one local/reference buyer-side `x402_payment.exact` path where signing happens after `VerifiedGatewayCheck`. -- auth.md provides the strongest pattern for credential refs, lifecycle drift/revocation, post-gate credential resolution, isolation, and redaction. - -The gap is not vocabulary. The gap is that custody proof is scattered across install evidence, credential refs, protected-path posture, bypass probes, policy input, gateway checks, credential resolution evidence, and projections. Without a source-owned packet or equivalent digest spine, customer-owned gateway custody can be overclaimed from fixture posture, adapter metadata, or a review projection. - -## Target State - -Add a narrow source-owned `GatewayCustodyProofPacket` under the credential-custody authority spine. It is evidence, not authority. - -The mechanism is: - -```text -gateway install evidence --> GatewayCredentialRef id/digest --> protected-path posture id/digest --> custody/bypass probe packet refs/digests --> custody proof packet id/digest --> action contract credential binding --> policy input and greenlight binding --> gateway-time revalidation before mutation --> post-gate CredentialResolutionEvidence --> redacted custody projection -``` - -The packet binds existing primitives instead of replacing them. Existing `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, policy checks, gateway checks, bypass probes, and projections should be extended to consume or expose the packet where necessary. Do not add a new custody approval, custody greenlight, wallet authorization, hosted trust certificate, or payment-custody object. - -The packet posture is provider-neutral and redaction-first. Candidate fields: - -- `gatewayCustodyProofPacketId` -- `gatewayCustodyProofPacketDigest` -- `gatewayCredentialRefId` -- `gatewayCredentialRefDigest` -- `protectedPathPostureId` -- `protectedPathPostureDigest` -- `gatewayInstallEvidenceRefs` -- `gatewayInstallEvidenceDigests` -- `bypassProbeIds` -- `bypassProbeDigests` -- `gatewayId` -- `gatewayRegistryEntryId` -- `protectedSurfaceKind` -- `actionClasses` -- `resourceRefs` -- `custodyProviderClass` -- `custodyProviderRegistryRef` -- `custodyProviderRegistryDigest` -- `opaqueKeyHandleRef` -- `opaqueKeyHandleDigest` -- `credentialKind` -- `credentialCustodyStatus` -- `custodyClaimLevel`: `local_fixture | customer_gateway_evidence | provider_gateway_evidence | proof_gap` -- `resolverRef` -- `resolverVersion` -- `resolverDigest` -- `leaseRef` -- `leaseVersion` -- `leaseIssuedAt` -- `leaseExpiresAt` -- `attestationRefs` -- `attestationDigests` -- `redactedAuditRefs` -- `redactedAuditDigest` -- `custodyDriftStatus`: `current | stale | provider_drift | resolver_drift | unsafe_custody | proof_gap` -- `resolverDriftStatus` -- `redactionStatus` -- `externalVerificationStatus`: `not_required | required_before_live_claim | verified_by_official_source` -- `redactionProfileRef` -- `secretMaterialIncluded: false` -- `recordedAt` -- `expiresAt` - -The packet must reject raw credentials, raw signer refs, raw vault/KMS/provider secret paths, bearer tokens, `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, mutation credentials, payment payloads, and access-token-looking values. Projection should expose refs, digests, statuses, and omitted fields only. - -## Assumptions - -- Tier 1 protocol meaning remains stable and is not redefined by custody proof. -- Customer-owned gateway custody means the customer/provider gateway owns or resolves the mutation credential; Handshake does not hold or manage the credential. -- x402 remains the first protected-action pack, not the protocol definition. -- The packet can be added as an evidence object under credential custody without introducing hosted operation. -- Custody proof is required first for credential-backed protected paths, including x402 signer custody. It should not become a global requirement for every `gateway_checked` path in this slice. -- Fixture/local/reference custody can support regression proof only and must project as `local_fixture`, not customer/provider custody. -- Named provider, vault, KMS, wallet, x402 provider, JWKS, Cloudflare, npm, MCP Registry, legal, or payment-regulatory details require official source verification before implementation. -- Object registry, public schema, projection schema, storage, migration, fixture, and package-export impacts are not fully verified in this planning pass and must be checked before source edits. - -## Decisions - -1. Add a custody proof packet, but keep it subordinate to existing primitives. - - Choice: add `GatewayCustodyProofPacket` as a typed evidence packet under `src/protocol/areas/credential-custody/`. - - Reason: extending only `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, and bypass probes leaves the custody story scattered. A buyer-readable claim needs one digest-bound packet that ties install evidence, credential ref, posture, probes, drift, redaction, and later gate/resolution evidence together. - - Boundary: the packet does not authorize mutation. Policy and gateway checks remain the enforcement points. - -2. Extend existing bindings instead of creating a new authority lane. - - `GatewayCredentialRef` remains the opaque credential handle. - - `ProtectedPathPosture` remains current, probe-backed posture. - - bypass probes remain hostile-path evidence. - - `CredentialResolutionEvidence` remains post-gate use/resolution evidence. - - policy and gateway checks must consume packet id/digest and drift state for custody-backed paths. - -3. Require custody proof first for credential-backed protected paths. - - x402 signer custody is the first target. - - Do not silently require custody proof for all `gateway_checked` paths until the first credential-backed path proves the mechanism. - -4. Treat x402 as a proof pack, not payment infrastructure. - - x402 maps signer custody into generic credential refs and custody proof packets. - - x402 remains one buyer-side exact paid HTTP action per call. - - No Handshake-held wallet, balance, settlement, facilitator, seller middleware, aggregate spend, or broad compatibility claim. - -5. Import auth.md learnings only as custody/ref lifecycle patterns. - - Reuse credential-ref binding, lifecycle drift, revocation/isolation, post-gate resolution, and redaction patterns. - - Do not turn Handshake into an auth provider, OAuth server, identity provider, or generic API gateway. - -6. Redacted projection is the adoption artifact. - - The buyer should read a custody projection that links packet, contract, policy/greenlight, gateway check, credential resolution, mutation/refusal/proof-gap refs, and omitted fields. - - Raw packet access is not the buyer-facing proof path. - -## Phases - -### Phase 0 - Source Map Verification - -Before implementation, inspect companion files outside the first-pass packet that likely own public aggregation, object registration, storage, fixture, and projection schema wiring. Confirm the exact edit set and update this plan if source ownership differs. - -Candidate paths to verify: - -- `src/protocol/kernel.ts` -- `src/protocol/areas/credential-custody/index.ts` -- `src/protocol/areas/credential-custody/types.ts` -- `src/protocol/areas/object-registry/*` -- `src/protocol/public/schemas.ts` -- `src/protocol/public/inputs.ts` -- `src/protocol/evidence-projections/schemas.ts` -- `src/storage/d1/*` -- `src/storage/memory/*` -- `test/support/fixtures.ts` -- `test/support/auth-md-flow.ts` -- adapter index/export files - -Exit criteria: exact source/test/doc edit map is confirmed before coding. - -### Phase 1 - Test-First Custody Packet Failures - -Add failing tests before implementation. The first tests should prove: - -- custody packet schema rejects raw credential and secret-looking fields. -- custody packet digest changes when credential ref, protected-path posture, bypass probes, resolver version, lease/version, attestation digest, redacted audit digest, drift status, redaction status, or expiry changes. -- policy refuses a credential-backed action that has valid credential ref and protected-path posture but no valid custody packet binding. -- gateway refuses when custody packet/posture/credential ref drifts after greenlight and before mutation. -- projections expose refs/digests/status only and omit secret-bearing material. -- fixtures cannot satisfy customer/provider custody claims. - -Exit criteria: focused tests fail for missing source-owned packet behavior, not unrelated fixture setup. - -### Phase 2 - Source-Owned Packet Schema And Transition - -Add `GatewayCustodyProofPacket` schema/input/transition under credential custody. Implement `recordGatewayCustodyProofPacket(input)` or the local equivalent. - -The transition must: - -- load the credential ref by id/digest. -- load current protected-path posture by id or exact scope. -- verify tenant/org/gateway/protected surface/action/resource agreement. -- verify posture is fresh, `gateway_checked`, and accepted-source probe-backed. -- verify required bypass probes are present and passed. -- verify credential custody can satisfy gateway-checked posture. -- canonicalize the packet digest after loaded refs are known. -- commit packet record and event through the source-owned object/store pattern. -- never retrieve, store, or project secret material. -- never create permission, greenlight, mutation proof, wallet custody, settlement, or payment state. - -Exit criteria: packet schema and transition tests pass with deterministic digest behavior and redaction failure handling. - -### Phase 3 - Bind Packet Into Contract, Policy, And Gateway Evaluation - -Extend the existing gateway credential binding path with custody packet id/digest and required drift/redaction status fields. Do not create a parallel policy evaluator. - -Policy must refuse before greenlight when: - -- packet is missing. -- packet digest mismatches the credential ref, posture, or binding. -- packet is stale or expired. -- credential ref is stale, isolated, scope-mismatched, or provider-drifted. -- provider registry digest, resolver version, lease/version, posture digest, or probe digest drifted. -- custody status is unsafe, agent-exposed, fixture-only for customer/provider claim, or proof gap. -- source authority is weak. -- required bypass probes are missing or failed. -- redaction failed. - -Gateway check must re-run the same current-state custody checks immediately before mutation and record what it saw. Prefer explicit `custodyProofPacketIdSeen`, `custodyProofPacketDigestSeen`, and `custodyDriftStatusSeen` fields on gateway evidence if schema ownership supports it. If not, prove that posture digest deterministically includes packet digest and drift status. - -Exit criteria: policy and gateway negative tests refuse before mutation and do not record downstream success as custody proof. - -### Phase 4 - x402 First Wedge Integration - -Make x402 use the generic custody primitives. - -Implementation direction: - -- x402 install proposal derives or references a `GatewayCredentialRef` for signer/payment credential custody. -- x402 action proposal binds the credential ref and custody packet digest on the candidate/contract path. -- wallet gateway continues to require `VerifiedGatewayCheck` before signing. -- wallet gateway records redacted `CredentialResolutionEvidence` after a passed gate and binds it to exact contract, greenlight, gate attempt, credential ref, and custody packet. -- x402 bypass/conformance tests distinguish local fixture custody from customer/provider custody. -- fixture custody projects as `local_fixture` and cannot satisfy live customer/provider custody claim guards. - -Exit criteria: x402 cannot call the signer on missing/stale/drifted/unsafe packet, raw sibling posture, replay, params mismatch, or gateway policy drift; x402 still does not introduce payment custody or payment management. - -### Phase 5 - auth.md Parity Pattern - -Use auth.md as a reference protected API profile for lifecycle and redaction semantics. - -Implementation direction: - -- bind auth.md credential refs to the same custody packet shape when custody proof is required. -- preserve revocation/lifecycle isolation. -- ensure metadata/provider digest drift blocks policy/gateway checks before credential resolution and downstream service calls. -- keep auth.md identity/claim/revocation evidence as provenance, not auth-provider authority. - -Exit criteria: auth.md drift, revocation, token replay, raw bearer passthrough, unsafe retry, and redaction failure still quarantine/refuse before credential use. - -### Phase 6 - Redacted Custody Projection - -Add a redacted projection that assembles the packet chain for buyers without exposing raw custody material. - -Projection fields should include: - -- custody proof packet ref/digest. -- credential ref/digest. -- protected-path posture ref/digest. -- action contract ref/digest. -- policy decision/greenlight ref/digest. -- gateway check ref/digest. -- credential resolution evidence refs. -- mutation/refusal/proof-gap/downstream reconciliation refs. -- custody provider class, provider registry digest, opaque key handle digest, resolver version, lease version/freshness, attestation digests, redacted audit digest. -- custody claim level, drift status, redaction status, external verification status, omitted fields, and reason codes. - -Projection must omit secret paths, signer material, raw key handles, bearer tokens, `PaymentPayload`, `PAYMENT-SIGNATURE`, mutation credentials, payment payloads, raw authorization headers, claim tokens, JWTs, PII, and provider secret coordinates. - -Exit criteria: projection tests prove the packet distinguishes gateway check, credential resolution, mutation/downstream outcome, refusal, and proof gap. - -### Phase 7 - Claim Guards And Canonical Docs - -Update canonical docs only after source/tests prove the packet. Keep docs compact and source-owned. - -Candidate docs: - -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` - -Claim guards must fail if docs/examples imply: - -- live provider/customer custody from fixture keys. -- Handshake-held wallet, payment credential, balance, settlement, payment management, seller/facilitator, marketplace, certification, or clearing-house operation. -- x402 as the protocol instead of the first protected-action pack. -- hosted trust or broad runtime/MCP/browser/shell interception. -- provider-specific vault/KMS/wallet correctness without official source verification. - -Exit criteria: claim-boundary and architecture tests pass before public/docs language changes are considered complete. - -### Phase 8 - Closeout - -Close only when focused protocol, adapter, projection, redaction, architecture, claim, and full repo gates pass. Planned evidence must be separated from existing evidence throughout closeout. - -## Task Graph - -```text -custody-000 - -> custody-010 - -> custody-020 - -> custody-030 - -> custody-040 - -> custody-050 - -> custody-060 - -> custody-070 - -> custody-080 - -> custody-090 -``` - -- `custody-000`: verify source map and exact edit ownership. -- `custody-010`: add failing protocol, gateway, projection, and claim tests. -- `custody-020`: add packet schema/input/canonicalization. -- `custody-030`: add packet record transition and source-owned persistence/event wiring. -- `custody-040`: bind packet into contract/policy/gateway checks. -- `custody-050`: integrate x402 signer custody with generic credential ref and packet. -- `custody-060`: apply auth.md parity for lifecycle/isolation/redaction. -- `custody-070`: add redacted custody projection. -- `custody-080`: update canonical docs and claim guards after source/tests. -- `custody-090`: run closeout gates and record evidence. - -Do not start adapter implementation before packet schema and binding semantics are stable. Otherwise x402 and auth.md will grow adapter-specific custody stories and the protocol primitive will rot. - -## Risks And Mitigations - -- P0: packet theatre. A packet emitted only as projection text is advisory, not Handshake. Mitigation: policy and gateway must require packet id/digest for custody-backed paths. -- P0: stale custody admitted after greenlight. Mitigation: gateway re-reads current credential ref, posture, packet, isolation, resolver/lease/provider registry status, and policy drift immediately before mutation. -- P0: agent-exposed signer path remains reachable. Mitigation: required bypass probes and raw sibling posture must fail closed before `gateway_checked` posture can satisfy policy. -- P0: redacted projection leaks secrets. Mitigation: allowlisted projection fields, denylist/fuzz tests, and `redaction_failed` refusal/proof gap instead of best-effort serialization. -- P0: payment custody/regulatory drift. Mitigation: explicit non-goals plus claim guards. -- P1: packet overfits x402. Mitigation: provider-neutral fields only; x402 maps into the generic packet. -- P1: fixture laundering. Mitigation: `custodyClaimLevel` and claim guards distinguish `local_fixture` from customer/provider evidence. -- P1: provider registry or resolver drift is weakly detected. Mitigation: require digests/versions/lease fields for custody-backed paths; absent digest becomes proof gap or unsafe posture. -- P1: runtime/MCP proposal surfaces imply enforcement. Mitigation: runtime/MCP/CLI/SDK remain proposal/evidence/read surfaces only. -- P2: operational ceremony blocks adoption. Mitigation: activation helpers may sequence source-owned transitions later, but cannot move authority out of policy/gateway. -- P2: storage/projection blast radius hidden. Mitigation: Phase 0 source map verification before source edits. - -## Validation Gates - -Focused future gates: - -```bash -npm run test -- test/protocol/credential-custody.test.ts test/protocol/kernel-policy-gateway.test.ts -npm run test -- test/protocol/evidence-projections.test.ts -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts -npm run test -- test/conformance/x402-payment-conformance.test.ts -npm run test -- test/adapters/auth-md-gateway-pressure.test.ts test/adapters/auth-md-serialization-redaction.test.ts -npm run test -- test/architecture/claim-boundary.test.ts test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Add new focused test files only if existing ownership cannot carry the cases, for example: - -- `test/protocol/customer-owned-gateway-custody-proof.test.ts` -- `test/adapters/x402-install-proposal.test.ts` -- `test/adapters/x402-payment-action-proposal.test.ts` - -Required behavioral evidence: - -- missing custody packet refuses before greenlight for custody-backed paths. -- stale packet/ref/posture refuses before greenlight and at gateway time. -- packet drift after greenlight refuses before mutation and records no downstream success. -- agent-exposed signer refuses during install/proposal/posture/policy/gateway paths. -- raw sibling signer/payment path prevents `gateway_checked` posture from satisfying policy. -- gateway check sees the exact packet/ref/posture digest expected by policy. -- credential resolution evidence is recorded only after a passed gateway check. -- replay cannot reuse a greenlight for another credential resolution or mutation. -- redacted projection omits secret material and distinguishes gateway check, credential resolution, mutation/downstream outcome, refusal, and proof gap. -- fixture custody cannot project or document as live customer/provider custody. - -## Cut Lines - -Cut from this slice: - -- Handshake-held payment custody, signer custody, balances, settlement, or payment management. -- provider-specific vault/KMS/wallet implementations before official source verification. -- live provider/customer custody claim from fixture keys. -- broad x402 compatibility, facilitator operation, seller middleware, marketplace, certification, clearing-house readiness, or settlement finality. -- aggregate x402 spend-window enforcement until a real ledger exists. -- broad runtime/MCP/browser/shell/network/package-manager/database/cloud interception. -- all-role SDK, CLI, MCP, or runtime mutation commands. -- raw custody record reads as buyer proof. -- dashboard/review UX unless it renders exact packet refs and cannot authorize anything. - -Antipatterns: - -- `custodyProof: true` without packet digest and policy/gateway enforcement. -- wallet gateway profile metadata treated as customer-owned custody proof. -- rendered review screen that says "gateway owned" without exact packet/contract/greenlight/gateway binding. This is review theatre. -- receipt that cannot distinguish gateway check from credential resolution and downstream result. This is evidence theatre. -- recording signer use before gateway check. -- one greenlight per workflow. This is ambient authority wearing a badge. -- fixture custody described as provider/customer custody. -- regex-only redaction for live provider custody. -- docs claiming live custody before packet, negative tests, and redacted projections exist. - -## Rollback / Stop Conditions - -Stop implementation if: - -- packet id/digest is not consumed by both policy and gateway checks for custody-backed paths. -- gateway cannot refuse before signer/credential use. -- implementation requires one greenlight to authorize multiple credential resolutions or mutations. -- fixture/local signer custody is the only evidence behind a customer/provider custody claim. -- redaction tests find raw signer, token, payment payload, secret path, bearer credential, mutation credential, or PII in projections. -- provider-specific vault/KMS/wallet behavior is required but official docs have not been verified. -- runtime/MCP/SDK convenience code starts issuing policy decisions, greenlights, gateway checks, receipts, mutation attempts, or credential-resolution records. -- aggregate spend, settlement, facilitator, seller middleware, balance, or payment-management language appears. -- public aggregation, object registry, storage, or projection schema ownership is unclear after Phase 0. - -Rollback should quarantine or remove the new packet/projection/claim surface while preserving existing `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, policy, gateway, and projection behavior. Partial schema without enforcement must be labeled advisory or removed. Do not leave a decorative packet in source. - -## Smallest Next Action - -Inspect Phase 0 companion files, then add the first failing tests in `test/protocol/credential-custody.test.ts` and `test/protocol/kernel-policy-gateway.test.ts` for: - -1. `GatewayCustodyProofPacket` schema redaction and deterministic digest binding. -2. packet binding to `GatewayCredentialRef`, `ProtectedPathPosture`, and bypass probe digests. -3. policy refusal when an otherwise valid custody-backed action lacks the packet binding. - -Do not touch x402 until those failures prove the protocol shape. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/RISKS.md deleted file mode 100644 index a770167..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/RISKS.md +++ /dev/null @@ -1,43 +0,0 @@ -# Risks - -## P0 - -| Risk | Failure Mode | Mitigation | -| --- | --- | --- | -| Packet theatre | A packet is emitted as projection/install text but policy and gateway do not require it before credential use. | Bind packet id/digest into credential-backed contract/policy/gateway checks; cut custody claims if enforcement is absent. | -| Stale custody after greenlight | Credential ref, resolver version, lease, provider registry, posture, or packet drifts after policy but before mutation. | Gateway re-reads current credential ref, posture, packet, isolation, resolver/lease/provider state, and policy drift before mutation. | -| Agent-exposed signer path | x402/auth-style adapters leave direct SDK signer, private key env, raw signature header, bearer passthrough, MCP/browser/network sibling, or retry loop outside the gateway. | Required bypass probes and raw sibling posture must fail closed before `gateway_checked` posture can satisfy policy. | -| Redaction leak | Projection exposes private keys, bearer tokens, provider secret paths, `PaymentPayload`, `PAYMENT-SIGNATURE`, mutation credentials, payment payloads, authorization headers, claim tokens, JWTs, or PII. | Allowlisted projection fields, denylist/fuzz tests, redaction-failure refusal/proof gap. | -| Payment custody drift | Work introduces Handshake-held wallets, balances, payment credentials, settlement, facilitator/seller operation, or payment management. | Non-goals, claim guards, and x402 limited to one buyer-side exact protected action per call. | - -## P1 - -| Risk | Failure Mode | Mitigation | -| --- | --- | --- | -| x402 overfit | Protocol fields become wallet/payment/x402-specific. | Keep packet provider-neutral; x402 maps into generic refs/digests/statuses. | -| Fixture laundering | `fixture_gateway_held` passes local tests and later docs imply provider/customer custody. | Add `custodyClaimLevel`; claim guards reject provider/customer custody from fixtures. | -| Weak drift detection | Null provider registry or resolver digests allow stale custody to pass. | Custody-backed paths require digest/version/lease presence or become `proof_gap`/unsafe. | -| Resolver failure misclassified | Credential resolution failure becomes downstream uncertainty after mutation. | Resolver failure must refuse before protected mutation; no mutation attempt on pre-gate custody failure. | -| auth.md scope creep | Credential/ref lifecycle lessons turn into auth-provider/OAuth claims. | Import lifecycle isolation/redaction only; cut identity-provider claims. | -| Review laundering | UI says "gateway owned" while contract/packet is stale or weaker. | Review/projection must bind exact contract digest, policy input/greenlight, packet digest, and uncertainty/reason codes. | -| Runtime/MCP authority drift | Proposal surfaces imply enforcement or gain signer/gateway authority. | Runtime/MCP/CLI/SDK remain proposal/evidence/read only; import/surface tests enforce this. | - -## P2 - -| Risk | Failure Mode | Mitigation | -| --- | --- | --- | -| Duplicate state | Packet duplicates credential ref, protected-path posture, and resolution evidence without ownership clarity. | Packet owns aggregation/digest binding only; existing primitives keep their meanings. | -| Hidden storage blast radius | New object needs registry, public schema, D1/memory store, migrations, or indexes not planned. | Phase 0 source map verification before coding. | -| Adoption ceremony | Integrators must manually assemble install evidence, refs, probes, posture, policy, gateway, resolution, and projection. | Add activation helper later, but helper only sequences source-owned transitions. | -| `.planning` becomes canon | Scratch terms leak into source exports, package scripts, CI, or README claims. | Canonical docs change only after source/tests; no planning labels in public source. | - -## Antipatterns - -- `custodyProof: true` without packet digest and policy/gateway checks. -- wallet profile metadata treated as customer-owned custody proof. -- recording credential resolution before a passed gateway check. -- one greenlight authorizing multiple mutations. -- fixture custody described as live provider/customer custody. -- provider-specific fields such as `vaultPath`, `secretPath`, `walletPrivateKey`, `PaymentPayload`, or `PAYMENT-SIGNATURE` in protocol records or projections. -- regex-only redaction for live provider custody. -- docs claiming hosted trust, marketplace readiness, clearing-house readiness, or broad runtime control. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/TASKS.jsonl deleted file mode 100644 index d6623f9..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/TASKS.jsonl +++ /dev/null @@ -1,10 +0,0 @@ -{"id":"custody-000","priority":"P0","phase":"Phase 0","title":"Verify implementation source map for custody packet ownership","owner":"executor","rationale":"The raw planning packet did not include all public aggregation, object registry, storage, fixture, and projection schema owners needed for safe implementation.","depends_on":[],"acceptance":["Companion source owners are inspected before edits","Exact source/test/doc edit map is recorded","Plan is revised or blocked if object registration or storage ownership contradicts the packet approach"],"candidate_paths":["src/protocol/kernel.ts","src/protocol/areas/credential-custody/index.ts","src/protocol/areas/credential-custody/types.ts","src/protocol/areas/object-registry","src/protocol/public/schemas.ts","src/protocol/public/inputs.ts","src/protocol/evidence-projections/schemas.ts","src/storage/d1","src/storage/memory","test/support/fixtures.ts","test/support/auth-md-flow.ts"],"non_goals":["Do not implement source changes during source map verification","Do not browse provider docs in this task"]} -{"id":"custody-010","priority":"P0","phase":"Phase 1","title":"Add failing custody packet and refusal tests","owner":"test-owner","rationale":"The packet must be enforced by tests before source implementation or it can become decorative evidence.","depends_on":["custody-000"],"acceptance":["Tests fail for missing GatewayCustodyProofPacket behavior","Tests cover redaction rejection, digest binding, missing packet refusal, stale/drift refusal, and fixture claim guard","Failures are specific to missing custody proof behavior"],"candidate_paths":["test/protocol/credential-custody.test.ts","test/protocol/kernel-policy-gateway.test.ts","test/protocol/evidence-projections.test.ts","test/architecture/claim-boundary.test.ts"],"non_goals":["Do not update docs to claim custody before source behavior exists","Do not make fixture custody satisfy provider/customer custody"]} -{"id":"custody-020","priority":"P0","phase":"Phase 2","title":"Define GatewayCustodyProofPacket schema and input","owner":"protocol-owner","rationale":"Customer-owned custody needs one provider-neutral, redaction-first packet that binds existing custody primitives by digest without creating authority.","depends_on":["custody-010"],"acceptance":["Packet schema includes credential ref digest, posture digest, bypass probe digests, provider registry digest, resolver version, lease/version, attestation digests, redacted audit digest, drift status, claim level, redaction status, and external verification status","Schema rejects raw credentials, secret paths, signer material, PaymentPayload, PAYMENT-SIGNATURE, bearer tokens, mutation credentials, and access-token-looking values","Digest changes when any authority-relevant packet field changes"],"candidate_paths":["src/protocol/areas/credential-custody/schemas.ts","src/protocol/areas/credential-custody/inputs.ts","test/protocol/credential-custody.test.ts"],"non_goals":["Do not add x402-specific payment fields to the generic packet","Do not store or resolve secrets"]} -{"id":"custody-030","priority":"P0","phase":"Phase 2","title":"Implement source-owned packet transition and record wiring","owner":"protocol-owner","rationale":"The packet must be source-owned evidence recorded from loaded refs/posture/probes, not caller-supplied prose.","depends_on":["custody-020"],"acceptance":["Transition loads and verifies GatewayCredentialRef and ProtectedPathPosture scope agreement","Transition requires fresh gateway_checked posture and accepted-source bypass probe coverage","Transition records packet and event through the source-owned object/store pattern","Transition never retrieves or stores secret material"],"candidate_paths":["src/protocol/areas/credential-custody/transitions.ts","src/protocol/areas/credential-custody/custody-posture.ts","src/protocol/areas/object-registry","src/protocol/public/schemas.ts","src/protocol/public/inputs.ts","src/storage/memory","src/storage/d1"],"non_goals":["Do not create a custody approval or custody greenlight","Do not add hosted provider operation"]} -{"id":"custody-040","priority":"P0","phase":"Phase 3","title":"Bind custody packet into contract, policy, and gateway checks","owner":"protocol-owner","rationale":"Custody proof is Handshake only if policy and gateway refuse missing, stale, drifted, unsafe, or redaction-failed packet state before mutation.","depends_on":["custody-030"],"acceptance":["Credential-backed actions bind custody packet id/digest with the credential ref","Policy refuses missing packet, digest mismatch, stale packet, provider drift, resolver drift, unsafe custody, weak source authority, failed probes, raw sibling, isolation, and redaction failure","Gateway revalidates current packet/ref/posture before mutation and records packet refs/digests seen or equivalent tested posture digest binding","No mutation attempt or downstream success is recorded for pre-mutation custody refusal"],"candidate_paths":["src/protocol/areas/policy-greenlight/transitions.ts","src/protocol/areas/gateway-gate/schemas.ts","src/protocol/areas/gateway-gate/artifacts.ts","src/protocol/areas/gateway-gate/transitions.ts","src/protocol/areas/credential-custody/transitions.ts","test/protocol/kernel-policy-gateway.test.ts"],"non_goals":["Do not create a parallel policy evaluator","Do not allow one greenlight to authorize multiple mutations"]} -{"id":"custody-050","priority":"P1","phase":"Phase 4","title":"Integrate x402 signer custody through generic credential refs and packet binding","owner":"x402-adapter-owner","rationale":"x402 is the first wedge, but it must prove the generic custody primitive instead of becoming payment infrastructure.","depends_on":["custody-040"],"acceptance":["x402 install/proposal binds signer custody through GatewayCredentialRef plus custody packet digest","Signer is called only after VerifiedGatewayCheck and valid packet/ref/posture state","Redacted CredentialResolutionEvidence is recorded after the passed gate","Fixture custody projects as local_fixture and cannot satisfy customer/provider custody claims","No wallet custody, balances, settlement, facilitator, seller middleware, aggregate spend, or payment-management state is added"],"candidate_paths":["src/adapters/x402-payment/install-proposal.ts","src/adapters/x402-payment/action-proposal.ts","src/adapters/x402-payment/wallet-gateway.ts","src/adapters/x402-payment/bypass-probes.ts","src/adapters/x402-payment/conformance.ts","test/adapters/x402-wallet-gateway.test.ts","test/adapters/x402-bypass-probes.test.ts","test/conformance/x402-payment-conformance.test.ts"],"non_goals":["Do not broaden x402 compatibility","Do not claim live provider custody from fixtures"]} -{"id":"custody-060","priority":"P1","phase":"Phase 5","title":"Apply auth.md lifecycle, isolation, and redaction parity","owner":"auth-adapter-owner","rationale":"auth.md has the right pattern for credential refs, revocation drift, post-gate resolution, and redaction without turning Handshake into an auth provider.","depends_on":["custody-040"],"acceptance":["auth.md custody-backed calls can bind the same packet shape when required","Revocation, metadata drift, stale ref, scope drift, resolver failure, token replay, raw bearer passthrough, unsafe retry, and redaction failure refuse before downstream call","CredentialResolutionEvidence remains post-gate only"],"candidate_paths":["src/adapters/auth-md/profiles.ts","src/adapters/auth-md/gateway.ts","src/adapters/auth-md/revocation.ts","src/adapters/auth-md/bypass-probes.ts","test/adapters/auth-md-gateway-pressure.test.ts","test/adapters/auth-md-serialization-redaction.test.ts"],"non_goals":["Do not add OAuth, identity-provider, auth-provider, or generic API gateway claims","Do not expose bearer material or raw credentials"]} -{"id":"custody-070","priority":"P1","phase":"Phase 6","title":"Add redacted custody projection","owner":"projection-owner","rationale":"Adoption depends on a buyer-readable packet that reconstructs custody by digest without exposing credential material.","depends_on":["custody-040"],"acceptance":["Projection exposes custody packet, credential ref, posture, contract, greenlight, gateway check, credential resolution, mutation/refusal/proof-gap refs and digests","Projection includes claim level, drift status, redaction status, external verification status, omitted fields, and reason codes","Projection omits secret paths, signer material, raw key handles, PaymentPayload, PAYMENT-SIGNATURE, bearer tokens, mutation credentials, payment payloads, authorization headers, claim tokens, JWTs, PII, and provider secret coordinates"],"candidate_paths":["src/protocol/evidence-projections/projections.ts","src/protocol/evidence-projections/assembly.ts","src/protocol/evidence-projections/schemas.ts","test/protocol/evidence-projections.test.ts"],"non_goals":["Do not expose raw packet browsing as buyer proof","Do not smooth redaction failure into success"]} -{"id":"custody-080","priority":"P1","phase":"Phase 7","title":"Update canonical docs and claim guards after source proof exists","owner":"docs-and-architecture-owner","rationale":"Product language must not exceed enforcement. Docs can change only after packet, negative tests, and projection behavior exist.","depends_on":["custody-050","custody-060","custody-070"],"acceptance":["Canonical docs describe customer-owned gateway custody as protected-action custody proof, not payment custody or x402 protocol meaning","Claim guards reject provider/customer custody from fixtures, Handshake-held payment custody, hosted trust, broad x402 compatibility, marketplace/certification/clearing-house readiness, and broad runtime control","Provider-specific vault/KMS/wallet details are marked as requiring official source verification before implementation"],"candidate_paths":["README.md","docs/internal/decisions.md","docs/internal/protocol-definition.md","docs/internal/protocol-kernel-architecture.md","docs/internal/protocol-layman.md","docs/internal/protocol-notes.md","test/architecture/claim-boundary.test.ts","test/architecture/import-posture.test.ts","test/architecture/root-exports.test.ts"],"non_goals":["Do not promote .planning labels into source or package scripts","Do not write provider setup docs from repo source alone"]} -{"id":"custody-090","priority":"P0","phase":"Phase 8","title":"Run focused and full closeout gates","owner":"executor","rationale":"The slice is complete only when enforcement, redaction, claims, and repo quality gates pass together.","depends_on":["custody-080"],"acceptance":["Focused protocol, projection, x402, auth.md, and architecture tests pass","quality:claims and quality:architecture pass","format/check/type/lint/test/pack/check:repo closeout passes or blockers are recorded with exact evidence","Closeout distinguishes existing evidence from planned evidence"],"candidate_paths":["test/protocol/credential-custody.test.ts","test/protocol/kernel-policy-gateway.test.ts","test/protocol/evidence-projections.test.ts","test/adapters/x402-wallet-gateway.test.ts","test/adapters/x402-bypass-probes.test.ts","test/conformance/x402-payment-conformance.test.ts","test/adapters/auth-md-gateway-pressure.test.ts","test/adapters/auth-md-serialization-redaction.test.ts","test/architecture/claim-boundary.test.ts","test/architecture/import-posture.test.ts","test/architecture/root-exports.test.ts"],"non_goals":["Do not stage or commit from the planning run","Do not claim completion if provider-specific verification remains required for live custody"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/VALIDATION.md deleted file mode 100644 index 4320f28..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/VALIDATION.md +++ /dev/null @@ -1,104 +0,0 @@ -# Validation - -## Proof Obligations - -- Customer/provider gateway custody is evidenced by source-owned packet refs/digests, not prose. -- The packet is required by policy and gateway checks for custody-backed protected paths. -- Exact contract, policy decision, greenlight, gateway check, credential resolution, mutation/refusal/proof-gap, and downstream reconciliation remain distinct. -- Redaction failure refuses or records proof gap; it never serializes raw custody material. -- Fixture custody cannot satisfy provider/customer custody claims. -- Provider-specific custody details are blocked until official source verification. - -## Focused Tests - -### Protocol - -- `test/protocol/credential-custody.test.ts` - - packet schema rejects raw private keys, bearer tokens, `PaymentPayload`, `PAYMENT-SIGNATURE`, provider secret paths, raw signer refs, mutation credentials, payment payloads, and access-token-looking fields. - - packet digest changes with credential ref digest, protected-path posture digest, bypass probe digests, provider registry digest, resolver version, lease/version, attestation digest, redacted audit digest, drift status, redaction status, and expiry. - - packet cannot bind mismatched tenant/org/gateway/action/resource scope. - - fixture custody projects as `local_fixture` and cannot satisfy customer/provider claim level. - -- `test/protocol/kernel-policy-gateway.test.ts` - - policy refuses missing packet, digest mismatch, stale packet, stale credential ref, provider drift, resolver drift, unsafe custody, weak source authority, failed probe, raw sibling present, active isolation, and redaction failure. - - gateway refuses the same conditions after greenlight and before mutation. - - replay cannot reuse a greenlight for another credential resolution or mutation. - - gateway evidence records packet refs/digests seen or proves posture digest includes packet digest and drift state. - -- `test/protocol/evidence-projections.test.ts` - - custody projection includes refs/digests/status/reason codes only. - - projection distinguishes gateway check, credential resolution, mutation attempt, downstream reconciliation, refusal, and proof gap. - - projection omits secret paths, signer material, raw key handles, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, payment payloads, mutation credentials, authorization headers, claim tokens, JWTs, PII, and provider secret coordinates. - -### x402 - -- `test/adapters/x402-wallet-gateway.test.ts` - - signer call count is zero on missing/stale/drifted/unsafe packet, raw sibling posture, replay, params mismatch, policy drift, or failed gateway check. - - signer use occurs only after `VerifiedGatewayCheck`. - - redacted credential resolution evidence is recorded after a passed gate and bound to exact contract, greenlight, gateway check, credential ref, and packet. - -- `test/adapters/x402-bypass-probes.test.ts` - - direct signer SDK, raw payment signature header, paid fetch/axios, MCP direct payment, token passthrough, wrapper drift, and failure-open posture fail closed. - -- `test/conformance/x402-payment-conformance.test.ts` - - x402 remains one buyer-side exact protected action per call. - - no balance, settlement, facilitator, seller middleware, broad compatibility, or payment-management claim is introduced. - -Add `test/adapters/x402-install-proposal.test.ts` and `test/adapters/x402-payment-action-proposal.test.ts` if existing test ownership cannot cover install/proposal binding. - -### auth.md - -- `test/adapters/auth-md-gateway-pressure.test.ts` - - revocation, metadata drift, stale credential ref, scope drift, resolver failure, raw bearer passthrough, token replay, direct HTTP/browser/network/MCP path, and unsafe retry refuse before downstream service call. - -- `test/adapters/auth-md-serialization-redaction.test.ts` - - auth-derived custody evidence never exposes bearer material, claims, tokens, raw credentials, or secret paths. - -### Architecture And Claims - -- `test/architecture/claim-boundary.test.ts` - - provider/customer custody claims fail when sourced from fixture keys. - - Handshake-held wallet/payment credential/balance/settlement/payment-management language fails. - - x402-as-protocol, broad compatibility, seller/facilitator, marketplace, certification, clearing-house, hosted trust, and broad runtime-control claims fail. - -- `test/architecture/import-posture.test.ts` - - runtime/MCP/CLI/SDK/projection surfaces cannot import or issue policy, greenlight, gateway check, receipt, credential resolution, signer, wallet, or raw custody internals. - -- `test/architecture/root-exports.test.ts` - - root exports do not expose secret resolution, signer, wallet, raw custody internals, or provider-specific secret coordinates. - -## Closeout Commands - -Focused: - -```bash -npm run test -- test/protocol/credential-custody.test.ts test/protocol/kernel-policy-gateway.test.ts -npm run test -- test/protocol/evidence-projections.test.ts -npm run test -- test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts -npm run test -- test/conformance/x402-payment-conformance.test.ts -npm run test -- test/adapters/auth-md-gateway-pressure.test.ts test/adapters/auth-md-serialization-redaction.test.ts -npm run test -- test/architecture/claim-boundary.test.ts test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts -npm run quality:claims -npm run quality:architecture -``` - -Full: - -```bash -npm run check:types -npm run lint -npm run format:check -npm run test -npm run pack:check -git diff --check -npm run check:repo -``` - -## End Criteria - -- Packet schema, canonicalization, transition, policy binding, gateway binding, x402 integration, auth.md parity, and projection tests pass. -- x402 signer cannot execute unless a valid packet/ref/posture/greenlight/gateway check chain exists. -- Credential resolution evidence is post-gate only. -- Redacted projection is reconstructable by digest and contains no secret-bearing material. -- Claim guards prevent overclaiming fixture custody, provider custody, payment custody, hosted trust, broad x402 compatibility, marketplace/certification, clearing-house readiness, or broad runtime control. -- Provider-specific details remain marked as requiring official source verification unless that verification has been performed in a later pass. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md deleted file mode 100644 index b7b839d..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/input.md +++ /dev/null @@ -1,178 +0,0 @@ -# Macro Plan Input: Customer-Owned Gateway Custody Proof - -Run ID: `customer-owned-gateway-custody-proof-20260524T071623Z` - -## Target - -Create a source-grounded macro plan for critical-path item 1 from `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md`: **Customer-Owned Gateway Custody Proof**. - -Goal: define the implementation path for proving a protected path is real because the mutation credential lives behind a customer/provider gateway that enforces the exact greenlight before consequence. - -The desired mechanism from the active register: - -```text -gateway install evidence --> credential ref binding --> protected-path posture --> custody/bypass probe packet --> gateway check binds exact contract --> redacted custody projection -``` - -## User Constraints - -- Use `$gsd-macro-plan` as a subagent-first workflow. -- This is planning only. Do not implement source changes under this run. -- Handshake is protected actions for automated decision making, not just engineering agents. -- x402 is the first wedge, but x402 must not define the protocol. -- Keep Tier 1 protocol/kernel meaning stable. -- Preserve customer-owned gateway custody as the enforcement model. -- Do not introduce Handshake-held wallets, payment credentials, balances, settlement state, or payment management. -- Do not claim live provider/customer custody until a source-owned custody proof packet, negative tests, and redacted projections exist. -- Do not add provider-specific vault/KMS architecture without marking official-doc/source verification as required before implementation. - -## Source Boundary - -Allowed source files for first-pass agents: - -- `AGENTS.md` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` -- `.planning/macro/README.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `.planning/macro/active/claim-boundary-cleanup/PLAN.md` -- `.planning/codebase/ARCHITECTURE.md` -- `.planning/codebase/CONCERNS.md` -- `.planning/codebase/CONVENTIONS.md` -- `.planning/codebase/INTEGRATIONS.md` -- `.planning/codebase/STACK.md` -- `.planning/codebase/STRUCTURE.md` -- `.planning/codebase/TESTING.md` -- `src/protocol/areas/credential-custody/schemas.ts` -- `src/protocol/areas/credential-custody/inputs.ts` -- `src/protocol/areas/credential-custody/custody-posture.ts` -- `src/protocol/areas/credential-custody/transitions.ts` -- `src/protocol/areas/protected-path-posture/schemas.ts` -- `src/protocol/areas/protected-path-posture/inputs.ts` -- `src/protocol/areas/protected-path-posture/transitions.ts` -- `src/protocol/areas/gateway-gate/schemas.ts` -- `src/protocol/areas/gateway-gate/inputs.ts` -- `src/protocol/areas/gateway-gate/artifacts.ts` -- `src/protocol/areas/gateway-gate/transitions.ts` -- `src/protocol/areas/policy-greenlight/transitions.ts` -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/evidence-projections/assembly.ts` -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/wallet-gateway.ts` -- `src/adapters/x402-payment/bypass-probes.ts` -- `src/adapters/x402-payment/conformance.ts` -- `src/adapters/auth-md/profiles.ts` -- `src/adapters/auth-md/gateway.ts` -- `src/adapters/auth-md/revocation.ts` -- `src/adapters/auth-md/bypass-probes.ts` -- `src/adapters/protected-path-probes` -- `test/protocol/credential-custody.test.ts` -- `test/protocol/evidence-projections.test.ts` -- `test/protocol/kernel-policy-gateway.test.ts` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/adapters/x402-bypass-probes.test.ts` -- `test/adapters/auth-md-gateway-pressure.test.ts` -- `test/adapters/auth-md-serialization-redaction.test.ts` -- `test/conformance/x402-payment-conformance.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` - -Forbidden files for first-pass agents: - -- sibling raw outputs under this run; -- normalized outputs under this run; -- the final `PLAN.md` for this run before chair synthesis; -- unrelated historical `.planning/macro/archive/**` files unless a specific current source file links to them; -- source files not listed above unless the agent first records why the listed source packet is insufficient. - -## Required Output Directory - -All artifacts for this item must stay under: - -```text -.planning/macro/active/customer-owned-gateway-custody-proof/ -``` - -First-pass outputs: - -```text -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/STRATEGY.md -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ARCH.md -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/EXECUTION.md -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/RISK.md -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ADOPTION.md -``` - -Chair outputs: - -```text -.planning/macro/active/customer-owned-gateway-custody-proof/PLAN.md -.planning/macro/active/customer-owned-gateway-custody-proof/CONTEXT.md -.planning/macro/active/customer-owned-gateway-custody-proof/ASSUMPTIONS.md -.planning/macro/active/customer-owned-gateway-custody-proof/DECISIONS.md -.planning/macro/active/customer-owned-gateway-custody-proof/RISKS.md -.planning/macro/active/customer-owned-gateway-custody-proof/VALIDATION.md -.planning/macro/active/customer-owned-gateway-custody-proof/TASKS.jsonl -.planning/macro/active/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/synthesis.md -``` - -## Plan Requirements - -The chair plan must include: - -- goal; -- non-goals; -- source boundary; -- current state; -- target state; -- assumptions; -- decisions; -- phases; -- task graph; -- risks and mitigations; -- validation gates; -- cut lines; -- rollback / stop conditions; -- smallest next action. - -The plan must explicitly cover: - -- whether to extend existing `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, and bypass probe primitives or add a new proof packet primitive; -- custody proof packet schema shape and digest binding; -- binding custody proof to protected-path posture, action contract, policy/greenlight, gateway check, and redacted projections; -- provider-neutral fields for custody provider, key handle, lease/version, attestation refs, resolver version, redacted audit refs, and drift status; -- negative tests for agent-exposed signer, stale credential ref, provider drift, resolver failure, missing custody packet, unsafe custody status, redaction failure, and raw sibling path; -- how x402 uses the custody proof without broadening into payment management or provider custody claims; -- how auth.md learnings around credential refs, revocation, and redaction inform this mechanism without turning Handshake into an auth provider; -- projection redaction rules that never expose secret paths, signer material, payment payloads, bearer tokens, or mutation credentials; -- claim guards preventing provider/customer custody claims from fixture keys; -- external verification that must happen later for any named vault/KMS/provider custody implementation. - -## Success Criteria - -- The macro plan is executable as a future implementation slice without altering Tier 1 protocol meaning. -- The plan strengthens the enforcement story for protected actions while preserving customer-owned custody and avoiding Handshake-held payment custody. -- Each task names source/test/doc candidate paths and closeout evidence. -- `TASKS.jsonl` parses as JSONL. -- Validation gates are specific enough to fail stale custody, drift, redaction, and unsafe signer exposure. -- The plan names antipatterns and stop conditions. - -## External Verification - -Do not browse by default for this planning pass. If a perspective proposes a named vault, KMS, wallet provider, x402 provider, JWKS, Cloudflare, npm, MCP Registry, legal, or payment-regulatory detail, it must mark that detail as requiring official source verification before implementation. Provider-neutral schema planning may proceed from repo source only. - -## 10 Star Product Bar - -Custody proof is successful when a buyer can see that the automated decision system never received the mutation credential, the customer-owned gateway had the credential, the exact greenlight was checked immediately before mutation, drift/stale/unsafe custody refuses before consequence, and the surviving evidence is redacted but reconstructable. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ADOPTION.md deleted file mode 100644 index 8e8eb70..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ADOPTION.md +++ /dev/null @@ -1,196 +0,0 @@ -# ADOPTION First Pass: Customer-Owned Gateway Custody Proof - -## Invariant At Stake - -A buyer must not be asked to trust a "gateway-protected" claim unless the first-use evidence shows: - -- the automated decision system never received the mutation credential; -- the customer/provider gateway held or resolved the credential behind its boundary; -- the exact one-use greenlight was checked immediately before mutation; -- stale, drifted, unsafe, missing, or bypassable custody refused before consequence; -- the surviving packet is redacted but reconstructable. - -If the buyer has to infer custody from scattered internal records, this is not adoption-ready. It may be source-true for a maintainer and still unreadable to an operator. - -## Source Posture For Adoption - -Current source already has adoption-relevant building blocks: - -- `GatewayCredentialRef` records opaque gateway-side custody without raw credential material. -- `CredentialResolutionEvidence` can be recorded only after a passed `GatewayCheckAttempt` and binds the exact contract, greenlight, gate attempt, credential ref digest, resolver metadata, request digest, redaction status, and result class. -- `ProtectedPathPosture` requires `gateway_checked` posture to be fresh, scope-bound, probe-backed, and backed by gateway/hosted-monitor-strength source authority. -- Policy and gateway evaluation both consult protected-path posture and credential-ref binding before authority proceeds. -- `GatewayCheckAttempt`, `MutationAttempt`, `Receipt`, `Refusal`, and `ProofGap` already distinguish gateway admission from downstream outcome. -- Redacted projections expose contract, agent transaction envelope, receipt timeline, idempotency recovery, and install health without raw signer, payment payload, bearer token, or provider secret-path material. -- x402 proves one local/reference buyer-side `x402_payment.exact` path with gateway signing only after `VerifiedGatewayCheck`. -- auth.md proves useful lifecycle lessons: credential refs, metadata/revocation drift, gateway-time credential resolution, isolation, and redaction without making Handshake an auth provider. - -Current source does not yet give the buyer one custody proof packet that ties install evidence, credential ref, posture/probes, exact contract, policy/greenlight, gateway check, credential resolution, and redacted projection into a single first-use artifact. That is the adoption blocker this plan must remove. - -## Adoption Path - -1. **Buyer chooses one protected path.** - Start with one tenant/org, one principal, one runtime, one action class, one gateway, and one resource. For the first wedge, use one buyer-side `x402_payment.exact` per-call path. Do not teach x402 as the protocol and do not teach aggregate payment-budget management. - -2. **Customer/operator installs the gateway boundary.** - The operator declares the gateway authority holder, protected surface, resource namespace, accepted action classes, policy version, enforcement mode, credential custody status, and resolver version. The mutation credential remains behind the customer/provider gateway. Handshake receives only opaque refs, digests, and redacted audit refs. - -3. **Developer compiles install records.** - The install path produces tool capability, action type, gateway registry entry, and operating envelope records. It must also produce or reference the future custody proof packet. Install refusal must be normal when the signer/credential is agent-exposed, bounds are wildcarded, resources are outside envelope, or provider evidence is incomplete. - -4. **Gateway records credential ref binding.** - Register `GatewayCredentialRef` with provider-neutral fields: custody provider class, credential kind, key/credential handle ref, provider registry ref/digest, resolver ref/version, lease or expiry, evidence expectation refs, redaction profile, and explicit `secretMaterialIncluded: false`. The contract later binds the ref ID and digest. - -5. **Gateway or hosted monitor runs hostile probes.** - Required probe kinds: credential custody, raw sibling blocking, MCP direct-call blocking, token passthrough blocking, wrapper drift, and failure-closed behavior. A `gateway_checked` posture should not be accepted from weak fixture-only or caller-reported evidence. If source authority is too weak, adoption should show a refusal, not a yellow success. - -6. **Protected-path posture is recorded.** - Create a fresh `ProtectedPathPosture` scoped to runtime, gateway, action class, resource, and protected surface. It must carry `postureState: "gateway_checked"`, safe credential custody, raw sibling absent/blocked, probe IDs, probe digests, and expiry. - -7. **Runtime proposes, but does not authorize.** - Runtime/MCP/CLI may help the developer propose the exact action. They must not hold signer material, evaluate policy, create greenlights, run gateway checks, mutate, export receipts, or mint certificates. - -8. **Policy refuses or greenlights from current custody state.** - Policy input must include the contract digest, protected-path posture digest/freshness, gateway credential ref binding, isolation snapshot, and idempotency state. Missing, stale, unsafe, drifted, or isolated custody refuses before any greenlight. - -9. **Gateway checks immediately before consequence.** - The gateway verifies the exact contract/greenlight/params/idempotency/posture/policy drift/credential binding. If passed, adapter mutation-side code receives `VerifiedGatewayCheck`. If not passed, no credential resolution and no mutation-side call occur. - -10. **Gateway records post-gate custody evidence.** - Credential resolution evidence is recorded only after a passed gate and must state whether the credential was resolved, used, refused, blocked by isolation, or became a proof gap. Redaction failure is a refusal/proof-gap path, not a best-effort warning. - -11. **Buyer reads one redacted custody proof packet.** - The packet should answer, without exposing secrets: who owned the gateway, what credential ref was expected, what probes passed, what exact contract was greenlit, what the gateway saw, whether the credential was resolved/used after the gate, what downstream evidence exists, and what proof gaps or refusals remain. - -## First-Use Checklist - -- Pick one action class: first wedge should be `x402_payment.exact`. -- Name the protected resource exactly: endpoint URL, network, payee, token, amount, request posture, selected payment requirement digest, and idempotency material. -- Name the customer/operator gateway authority holder and gateway ID. -- Verify the mutation credential is not available to the agent/runtime, MCP tool, browser path, shell path, environment, sibling wrapper, or direct SDK client. -- Register the gateway registry entry with enforcement mode, policy version, credential custody status, and authority holder. -- Register an opaque `GatewayCredentialRef`; reject any raw private key, bearer token, `PaymentPayload`, `PAYMENT-SIGNATURE`, provider secret path, or access-token-looking value. -- Run all required hostile probes and keep the probe evidence refs redacted. -- Record `ProtectedPathPosture` only after all required probes pass from an accepted source authority. -- Compile one runtime proposal and one exact `ActionContract`; ensure the contract binds the gateway credential ref digest. -- Evaluate policy and confirm either a one-use greenlight or a durable refusal. -- Run the gateway check with gateway-observed parameters, not runtime-trusted parameters. -- Confirm a replay of the same greenlight refuses before mutation. -- Record `CredentialResolutionEvidence` only after the passed gate. -- Read the redacted custody proof packet and verify it does not expose secret paths, signer material, payment payloads, bearer tokens, mutation credentials, raw authorization headers, claim tokens, JWTs, or PII. -- Run negative-path checks for agent-exposed signer, stale credential ref, provider drift, resolver failure, missing custody packet, unsafe custody status, redaction failure, raw sibling path, and weak source authority. - -## Missing Docs And Examples - -- A buyer/operator "customer-owned gateway custody proof" quickstart is missing. Candidate future path: `examples/customer-owned-gateway-custody-proof/README.md`. It should teach the one-path install, probes, posture, proposal, policy, gateway check, resolution evidence, replay refusal, and redacted packet readback. -- A machine-readable example packet is missing. Candidate future path: `examples/customer-owned-gateway-custody-proof/output/latest.json`. It should include refs/digests, not raw records or secrets. -- A buyer-readable Markdown packet is missing. Candidate future path: `examples/customer-owned-gateway-custody-proof/output/latest.md`. It should be readable by a security/operator buyer without knowing protocol internals. -- `README.md` should eventually expose the smallest custody proof command or walkthrough only after the packet exists. Do not add a hosted/provider custody claim. -- `docs/internal/protocol-definition.md` and `docs/internal/protocol-kernel-architecture.md` should eventually name the custody proof packet or explicitly say it is a redacted projection over existing records. Do not change Tier 1 object meaning. -- `docs/internal/protocol-layman.md` needs the operator explanation: "the gateway had the credential; the agent did not; this exact pass was checked before use." -- x402 walkthrough docs need a custody-proof subsection that keeps local/reference fixture status visible and refuses provider/customer custody claims from fixture keys. -- Support/debug docs are missing for reason-code-to-fix mapping: `gateway_credential_ref_missing`, `gateway_credential_ref_stale`, `gateway_credential_ref_provider_drift`, `gateway_credential_ref_unsafe_custody`, `protected_path_probe_failed`, `protected_path_source_authority_weak`, `protected_path_raw_sibling_tool_present`, `gateway_policy_drift`, `params_mismatch`, `already_consumed`, `redaction_failed`, and downstream proof-gap reasons. -- Provider-specific vault/KMS/wallet setup docs must not be written from repo source alone. They require official source verification before implementation. - -## Success Metrics - -- A developer can produce the first local/reference custody proof packet from a clean checkout with one documented command or short checklist. -- A buyer can answer five questions from the packet without reading source: Did the agent receive the credential? Who held it? What exact contract was greenlit? Did the gateway check it before mutation? What evidence is missing or redacted? -- Every unsafe custody path produces a named refusal or proof gap before mutation. -- Negative tests cover all required custody failure classes and assert zero credential resolution and zero mutation when pre-gate evidence fails. -- Redacted packet serialization contains no raw credential material under current x402/auth.md secret patterns. -- Support can map every custody failure reason code to an operator action. -- Claim guards fail if docs/examples imply live provider custody, Handshake-held wallets/payment credentials, hosted operation, settlement, aggregate spend enforcement, generic MCP/runtime protection, or broad x402 compatibility. -- The first-use path does not require all-role SDK clients, raw protocol record reads, or direct adapter internals. - -## Adoption Blockers And Fixes - -| Blocker | Why it blocks adoption | Fix | -| --- | --- | --- | -| Custody evidence is scattered across refs, posture, probes, gate, resolution, receipt, and projections. | Buyers cannot verify custody without protocol expertise. | Add a redacted custody proof packet or projection that assembles the chain and exposes digest-bound refs. | -| The packet primitive is not source-owned yet. | Docs would have to describe an implied artifact. That becomes evidence theatre. | Define packet schema or projection contract before buyer docs. | -| Gateway setup ceremony is long. | Integrators may skip probes/posture or move authority into runtime/MCP for convenience. | Build an activation helper that sequences existing calls while keeping policy, greenlight, gateway check, signer/custody, and mutation authority out of runtime/MCP. | -| x402 local fixture can be mistaken for live custody. | Fixture keys and local sandbox evidence do not prove provider/customer custody. | Keep fixture/local/reference status in packet and claim guards; require official provider verification before live custody docs. | -| Provider-neutral custody fields are incomplete for buyer language. | A buyer needs key handle, lease/version, attestation refs, resolver version, audit refs, and drift status in one place. | Add these to the packet, reusing `GatewayCredentialRef` where possible and adding packet-level fields only where the existing ref is not enough. | -| Source-authority expectations can confuse implementers. | `gateway_checked` posture is accepted only from gateway/hosted-monitor-strength evidence; weaker fixture/caller evidence must refuse. | Document accepted source authorities and add tests that weak source authority refuses with a readable reason. | -| Runtime/MCP x402 posture parity gaps exist in the codebase map. | Proposal surfaces can teach weaker request-body/provider-environment semantics than the direct adapter path. | Use direct adapter/runtime-client path for first custody proof, then add runtime/MCP parity before exposing MCP as the first-use path. | -| Redaction is partly pattern-based. | Unknown provider credential formats can leak or force overbroad omission. | Prefer allowlisted packet fields and add provider-format fuzz tests before live provider custody. | -| Existing demos prove local/reference x402, not customer-owned custody. | The buyer may see "wallet gateway" and infer real customer/provider control. | Add explicit packet fields for `fixture_only`, `local_reference`, `customer_gateway_adapter`, or `provider_gateway` posture and fail claims from fixture-only packets. | -| Support/debug output is not organized around operator fixes. | A refusal is good protocol behavior but bad adoption if the operator cannot repair install state. | Add reason-code remediation table and packet-level `nextOperatorAction` labels. | - -## Assumptions - -- Tier 1 protocol meaning remains stable: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof-gap, and isolation semantics do not change. -- Customer-owned gateway custody can be implemented as an additive packet/projection over existing primitives unless architecture proves a new protocol object is necessary. -- x402 remains the first wedge, but the custody mechanism must stay provider-neutral. -- Handshake does not hold wallets, signers, payment credentials, balances, settlement state, or payment-management state. -- Live provider/customer custody claims are blocked until source-owned packet, negative tests, redacted projections, and official provider verification exist. -- `.planning/` remains scratch and should not become repo-facing canon. - -## Dependencies - -- Existing protocol primitives: `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, `BypassProbe`, `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `Receipt`, `Refusal`, `ProofGap`, and `IsolationState`. -- Existing x402 adapter path: install proposal, action proposal, wallet gateway, hostile bypass probes, and conformance posture. -- Existing auth.md lessons: credential ref binding, metadata/revocation drift, post-gate credential resolution, lifecycle isolation, and redaction. -- Evidence projection assembly and redaction rules. -- Claim-boundary tests preventing fixture/local evidence from becoming provider/customer custody claims. -- Future official-source verification for any named vault, KMS, wallet provider, x402 provider, Cloudflare, JWKS, npm, MCP Registry, legal, or payment-regulatory details. - -## Risks - -- **Review theatre:** A pretty custody packet that is not structurally bound to the exact contract, policy input, greenlight, gateway check, and credential ref digest. -- **Evidence theatre:** A packet that cannot distinguish gateway check, credential resolution, mutation attempt, downstream response, refusal, and proof gap. -- **Fixture laundering:** Local fixture signer custody gets presented as customer/provider custody. -- **Runtime authority drift:** Activation convenience moves signer custody or gateway checks into runtime, MCP, CLI, or SDK surfaces. -- **Provider lock-in:** A provider-specific KMS/vault model leaks into protocol fields before official verification. -- **Redaction failure:** Unknown credential formats evade current string/pattern redaction. -- **Stale acceptance:** A custody proof packet remains accepted after provider registry digest, resolver version, lease, posture, or policy drift. -- **Support opacity:** Refusals are correct but not operator-actionable, causing teams to bypass the gateway. -- **x402 overreach:** The first wedge drifts into settlement, seller/facilitator operation, signed offers/receipts, aggregate spend windows, or broad compatibility. - -## Validation Gates - -- Schema/canonicalization tests for the custody proof packet or projection digest. -- Policy tests refusing missing packet, stale packet, unsafe custody, provider drift, resolver failure, weak source authority, failed probes, and active credential-ref isolation. -- Gateway tests refusing params drift, gateway policy drift, stale credential ref, missing credential ref, unsafe custody, replay, and raw sibling path before credential resolution or mutation. -- Adapter tests proving x402 signing receives only `VerifiedGatewayCheck`, and signing count remains zero on refusal/replay/drift. -- Redaction tests serializing the full packet and asserting absence of private keys, `PAYMENT-SIGNATURE`, `PaymentPayload`, bearer tokens, provider secret paths, raw authorization material, claim tokens, JWTs, and PII. -- Projection tests showing the packet distinguishes gateway admission from downstream outcome and proof gap. -- Claim-boundary tests preventing provider/customer custody claims from fixture keys and preventing Handshake-held wallet/payment-management language. -- Docs/example tests for the buyer-readable packet, including refusal and proof-gap paths, not only success. -- Focused future gates: `npm run quality:claims`, custody/projection protocol tests, x402 adapter/probe tests, auth.md redaction/gateway pressure tests, and architecture import/root export tests if public surfaces change. -- Full future closeout: `npm run check:repo`. - -## Cut Lines - -- No Handshake-held wallets, private keys, bearer tokens, payment credentials, balances, settlement state, or payment management. -- No provider-specific vault/KMS/wallet architecture without official source verification. -- No live provider/customer custody claim from local fixtures, local sandbox, conformance fixtures, or fixture keys. -- No aggregate x402 spend-window enforcement until a real ledger exists. -- No seller middleware, facilitator operation, settlement finality, signed offers, signed receipts, batch settlement, `upto`, or MCP auto-pay in this slice. -- No broad runtime, MCP, browser, shell, package-manager, cloud, repo, database, or network interception claim. -- No raw protocol record reads as the buyer-facing proof path. -- No all-role SDK or CLI/MCP mutation command in first-use docs. -- No greenlight reuse or multi-mutation authority. -- No "installed" or "protected" label unless current probe-backed posture and custody packet are present. - -## Antipatterns - -- "The gateway is trusted" without a gate attempt, credential ref digest, and probe-backed posture. -- "Approved plan" as a substitute for exact contract binding. -- "The signer is in a vault" with no resolver version, provider registry digest, lease/freshness, and post-gate resolution evidence. -- "Local fixture gateway-held" described as provider custody. -- "MCP payment tool" that can produce payment payloads or signatures. -- "Support mode" that exposes raw records, secret paths, signer refs, `PaymentPayload`, or bearer material. -- "One greenlight per workflow" instead of one greenlight per exact mutation attempt. -- "Downstream succeeded" inferred from a gateway check or receipt without reconciliation evidence. -- "Unknown" smoothed into success instead of a `ProofGap`. -- Docs that teach x402 as the protocol rather than the first protected-action pack. - -## Blocked Checks - -- No external official documentation was verified in this first pass. Any named provider, vault, KMS, x402 provider, Cloudflare, JWKS, npm, MCP Registry, legal, or payment-regulatory detail remains blocked on official source verification before implementation. -- Sibling raw outputs, normalized outputs, and the final plan for this run were not read, by instruction. -- No source, test, docs, package, or prior planning artifact was modified. -- No tests were run because this is a planning-only first-pass artifact with a hard write boundary. -- Unlisted example files were not inspected; missing docs/examples above are candidate future paths, not verified current contents. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ARCH.md deleted file mode 100644 index f8fc292..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/ARCH.md +++ /dev/null @@ -1,400 +0,0 @@ -# ARCH First-Pass Plan: Customer-Owned Gateway Custody Proof - -## Invariant at stake - -A protected path is real only when the mutation credential lives behind a customer or provider gateway, the exact one-use greenlight is checked immediately before consequence, stale or unsafe custody refuses before mutation, and the surviving evidence is redacted but reconstructable. - -If this work only adds a report, install label, fixture signer posture, or projection text, this is advisory, not Handshake. - -## Architecture implications - -The current source already has the authority spine needed for this slice: - -- `GatewayCredentialRef` is provider-neutral, opaque, digest-bound, scoped to tenant/org/gateway/action/resource, and rejects raw credential-looking material. -- `CredentialResolutionEvidence` is post-gate evidence only. It binds exact `ActionContract`, `Greenlight`, `GatewayCheckAttempt`, optional `MutationAttempt`, credential ref digest, resolver metadata, request digest, redaction status, and result class. -- `ProtectedPathPosture` is current-state evidence for runtime/gateway/action/resource. It already carries posture state, credential custody status, raw sibling status, bypass probe IDs/digests, source authority, expiry, and a posture digest. -- Policy evaluation and gateway check both re-read current protected-path posture and gateway credential bindings before greenlighting or admitting mutation. -- Gateway check records the contract digest, greenlight digest, params digest, protected-path posture seen, drift status, refusal/proof-gap/admission, and one-use greenlight consumption. -- Evidence projections already expose redacted contract evidence, agent transaction envelopes, credential refs/resolution evidence refs, receipt timelines, idempotency recovery, and protected-path install health. - -The missing architecture object is not another permission path. The gap is a source-owned custody proof packet that turns "gateway owns or controls the mutation credential" from a field assertion into digest-bound install evidence that can be: - -```text -gateway install evidence --> credential ref binding --> protected-path posture --> custody/bypass probe packet --> exact contract / policy input / greenlight / gateway check --> redacted custody projection -``` - -Without that packet, `GatewayCredentialRef.custodyStatus`, gateway registry custody status, and `ProtectedPathPosture.credentialCustodyStatus` are still too easy to treat as caller-reported posture. The current tests already reject weak posture source authority and fixture-only x402 custody, but there is no first-class custody packet digest tying install evidence, credential ref, posture, probes, resolver version, and redacted audit refs together. - -## Extend vs new primitive recommendation - -Add a new custody proof packet record inside the existing credential-custody/protected-path authority spine. Do not create a parallel authority primitive. - -Recommended shape: - -- Add a `GatewayCustodyProofPacket` or `CustomerGatewayCustodyProofPacket` schema and transition under `src/protocol/areas/credential-custody/`. -- Bind that packet into `GatewayCredentialRef` and `ProtectedPathPosture` by ID and digest. -- Include the packet digest in policy input and gateway-time revalidation through the existing protected-path posture and credential-ref checks. -- Extend redacted evidence projections to expose custody proof refs/digests/status, never raw provider paths or signer material. -- Keep `CredentialResolutionEvidence` post-gate. It must not become pre-gate install proof. - -Why not only extend existing fields: - -- Overloading `GatewayCredentialRef.evidenceExpectationRefs` leaves custody proof as loose refs with no typed drift semantics. -- Overloading `ProtectedPathPosture.evidenceRefs` lets a posture claim look current without proving which gateway install and credential ref it depended on. -- Overloading bypass probes alone proves hostile-path posture, not the customer-owned custody chain from gateway install to credential ref to resolver/version to redacted audit refs. - -Why not add a new top-level authority primitive: - -- The protocol primitive is still one exact contract, one policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap. -- Custody proof is evidence that a required protected path may be considered gateway-owned. It does not authorize mutation. -- Any new "custody approval", "custody greenlight", "wallet authorization", or "provider trust decision" would create a second permission plane. - -Brutal verdict: add a new proof packet record, but keep it subordinate to `GatewayCredentialRef`, `ProtectedPathPosture`, policy evaluation, and gateway check. - -## Proposed custody proof packet boundary - -The packet should be provider-neutral and redaction-first. - -Candidate fields: - -- `custodyProofPacketId` -- `custodyProofPacketDigest` -- `gatewayInstallEvidenceRef` -- `gatewayInstallEvidenceDigest` -- `gatewayCredentialRefId` -- `gatewayCredentialRefDigest` -- `gatewayId` -- `gatewayRegistryEntryId` -- `protectedSurfaceKind` -- `actionClasses` -- `resourceRefs` -- `custodyProviderClass` -- `custodyProviderRegistryRef` -- `custodyProviderRegistryDigest` -- `opaqueKeyHandleRef` -- `opaqueKeyHandleDigest` -- `credentialKind` -- `credentialCustodyStatus` -- `resolverRef` -- `resolverVersion` -- `leaseRef` -- `leaseVersion` -- `leaseIssuedAt` -- `leaseExpiresAt` -- `attestationRefs` -- `attestationDigests` -- `redactedAuditRefs` -- `redactedAuditDigest` -- `driftStatus`: `current | stale | provider_drift | resolver_drift | unsafe_custody | proof_gap` -- `bypassProbeIds` -- `bypassProbeDigests` -- `redactionProfileRef` -- `secretMaterialIncluded: false` -- `recordedAt` -- `expiresAt` - -The packet must reject raw credential material and provider secret paths in the same spirit as `GatewayCredentialRefSchema` and auth.md/x402 projection redaction. For live providers, use opaque handles and digests, not `vault://team/prod/secret`, private key refs, `PAYMENT-SIGNATURE`, `PaymentPayload`, bearer tokens, API keys, raw signer refs, or path-like secret coordinates. - -## Data and control flow - -### Install and proof recording - -```text -adapter install proposal --> gateway registry entry --> gateway credential ref --> custody proof packet --> bypass probes --> protected-path posture -``` - -The install path should compile or record the credential ref and proof packet before any `gateway_checked` posture can be accepted. For x402, this means the wallet/signer boundary becomes a gateway credential ref plus custody proof packet, not only `walletGatewayProfile.signerRef` on the gateway registry entry. - -For auth.md, the existing pattern is the model to copy: raw credential intake is adapter-local, registration/revocation evidence is redacted and digest-bound, and the protocol sees an opaque `GatewayCredentialRef`. - -### Policy - -Policy already includes: - -- protected-path posture input; -- gateway credential binding input; -- isolation state; -- sequence dependency state; -- idempotency state. - -The plan should extend policy input so custody proof is included through: - -- `GatewayCredentialRef` proof packet refs/digests; and/or -- `ProtectedPathPosture` proof packet refs/digests. - -Policy must refuse before greenlight when: - -- custody proof packet is missing; -- packet digest does not match the credential ref or posture binding; -- packet is stale or expired; -- packet drift status is unsafe; -- packet source authority is weak or fixture-only when a live/customer-owned claim is being made; -- redaction status is failed; -- credential ref is stale, provider-drifted, scope-mismatched, or isolated. - -### Gateway check - -Gateway check should keep its current role: exact final admission before mutation. - -The gateway check should re-read current custody packet state indirectly through current protected-path posture and credential binding, or directly if the implementation adds custody-proof lookup. It must refuse before mutation when the proof packet seen at policy time no longer matches current gateway custody state. - -The resulting `GatewayCheckAttempt` should either: - -- add `custodyProofPacketIdSeen`, `custodyProofPacketDigestSeen`, and `custodyProofDriftStatusSeen`; or -- keep the gateway record unchanged only if `protectedPathPostureDigestSeen` deterministically includes the custody proof packet digest and tests prove that drift changes the posture digest. - -The first option is more auditable. The second is smaller but risks hiding the custody proof inside a posture digest. - -### Resolution and mutation - -Credential resolution remains after a passed gateway check. The packet proves custody posture before authority; `CredentialResolutionEvidence` proves gateway-side credential resolution/use after authority admission. - -For x402: - -```text -verified gateway check --> gateway-held signing surface creates PaymentPayload / PAYMENT-SIGNATURE evidence --> redacted signature/payload digests recorded as evidence refs --> downstream sandbox/provider response becomes reconciliation or proof gap -``` - -Do not add Handshake-held wallets, balances, signer APIs, payment settlement state, facilitator operation, seller middleware, or aggregate spend state. - -### Projection - -Evidence projection should add a redacted custody projection rather than raw proof packet browsing. - -Candidate projection fields: - -- `custodyProofPacketRef` -- `custodyProofPacketDigest` -- `gatewayCredentialRef` -- `gatewayCredentialRefDigest` -- `gatewayId` -- `protectedSurfaceKind` -- `actionClasses` -- `resourceRefs` -- `custodyProviderClass` -- `custodyProviderRegistryDigest` -- `opaqueKeyHandleDigest` -- `resolverRef` -- `resolverVersion` -- `leaseVersion` -- `attestationDigests` -- `redactedAuditDigest` -- `driftStatus` -- `expiresAt` -- `redactionProfileRef` -- `omittedFields` - -This projection should be available to contract/agent transaction/install-health evidence without exposing secret paths, signer material, payment payloads, bearer tokens, mutation credentials, provider secret URIs, or raw audit payloads. - -## Boundaries that must not move - -- `src/protocol/areas/*` owns protocol meaning. Adapters can produce evidence and execute after `VerifiedGatewayCheck`; they must not define custody proof semantics alone. -- `src/runtime`, `src/mcp`, `src/cli`, and SDK role clients remain proposal/evidence/read surfaces. They must not record custody proof, resolve credentials, issue policy decisions, mint greenlights, run gateway checks, export receipts, or mutate. -- Gateway check remains the enforcement boundary before consequence. Custody proof cannot replace the exact contract or one-use greenlight. -- `GatewayCredentialRef` stays opaque and non-secret. No protocol API should retrieve secrets or expose provider secret paths. -- `CredentialResolutionEvidence` stays post-gate. It must not become permission or install proof. -- `ProtectedPathPosture` stays current and probe-backed. A caller-reported or fixture posture cannot satisfy customer-owned custody. -- x402 remains one buyer-side `x402_payment.exact` per-call protected action pack. It must not become payment management, wallet custody, balance tracking, facilitator operation, seller middleware, settlement, or broad x402 compatibility. -- auth.md learnings apply to credential refs, lifecycle isolation, redaction, and revocation evidence. They must not turn Handshake into an auth provider. -- `.planning/` remains scratch. Any durable doctrine belongs in compact canonical docs only after implementation proves it. - -## Likely source paths - -Protocol: - -- `src/protocol/areas/credential-custody/schemas.ts` -- `src/protocol/areas/credential-custody/inputs.ts` -- `src/protocol/areas/credential-custody/transitions.ts` -- `src/protocol/areas/credential-custody/custody-posture.ts` -- `src/protocol/areas/protected-path-posture/schemas.ts` -- `src/protocol/areas/protected-path-posture/inputs.ts` -- `src/protocol/areas/protected-path-posture/transitions.ts` -- `src/protocol/areas/policy-greenlight/transitions.ts` -- `src/protocol/areas/gateway-gate/schemas.ts` -- `src/protocol/areas/gateway-gate/artifacts.ts` -- `src/protocol/areas/gateway-gate/transitions.ts` -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/evidence-projections/assembly.ts` - -Adapter and probe surfaces: - -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/wallet-gateway.ts` -- `src/adapters/x402-payment/bypass-probes.ts` -- `src/adapters/x402-payment/conformance.ts` -- `src/adapters/auth-md/profiles.ts` -- `src/adapters/auth-md/gateway.ts` -- `src/adapters/auth-md/revocation.ts` -- `src/adapters/auth-md/bypass-probes.ts` -- `src/adapters/protected-path-probes/index.ts` -- `src/adapters/protected-path-probes/executor.ts` - -Likely additional implementation paths to verify before execution: - -- `src/protocol/areas/object-registry/*` -- `src/protocol/public/inputs.ts` -- `src/protocol/public/schemas.ts` -- `src/protocol/kernel.ts` -- `src/protocol/store/port.ts` -- `src/storage/d1/*` -- `src/storage/memory/*` -- `src/http/routes/*` -- `src/http/handlers/evidence-read.ts` -- `src/sdk/surface-clients/evidence-client.ts` -- `src/mcp/resources.ts` -- `src/cli/projection-evidence.ts` - -Docs: - -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-notes.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/PLAN.md` after chair synthesis only - -Tests: - -- `test/protocol/credential-custody.test.ts` -- `test/protocol/evidence-projections.test.ts` -- `test/protocol/kernel-policy-gateway.test.ts` -- new or extended `test/protocol/customer-owned-gateway-custody-proof.test.ts` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/adapters/x402-bypass-probes.test.ts` -- `test/adapters/auth-md-gateway-pressure.test.ts` -- `test/adapters/auth-md-serialization-redaction.test.ts` -- `test/conformance/x402-payment-conformance.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` - -## Compatibility and migration risks - -- Adding required fields directly to `GatewayCredentialRef` or `ProtectedPathPosture` will break existing fixtures and stored records. Prefer additive nullable/default fields first, then tighten required status only for action contracts that require `gateway_checked` and custody proof. -- If custody proof affects `paramsDigest`, `policyInputDigest`, `postureDigest`, or contract digest, existing tests that assert exact duplicate/refusal behavior may need fixture updates. That is acceptable only if the digest change reflects real authority input. -- Existing x402 install proposals store signer posture on `walletGatewayProfile` and gateway registry metadata. Migrating x402 to protocol-level credential refs may require install compiler output changes beyond the allowed source packet. -- Current projection redaction is pattern-based with known gaps for unknown provider formats. Live provider custody claims need allowlisted projection fields and provider-format fuzz tests before they are credible. -- `CredentialResolutionEvidence` requires an existing passed gateway check. If implementation tries to use it for install custody, it will invert the state machine. -- Store/object registry/public aggregation paths were not in the allowed packet. A new protocol object type will likely require updates there before tests compile. -- D1 migration/index requirements are unknown from this packet. If custody proof needs first-class lookup by credential ref, gateway, tenant/org, or contract, storage indexes may be needed. -- Existing `sourceAuthorityCanSatisfyGatewayChecked` accepts `gateway_probe` and `hosted_monitor`. A custody proof packet must not backdoor `conformance_fixture` or `operator_attestation` into live customer-owned custody. -- x402 fixture tests currently distinguish `fixture_gateway_held` from real gateway-held posture. Preserve that distinction or claim guards will regress. - -## Architecture validation gates - -Protocol/schema gates: - -- Custody proof packet schema rejects raw private keys, bearer tokens, API keys, `PaymentPayload`, `PAYMENT-SIGNATURE`, raw signer refs, secret URIs, and provider secret paths. -- Custody proof packet digest changes when gateway install evidence, credential ref digest, resolver version, lease/version, attestation digest, redacted audit digest, or drift status changes. -- `GatewayCredentialRef` binds to the custody proof packet by ID/digest or refuses when a required proof packet is missing. -- `ProtectedPathPosture` digest includes custody proof packet ID/digest and all required bypass probe digests. -- Policy refuses missing custody packet, stale packet, provider drift, resolver drift, unsafe custody status, weak source authority, and redaction failure before greenlight. -- Gateway check refuses when custody proof or protected-path posture drifts after greenlight and before mutation. - -Adapter gates: - -- x402 install refuses `agent_exposed` signer custody and fixture-only posture for customer-owned custody claims. -- x402 gateway never calls the signer on params mismatch, replay, stale custody proof, missing custody proof, unsafe custody proof, provider drift, or raw sibling posture. -- x402 official SDK PaymentPayload / `PAYMENT-SIGNATURE` evidence remains post-gate, redacted, and local/reference unless official provider/customer custody verification is added later. -- auth.md gateway continues to record credential resolution after passed gate only and quarantines credential refs on revocation/lifecycle drift. - -Projection/redaction gates: - -- Contract/evidence projections expose custody proof refs and digests, not raw proof payloads or secret coordinates. -- Agent transaction envelope distinguishes gateway check evidence, custody proof evidence, credential resolution evidence, mutation evidence, downstream reconciliation, refusal, and proof gap. -- Redaction failure produces refusal or proof gap; it never serializes raw custody material. - -Architecture/claim gates: - -- Claim guards reject live provider/customer custody claims from fixture keys. -- Claim guards keep x402 as per-call exact protected action, not payment management or provider custody. -- Import posture keeps custody proof protocol meaning out of adapters, runtime, MCP, CLI, SDK, and projections. -- Root exports do not expose secret resolution, signer, wallet, or raw custody internals. - -Closeout command candidates: - -- `npm run test -- test/protocol/credential-custody.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts` -- `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts test/adapters/auth-md-gateway-pressure.test.ts test/adapters/auth-md-serialization-redaction.test.ts` -- `npm run test -- test/conformance/x402-payment-conformance.test.ts` -- `npm run test -- test/architecture/claim-boundary.test.ts test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts` -- `npm run quality:claims` -- `npm run quality:architecture` -- `npm run check:repo` - -## Assumptions - -- Tier 1 protocol meaning remains stable: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap. -- Customer-owned gateway custody is the enforcement model. Handshake does not hold wallets, signer credentials, balances, settlement state, or payment credentials. -- x402 is the first proof pack, not the protocol definition. -- Provider-neutral schema planning can proceed from repo source. Named vault/KMS/wallet/provider behavior requires official source verification before implementation. -- A custody proof packet can be added without requiring hosted operation. -- Existing object registry/store/public aggregation can accept a new object type, but this was not verified because those files were outside the packet. - -## Dependencies - -- Claim-boundary cleanup must land first or in parallel only if this plan keeps its non-claim language intact. -- The implementation needs a source-owned object-type route for custody proof packet records. -- Policy and gateway checks depend on current store lookup for credential refs, protected-path posture, isolation, and potentially custody proof packet records. -- x402 adapter changes depend on the install compiler being able to emit or sequence gateway credential refs and custody proof packets. -- Redacted projections depend on schema additions in evidence projection types not included in this packet. -- Provider-specific custody implementation depends on later official documentation/source verification for any named vault, KMS, wallet provider, x402 provider, JWKS, Cloudflare, or regulatory claim. - -## Risks - -- The proof packet becomes a decorative certificate. Mitigation: policy and gateway refuse when the packet is missing, stale, drifted, unsafe, or not bound to the exact credential ref/posture. -- The packet duplicates `GatewayCredentialRef` without adding enforcement. Mitigation: keep the credential ref as the opaque handle and make the packet prove install/custody/drift state for that handle. -- x402 signer fixture gets relabeled as customer-owned custody. Mitigation: claim guards and x402 bypass tests must distinguish `fixture_gateway_held` from customer/provider custody. -- Provider secret paths leak through "opaque" fields. Mitigation: safe-string schema, allowlisted projection fields, serialized redaction tests, and redaction-failure refusal/proof gap. -- Gateway check only records protected-path posture digest, hiding custody proof drift. Mitigation: either add custody proof seen fields to `GatewayCheckAttempt` or test that posture digest changes deterministically include proof packet drift. -- Runtime/MCP/CLI adoption pressure moves custody setup into model-facing surfaces. Mitigation: keep runtime/MCP/CLI as proposal/evidence/read only and enforce with import/surface tests. -- New schema required fields break older local demos before migration. Mitigation: additive fields first, then enforce only when `requiredProtectedPathState` is `gateway_checked` for custody-requiring action classes. -- External provider docs are inferred instead of verified. Mitigation: mark all named provider details as blocked until official verification. - -## Cut lines - -Cut from this slice: - -- Handshake-held wallet, signer, token, bearer credential, payment credential, balance, settlement, or payment-management state. -- Aggregate x402 session/day/review spend enforcement. -- Facilitator operation, seller middleware, settlement finality, or broad x402 compatibility. -- Hosted operation, production RBAC, tenant audit/search, live JWKS, revocation service, marketplace, certification, or clearing-house claims. -- Broad MCP/browser/shell/network/package-manager interception. -- Provider-specific vault/KMS/wallet architecture before official source verification. -- Any runtime, MCP, CLI, SDK, or review-renderer authority path. -- Raw proof packet read APIs that expose internal custody payloads. - -Split if the implementation needs: - -- D1 migration and hosted evidence indexing beyond local proof storage. -- New provider SDK integration. -- New public package exports. -- A provider-specific gateway adapter. -- Hosted admission or verifier trust plane work. - -## Blocked checks - -- Did not read sibling raw outputs, normalized outputs, or the final `PLAN.md` for this run by instruction. -- Did not read files outside the immutable packet's allowed source list. -- Did not inspect `src/protocol/areas/object-registry/*`, `src/protocol/public/*`, `src/protocol/kernel.ts`, `src/protocol/store/port.ts`, `src/storage/*`, `src/http/*`, `package.json`, or migrations because they were not in the allowed packet. Those paths must be verified before implementation. -- Did not inspect `src/protocol/areas/action-contract/*` directly because it was not in the allowed packet. Contract binding recommendations are inferred from canonical docs, projection code, and policy/gateway transition use. -- Did not inspect projection schema definitions because only projection assembly/logic files were allowed. Projection field additions must verify schema owners before execution. -- Did not run tests. This was a planning-only first pass constrained to reading the packet and allowed source files. -- Did not browse official provider, vault, KMS, wallet, x402, Cloudflare, JWKS, npm, MCP Registry, legal, or payment-regulatory sources. Any named provider custody implementation must be officially verified later. - -## Smallest next mechanism to build - -Define the custody proof packet schema under `src/protocol/areas/credential-custody/`, add one failing protocol test that refuses policy greenlight when `requiredProtectedPathState: "gateway_checked"` has a credential ref and posture but no custody proof packet digest, then bind that digest into protected-path posture before touching x402. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/EXECUTION.md deleted file mode 100644 index 03a7ed5..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/EXECUTION.md +++ /dev/null @@ -1,522 +0,0 @@ -# Execution First Pass: Customer-Owned Gateway Custody Proof - -## Invariant at stake - -A protected path is real only when the mutation credential is behind a customer/provider gateway, the exact one-use greenlight is checked immediately before consequence, stale or unsafe custody refuses before mutation, and the surviving evidence is redacted but reconstructable. - -Current source already has strong pieces: - -- `GatewayCredentialRef` and `CredentialResolutionEvidence` in `src/protocol/areas/credential-custody/*`. -- Probe-backed `ProtectedPathPosture` in `src/protocol/areas/protected-path-posture/*`. -- Policy and gateway re-checks for protected-path posture and gateway credential bindings in `src/protocol/areas/policy-greenlight/transitions.ts` and `src/protocol/areas/gateway-gate/transitions.ts`. -- x402 wallet gateway signing only after `VerifiedGatewayCheck` in `src/adapters/x402-payment/wallet-gateway.ts`. -- auth.md reference gateway recording `CredentialResolutionEvidence` after a passed gate and before downstream service execution in `src/adapters/auth-md/gateway.ts`. - -The execution gap is not "add a gateway check." The gap is a source-owned custody proof packet that binds install evidence, credential refs, protected-path posture, custody/bypass probes, policy/gateway evaluation, and redacted projections into one digest-bearing evidence object. Without that packet, x402 signer custody can remain profile metadata plus adapter evidence, which is too easy to overclaim as customer-owned gateway custody. - -## Recommended phase sequence - -### Phase 0 - Implementation source map verification - -Before any code change, the executor must inspect companion files not included in this first-pass source packet but required for a real implementation: - -- `src/protocol/kernel.ts` -- `src/protocol/areas/credential-custody/index.ts` -- `src/protocol/areas/credential-custody/types.ts` -- `src/protocol/areas/object-registry/*` -- `src/protocol/public/schemas.ts` -- `src/protocol/public/inputs.ts` -- `src/protocol/evidence-projections/schemas.ts` -- `test/support/fixtures.ts` -- `test/support/auth-md-flow.ts` -- x402/auth.md adapter index/export files - -Closeout: confirm exact edit set before touching source. If these files show a different public aggregation pattern than expected, update the plan before implementation. - -### Phase 1 - Test-first custody packet failures - -Add failing tests before adding implementation. - -Primary tests: - -- `test/protocol/credential-custody.test.ts` - - rejects raw credential material in custody proof packet fields; - - creates a custody proof packet only when it binds a stored `GatewayCredentialRef` and a current `ProtectedPathPosture`; - - proves the packet digest includes credential ref digest, protected-path posture digest, bypass probe digests, provider-neutral key handle/lease/resolver/attestation refs, drift status, and expiry; - - refuses stale credential ref, provider drift, resolver failure, unsafe custody, missing packet, digest mismatch, redaction failure, and agent-exposed signer. -- `test/protocol/kernel-policy-gateway.test.ts` - - policy refuses when a contract requiring gateway custody lacks a valid custody proof packet; - - policy greenlights only when current posture, credential ref, and packet all agree; - - gateway refuses if the packet drifts or expires after greenlight but before gateway check; - - gateway does not consume the greenlight when custody refusal happens before mutation. -- `test/protocol/evidence-projections.test.ts` - - transaction envelope and contract projection expose custody packet refs/digests/status only; - - projections omit key handles that look like secret paths, signer material, payment payloads, bearer tokens, provider secret paths, and mutation credentials. - -Adapter tests: - -- `test/adapters/x402-install-proposal.test.ts` - - x402 install emits a gateway credential ref intent and custody packet expectation, not a Handshake-held wallet. - - fixture custody remains explicitly local/reference and cannot become live provider/customer custody. -- `test/adapters/x402-payment-action-proposal.test.ts` - - x402 candidate binds the signer credential ref and custody proof packet digest. - - x402 proposal refuses when signer custody is agent-exposed or packet binding is missing. -- `test/adapters/x402-wallet-gateway.test.ts` - - no signer call when custody packet is missing/stale/drifted/unsafe; - - signer call still happens only after `VerifiedGatewayCheck`; - - credential resolution/use evidence is recorded as redacted custody evidence for the exact contract and gate. -- `test/adapters/auth-md-gateway-pressure.test.ts` - - preserve auth.md drift/revocation behavior while adding packet binding. - -Architecture/claim tests: - -- `test/architecture/claim-boundary.test.ts` - - docs cannot claim provider/customer custody from fixture keys; - - docs cannot claim Handshake-held wallets, balances, settlement, payment management, or live provider custody. - -### Phase 2 - Add the protocol custody proof packet primitive - -Recommendation: add a narrow packet object under `src/protocol/areas/credential-custody/`, not a new authority lane. - -Do not replace `GatewayCredentialRef`, `CredentialResolutionEvidence`, or `ProtectedPathPosture`. Add a packet that binds them. - -Candidate object name: - -```text -GatewayCustodyProofPacket -``` - -Minimum schema shape: - -```text -gatewayCustodyProofPacketId -gatewayCustodyProofPacketDigest -gatewayCredentialRefId -gatewayCredentialRefDigest -protectedPathPostureId -protectedPathPostureDigest -bypassProbeIds -bypassProbeDigests -gatewayInstallEvidenceRefs -custodyProviderClass -custodyProviderRef -custodyProviderDigest -keyHandleRef -keyHandleDigest -leaseRef -leaseVersion -leaseExpiresAt -resolverRef -resolverVersion -resolverDigest -attestationRefs -attestationDigests -redactedAuditRefs -custodyStatus -custodyDriftStatus -resolverDriftStatus -redactionStatus -externalVerificationStatus -redactionProfileRef -secretMaterialIncluded: false -issuedAt -expiresAt -``` - -Field rules: - -- `custodyProviderClass`, `custodyProviderRef`, `keyHandleRef`, `leaseRef`, `resolverRef`, `attestationRefs`, and `redactedAuditRefs` are opaque refs, not provider-specific vault/KMS APIs. -- The schema must reject raw credential material and obvious secret paths using the same posture as existing credential custody redaction. -- `externalVerificationStatus` should allow provider-neutral local planning without implying official provider verification. Any named vault/KMS/wallet/provider implementation remains blocked until official source verification. -- `fixture_gateway_held` can support local/reference evidence only; it must not project as live customer/provider custody. - -Transition: - -```text -recordGatewayCustodyProofPacket(input) -``` - -Transition checks: - -- loads the credential ref by ID; -- loads current protected-path posture by ID or scope; -- verifies tenant/org/gateway/protected surface/action/resource agreement; -- verifies posture is fresh, `gateway_checked`, and probe-backed; -- verifies required bypass probe kinds are present and passed; -- verifies credential custody can satisfy gateway-checked posture; -- canonicalizes packet digest after all loaded refs are known; -- commits packet record and event; -- never retrieves or stores secret material; -- never creates permission, greenlight, mutation proof, wallet custody, settlement, or payment state. - -### Phase 3 - Bind the packet into contract, policy, and gateway evaluation - -Extend the existing `GatewayCredentialBinding` path instead of creating a parallel policy path. - -Candidate binding additions: - -```text -custodyProofPacketId -custodyProofPacketDigest -requiredCustodyDriftStatus -requiredResolverDriftStatus -``` - -Policy/gateway execution changes: - -- `evaluateGatewayCredentialBindings()` loads both the credential ref and packet. -- Policy input includes credential ref posture plus packet posture, freshness, drift, redaction status, and packet digest. -- Policy refuses before greenlight for missing packet, digest mismatch, stale packet, packet/ref scope mismatch, unsafe custody status, provider drift, resolver drift, weak posture, failed probes, or redaction failure. -- Gateway re-runs the same evaluation immediately before mutation and refuses without consuming the greenlight when custody drift blocks pre-mutation admission. -- Gateway check artifacts should record packet refs/digests seen, either directly on `GatewayCheckAttempt` if schema ownership supports it or through evidence refs on receipt/projection if the schema change is too wide. - -Do not change the Tier 1 authority rule. The packet strengthens evidence required for `gateway_checked` custody. It does not authorize mutation by itself. - -### Phase 4 - Make x402 use credential-ref custody proof - -x402 is the critical adapter because current install/profile code carries signer posture in `X402WalletGatewayProfile` and gateway registry metadata, while the candidate contract currently uses `secretRefs: {}` and does not bind a generic `GatewayCredentialRef`. - -Implementation direction: - -- `src/adapters/x402-payment/install-proposal.ts` - - derive a provider-neutral gateway credential ref for the wallet signer/payment credential; - - keep signer refs opaque and redacted; - - mark fixture custody as fixture/local only; - - add packet expectation refs to install output and human summary without claiming live provider custody; - - preserve per-call x402 exact scope and no aggregate payment-budget management. -- `src/adapters/x402-payment/action-proposal.ts` - - add credential ref and custody packet binding to the candidate `gatewayCredentialRefs`; - - include packet digest in candidate/contract digest path through the existing binding; - - refuse if x402 attempt cannot bind a valid packet for the installed gateway. -- `src/adapters/x402-payment/wallet-gateway.ts` - - continue calling `gatewayCheck()` before signer invocation; - - after `VerifiedGatewayCheck`, record redacted credential resolution/use evidence for the signer credential ref and custody packet; - - do not call the official signer when packet/ref/posture/gateway check refuses; - - do not expose `PaymentPayload`, `PAYMENT-SIGNATURE`, private keys, payment credentials, or provider secret paths in packet, resolution evidence, reconciliation evidence, or projections. -- `src/adapters/x402-payment/bypass-probes.ts` and `src/adapters/x402-payment/conformance.ts` - - keep hostile probe posture as packet inputs; - - distinguish `gateway_held` from `fixture_gateway_held`; - - require external verification before any named live provider custody implementation. - -x402 must remain the first wedge, not the protocol definition. The implementation must not add balances, settlement state, payment management, facilitator operation, seller middleware, or Handshake-held wallet concepts. - -### Phase 5 - Apply auth.md learnings without turning Handshake into auth - -auth.md already has the right execution posture: - -- gateway check first; -- no downstream execution if gate/ref/metadata/scope drift refuses; -- `CredentialResolutionEvidence` after passed gate; -- revocation/lifecycle evidence maps to credential-ref isolation; -- redaction assertions block bearer material. - -Implementation direction: - -- bind auth.md protected API call candidates to the same custody proof packet shape; -- keep auth.md discovery, registration, claim, identity, and revocation as provenance/evidence only; -- packet drift or revocation-driven isolation must block both policy and gateway checks; -- do not introduce auth provider, OAuth server, WorkOS alternative, or generic API gateway claims. - -### Phase 6 - Redacted custody projections - -Add a buyer-readable custody projection without exposing secret-bearing material. - -Candidate projection fields: - -```text -custodyProofPacketRef -custodyProofPacketDigest -gatewayCredentialRef -gatewayCredentialRefDigest -protectedPathPostureRef -protectedPathPostureDigest -custodyProviderClass -custodyProviderRef -keyHandleDigest -leaseVersion -leaseFreshness -resolverVersion -custodyDriftStatus -resolverDriftStatus -redactedAuditRefs -attestationRefs -externalVerificationStatus -secretMaterialIncluded: false -redactionProfileRef -omittedFields -``` - -Candidate source paths: - -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/evidence-projections/assembly.ts` -- `src/protocol/evidence-projections/schemas.ts` (not read in this first pass; implementation must verify) - -Projection tests must assert absence of: - -- secret paths; -- signer material; -- raw private keys; -- `PaymentPayload`; -- `PAYMENT-SIGNATURE`; -- bearer tokens; -- mutation credentials; -- provider-specific secret locator strings. - -### Phase 7 - Canon and claim guards - -Docs should change only after source/tests define the packet. - -Candidate docs: - -- `README.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-notes.md` -- `docs/internal/protocol-layman.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` only as scratch alignment - -Required wording: - -- protected path is installed only when a gateway owns or controls the mutation credential, custody packet evidence is current, the exact greenlight is checked before mutation, and drift/unsafe custody refuses; -- fixture custody is local/reference only; -- x402 uses the custody proof as one protected-action pack and does not define the protocol; -- Handshake does not hold wallets, payment credentials, balances, settlement state, payment management, provider custody, or auth-provider custody; -- named vault/KMS/provider custody implementations require official source verification before implementation. - -## Task graph - -| Task | Owner lane | Depends on | Candidate paths | Closeout evidence | -| --- | --- | --- | --- | --- | -| T0 source map verification | Executor | input packet | kernel, object registry, public aggregators, projection schemas, fixtures | confirmed exact edit map | -| T1 failing protocol tests | Protocol tests | T0 | `test/protocol/credential-custody.test.ts`, `test/protocol/kernel-policy-gateway.test.ts` | focused tests fail for missing packet | -| T2 packet schema/input | Protocol | T1 | `src/protocol/areas/credential-custody/schemas.ts`, `inputs.ts` | schema rejects secret material and unsafe field shape | -| T3 packet transition/registry | Protocol | T2 | `src/protocol/areas/credential-custody/transitions.ts`, companion public/kernel/object-registry files | packet record/event commits and binds ref/posture/probes | -| T4 policy/gateway binding | Protocol | T3 | `credential-custody/transitions.ts`, `policy-greenlight/transitions.ts`, `gateway-gate/transitions.ts`, `gateway-gate/artifacts.ts` | policy/gateway refuse missing/stale/drifted/unsafe packet | -| T5 x402 install/proposal/gateway | Adapter | T4 | `src/adapters/x402-payment/install-proposal.ts`, `action-proposal.ts`, `wallet-gateway.ts`, `bypass-probes.ts`, `conformance.ts` | no signer call without valid packet; no wallet/payment-management claim | -| T6 auth.md parity | Adapter | T4 | `src/adapters/auth-md/gateway.ts`, `profiles.ts`, `revocation.ts`, `bypass-probes.ts` | packet drift/revocation blocks credential resolution and downstream call | -| T7 projections | Protocol projections | T4 | `src/protocol/evidence-projections/projections.ts`, `assembly.ts`, schemas companion | redacted custody projection includes refs/digests/status only | -| T8 docs and claim guards | Docs/architecture tests | T5, T7 | canonical docs, `test/architecture/claim-boundary.test.ts` | fixture/live custody and payment-management claims fail if reintroduced | -| T9 closeout gates | Executor | T1-T8 | package scripts | focused gates and `npm run check:repo` pass | - -## Dependency map - -```text -T0 - -> T1 - -> T2 - -> T3 - -> T4 - -> T5 - -> T6 - -> T7 - -> T8 - -> T9 -``` - -Hard dependency: x402/auth.md adapter work should not begin until the packet schema and binding semantics are stable. Otherwise each adapter will invent its own custody proof shape and the protocol will lose the customer-owned gateway custody primitive. - -## Critical path - -```text -failing protocol tests --> packet schema/input --> packet transition and digest --> extend GatewayCredentialBinding evaluation --> x402 binds signer credential ref and packet --> gateway refuses stale/drifted/unsafe packet before signer --> projection redacts custody evidence --> claim guards prevent fixture/live custody overclaim --> focused tests and check:repo -``` - -The riskiest segment is `GatewayCredentialBinding` extension. It sits in candidate/contract digest, policy input, and gateway evaluation. If it is added as optional metadata instead of required evidence for gateway-custody actions, the packet becomes advisory. - -## What can run in parallel - -After T2 field names are stable: - -- Protocol projection tests and architecture claim guards can be drafted in parallel. -- x402 and auth.md adapter test cases can be drafted in parallel, as long as they use the same packet binding shape. -- Docs wording can be prepared in parallel but should not land before source/tests prove packet behavior. -- Redaction fuzz cases can be added in parallel with adapter integration. - -Do not parallelize by giving x402 a local custody shape and auth.md a separate shape. That creates two adapter-specific evidence stories and no protocol primitive. - -## First executable step - -Implementation turn first step: - -```text -Inspect required companion files from Phase 0, then add the first failing tests in -test/protocol/credential-custody.test.ts for: -1. GatewayCustodyProofPacket schema redaction. -2. Packet digest binding to GatewayCredentialRef + ProtectedPathPosture + bypass probe digests. -3. Policy refusal when an otherwise valid contract lacks the packet binding. -``` - -Only after those tests fail for the expected reason should source implementation begin. - -## Source/test/doc candidate paths - -Protocol source candidates: - -- `src/protocol/areas/credential-custody/schemas.ts` -- `src/protocol/areas/credential-custody/inputs.ts` -- `src/protocol/areas/credential-custody/custody-posture.ts` -- `src/protocol/areas/credential-custody/transitions.ts` -- `src/protocol/areas/protected-path-posture/schemas.ts` -- `src/protocol/areas/protected-path-posture/inputs.ts` -- `src/protocol/areas/protected-path-posture/transitions.ts` -- `src/protocol/areas/policy-greenlight/transitions.ts` -- `src/protocol/areas/gateway-gate/schemas.ts` -- `src/protocol/areas/gateway-gate/inputs.ts` -- `src/protocol/areas/gateway-gate/artifacts.ts` -- `src/protocol/areas/gateway-gate/transitions.ts` -- `src/protocol/evidence-projections/projections.ts` -- `src/protocol/evidence-projections/assembly.ts` - -Likely implementation companion paths not read in this first pass: - -- `src/protocol/kernel.ts` -- `src/protocol/areas/credential-custody/index.ts` -- `src/protocol/areas/credential-custody/types.ts` -- `src/protocol/areas/object-registry/*` -- `src/protocol/public/schemas.ts` -- `src/protocol/public/inputs.ts` -- `src/protocol/evidence-projections/schemas.ts` -- `src/storage/d1/*` and migrations if the new object needs durable indexed storage -- `test/support/fixtures.ts` -- `test/support/auth-md-flow.ts` - -Adapter source candidates: - -- `src/adapters/x402-payment/install-proposal.ts` -- `src/adapters/x402-payment/action-proposal.ts` -- `src/adapters/x402-payment/wallet-gateway.ts` -- `src/adapters/x402-payment/bypass-probes.ts` -- `src/adapters/x402-payment/conformance.ts` -- `src/adapters/auth-md/profiles.ts` -- `src/adapters/auth-md/gateway.ts` -- `src/adapters/auth-md/revocation.ts` -- `src/adapters/auth-md/bypass-probes.ts` -- `src/adapters/protected-path-probes/index.ts` -- `src/adapters/protected-path-probes/executor.ts` - -Test candidates: - -- `test/protocol/credential-custody.test.ts` -- `test/protocol/evidence-projections.test.ts` -- `test/protocol/kernel-policy-gateway.test.ts` -- `test/adapters/x402-install-proposal.test.ts` -- `test/adapters/x402-payment-action-proposal.test.ts` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/adapters/x402-bypass-probes.test.ts` -- `test/conformance/x402-payment-conformance.test.ts` -- `test/adapters/auth-md-gateway-pressure.test.ts` -- `test/adapters/auth-md-serialization-redaction.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` - -Doc candidates: - -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` only if source ownership changes -- `docs/internal/decisions.md` -- `docs/internal/protocol-definition.md` -- `docs/internal/protocol-kernel-architecture.md` -- `docs/internal/protocol-layman.md` -- `docs/internal/protocol-notes.md` -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` only as scratch alignment - -## Validation gates - -Focused gates: - -```bash -npm run test -- test/protocol/credential-custody.test.ts test/protocol/kernel-policy-gateway.test.ts -npm run test -- test/protocol/evidence-projections.test.ts -npm run test -- test/adapters/x402-install-proposal.test.ts test/adapters/x402-payment-action-proposal.test.ts test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts -npm run test -- test/conformance/x402-payment-conformance.test.ts -npm run test -- test/adapters/auth-md-gateway-pressure.test.ts test/adapters/auth-md-serialization-redaction.test.ts -npm run quality:claims -npm run quality:architecture -``` - -Full closeout: - -```bash -npm run check:types -npm run lint -npm run format:check -npm run test -npm run pack:check -git diff --check -npm run check:repo -``` - -Required behavioral evidence: - -- Missing custody packet refuses before greenlight. -- Stale custody packet refuses before greenlight and before gateway mutation. -- Packet drift after greenlight refuses at gateway and does not call signer/downstream surface. -- Agent-exposed signer refuses during install/proposal/posture/policy path. -- Raw sibling bypass posture fails protected path posture and prevents greenlight. -- Credential resolution evidence is recorded only after a passed gateway check. -- Redacted projections never expose signer material, payment payloads, bearer tokens, mutation credentials, or provider secret paths. -- Fixture custody cannot project as live provider/customer custody. - -## Cut lines - -Keep out of this implementation slice: - -- Handshake-held wallets or payment credentials. -- Balance tracking, settlement, payment management, facilitator operation, seller middleware, spend-window ledger enforcement, or aggregate payment budgets. -- Live provider/customer custody claims from fixture keys. -- Provider-specific vault/KMS architecture unless official source verification is performed in a later implementation pass. -- Hosted operation, hosted verifier, live JWKS/revocation, cross-org trust, marketplace, certification, or clearing-house claims. -- Broad MCP/browser/shell/network/package-manager interception claims. -- New dashboard/review UX unless it renders exact packet refs and cannot authorize anything. -- A second adapter-specific custody proof shape. - -## Assumptions - -- The implementation may add a new credential-custody protocol object without changing Tier 1 authority semantics. -- Existing `GatewayCredentialRef` remains the opaque credential reference; the packet binds install/posture/probe evidence around it. -- Existing policy and gateway evaluation should remain the enforcement points. -- x402 must migrate from signer-profile metadata toward generic credential-ref/packet binding for custody claims. -- auth.md remains a reference protected API call profile and should inform lifecycle/isolation/redaction patterns only. -- `.planning/` is scratch and should not become source/package/public API naming. - -## Risks - -- Optional packet risk: if packet binding is optional on candidates, x402 can keep running on signer metadata while docs claim custody proof. This is advisory, not Handshake. -- Digest drift risk: if packet digest is not included in candidate/contract/policy/gateway inputs, a stale packet can be swapped after review. -- Gateway consumption risk: if custody refusal consumes the greenlight, safe retry/recovery semantics get muddied. Pre-mutation custody refusal should not become mutation evidence. -- Fixture overclaim risk: `fixture_gateway_held` can pass local tests but must not support live provider/customer custody language. -- Redaction pattern risk: current redaction relies partly on pattern detection. Unknown provider refs can evade it. Prefer allowlisted projection fields and digest-only provider material. -- x402 scope creep risk: custody proof can invite wallet/payment-management fields. Keep the packet provider-neutral and action-bound. -- Migration blast radius: public schemas, object registry, kernel facade, storage, and projections may all need updates. Do not hide those changes inside adapter-only work. - -## Antipatterns - -- Adding `custodyProof: true` to install output without a protocol object and digest. -- Treating wallet gateway profile metadata as customer-owned custody proof. -- Recording credential resolution evidence before a passed gateway check. -- Letting x402 call the signer after a failed packet/ref/posture check. -- Storing provider secret paths, raw signer refs, payment payloads, bearer tokens, or private keys in packet fields. -- Creating x402-specific custody proof that auth.md cannot reuse. -- Calling fixture custody "provider custody" or "customer custody." -- Using docs to claim live custody before source-owned packet, negative tests, and redacted projections exist. -- Browsing or adding named provider architecture during implementation without official source verification. - -## Blocked checks - -- Did not read sibling raw outputs, normalized outputs, or final `PLAN.md` for this run. -- Did not browse or verify any named vault/KMS/wallet/x402/provider documentation; any provider-specific custody implementation remains blocked on official source verification. -- Did not inspect companion implementation files outside the input packet, including kernel facade, object registry, public aggregators, projection schemas, storage migrations, and fixture helpers. -- Did not run tests because this is a planning-only first pass and source was not modified. -- Did not verify whether D1 storage needs a migration/index for the new packet object; implementation must check object registry/store behavior before coding. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/RISK.md deleted file mode 100644 index ae0fc8e..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/RISK.md +++ /dev/null @@ -1,142 +0,0 @@ -# RISK First Pass: Customer-Owned Gateway Custody Proof - -## Invariant At Stake - -A path is protected only when the customer/provider gateway owns the mutation credential, the exact one-use greenlight is checked immediately before consequence, unsafe or drifted custody refuses before mutation, and surviving evidence is redacted but reconstructable. Anything weaker is advisory, not Handshake. - -## Current Risk Read - -The current source already has useful enforcement primitives: `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, required bypass probe coverage, policy-time and gateway-time posture checks, one-use greenlight replay refusal, gateway policy drift refusal, credential-ref isolation, and redacted evidence projections. - -The risk is not "can the repo name custody." The risk is that a custody proof packet becomes claim material without becoming a policy and gateway constraint. If the packet is just projection text, install metadata, or adapter evidence not bound into the exact contract, greenlight, gateway check, and receipt chain, it will overstate customer-owned custody. - -## Recommended Risk Shape - -Extend existing primitives first, and add a distinct custody proof packet only if the existing `GatewayCredentialRef` plus `CredentialResolutionEvidence` shape cannot carry install evidence, provider-neutral resolver/lease/drift fields, and redacted projection requirements without overloading their meaning. - -Minimum safe chain: - -```text -gateway install evidence --> gateway credential ref binding --> protected-path posture with required gateway-owned bypass probes --> custody proof packet digest --> action contract and policy input include the packet/ref digest --> gateway check re-reads packet/ref/posture before mutation --> credential resolution evidence records post-gate use only --> redacted custody projection exposes refs/digests/status, never secret material -``` - -Cut line: do not claim live customer/provider custody until source-owned packet schema, policy/gateway refusals, negative tests, redacted projection tests, and claim guards all exist. - -## P0 Risk Register - -| Risk | Failure Mode | Mitigation Or Cut Line | -| --- | --- | --- | -| P0: Custody proof becomes receipt/projection theatre | The packet is emitted after the fact or rendered in projections, but policy and gateway do not require it before signer/credential use. | The custody packet/ref digest must be included in contract canonicalization, policy input digest, greenlight binding, gateway check evaluation, and receipt/projection evidence refs. If any of those bindings are not implemented, cut custody claims to "advisory evidence only." | -| P0: Gateway check does not verify current custody immediately before mutation | A greenlight issued against fresh custody is used after credential ref, provider registry, resolver version, lease, or protected-path posture drifts. | Gateway check must re-read current `GatewayCredentialRef`, protected-path posture, isolation state, gateway registry policy version, and custody packet drift status. Missing, stale, unsafe, drifted, or isolated custody refuses with no `MutationAttempt`. | -| P0: Agent-exposed signer path remains reachable | x402 or auth-style adapters have a direct SDK signer, private key env, raw signature header, bearer passthrough, MCP/browser/network sibling, or retry loop available outside the gateway. | Required bypass probe kinds must pass from `gateway_probe` or stronger source authority before `gateway_checked` posture. Raw sibling status `present` or `unknown` must refuse. Synthetic/conformance-only probes must not establish live custody. | -| P0: Redacted custody projection leaks secrets | Projection evidence refs or provider refs expose `PaymentPayload`, `PAYMENT-SIGNATURE`, private key paths, vault secret paths, bearer tokens, auth.md credentials, PII, or payment-sensitive payloads. | Use typed redaction schemas plus denylist/fuzz tests. Prefer allowlisted projection ref prefixes for live providers. `redaction_failed` must become refusal or proof gap, not an emitted projection. | -| P0: Payment custody / regulatory claim drift | The plan accidentally introduces Handshake-held wallets, balances, signer custody, settlement state, payment management, or facilitator/seller operation. | Explicit non-goal in plan and claim guards. x402 remains one buyer-side exact per-call protected action. No Handshake-held payment credential, no spend ledger claim, no settlement/facilitator/customer custody claim without later official-source verification and source-owned implementation. | - -## P1 Risk Register - -| Risk | Failure Mode | Mitigation Or Cut Line | -| --- | --- | --- | -| P1: Custody proof overfits x402 | Schema names payment payloads, wallet providers, or x402-specific surfaces and pollutes protocol meaning. | Keep provider-neutral fields: custody provider class, key/credential handle ref, lease/version, resolver ref/version, provider registry ref/digest, attestation refs, redacted audit refs, drift status, redaction profile. x402 maps into the packet as an adapter profile only. | -| P1: Fixture custody is mistaken for customer-owned custody | Local fixture keys and `fixture_gateway_held` posture pass tests and docs later imply provider/customer custody. | Claim guards must distinguish `fixture_gateway_held` from customer/provider gateway custody. Projection should expose fixture/reference posture as local evidence only. Live-custody language stays blocked until non-fixture provider/customer gateway evidence exists. | -| P1: Provider registry digest comparison is too permissive | Current binding only refuses digest mismatch when both binding and stored ref have non-null digests; a null digest path can allow weak drift detection. | For custody proof packets, require digest presence when provider registry or resolver posture matters. If digest is absent, status must be `proof_gap` or `unsafe`, not `gateway_checked`. | -| P1: Lease/version semantics are underspecified | A custody ref has `issuedAt`/`expiresAt`, but no explicit provider lease, resolver lease, rotation epoch, or attestation freshness semantics. | Packet should carry `custodyLeaseRef`, `custodyLeaseVersion`, `resolverVersion`, `attestationRefs`, `observedAt`, `expiresAt`, and `driftStatus`. Stale/unknown lease refuses before greenlight and gateway check. | -| P1: Resolver failure becomes downstream uncertainty | Gateway cannot resolve a credential, but the system records a proof gap after a mutation attempt or treats failure as pending downstream status. | Resolver failure must happen before protected mutation. It should produce gateway refusal or credential-resolution refusal evidence with `mutationAttempted: false`, unless there is explicit evidence the mutation already started. | -| P1: Auth.md lifecycle learning is imported as identity-provider scope | Revocation, claim, JWT, or metadata evidence turns Handshake into an auth provider or OAuth server. | Import only the custody/ref lifecycle pattern: credential-ref isolation, metadata/provider digest drift, redacted revocation evidence, and future policy/gateway blocking. Cut identity-provider claims. | -| P1: Projection redaction remains pattern-only | Unknown provider credential formats bypass regex redaction. | Add provider-format fuzz tests and allowlist projected custody fields. Unknown provider refs should project as opaque digest/status, not raw URI/path, until provider docs are verified. | -| P1: Review artifact laundering | A review surface displays "gateway owned" while the underlying contract/custody packet has weaker or stale status. | Review renderer must bind to exact contract digest, policy input digest, custody proof digest, and rendered uncertainty digest. Missing binding is review theatre. | -| P1: Runtime/MCP proposal surfaces imply enforcement | MCP/runtime proposals include custody metadata and users infer mutation protection, even though those surfaces cannot gate signer use. | Runtime/MCP can propose and read evidence only. They must not create custody proof packets, policy decisions, greenlights, gateway checks, receipts, or credential resolution evidence. | - -## P2 Risk Register - -| Risk | Failure Mode | Mitigation Or Cut Line | -| --- | --- | --- | -| P2: New primitive creates duplicate custody state | A new packet duplicates `GatewayCredentialRef`, `CredentialResolutionEvidence`, and `ProtectedPathPosture` without clear ownership. | Decide ownership up front. Either extend existing records or define a packet that references them by digest and owns only install/custody proof aggregation. No parallel secret or permission model. | -| P2: Plan expands into hosted/provider architecture | Custody proof planning drifts into Cloudflare, KMS, wallet provider, JWKS, registry, legal, or payment-regulatory implementation details. | Mark all named provider/KMS/wallet/legal/payment details as requiring official-source verification before implementation. Provider-neutral schema can proceed now. | -| P2: Operational ceremony blocks adoption | Integrators must manually sequence install evidence, credential ref, probes, posture, policy, gateway, credential resolution, and projections. | Future implementation can add activation helpers, but helpers must only sequence existing source-owned transitions. They must not move authority into runtime/MCP/SDK convenience layers. | -| P2: Evidence assembly scale is ignored | Projection assembly and receipt timelines can become broad tenant/org scans under hosted volume. | Keep this slice local/kernel. Hosted audit/search claims require scoped indexes, pagination, and retention policy in a later plan. | -| P2: `.planning` scratch becomes canon | Active planning language gets promoted into README/tests/exports without source validation. | Chair plan should treat `.planning` as scratch and name canonical source/test/doc paths for each implementation task. No planning-stage labels in source, scripts, package exports, or CI names. | - -## Validation Gates - -Implementation must be blocked until these gates exist and pass: - -- Schema/canonicalization: custody proof packet or extended custody records have deterministic digest tests, reject raw credential material, require provider-neutral lease/version/drift fields, and preserve Tier 1 protocol meaning. -- Policy gate: missing packet/ref, stale packet/ref, unsafe custody status, provider registry drift, resolver/version drift, weak source authority, missing probe coverage, failed probe, raw sibling present, and active credential-ref isolation all refuse before greenlight. -- Gateway gate: the same stale/drift/unsafe/missing cases refuse at gateway time after a greenlight and produce no mutation attempt or signer call. -- Adapter negative tests: x402 agent-exposed signer, raw private key env, direct official SDK signing, paid fetch/axios, raw payment signature header, sibling x402 wrapper, MCP direct payment, token passthrough, wrapper drift, failure-open posture, and live/unknown provider posture fail closed. -- Auth.md regression tests: revocation, metadata drift, downstream 401, stale credential ref, scope drift, raw bearer passthrough, direct HTTP/browser/network/MCP path, token replay, unsafe retry loop, and redaction failure quarantine/refuse before credential use. -- Projection tests: redacted custody projection includes refs/digests/status/reason codes and omits secret paths, signer material, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, raw provider credentials, payment payloads, and PII. -- Claim guards: docs/examples/tests fail if fixture keys imply customer/provider custody, if x402 becomes payment management, if Handshake-held wallets/balances/settlement appear, or if provider-specific custody is claimed without official-source verification. -- Closeout gates: focused protocol/adapter/projection/claim tests first, then `npm run quality:claims`, `npm run quality:architecture`, `npm run format:check`, and `npm run check:repo`. - -Candidate focused test paths: - -- `test/protocol/credential-custody.test.ts` -- `test/protocol/evidence-projections.test.ts` -- `test/protocol/kernel-policy-gateway.test.ts` -- `test/adapters/x402-wallet-gateway.test.ts` -- `test/adapters/x402-bypass-probes.test.ts` -- `test/adapters/auth-md-gateway-pressure.test.ts` -- `test/adapters/auth-md-serialization-redaction.test.ts` -- `test/conformance/x402-payment-conformance.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/import-posture.test.ts` -- `test/architecture/root-exports.test.ts` - -## Rollback And Stop Conditions - -Stop the implementation slice if: - -- custody proof is not consumed by both policy and gateway checks; -- the gateway cannot refuse before signer/credential use; -- one greenlight can be reused for multiple custody resolutions or mutations; -- fixture/local signer custody is the only evidence behind a customer/provider custody claim; -- redaction tests find any raw signer, token, payment payload, secret path, bearer credential, or PII in projections; -- provider-specific vault/KMS/wallet behavior is needed but official docs have not been verified; -- runtime/MCP/SDK convenience code starts issuing policy, greenlight, gateway, receipt, mutation, or credential-resolution records; -- aggregate spend, settlement, facilitator, seller middleware, balance, or payment-management language appears in the slice. - -Rollback should remove or quarantine the new custody packet/projection/claim surface and keep existing `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, policy, gateway, and projection behavior unchanged. If partial schema lands without enforcement, it must be marked advisory or removed. - -## Assumptions - -- Customer-owned gateway custody remains the enforcement model. -- Handshake does not hold wallets, payment credentials, balances, settlement state, or payment-management authority. -- x402 remains the first wedge but does not define protocol primitives. -- Tier 1 protocol meaning remains stable: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, isolation. -- Existing credential custody and protected-path posture primitives are reusable unless implementation proves a source-level schema conflict. -- Provider-neutral custody schema planning can proceed without browsing; named provider/KMS/wallet/legal/payment details cannot. - -## Dependencies - -- Current `GatewayCredentialRef` and `CredentialResolutionEvidence` schemas and transition checks. -- Current protected-path posture evaluator, required bypass probe kinds, and source-authority rules. -- Current policy and gateway checks that evaluate protected-path posture, credential refs, idempotency, isolation, gateway policy drift, params digest, and sequence dependencies. -- x402 install proposal, wallet gateway, hostile bypass probes, and conformance posture. -- auth.md credential intake, lifecycle isolation, protected API gateway, bypass probes, and serialization redaction patterns. -- Evidence projection assembly and redaction behavior for contract views, agent transaction envelopes, receipt timelines, idempotency recovery, and protected-path health. - -## Antipatterns - -- "Custody proof" as a receipt label without pre-mutation enforcement. -- A rendered review screen that says "customer gateway holds credential" without binding to the exact custody proof digest. -- A provider-specific field named `vaultPath`, `secretPath`, `walletPrivateKey`, `PaymentPayload`, or `PAYMENT-SIGNATURE` in protocol records or projections. -- `fixture_gateway_held` presented as customer/provider custody. -- A helper that gives runtime/MCP/SDK code access to signer, credential resolver, gateway check, or credential-resolution writes. -- Treating spend session/day/review bounds as enforced before a ledger exists. -- Collapsing credential resolution failure into downstream unknown after mutation. -- Regex-only redaction for live provider custody. - -## Blocked Checks - -- No external official-provider, vault/KMS, wallet, x402, JWKS, legal, or payment-regulatory verification was performed; the input packet explicitly said not to browse by default. -- I did not read source files outside the immutable packet's allowed source boundary. In particular, exact `ActionContract` schema internals, action-proposal internals, HTTP handlers, D1 storage, runtime ingress, MCP proposal code, and product example generators were not read unless included indirectly in allowed tests/docs. -- I did not run tests; this is a planning-only first-pass risk artifact. -- I did not read sibling raw outputs, normalized outputs, or the final run `PLAN.md`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/STRATEGY.md deleted file mode 100644 index b6e69c8..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/raw/STRATEGY.md +++ /dev/null @@ -1,338 +0,0 @@ -# STRATEGY: Customer-Owned Gateway Custody Proof - -## Invariant at stake - -A protected path is real only when the mutation credential stays behind the gateway boundary, the exact one-use greenlight is checked immediately before consequence, unsafe drift refuses before mutation, and the surviving evidence can reconstruct that chain without exposing credential material. - -If the source cannot show that chain as one digest-bound custody story, any customer-owned gateway claim is theatre. - -## Findings - -1. The strategic goal is not "better x402." The goal is a reusable custody proof for protected actions for automated decision making. x402 is the first wedge because paid HTTP makes credential custody concrete, but x402 must remain a proof profile, not the protocol definition. - -2. The existing kernel already has most control pieces: - - `GatewayCredentialRef` stores opaque gateway-side credential custody metadata without raw material. - - `CredentialResolutionEvidence` is recorded only after a passed `GatewayCheckAttempt`. - - `ProtectedPathPosture` requires current `gateway_checked` state, gateway/host source authority, raw sibling status, and required bypass probe coverage. - - policy and gateway transitions both re-check protected-path posture and credential ref bindings. - - evidence projections expose redacted transaction, contract, receipt, install-health, and credential refs. - -3. The gap is not enforcement vocabulary. The gap is a source-owned custody proof packet or equivalent projection spine that binds install evidence, credential ref, protected-path posture, bypass probes, exact contract, greenlight, gateway check, and redacted custody evidence into one reconstructable object. Today the ingredients exist but the buyer-readable custody claim is assembled from scattered records. - -4. x402 currently proves "sign only after `VerifiedGatewayCheck`" but does not yet prove customer-owned gateway custody. The x402 install path has `walletGatewayProfile.signerRef` and `signerCustodyStatus`, and the gateway creates payment signature evidence after the gate. It does not yet bind x402 signer custody through `GatewayCredentialRef` on the action contract or record x402 signer use as `CredentialResolutionEvidence`. - -5. Fixture/local custody must stay visibly below customer-owned custody. `fixture_gateway_held` can support local regression proof. It must not satisfy a public "customer-owned gateway custody established" claim. The proof packet/projection needs an explicit claim level so local fixture keys cannot launder into provider/customer custody. - -6. auth.md gives the correct pattern: opaque credential refs, lifecycle drift/revocation mapped into isolation or quarantine, post-gate credential-resolution evidence, and redacted projections split by evidence type. Reuse that pattern. Do not turn Handshake into an auth provider, OAuth server, wallet provider, vault provider, or payment custodian. - -7. The 10-star product shape is a custody receipt a buyer can read: - - the automated decision system proposed an exact action; - - the agent/runtime never received signer or mutation credential material; - - the customer/provider gateway held or resolved the credential; - - stale, drifted, missing, unsafe, raw sibling, or redaction-failed custody refused before consequence; - - the gateway checked the exact greenlight immediately before signer use; - - the resulting evidence is redacted but reconstructable by digest refs. - -## Recommended macro shape - -### 0. Claim boundary lock - -Start by freezing the claim: - -```text -customer-owned gateway custody proof = source-owned evidence that a protected path's mutation credential is held or resolved by the gateway boundary and used only after an exact gateway check. -``` - -This slice must not claim: - -- Handshake-held wallet custody; -- payment balances, settlement, or payment management; -- live provider custody; -- broad x402 compatibility; -- hosted operation; -- provider-specific vault/KMS correctness. - -Closeout should include claim guards before product docs or demos can say "customer-owned custody" from fixture keys. - -### 1. Add a narrow custody proof packet, not a new authority path - -Recommended primitive: add a `GatewayCustodyProofPacket` or similarly named protocol object as evidence, not authority. - -Its job is to bind existing primitives, not replace them: - -```text -gateway install evidence digest --> GatewayCredentialRef id/digest --> provider registry ref/digest --> resolver ref/version --> lease/version or custody generation --> attestation refs / redacted audit refs --> protected path posture id/digest --> bypass probe ids/digests --> drift status --> custody proof digest -``` - -It must not contain: - -- signer material; -- `PaymentPayload`; -- `PAYMENT-SIGNATURE`; -- bearer tokens; -- provider secret paths; -- raw vault/KMS addresses; -- payment settlement or balance state. - -Strategic reason to add a packet: extending only `GatewayCredentialRef`, `ProtectedPathPosture`, and `CredentialResolutionEvidence` leaves the proof scattered. A buyer-facing custody claim needs one digest-bound packet that can be projected and tested as an artifact. - -Boundary: this packet is evidence. It creates no permission, no greenlight, no gateway check, no mutation proof, no downstream success, and no provider custody claim by itself. - -### 2. Bind x402 to the generic custody primitives - -x402 should become the first use of the custody proof without becoming payment management. - -Minimum strategic path: - -1. x402 install proposal registers or references a `GatewayCredentialRef` for the signer boundary. -2. x402 runtime/action proposal includes that credential ref binding in the `CandidateAction` and resulting `ActionContract`. -3. x402 policy/gateway checks inherit the existing credential-ref and protected-path refusal behavior. -4. x402 wallet gateway records post-gate signer use as `CredentialResolutionEvidence` before or alongside payment-signature reconciliation. -5. x402 redacted projection surfaces the custody proof packet and credential-resolution refs without exposing signature payloads. - -This keeps x402 as: - -```text -one buyer-side exact paid HTTP action --> one gateway-held signer boundary --> one policy decision --> one gateway check --> one redacted signer-use proof or proof gap -``` - -It must not add: - -- Handshake-held wallets; -- account balances; -- spend-window ledgers; -- facilitator operation; -- seller middleware; -- settlement finality; -- provider custody claims from local fixtures. - -### 3. Make protected-path posture consume custody packet evidence - -The current protected-path posture already requires current gateway probes and raw sibling blocking. The plan should decide whether customer-owned custody proof is: - -- required only for adapter packs that declare a gateway credential binding; or -- required for every `requiredProtectedPathState: "gateway_checked"` path. - -Strategy recommendation: require it first only for credential-backed paths, including x402 signer custody. Do not silently change Tier 1 meaning for every protected action. After x402 proves the mechanism, promote the requirement to other custody-backed adapter packs. - -### 4. Add a redacted custody projection - -The product proof should be a projection, not raw record access. - -Recommended projection shape: - -```text -custodyProofRef -custodyProofDigest -claimLevel: local_fixture | customer_gateway_evidence | provider_gateway_evidence | proof_gap -gatewayCredentialRef -gatewayCredentialRefDigest -protectedPathPostureRef -protectedPathPostureDigest -bypassProbeCoverage -credentialResolutionEvidenceRefs -gatewayCheckRef -greenlightRef -actionContractRef -driftStatus -redactionStatus -omittedFields -proofGapRefs -refusalReasonCodes -``` - -The projection should answer the buyer question directly: "Did the automated system ever receive the mutation credential?" The safe answer is not prose. It is the absence of exposed material plus evidence that signer use happened only after a verified gate. - -### 5. Preserve source-owned negative proof - -The plan must make the negative tests the product, not an afterthought. The first execution slice should fail closed on: - -- agent-exposed signer; -- missing custody packet; -- stale credential ref; -- provider registry drift; -- resolver version drift; -- resolver failure; -- unsafe custody status; -- protected-path posture stale or not gateway checked; -- required bypass probe missing or failed; -- raw sibling signer/payment path present; -- redaction failure; -- replayed greenlight; -- fixture custody trying to claim customer-owned/provider custody. - -## What to cut - -- Cut Handshake-held wallets, signing keys, payment credentials, balances, settlement, facilitator state, or spend management. -- Cut provider-specific vault/KMS architecture from this macro plan unless every named provider detail is marked "requires official source verification before implementation." -- Cut any public claim that local `fixture_gateway_held` proves customer-owned or provider custody. -- Cut a "custody dashboard" unless it is a redacted projection over exact records. A UI without digest binding is review theatre. -- Cut generic "secure custody" language. Use exact custody statuses, refs, digests, drift status, and refusal codes. -- Cut a new payment abstraction. The reusable thing is protected-action custody proof, not x402 payment infrastructure. -- Cut broad x402 compatibility. Keep `x402_payment.exact` as the first buyer-side per-call path. -- Cut aggregate spend windows. Session/day/review bounds remain metadata until a ledger exists. - -## What must be decided before execution - -1. Primitive name and object type: choose whether the evidence object is `GatewayCustodyProofPacket`, `CredentialCustodyProofPacket`, or a narrowly named projection-only packet. Do not let the name imply authority. - -2. Requirement scope: decide whether custody proof packet is required for all `gateway_checked` protected paths or only for paths with `GatewayCredentialRef` bindings. Strategy recommendation: credential-backed paths first. - -3. Fixture semantics: decide the exact claim level for `fixture_gateway_held`. Strategy recommendation: fixture can pass local regression posture but must project `claimLevel: "local_fixture"` and fail any customer/provider custody claim guard. - -4. x402 migration shape: decide whether `X402WalletGatewayProfile.signerRef` remains as adapter-local install metadata or becomes a `GatewayCredentialRef`-backed field. Strategy recommendation: preserve adapter metadata if useful, but the action contract must carry a generic `GatewayCredentialRef` binding before customer-owned custody proof can be claimed. - -5. Post-gate signer evidence: decide whether x402 wallet gateway must record `CredentialResolutionEvidence` before the payment signature evidence or after the signature is created. Strategy recommendation: record a redacted credential-use evidence object after a passed gate and before projecting the downstream reconciliation as custody proof. - -6. Projection surface: decide whether custody projection is part of the existing agent transaction envelope or a separate `projectGatewayCustodyProof` read. Strategy recommendation: create a separate projection and link it from the transaction envelope to avoid making every transaction projection custody-heavy. - -7. External verification boundary: decide which future provider/vault/wallet details require official docs. For this macro, every named provider implementation detail is blocked until official source verification. - -## Six-month regret scenario - -Six months from now, the failure mode is not "we did not support enough x402 providers." The failure mode is that Handshake shipped a clean demo where the agent did not see a signer, then called that customer-owned custody while the actual source only proved a local fixture signer behind a reference adapter. - -That regret creates three wounds: - -1. Customers treat Handshake as a payment custodian or wallet manager when it is neither. -2. Future adapter teams copy x402-specific signer fields instead of generic custody refs, making every protected action pack invent its own credential story. -3. Receipts cannot prove whether a mutation credential was gateway-held, provider-held, fixture-held, stale, drifted, or simply redacted away. - -The antidote is a narrow proof packet with explicit claim levels and negative tests that make fixture custody unable to masquerade as customer-owned custody. - -## Smallest strategically valid first move - -The smallest valid first move is not a provider integration. It is a source-owned x402 custody proof skeleton: - -```text -GatewayCredentialRef-bound x402 signer --> custody proof packet digest --> x402 ActionContract includes credential binding --> policy refuses missing/stale/unsafe/drifted custody --> gateway refuses drift before signing --> x402 gateway records redacted CredentialResolutionEvidence after VerifiedGatewayCheck --> custody projection shows local_fixture vs customer_gateway_evidence explicitly -``` - -This first move is strategically valid because it proves the reusable Handshake primitive without broadening x402, holding money, or pretending provider custody is done. - -## Assumptions - -- The current Tier 1 protocol spine remains stable: exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap. -- x402 remains the first wedge and does not define the protocol. -- `.planning/` is scratch; tracked canon and source/tests control implementation truth. -- Customer-owned gateway custody means the customer/provider gateway owns or controls the mutation credential, not Handshake. -- Provider-neutral schema planning can proceed from repo source; named provider/vault/KMS details require later official source verification. -- The current local x402 signing path is useful as a proof harness, but it does not establish live provider/customer custody. - -## Dependencies - -- Claim-boundary cleanup must remain in force so new docs/tests cannot reintroduce payment-management or provider-custody claims. -- Existing `GatewayCredentialRef`, `CredentialResolutionEvidence`, `ProtectedPathPosture`, bypass probe, policy, and gateway transitions are the implementation base. -- x402 install/action/gateway paths must accept generic credential bindings rather than keeping signer custody as adapter-local metadata only. -- Evidence projections must either add a custody projection or link to one from the agent transaction envelope. -- Claim-boundary tests must be extended before public/demo wording changes. -- Official provider/vault/wallet documentation is a future dependency only if execution chooses a named provider implementation. - -## Risks - -1. Proof packet theatre: a new packet that only repeats claims without binding exact refs/digests is worse than no packet. - -2. Tier 1 drift: making custody proof globally required for all `gateway_checked` paths in one slice can change protocol meaning. Keep the first requirement scoped to credential-backed paths. - -3. x402 capture: payment-specific fields can leak into generic protocol objects. Keep payment payload and signature evidence adapter-owned and redacted. - -4. Fixture laundering: local fixture custody can accidentally become customer-owned custody language. Add claim-level fields and guards. - -5. Redaction failure: unknown provider credential formats can bypass pattern-based redaction. Prefer allowlisted projection fields and fuzz redaction with credential-looking refs. - -6. Adoption drag: requiring every integrator to hand-assemble install evidence, credential ref, probes, posture, contract, policy, gate, and projection is too much ceremony. The macro should plan activation helpers later, but not move authority into runtime or MCP. - -7. Provider drift blind spot: without lease/version and resolver-version binding, a stale proof packet can keep passing after gateway credential rotation. - -8. Gateway bypass optimism: runtime/MCP evidence can observe bypass-shaped calls, but cannot prove all host paths are blocked. The proof should be honest about installed protected paths only. - -## Validation gates - -Planning should require future execution to close with focused gates before full repo gates: - -1. Protocol schema/canonicalization tests for the custody proof packet: - - digest changes when credential ref, provider registry digest, resolver version, lease/version, posture digest, probe digest, or drift status changes; - - raw credential-looking fields are rejected or excluded. - -2. Policy/gateway negative tests: - - missing custody packet refuses; - - stale credential ref refuses; - - provider registry drift refuses; - - resolver drift/refusal refuses; - - unsafe custody status refuses; - - protected-path posture stale or not gateway checked refuses; - - raw sibling path present refuses; - - replay refuses before signer reuse. - -3. x402 adapter tests: - - x402 install compiles a signer `GatewayCredentialRef` binding; - - x402 action contract carries credential ref binding; - - signer use occurs only after `VerifiedGatewayCheck`; - - x402 gateway records redacted `CredentialResolutionEvidence`; - - fixture custody projects as local fixture, not customer/provider custody. - -4. Projection/redaction tests: - - custody projection omits signer material, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, provider secret paths, and mutation credentials; - - projection distinguishes gateway check, credential resolution, downstream reconciliation, and proof gap. - -5. Claim guards: - - canonical docs and demo outputs cannot claim live provider/customer custody from fixture keys; - - x402 wording stays per-call exact buyer-side protected action; - - no Handshake-held wallet/payment-custody/payment-management language appears. - -6. Closeout command candidates for the future implementation: - - `npm run quality:claims` - - `npm run test -- test/protocol/credential-custody.test.ts test/protocol/evidence-projections.test.ts test/protocol/kernel-policy-gateway.test.ts` - - `npm run test -- test/adapters/x402-wallet-gateway.test.ts test/adapters/x402-bypass-probes.test.ts test/conformance/x402-payment-conformance.test.ts` - - `npm run test -- test/architecture/claim-boundary.test.ts test/architecture/import-posture.test.ts test/architecture/root-exports.test.ts` - - `npm run format:check` - - `npm run check:repo` - -## Cut lines - -- No mutation credential may cross into runtime, MCP, CLI, SDK, or model-facing surfaces. -- No greenlight may authorize more than one exact gateway-checked mutation attempt. -- No custody proof packet may create permission. -- No receipt or projection may claim downstream payment success without downstream evidence. -- No fixture key may satisfy customer/provider custody claims. -- No provider/vault/KMS claim may ship without official source verification and provider-specific negative tests. -- No broad x402 compatibility, facilitator operation, settlement finality, seller middleware, or spend-window enforcement in this slice. -- No raw record route or generic projection may expose credential material or secret-bearing refs. - -## Antipatterns - -- "Custody status: safe" without credential ref digest, resolver version, lease/version, posture digest, probe digest, and drift status. -- Adding a wallet provider abstraction before the generic custody proof works. -- Treating `signerRef` strings as proof of custody. -- Recording signer use before the gateway check. -- Recording signer use after the gateway check but failing to bind it to the exact contract, greenlight, and gate attempt. -- Hiding redaction failure as success. -- Letting x402 provider-environment fields default away live/unknown posture. -- Using dashboard copy to imply protection where the gateway cannot block mutation. -- Using MCP proposal evidence as if it proves host-wide bypass prevention. - -## Blocked checks - -- Did not browse or verify official provider, vault, KMS, wallet, x402 provider, legal, or payment-regulatory details. The input packet said not to browse by default; any named provider architecture remains blocked on official source verification before implementation. -- Did not read sibling raw outputs, normalized outputs, or the final plan for this run. -- Did not run tests because this is a planning-only first-pass artifact. -- Did not inspect source files outside the immutable input packet and allowed source boundary. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/synthesis.md deleted file mode 100644 index 2d3f7b2..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/customer-owned-gateway-custody-proof/runs/customer-owned-gateway-custody-proof-20260524T071623Z/synthesis.md +++ /dev/null @@ -1,54 +0,0 @@ -# Chair Synthesis - -## Invariant At Stake - -A protected action is real only when the mutation credential remains behind a customer/provider gateway boundary, the exact one-use greenlight is checked immediately before consequence, unsafe or drifted custody refuses before mutation, and the surviving evidence is redacted but reconstructable. - -## Synthesis Decision - -The final plan chooses a new source-owned `GatewayCustodyProofPacket` as evidence, not authority. - -This is not a new permission primitive. The packet is subordinate to existing `GatewayCredentialRef`, `ProtectedPathPosture`, bypass probes, policy evaluation, gateway check, `CredentialResolutionEvidence`, and redacted projections. - -Reasoning: - -- Extending only existing fields keeps the custody story scattered and too easy to overclaim. -- A new top-level authority primitive would violate Tier 1 protocol meaning. -- A packet under credential custody can bind install evidence, credential ref, posture, probes, drift, redaction, and claim level while policy and gateway remain the enforcement points. - -## Perspective Reconciliation - -- Strategy emphasized that Handshake is protected actions for automated decision making, x402 is the first wedge, and fixture custody must not become customer/provider custody. -- Architecture emphasized that existing primitives are strong, but a source-owned packet is needed to make custody proof digest-bound and reconstructable. -- Execution emphasized test-first sequencing and warned that x402/auth.md adapter work must wait until packet binding semantics are stable. -- Risk emphasized that a packet not consumed by policy and gateway is advisory, not Handshake. -- Adoption emphasized the buyer-readable projection: the buyer should not infer custody from scattered protocol records. - -The plan therefore sequences source map verification, failing tests, packet schema/transition, policy/gateway binding, x402 integration, auth.md parity, redacted projection, claim guards, and closeout gates. - -## Preserved Boundaries - -- Handshake does not hold wallets, private keys, bearer tokens, payment credentials, balances, settlement state, or payment-management state. -- x402 remains one buyer-side exact protected action per call and does not define the protocol. -- customer-owned gateway custody remains the enforcement model. -- Tier 1 meaning remains exact contract, policy decision, one-use greenlight, gateway check, receipt/refusal/proof gap, and isolation. -- Provider-specific vault/KMS/wallet/x402 provider details require later official source verification before implementation. -- Fixture/local/reference custody is regression evidence only and cannot support live customer/provider custody claims. - -## Blocked Checks - -- Did not inspect companion implementation files outside the allowed planning packet, including protocol public aggregation, object registry, kernel facade, projection schemas, storage/migrations, fixtures, or adapter exports. -- Did not browse official provider, vault, KMS, wallet, x402 provider, JWKS, Cloudflare, npm, MCP Registry, legal, or payment-regulatory sources. -- Did not run tests because this was a planning-only synthesis with a hard write boundary. -- Did not read archive macro runs. -- Did not stage or commit. - -## Output Files - -- `.planning/macro/active/customer-owned-gateway-custody-proof/PLAN.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/CONTEXT.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/ASSUMPTIONS.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/DECISIONS.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/RISKS.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/VALIDATION.md` -- `.planning/macro/active/customer-owned-gateway-custody-proof/TASKS.jsonl` diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/ASSUMPTIONS.md deleted file mode 100644 index 2f2cd25..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/ASSUMPTIONS.md +++ /dev/null @@ -1,35 +0,0 @@ -# Assumptions: Host-Specific Bypass Harnesses - -## Hard Assumptions - -- Handshake is protected actions for automated decision making, not engineering-agent-only infrastructure. -- x402 exact per-call is the first proof wedge, not the protocol center. -- A host harness proves only named configured installed path behavior against named bypass routes at a recorded freshness state. -- No host harness can claim host-wide containment. -- No fixture can manufacture establishment custody or gateway-checked posture. -- CLI and MCP surfaces do not enforce unless paired with blocking gateway checks. - -## Technical Assumptions - -- `runBypassProbeExecutors` and `BypassProbeExecutor` are reusable for host harness probe execution. -- Existing x402 hostile bypass probe executors are a useful calibration pattern. -- Package-install conformance can supply the first protected action fixture boundary. -- Host tool identity can be represented with host id, resolved path, digest, adapter version, registry entry, and freshness timestamp. -- Wrapper drift and stale tool metadata are common enough to be first-class refusal states. -- Raw sibling paths can be named in a fixture manifest. -- Redacted evidence can preserve enforcement distinctions without leaking secrets. - -## Product Assumptions - -- The first useful adoption surface is CLI reporting. -- Operators need explicit non-claims more than broad safety language. -- Exit states are more valuable than prose confidence. -- Dashboard work should wait until the proof packet and posture derivation are stable. - -## Unknowns - -- Exact package-install host names and paths for the first fixture. -- Final shape of package-install adapter expansion. -- Whether current claim guard scripts already cover all host-wide overclaims. -- Whether existing conformance fixtures expose enough metadata for host digest and wrapper integrity checks. -- How much redaction should happen in source evidence versus projection. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/CONTEXT.md deleted file mode 100644 index f81966c..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/CONTEXT.md +++ /dev/null @@ -1,105 +0,0 @@ -# Context: Host-Specific Bypass Harnesses - -## Invariant - -Handshake controls protected actions for automated decision making. It is not engineering-agent-only. A host harness is valid only when it binds a protected action attempt to a named configured installed path and records whether named bypass routes were refused, detected, proof-gapped, or left advisory-only. - -## Why This Macro Exists - -Handshake already has bypass probe executor machinery and x402 hostile bypass probe precedent. That is not enough to claim host protection. - -The missing mechanism is host-specific evidence: - -- which host was tested -- which installed path was configured -- which protected action was attempted -- which wrapper was expected -- which raw sibling routes were reachable -- which registry entry bound the gateway -- which freshness state applied -- which evidence survived redaction -- which claims are explicitly not made - -## Product Boundary - -Handshake is protected actions for automated decision making. - -Engineering-agent actions are still an important wedge, but the product category is broader. The host harness must avoid language that narrows Handshake into engineering-agent-only infrastructure. - -x402 exact per-call remains the first proof wedge because it demonstrates exact action contract, policy, gateway check, refusal, and bypass evidence. It is not the protocol center. - -## First Host Choice - -Choose package-manager local host first, after package-install conformance is stable. - -Reason: - -- package installs are consequential protected actions -- local host paths have visible wrapper and raw sibling distinctions -- package manager bypasses are concrete enough to test -- the adoption path is understandable to engineering organizations -- the evidence boundary can stay narrow - -x402 hostile bypass probes should be used second as calibration for hostile probe discipline. - -MCP host harnesses are deferred until the package-install host contract is boring. MCP and CLI are proposal, evidence, and read surfaces unless paired with blocking gateway enforcement. - -## Evidence Shape - -The required evidence object is `BypassProofPacket`. - -It must include: - -- manifest reference -- host identity -- environment identity -- adapter identity and version -- registry entry -- policy identity -- protected action type -- protected path -- wrapper identity and resolved path -- raw sibling candidates -- tool list digest -- freshness timestamp -- probe results -- wrapper integrity result -- gateway binding result -- gateway check result -- downstream execution result -- refusal evidence -- bypass evidence -- proof gaps -- redacted projection -- non-claims - -Redaction must not erase the distinction between gateway check, downstream execution, refusal, bypass, and proof gap. - -## Adoption Surface - -CLI report comes first. - -Target command shape: - -- `handshake harness init --host codex --protected-path package-install` -- `handshake harness check --host codex --protected-path package-install` -- `handshake harness probe --host codex --protected-path package-install` -- `handshake harness report --host codex --protected-path package-install` -- `handshake harness doctor --host codex --protected-path package-install` - -The CLI must report status and non-claims. Dashboard rendering is deferred until the evidence object is stable. - -## Product Bar - -A 10-star version does not say "safe." - -It says: - -- ready for this host fixture -- advisory only for these routes -- stale for this digest -- drifted at this wrapper -- unbound at this gateway -- raw sibling mutation possible at this named path -- proof gap for this missing evidence -- not tested for browser, shell, network, MCP, platform, or ecosystem coverage diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/DECISIONS.md deleted file mode 100644 index b174c52..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/DECISIONS.md +++ /dev/null @@ -1,98 +0,0 @@ -# Decisions: Host-Specific Bypass Harnesses - -## D01: First Host Harness Is Package-Manager Local Host - -Use package-manager local host first after package-install conformance. - -Reason: package installs are concrete protected actions with obvious wrapper and raw sibling bypass risks. - -Rejected alternatives: - -- x402 first as host center: rejected because x402 is calibration and proof wedge, not protocol center. -- MCP host first: rejected because MCP surface posture is still proposal/evidence/read unless blocking gateway enforcement is paired. -- generic host harness first: rejected because it invites host-wide claims. - -## D02: Define HostFixtureManifest v1 Before Probe Expansion - -The manifest must bind: - -- host identity -- environment identity -- protected action type -- protected path -- adapter identity and version -- wrapper identity -- wrapper configured path -- wrapper resolved path -- raw sibling candidates -- registry entry -- policy identity -- freshness timestamp -- tool list digest -- expected posture -- redaction policy -- non-claims - -Missing required fields fail closed. - -## D03: Define BypassProofPacket As Durable Evidence - -The packet must preserve: - -- probe execution inputs -- probe execution outputs -- wrapper integrity -- gateway binding -- freshness decisions -- protected-path posture -- gateway check result -- downstream execution result -- refusal evidence -- bypass evidence -- proof gaps -- redacted projection -- non-claims - -The packet is not a marketing artifact. It is reconstruction evidence. - -## D04: Stale Metadata Refuses Or Proof-Gaps - -Stale tool list digest, changed host tool digest, stale probe freshness, missing registry binding, wrapper drift, or unknown raw sibling posture cannot produce `READY`. - -Allowed outcomes are refusal, proof gap, or advisory-only posture. - -## D05: Protected-Path Posture Is Fixture-Specific - -Posture attaches to one host fixture at one freshness state. - -It does not attach to: - -- the whole host -- all tools in the host -- the package manager ecosystem -- MCP generally -- shell/browser/network paths -- x402 generally -- engineering agents generally - -## D06: CLI Report First, Dashboard Later - -CLI is the first adoption surface because it can show exact status, evidence, and non-claims without creating review theatre. - -Dashboard comes after proof packet stability. - -## D07: Exit States Are Product Surface - -Required exit states: - -- `READY` -- `ADVISORY_ONLY` -- `WRAPPER_MISSING` -- `WRAPPER_DRIFTED` -- `GATEWAY_UNBOUND` -- `RAW_SIBLING_MUTATION_POSSIBLE` -- `STALE_PROBE` -- `HOST_TOOL_DIGEST_CHANGED` -- `PROOF_GAP` - -These states are not internal details. They are the control vocabulary. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/PLAN.md deleted file mode 100644 index d46d126..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/PLAN.md +++ /dev/null @@ -1,326 +0,0 @@ -# GSD Macro Plan: Host-Specific Bypass Harnesses - -## Goal - -Invariant at stake: a protected action for automated decision making must not execute through an uncontracted host path while Handshake claims gateway-checked control. - -Build the first host-specific bypass harness for one configured installed host path, beginning with package-manager local host after package-install conformance is boring. The harness must prove only this narrow claim: - -In environment E, host H, adapter A, policy P, action T, Handshake resisted named bypass routes B and recorded evidence R at freshness state F. - -The harness must not claim host-wide containment, platform safety, package-manager safety, MCP safety, browser/shell/network protection, or x402 ecosystem coverage. - -x402 exact per-call remains the first proof wedge and calibration surface. It is not the protocol center. Handshake is protected actions for automated decision making, not engineering-agent-only infrastructure. - -## Non-Goals - -- No generic host sandbox. -- No host-wide safety claim. -- No MCP-wide or CLI-wide enforcement claim. -- No browser, shell, network, package-manager ecosystem, or platform containment claim. -- No claim that a host harness proves all sibling tools are blocked. -- No claim that x402 coverage implies broader payment ecosystem coverage. -- No dashboard-first delivery. -- No implementation in this macro step. -- No use of fixture evidence to manufacture establishment custody, gateway ownership, or host-wide control. - -## Source Boundary - -Current source named by the input packet: - -- `src/adapters/protected-path-probes/executor.ts` - - already contains `runBypassProbeExecutors` - - already contains `BypassProbeExecutor` -- conformance fixture support already has `fixtureGatewayCheckedBypassProbeExecutors` -- `src/adapters/x402-payment/bypass-probes.ts` - - already contains hostile x402 bypass probe executors -- existing x402 tests already prove: - - policy greenlights only after gateway-owned hostile probes pass - - raw x402 bypass paths cause policy refusal - - official SDK side channels are raw sibling bypass evidence - - direct payment, token passthrough, wrapper drift, and failure-open probes are distinct - - conformance fixture probes cannot manufacture gateway-checked posture - - fixture wallet custody is not establishment custody evidence -- auth.md bypass probes and MCP surface posture tests exist, but MCP and CLI are proposal, evidence, and read surfaces unless paired with blocking gateway enforcement. - -Canonical planning boundary: - -- This macro plan is scratch under `.planning/`. -- Repo-facing durable truth must only move into canonical docs or source after implementation validates it. -- No planning label from this macro may become an exported product claim. - -## Current State - -Handshake already has reusable bypass probe executor machinery and x402 hostile probe examples. That proves the shape of gateway-owned hostile probing, but not a host-specific harness for an installed configured host path. - -The current evidence posture is narrower than many tempting claims: - -- x402 evidence proves exact per-call bypass behavior for named payment paths. -- conformance fixture probes prove fixture behavior only. -- MCP and CLI surfaces can report, propose, or show evidence, but they do not enforce unless a gateway blocks mutation. -- existing probe results do not prove host-wide containment. -- existing probe results do not prove sibling package-manager, browser, shell, network, MCP, or SDK safety. - -The missing layer is a host fixture contract that binds a configured host, protected path, wrapped tool identity, raw sibling routes, freshness, wrapper integrity, expected posture, evidence redaction, and non-claims. - -## Target State - -A package-manager local host harness exists behind a strict fixture manifest. - -The first acceptable report states: - -- host identity -- environment identity -- adapter identity and version -- protected action type -- protected path -- configured wrapper path -- resolved wrapper path -- raw sibling candidates -- tool list digest -- registry entry -- policy identity -- freshness timestamp -- probe classes -- wrapper integrity result -- gateway binding result -- one-use greenlight result -- raw sibling refusal, detection, proof gap, or stop condition -- protected-path posture -- redacted bypass proof packet -- explicit non-claims - -The product bar is 10-star only if the report makes the boundary impossible to misunderstand: - -- it names exactly what was protected -- it names exactly what was probed -- it names exactly what was not probed -- it refuses stale metadata -- it refuses wrapper drift -- it distinguishes gateway check from downstream execution -- it records proof gaps instead of smoothing uncertainty -- it treats raw sibling reachability as evidence, not as a hidden detail -- it never lets redaction erase enforcement distinctions -- it exits advisory-only when the gateway cannot block consequence - -## Assumptions - -- Package-install conformance is the prerequisite first host boundary because package installation is a concrete protected action with visible raw sibling paths. -- x402 hostile probes are calibration examples, not the center of the protocol. -- A host harness can only speak about a named configured installed path and named bypass routes at a recorded freshness state. -- Host tool identity and resolved path can drift between runs. -- Tool catalogs can become stale. -- Raw sibling tools may remain reachable. -- Wrapper integrity can drift independently from policy logic. -- CLI and MCP reports are evidence surfaces unless paired with blocking gateway enforcement. -- Redaction is necessary, but redaction must preserve gateway, downstream, refusal, bypass, and proof-gap distinctions. - -## Decisions - -1. Choose package-manager local host first. - - Rationale: package install is a protected action with direct raw sibling risk and clear local host fixture boundaries. - - Constraint: start only after package-install conformance is stable enough to avoid fixture laundering. - -2. Use x402 hostile probes second as calibration. - - Rationale: x402 already has hostile bypass executor shape and exact per-call discipline. - - Constraint: do not recenter the protocol around x402. - -3. Define `HostFixtureManifest` v1 before adding more probes. - - Required bindings: host, environment, adapter, action type, protected path, wrapper path, raw sibling paths, registry entry, freshness, redaction, expected posture, non-claims. - -4. Define `BypassProofPacket` as the durable evidence object. - - Required sections: probes, wrapper integrity, freshness decisions, protected-path posture, raw sibling results, redacted projection, proof gaps, non-claims. - -5. Treat stale metadata as refusal or proof gap. - - Stale tool list digest, changed host tool digest, wrapper drift, stale probe results, or missing registry binding cannot produce gateway-checked posture. - -6. Keep protected-path posture fixture-specific. - - Posture is derived for one fixture, one host, one adapter, one action type, one freshness state. - - It is never host-wide. - -7. Put CLI report first. - - Dashboard can render later. - - First commands are conceptual product targets: `handshake harness init`, `check`, `probe`, `report`, and `doctor`. - -8. Keep MCP and CLI as separate host boundaries. - - They may show proposal and evidence posture. - - They are not enforcement unless paired with blocking gateway checks. - -## Phases - -Phase 0: Scope Lock And Precondition - -- Confirm package-install conformance is the first host harness target. -- Confirm x402 hostile probes remain calibration only. -- Write claim guards before new product claims can land. -- Stop if the plan drifts into host-wide protection. - -Phase 1: Host Fixture Contract - -- Define `HostFixtureManifest` v1. -- Bind host identity, protected action path, wrapper identity, raw sibling candidates, registry entry, adapter version, policy identity, freshness timestamp, expected posture, redaction policy, and non-claims. -- Add fixture validation that fails closed on missing or stale bindings. - -Phase 2: Wrapped Path Success - -- Prove a wrapped package-install path can receive one exact greenlight. -- Bind greenlight to one action contract and one gateway check. -- Record downstream execution separately from gateway acceptance. -- Stop if a greenlight can authorize multiple mutations. - -Phase 3: Raw Sibling Probes - -- Add raw sibling probes for package-manager bypass paths. -- Record each raw sibling as refusal, detection, proof gap, or stop condition. -- Stop if raw sibling mutation succeeds without refusal, proof gap, or quarantine evidence. - -Phase 4: Wrapper Integrity And Freshness - -- Detect wrapper missing, wrapper drift, gateway unbound, host tool digest changed, and stale probe results. -- Refuse or proof-gap stale metadata. -- Do not allow stale success to produce gateway-checked posture. - -Phase 5: Bypass Proof Packet And Redacted Projection - -- Emit `BypassProofPacket`. -- Emit redacted projection for CLI reports. -- Preserve distinctions between gateway check, downstream result, refusal, bypass evidence, and proof gap. - -Phase 6: Protected-Path Posture Updates - -- Derive fixture-specific protected-path posture from manifest plus proof packet. -- Supported exit states: - - `READY` - - `ADVISORY_ONLY` - - `WRAPPER_MISSING` - - `WRAPPER_DRIFTED` - - `GATEWAY_UNBOUND` - - `RAW_SIBLING_MUTATION_POSSIBLE` - - `STALE_PROBE` - - `HOST_TOOL_DIGEST_CHANGED` - - `PROOF_GAP` - -Phase 7: CLI Report And Claim Guard Closeout - -- CLI report shows protected path, tool list digest, wrapper integrity, gateway binding, probe freshness, raw sibling attempts, evidence, and non-claims. -- Dashboard remains deferred. -- Claim guards reject host-wide, platform-wide, MCP-wide, package-manager-wide, x402-ecosystem-wide, or engineering-agent-only framing. - -## Task Graph - -- T01 locks the scope and precondition. -- T02 defines `HostFixtureManifest` v1. -- T03 defines package-install fixture data. -- T04 proves wrapped path success with one-use greenlight. -- T05 adds raw sibling probes. -- T06 adds wrapper integrity checks. -- T07 adds freshness refusal and proof-gap behavior. -- T08 defines `BypassProofPacket`. -- T09 derives protected-path posture. -- T10 adds CLI report shape. -- T11 adds claim guards and closeout validation. - -No later task may claim posture without T02, T06, T07, and T08. - -## Risks And Mitigations - -- Stale tool list: - - Mitigation: bind tool list digest and freshness timestamp; stale digest becomes refusal or proof gap. - -- Wrapper drift: - - Mitigation: bind resolved path and wrapper digest; drift exits `WRAPPER_DRIFTED`. - -- Raw sibling reachability: - - Mitigation: enumerate named siblings in manifest; mutation-capable sibling exits `RAW_SIBLING_MUTATION_POSSIBLE`. - -- MCP or CLI overclaim: - - Mitigation: claim guard text says proposal/evidence/read surface unless blocking gateway enforcement exists. - -- Weak `sourceAuthority` fixtures: - - Mitigation: fixture source authority cannot stand in for establishment custody or host-wide posture. - -- Token passthrough: - - Mitigation: keep token passthrough as a distinct bypass class, not a generic wrapper failure. - -- Fixture laundering: - - Mitigation: conformance fixtures cannot manufacture gateway-checked posture. - -- Redaction leakage: - - Mitigation: redaction policy must hide sensitive values while preserving enforcement distinctions. - -- Evidence projection flattening: - - Mitigation: CLI report must keep gateway check, downstream execution, refusal, bypass, and proof gap separate. - -## Validation Gates - -Precondition gates: - -- package-install conformance passes before host harness posture can be claimed. -- x402 hostile bypass tests remain passing as calibration. -- existing bypass probe executor tests remain passing. - -Implementation closeout commands, once code exists: - -- `npm run quality:claims` -- `npm run quality:architecture` -- `npm run format:check` -- `npm run check:repo` - -Focused validation targets to add or run when available: - -- host fixture manifest schema tests -- wrapped package-install path one-use greenlight test -- raw sibling refusal or proof-gap tests -- wrapper missing and wrapper drift tests -- stale tool digest and stale probe tests -- bypass proof packet redaction tests -- protected-path posture derivation tests -- CLI report non-claim tests - -Report validation must show: - -- protected path -- tool list digest -- wrapper integrity -- gateway binding -- probe freshness -- raw sibling attempts -- evidence -- non-claims - -## Cut Lines - -Cut any claim that says or implies: - -- Handshake protects the whole host. -- Handshake protects all package-manager operations. -- Handshake protects MCP tools generally. -- Handshake protects browser, shell, or network paths. -- Handshake proves platform-wide containment. -- x402 coverage proves payment ecosystem coverage. -- Host harnesses prove engineering-agent safety generally. -- Fixture evidence proves establishment custody. -- A report is enforcement. -- A CLI or MCP surface is blocking without a gateway. -- A wrapped path success covers raw siblings. -- A redacted report can omit proof gaps. - -## Rollback / Stop Conditions - -Stop immediately if: - -- raw sibling mutation succeeds without refusal, quarantine, or proof-gap evidence -- gateway check and downstream execution are collapsed into one receipt field -- stale metadata still produces `READY` -- wrapper drift still produces gateway-checked posture -- one greenlight can authorize more than one mutation attempt -- fixture probes manufacture gateway-checked posture -- redacted projection hides bypass/proof-gap distinction -- CLI or MCP report claims enforcement without blocking gateway checks -- package-install harness expands into host-wide claims - -Rollback posture to `ADVISORY_ONLY` or `PROOF_GAP` when evidence is incomplete. - -## Smallest Next Action - -Write the `HostFixtureManifest` v1 contract for the package-manager local host harness, including non-claims and freshness refusal rules, before adding any new probe implementation. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/RISKS.md deleted file mode 100644 index 1628e9e..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/RISKS.md +++ /dev/null @@ -1,67 +0,0 @@ -# Risks: Host-Specific Bypass Harnesses - -## R01: Host-Wide Overclaim - -Failure mode: a fixture-level result is described as host protection. - -Mitigation: claim guards must reject host-wide, platform-wide, package-manager-wide, MCP-wide, browser/shell/network, and ecosystem-wide claims. - -Stop condition: any report says or implies host-wide containment. - -## R02: Stale Tool List - -Failure mode: a previously valid wrapper or raw sibling list changes, but old probe results still produce `READY`. - -Mitigation: bind tool list digest and freshness timestamp. Digest change exits `HOST_TOOL_DIGEST_CHANGED` or `STALE_PROBE`. - -## R03: Wrapper Drift - -Failure mode: the configured wrapper path changes or no longer binds to the gateway. - -Mitigation: compare configured path, resolved path, wrapper digest, and registry binding. Drift exits `WRAPPER_DRIFTED` or `GATEWAY_UNBOUND`. - -## R04: Raw Sibling Mutation - -Failure mode: package install succeeds through an unwrapped sibling path while Handshake reports protected posture. - -Mitigation: raw sibling probes are required. Mutation-capable sibling exits `RAW_SIBLING_MUTATION_POSSIBLE` and blocks `READY`. - -Stop condition: raw sibling mutation succeeds without refusal, quarantine, or proof-gap evidence. - -## R05: Gateway/Downstream Evidence Collapse - -Failure mode: receipt cannot distinguish gateway check from downstream execution. - -Mitigation: `BypassProofPacket` has separate gateway check and downstream result fields. - -Stop condition: evidence projection flattens these fields. - -## R06: MCP/CLI Enforcement Overclaim - -Failure mode: report or proposal surfaces are treated as enforcement. - -Mitigation: MCP and CLI are proposal/evidence/read surfaces unless paired with blocking gateway checks. - -## R07: Weak Source Authority - -Failure mode: fixture `sourceAuthority` is treated as establishment custody or real gateway ownership. - -Mitigation: fixture authority remains fixture-only and cannot produce establishment custody evidence. - -## R08: Token Passthrough - -Failure mode: a token or payment proof is passed around the wrapper, creating false gateway posture. - -Mitigation: token passthrough remains a distinct bypass class and must be recorded separately. - -## R09: Fixture Laundering - -Failure mode: conformance fixture probes are used to manufacture gateway-checked host posture. - -Mitigation: conformance fixture evidence can satisfy schema behavior only, not host posture. - -## R10: Redaction Erases Control Meaning - -Failure mode: redacted report hides the difference between refusal, bypass, downstream uncertainty, and proof gap. - -Mitigation: redaction policy must preserve control-state labels and evidence categories. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/TASKS.jsonl deleted file mode 100644 index f4d0e00..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/TASKS.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"id":"T01","priority":"P0","phase":"scope-lock","title":"Lock package-manager local host as first harness target","owner":"implementation agent","rationale":"The first harness needs a concrete protected action boundary and must not drift into host-wide or x402-centered claims.","depends_on":[],"acceptance":["package-manager local host is named as the first target","package-install conformance is documented as a precondition","x402 is documented as calibration only","host-wide and ecosystem claims are explicitly excluded"],"candidate_paths":[".planning/macro/active/host-specific-bypass-harnesses/PLAN.md","docs/internal/decisions.md"],"non_goals":["implement probes","claim host-wide containment","recenter protocol on x402"]} -{"id":"T02","priority":"P0","phase":"fixture-contract","title":"Define HostFixtureManifest v1","owner":"implementation agent","rationale":"Posture cannot be derived until host identity, protected path, wrapper, raw siblings, freshness, redaction, and non-claims are bound.","depends_on":["T01"],"acceptance":["manifest binds host identity, environment, adapter version, protected action type, protected path, wrapper path, raw siblings, registry entry, policy identity, freshness, tool digest, expected posture, redaction, and non-claims","missing required fields fail closed","manifest language states fixture-specific scope"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["define generic host sandbox","cover MCP host","cover browser shell or network"]} -{"id":"T03","priority":"P0","phase":"fixture-contract","title":"Create package-install host fixture seed","owner":"implementation agent","rationale":"The manifest needs concrete package-install fixture data before meaningful wrapped and raw sibling probes can run.","depends_on":["T02"],"acceptance":["fixture names one package-install protected path","fixture names configured wrapper and resolved path","fixture names raw sibling package-manager routes","fixture includes freshness timestamp and tool list digest","fixture includes explicit non-claims"],"candidate_paths":["src/adapters/package-install","tests/fixtures","docs/internal/protocol-notes.md"],"non_goals":["prove package-manager ecosystem safety","support multiple hosts initially","dashboard rendering"]} -{"id":"T04","priority":"P0","phase":"wrapped-path","title":"Prove wrapped path one-use greenlight behavior","owner":"implementation agent","rationale":"A harness must prove that the protected path executes only through an exact one-use gateway-bound greenlight.","depends_on":["T03"],"acceptance":["wrapped package-install attempt receives one exact greenlight","greenlight binds to one action contract","gateway check occurs before mutation","reuse of the greenlight is refused","gateway check and downstream result are recorded separately"],"candidate_paths":["src/adapters/protected-path-probes/executor.ts","src/adapters/package-install","tests"],"non_goals":["raw sibling coverage","host-wide readiness","MCP enforcement"]} -{"id":"T05","priority":"P0","phase":"raw-sibling-probes","title":"Add raw sibling package-manager bypass probes","owner":"implementation agent","rationale":"Wrapped success is meaningless if raw sibling mutation can bypass the contract boundary.","depends_on":["T03","T04"],"acceptance":["each named raw sibling route is attempted or proof-gapped","raw sibling mutation possibility blocks READY","raw sibling refusal records evidence","raw sibling probe class is recorded in proof packet inputs"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["discover all possible host tools","claim complete package-manager safety","execute destructive real installs"]} -{"id":"T06","priority":"P0","phase":"wrapper-integrity","title":"Add wrapper integrity and gateway binding checks","owner":"implementation agent","rationale":"A configured wrapper path is not authority unless it resolves to the expected gateway-bound wrapper at freshness time.","depends_on":["T02","T03"],"acceptance":["missing wrapper exits WRAPPER_MISSING","digest drift exits WRAPPER_DRIFTED","missing gateway binding exits GATEWAY_UNBOUND","resolved path and adapter version are recorded"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["trust configured path without resolution","allow wrapper drift under READY","host-wide wrapper inventory"]} -{"id":"T07","priority":"P0","phase":"freshness","title":"Implement stale metadata refusal and proof-gap rules","owner":"implementation agent","rationale":"Old probe success cannot authorize current posture after tool list, host digest, wrapper, or registry drift.","depends_on":["T02","T06"],"acceptance":["stale probe exits STALE_PROBE","changed host tool digest exits HOST_TOOL_DIGEST_CHANGED","missing freshness exits PROOF_GAP","stale metadata cannot produce READY"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["best-effort freshness warnings","silent stale success","long-lived ambient authorization"]} -{"id":"T08","priority":"P0","phase":"proof-packet","title":"Define BypassProofPacket and redacted projection","owner":"implementation agent","rationale":"Reconstruction requires one evidence object that preserves gateway, downstream, refusal, bypass, freshness, and proof-gap distinctions.","depends_on":["T04","T05","T06","T07"],"acceptance":["packet includes manifest reference and probe results","packet separates gateway check from downstream execution","packet records refusal, bypass, and proof gaps separately","redacted projection hides secrets without erasing control distinctions","non-claims are included"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["marketing report","lossy redaction","single pass fail boolean only"]} -{"id":"T09","priority":"P1","phase":"posture","title":"Derive protected-path posture from manifest and proof packet","owner":"implementation agent","rationale":"Posture must be computed from evidence, not asserted by adapter optimism.","depends_on":["T08"],"acceptance":["READY requires fresh manifest, wrapper integrity, gateway binding, one-use greenlight, and no raw sibling mutation evidence","ADVISORY_ONLY is used for non-blocking surfaces","all required exit states are represented","posture is fixture-specific and never host-wide"],"candidate_paths":["src/adapters/protected-path-probes","src/adapters/package-install","tests"],"non_goals":["manual posture override","host-wide posture","dashboard status badges"]} -{"id":"T10","priority":"P1","phase":"cli-report","title":"Specify CLI report shape for harness evidence","owner":"implementation agent","rationale":"Adoption starts with a report that makes evidence and non-claims explicit before dashboard work creates review theatre risk.","depends_on":["T08","T09"],"acceptance":["report shows protected path, tool list digest, wrapper integrity, gateway binding, probe freshness, raw sibling attempts, evidence, and non-claims","report supports READY, ADVISORY_ONLY, WRAPPER_MISSING, WRAPPER_DRIFTED, GATEWAY_UNBOUND, RAW_SIBLING_MUTATION_POSSIBLE, STALE_PROBE, HOST_TOOL_DIGEST_CHANGED, and PROOF_GAP","report does not claim enforcement without blocking gateway checks"],"candidate_paths":["src/cli","src/adapters/protected-path-probes","tests"],"non_goals":["dashboard implementation","operator approval UI","generic compliance report"]} -{"id":"T11","priority":"P0","phase":"claim-guards","title":"Add claim guards and closeout validation for harness scope","owner":"implementation agent","rationale":"The hardest failure is a correct fixture result turned into an incorrect product claim.","depends_on":["T01","T09","T10"],"acceptance":["claim guards reject host-wide, platform-wide, package-manager-wide, MCP-wide, browser shell network, x402 ecosystem, and engineering-agent-only claims","quality and repo checks are documented as closeout gates","validation includes non-claim report checks"],"candidate_paths":["scripts","docs/internal","tests","QUALITY.md"],"non_goals":["broaden product category incorrectly","ship without claim checks","turn planning labels into source API names"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/VALIDATION.md deleted file mode 100644 index ae0f99d..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/VALIDATION.md +++ /dev/null @@ -1,93 +0,0 @@ -# Validation: Host-Specific Bypass Harnesses - -## Validation Principle - -A host harness passes only when it proves a narrow protected-path claim and records explicit non-claims. Broad confidence is failure. - -## Precondition Gates - -- Package-install conformance must pass before package-manager local host posture can be claimed. -- Existing x402 hostile bypass tests must remain passing as calibration. -- Existing bypass probe executor behavior must remain passing. -- Claim guards must reject engineering-agent-only framing and host-wide safety language. - -## Required Test Classes - -1. Host fixture manifest schema - - missing host fails - - missing protected path fails - - missing wrapper fails - - missing raw sibling list fails - - missing freshness fails - - missing non-claims fails - -2. Wrapped path success - - wrapped package-install path receives one exact greenlight - - greenlight binds to one action contract - - gateway check is recorded before mutation - - downstream execution is recorded separately - -3. Raw sibling probes - - named raw sibling attempts are executed or proof-gapped - - raw sibling mutation blocks `READY` - - raw sibling refusal records evidence - -4. Wrapper integrity - - missing wrapper exits `WRAPPER_MISSING` - - digest drift exits `WRAPPER_DRIFTED` - - gateway-unbound wrapper exits `GATEWAY_UNBOUND` - -5. Freshness - - stale probe exits `STALE_PROBE` - - changed host tool digest exits `HOST_TOOL_DIGEST_CHANGED` - - stale metadata cannot produce `READY` - -6. Bypass proof packet - - packet includes manifest reference - - packet separates gateway check from downstream result - - packet records refusal, bypass, and proof-gap evidence separately - -7. Redacted projection - - secrets are hidden - - control distinctions remain visible - - non-claims remain visible - -8. Protected-path posture - - `READY` requires wrapper integrity, gateway binding, fresh probes, and no raw sibling mutation evidence - - `ADVISORY_ONLY` is used when reporting exists without blocking enforcement - - `PROOF_GAP` is used when evidence is missing - -9. CLI report - - shows protected path - - shows tool list digest - - shows wrapper integrity - - shows gateway binding - - shows probe freshness - - shows raw sibling attempts - - shows evidence - - shows non-claims - -## Closeout Commands - -Run when implementation exists: - -- `npm run quality:claims` -- `npm run quality:architecture` -- `npm run format:check` -- `npm run check:repo` - -Focused commands should be added or used for: - -- host fixture manifest tests -- package-install conformance tests -- protected-path bypass probe tests -- x402 hostile bypass calibration tests -- claim guard tests - -## Acceptance Claim - -The only acceptable product claim after closeout: - -In environment E, host H, adapter A, policy P, action T, Handshake resisted named bypass routes B and recorded evidence R at freshness state F. - -Any stronger claim fails validation. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/input.md deleted file mode 100644 index a965057..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/input.md +++ /dev/null @@ -1,100 +0,0 @@ -# GSD Macro Input: Host-Specific Bypass Harnesses - -Run id: `host-specific-bypass-harnesses-20260524T084500Z` -Date: 2026-05-24 - -## Hard Frame - -Handshake is protected actions for automated decision making, not engineering-agent-only. - -x402 exact per-call protected action is the first wedge, not the protocol center. - -Host-specific bypass harnesses must prove a configured installed path resisted named host/runtime bypass in a specific environment. They must not claim host-wide MCP/browser/shell/network/package-manager protection. - -The target proof shape: - -```text -host fixture --> wrapped protected action succeeds only after gateway --> raw sibling attempt refused or detected --> bypass proof packet --> protected-path posture update -``` - -## Current Source State - -Existing source already contains: - -- `runBypassProbeExecutors()` and `BypassProbeExecutor` in `src/adapters/protected-path-probes/executor.ts`. -- `fixtureGatewayCheckedBypassProbeExecutors()` for conformance fixture probes. -- x402 hostile bypass probe executors in `src/adapters/x402-payment/bypass-probes.ts`. -- x402 hostile tests proving: - - policy greenlights only after gateway-owned hostile probes pass; - - raw x402 bypass paths cause policy refusal; - - official SDK side channels are raw sibling bypass evidence; - - direct payment, token passthrough, wrapper drift, and failure-open probes are distinct; - - conformance fixture probes cannot manufacture gateway-checked posture; - - fixture wallet custody is not establishment custody evidence. -- Auth.md bypass probes and MCP surface posture tests exist. - -Current `.planning/codebase/CONCERNS.md` says: - -- Broad host interception is not proven. -- Runtime ingress and MCP record observed or synthetic bypass-shaped evidence. -- They do not prove all browser, shell, MCP, package-manager, cloud, network, database, or repo mutation paths are intercepted in a real host. -- Require host-specific bypass probes and gateway-owned credentials before claiming protection for a runtime, MCP host, browser tool, shell wrapper, package manager, or cloud adapter. - -Current `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` says host-specific bypass harnesses should implement: - -```text -host fixture --> wrapped protected action succeeds only after gateway --> raw sibling attempt refused or detected --> bypass proof packet --> protected-path posture update -``` - -Mechanisms: - -- host/runtime fixture manifest; -- raw sibling attempt probes; -- wrapper integrity checks; -- stale host metadata refusal; -- redacted bypass projection. - -Tests: - -- fixture pass/fail tests; -- stale metadata tests; -- claim guards preventing host-wide protection language. - -Failure mode: - -- Host tool list changes after posture is recorded, but gateway still trusts old posture. -- Must refuse or downgrade posture until probes are refreshed. - -## Planning Question - -Create a macro plan for host-specific bypass harnesses that makes the harnesses source-owned, host-specific, freshness-bound, and impossible to launder into broad host protection claims. - -Select the first host harness target. Likely answer: start with local package-manager host harness after package-install adapter conformance, because package install is the next adapter pack and raw package-manager bypass is the sharpest first risk. Challenge if x402-hostile or MCP-host harness should come first. - -## Required Output Properties - -The plan must include: - -- selected first host harness and why; -- explicit non-goals and cut lines; -- host fixture manifest contract; -- raw sibling attempt probes; -- wrapper integrity checks; -- stale metadata and freshness refusal; -- protected-path posture update rules; -- bypass proof packet/redacted projection; -- relationship to package-install adapter expansion; -- relationship to MCP/CLI proposal-only surfaces; -- validation gates and closeout commands; -- claim guards preventing broad host protection language; -- 10-star product bar and antipatterns. - -Do not implement source changes in this run. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ADOPTION.md deleted file mode 100644 index 1fd2751..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ADOPTION.md +++ /dev/null @@ -1,176 +0,0 @@ -# ADOPTION: Host-Specific Bypass Harnesses - -## Invariant At Stake - -A host-specific bypass harness may prove only one installed protected path. If it implies whole-host containment while raw sibling tools can still mutate, it becomes evidence theatre. - -## Operator Workflow - -1. Install one protected adapter path, e.g. `package-install`. -2. Register the expected host surface: - `handshake harness init --host codex --protected-path package-install` -3. Run readiness: - `handshake harness check --host codex --path package-install` -4. Run bypass probes: - `handshake harness probe --host codex --path package-install` -5. Review the report: - `handshake harness report --host codex --path package-install` -6. Decide posture: - `ready`, `advisory`, `blocked`, or `unknown`. - -The workflow should answer one question: - -> "For this host, is this installed protected package-install path actually gateway-bound, and what nearby raw paths remain outside Handshake?" - -Not: - -> "Is this host safe?" - -## Report Affordances - -The report should be intentionally narrow: - -```text -Host: codex -Protected path: package-install -Adapter version: ... -Tool list digest: sha256:... -Wrapper integrity: pass/fail/unknown -Probe freshness: 2026-05-24T... -Gateway authority holder: ... -Raw sibling attempts: detected/refused/unobserved/not-tested -Protected path posture: enforced/advisory/missing/drifted -Non-claims: listed explicitly -``` - -Required sections: - -- `Protected Path`: exact tool/action path under test. -- `Tool List Digest`: host-exposed tool inventory hash at probe time. -- `Wrapper Integrity`: whether the installed wrapper matches expected adapter identity/config. -- `Gateway Binding`: whether mutation requires exact greenlight verification. -- `Probe Freshness`: when probes last ran, against which host digest. -- `Raw Sibling Attempts`: nearby mutation routes attempted outside the wrapper. -- `Evidence`: receipts, refusals, proof gaps, bypass findings. -- `Non-Claims`: what this report does not prove. - -## Command Names - -Keep command names boring and explicit: - -```bash -handshake harness init --host codex --protected-path package-install -handshake harness check --host codex --protected-path package-install -handshake harness probe --host codex --protected-path package-install -handshake harness report --host codex --protected-path package-install -handshake harness doctor --host codex --protected-path package-install -``` - -Avoid names like `secure-host`, `contain`, `lockdown`, or `verify-agent`. They overclaim. - -Useful exit states: - -```text -READY -ADVISORY_ONLY -WRAPPER_MISSING -WRAPPER_DRIFTED -GATEWAY_UNBOUND -RAW_SIBLING_MUTATION_POSSIBLE -STALE_PROBE -HOST_TOOL_DIGEST_CHANGED -PROOF_GAP -``` - -## Diagnostics And Errors - -Good errors name the broken boundary. - -```text -GATEWAY_UNBOUND: -The package-install adapter produced evidence, but no gateway check enforced an exact greenlight before mutation. -This is advisory, not Handshake. -``` - -```text -RAW_SIBLING_MUTATION_POSSIBLE: -The protected package-install path is wrapped, but the host still exposes a raw sibling install path. -This harness does not prove host containment. -``` - -```text -HOST_TOOL_DIGEST_CHANGED: -The host tool list changed since the last passing probe. -Re-run bypass probes before relying on this readiness report. -``` - -```text -WRAPPER_DRIFTED: -The installed wrapper does not match the expected adapter digest. -Do not treat prior receipts as evidence for the current protected path. -``` - -```text -PROOF_GAP: -The harness could not determine whether the mutation reached the gateway before consequence. -Record the gap; do not smooth it into pass/fail. -``` - -## Anti-Frustration Details - -- Always show the one protected path that is in scope. -- Always show raw sibling paths separately from protected path failures. -- Do not fail the whole harness because whole-host containment is absent; mark posture as `ADVISORY_ONLY` or `RAW_SIBLING_MUTATION_POSSIBLE`. -- Cache prior passing probes, but invalidate on host digest, adapter digest, gateway config, or policy version change. -- Give a copy-paste next command after every failure. -- Make `doctor` explain whether the operator needs to install a wrapper, bind a gateway, rerun probes, or accept a non-claim. -- Let operators produce a report even when blocked. A blocked report is useful evidence. -- Do not require dashboard setup for first value. CLI report first; UI later. - -## 10-Star Bar - -A 10-star first host harness does this: - -- Proves one package-install path is gateway-bound before mutation. -- Detects wrapper drift deterministically. -- Hashes the host tool list and invalidates stale readiness. -- Attempts raw sibling package-install routes and reports their posture. -- Separates `protected path enforced` from `host contained`. -- Emits receipts/refusals/proof gaps with stable IDs. -- Produces an operator-readable report in under one minute. -- Gives precise remediation commands. -- Makes non-claims impossible to miss. -- Never lets CLI/MCP evidence masquerade as enforcement. - -## Cut Lines - -Cut whole-host containment claims. - -Cut "agent safety" language. - -Cut host-wide badges unless every consequential sibling path is gateway-enforced. - -Cut CLI/MCP mutation unless it performs a real gateway check before consequence. - -Cut dashboard dependency for the first harness. - -Cut generic "policy passed" language unless the exact contract and one-use greenlight are shown. - -Cut any report that cannot distinguish: - -```text -proposal observed -policy evaluated -gateway checked -mutation attempted -downstream result known -proof gap recorded -``` - -## Brutal Verdict - -Keep the host-specific bypass harness, but narrow it hard. - -The first harness should be a package-install protected-path readiness report, not a host security product. Its job is to make an operator confident that one installed adapter path is real Handshake enforcement, while loudly showing every adjacent path that remains advisory, raw, stale, or unproven. - -Smallest next mechanism to build: define the `package-install` harness report schema with `host`, `protectedPath`, `toolListDigest`, `wrapperIntegrity`, `probeFreshness`, `rawSiblingAttempts`, `protectedPathPosture`, `evidenceRefs`, and `nonClaims`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ARCH.md deleted file mode 100644 index 34f77bd..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/ARCH.md +++ /dev/null @@ -1,230 +0,0 @@ -# ARCH: Host-Specific Bypass Harnesses - -## Invariant At Stake - -Host-specific bypass harnesses must prove only this: for a named environment, the protected path, wrapper path, raw sibling path, stale metadata path, and redacted evidence path behaved as expected under source-owned fixtures. They must not imply host-wide protection, platform-wide safety, or unobserved gateway enforcement. - -## Architecture Plan - -### 1. Host Fixture Manifest Contract - -Create a source-owned manifest that declares the named host fixture, not the host category. - -```ts -type HostFixtureManifest = { - schemaVersion: "host-fixture-manifest.v1"; - manifestId: string; - host: { - kind: "package-install" | "mcp" | "cli" | "x402" | "custom"; - name: string; - fixtureVersion: string; - adapterPackage?: string; - }; - protectedPaths: ProtectedPathFixture[]; - wrappers: WrapperFixture[]; - rawSiblings: RawSiblingFixture[]; - freshness: FreshnessPolicyFixture; - redaction: RedactionPolicyFixture; - expectedPosture: ProtectedPathPostureExpectation; -}; -``` - -The manifest must bind every probe to: - -- exact host fixture identity; -- exact protected path; -- gateway registry entry; -- wrapper entrypoint; -- raw sibling entrypoint, if known; -- expected refusal/proof-gap behavior; -- metadata freshness policy. - -No manifest field may say or imply "host protected." Valid language is "fixture observed," "fixture refused," "fixture proof gap," or "fixture inconclusive." - -### 2. Bypass Proof Packet - -`runBypassProbeExecutors()` should emit a packet that preserves the chain without overclaiming. - -```ts -type BypassProofPacket = { - packetId: string; - manifestId: string; - generatedAt: string; - host: HostFixtureManifest["host"]; - probes: BypassProbeRecord[]; - wrapperIntegrity: WrapperIntegrityRecord[]; - freshnessDecisions: FreshnessDecisionRecord[]; - protectedPathPosture: ProtectedPathPostureRecord; - projection: RedactedBypassProjection; -}; -``` - -The packet is evidence of a fixture run. It is not a receipt for real host behavior and not proof that all sibling mutation paths are covered. - -### 3. Freshness And Staleness Model - -Freshness should be explicit policy, not timestamp vibes. - -Each manifest declares: - -- `metadataIssuedAt`; -- `metadataExpiresAt`; -- `gatewayRegistryDigest`; -- `wrapperDigest`; -- `adapterDigest`; -- `hostFixtureDigest`; -- `maxAgeMs`; -- `requiredClockSkewMs`. - -Stale metadata must produce a refusal-like result: - -```ts -type FreshnessDecision = - | "fresh" - | "stale_metadata_refused" - | "missing_metadata_refused" - | "digest_mismatch_refused" - | "clock_uncertain_proof_gap"; -``` - -The important boundary: stale fixture metadata cannot update protected-path posture to "covered." At most it can produce `proof_gap_stale_metadata`. - -### 4. Protected-Path Posture Update Rules - -Posture must be derived from packet evidence, never set by the adapter claiming safety. - -Recommended posture states: - -```ts -type ProtectedPathPosture = - | "not_declared" - | "declared_unprobed" - | "gateway_checked_fixture_passed" - | "raw_sibling_refused" - | "raw_sibling_bypass_observed" - | "wrapper_integrity_failed" - | "stale_metadata_refused" - | "proof_gap" - | "inconclusive"; -``` - -Update rules: - -- gateway-checked probe passed: may mark only that exact protected path as `gateway_checked_fixture_passed`; -- raw sibling attempt refused: may mark only that named sibling path as `raw_sibling_refused`; -- raw sibling attempt succeeds: path becomes `raw_sibling_bypass_observed`; -- wrapper digest mismatch: `wrapper_integrity_failed`; -- stale metadata: `stale_metadata_refused`; -- missing executor or unmodeled sibling: `proof_gap`; -- conflicting records: `inconclusive`. - -Never aggregate from one fixture to a host-wide posture. - -### 5. Redacted Projection - -The redacted projection is the shareable artifact for docs, dashboards, CI, or package users. - -It should expose: - -- manifest id; -- host kind/name; -- protected path ids; -- probe outcomes; -- posture state; -- refusal/proof-gap reasons; -- timestamps; -- digests or digest prefixes; -- redacted executor labels. - -It must hide: - -- credentials; -- raw host tokens; -- concrete secret-bearing request bodies; -- local filesystem paths unless explicitly safe; -- environment variables; -- private package registry URLs if sensitive; -- full downstream responses that may contain secrets. - -Projection rule: redaction is not allowed to erase the distinction between gateway check, downstream execution, refusal, bypass, and proof gap. If redaction would destroy that distinction, emit `redaction_limited_projection` as a proof gap. - -### 6. Relationship To Package-Install Adapter Pack - -The package-install adapter pack should become the first named host-family proving ground, not a generic bypass guarantee. - -It should provide: - -- one manifest per package-manager fixture; -- gateway-checked install probe; -- raw sibling install attempt probe; -- wrapper integrity probe; -- stale metadata fixture; -- redacted bypass projection fixture. - -Example fixture families: - -- `npm-install.fixture.v1`; -- `pnpm-install.fixture.v1`; -- `bun-add.fixture.v1`; -- `pip-install.fixture.v1`, only when the adapter actually exists. - -Do not claim "package installs protected." Claim "this adapter fixture observed exact gateway enforcement and raw sibling refusal for these declared entrypoints." - -### 7. MCP / CLI Boundary - -MCP and CLI must be treated as separate host boundaries. - -For MCP: - -- manifest binds server name, tool name, tool schema digest, gateway registry id, and raw tool-call sibling if available; -- probe executor attempts both wrapped MCP call and declared raw sibling call; -- receipt must distinguish MCP transport acceptance from gateway authorization. - -For CLI: - -- manifest binds command, subcommand, argument normalization, wrapper binary digest, and raw executable sibling; -- raw sibling probe must prove whether direct command execution bypasses the wrapper; -- if the CLI can shell out to another executable, that must become either a declared sibling or a proof gap. - -Boundary rule: an MCP server exposing a CLI-backed tool does not inherit CLI protection unless the CLI path is separately declared and probed. - -### 8. Import / Export Posture - -Exports should be narrow and product-facing only where the invariant is stable. - -Recommended public exports: - -```ts -export type HostFixtureManifest; -export type BypassProofPacket; -export type RedactedBypassProjection; -export type ProtectedPathPosture; -export function runBypassProbeExecutors(...); -export function projectBypassProofPacket(...); -``` - -Keep internal: - -- hostile executor implementations; -- raw sibling harness internals; -- fixture secret handling; -- digest construction helpers if unstable; -- host-specific test-only executors. - -Import rule: adapters import manifest/probe contracts from core. Core must not import package-install, MCP, or CLI adapter internals. Adapter packs register fixtures outward. - -## Build Order - -1. Define `HostFixtureManifest` and validation tests. -2. Extend probe records into `BypassProofPacket`. -3. Add freshness refusal decisions. -4. Add raw sibling attempt probes. -5. Add wrapper integrity checks. -6. Implement protected-path posture derivation. -7. Add redacted projection. -8. Wire package-install adapter fixtures as the first adapter pack. -9. Add MCP and CLI manifests only after package-install proves the contract shape. - -## Brutal Verdict - -Keep the harness idea, but keep it small. Host harnesses are conformance fixtures, not universal host protection. The smallest next mechanism to build is the `HostFixtureManifest` plus a packet-level posture derivation test that proves stale metadata and raw sibling bypass cannot be smoothed into "protected." diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/EXECUTION.md deleted file mode 100644 index 89de6bb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/EXECUTION.md +++ /dev/null @@ -1,259 +0,0 @@ -# EXECUTION: Host-Specific Bypass Harnesses - -## Invariant At Stake - -Broad host interception is not proven until a host-specific harness shows the exact protected path is enforced, a raw sibling path is refused or detected, stale host posture is rejected, and the surviving evidence is reconstructable. - -## First Host Target - -First target: **package-manager local host**, after package-install conformance lands. - -Reason: package install is consequential, local, cheap to fixture, and has obvious raw siblings: `npm install`, `pnpm add`, `bun add`, `npx`, lockfile mutation, lifecycle scripts, and direct binary invocation. It is narrower and less flaky than preview deploys or cloud APIs, but still exercises the real primitive: generated automation can bypass the wrapped gateway path through the host. - -This plan must stay host-specific. Do not claim broad host interception from one package-manager harness. - -## Phase 0: Scope Lock And Preconditions - -Tasks: - -1. Confirm package-install conformance defines the canonical protected action contract. -2. Identify the wrapped package-install path that already requires policy greenlight and gateway check. -3. Define the raw sibling paths for the first host: - - direct package-manager command - - alternate package-manager binary if present - - package-manager subcommand that mutates lockfile or dependency manifest - - lifecycle-script-triggered mutation path if safe to fixture -4. Define the minimum host metadata required before any host claim: - - host kind - - package-manager binary path - - package-manager version - - project root - - manifest path - - lockfile path - - interception adapter version - - timestamp / freshness window - - fixture id - -Dependencies: - -- Package-install action catalog entry exists. -- Gateway check can bind greenlight to one exact package-install mutation attempt. -- Receipt model can distinguish gateway check from downstream package-manager result. - -Validation gate: - -- If package-install conformance is not landed, stop. A bypass harness without the canonical wrapped path becomes theatre. - -## Phase 1: Host Fixture Contract - -Tasks: - -1. Add a fixture definition for `package-manager-local`. -2. Make the fixture describe both paths: - - `wrappedPath`: expected to succeed only after exact gateway greenlight - - `rawSiblingPath`: expected to be refused, blocked, or detected as bypass -3. Require fixture metadata to be fresh. -4. Define stale metadata refusal: - - stale fixture timestamp - - binary path changed - - package-manager version changed - - manifest or lockfile path changed - - adapter version mismatch -5. Emit a refusal when metadata is stale, not a warning. - -Dependencies: - -- Host fixture model. -- Reason-code registry or equivalent refusal taxonomy. -- Protected path posture store. - -Validation gate: - -- A stale host fixture must produce a refusal/proof-gap receipt before any mutation attempt is allowed. - -## Phase 2: Wrapped Path Success - -Tasks: - -1. Use the package-manager fixture to propose one exact package-install contract. -2. Evaluate policy. -3. Issue one greenlight. -4. Run the wrapped package-manager path through the gateway. -5. Record: - - candidate action - - canonical contract hash - - policy decision - - gateway check result - - package-manager execution result - - manifest/lockfile evidence - - greenlight consumed state - -Dependencies: - -- Deterministic canonicalization. -- One-use greenlight enforcement. -- Receipt store can record gateway and downstream result separately. - -Validation gate: - -- The wrapped path must fail without greenlight. -- The wrapped path must succeed with exact greenlight. -- Reusing the same greenlight must fail. - -## Phase 3: Raw Sibling Refusal Or Detection - -Tasks: - -1. Execute the equivalent raw package-manager sibling path inside the host fixture. -2. Confirm one of the allowed outcomes: - - refused before mutation - - blocked by host interception - - detected as bypass with proof packet -3. Forbid success-without-evidence. -4. Record the bypass attempt against the same fixture id and protected surface. - -Dependencies: - -- Raw sibling command list. -- Interception adapter or detector for package-manager local host. -- Receipt shape for bypass proof packet. - -Validation gate: - -- If raw sibling mutation succeeds and no bypass proof packet is recorded, stop. The generated program escaped the contract boundary. - -## Phase 4: Bypass Proof Packet - -Tasks: - -1. Define the proof packet fields: - - fixture id - - host kind - - protected surface - - wrapped action contract hash if related - - raw sibling command or invocation fingerprint - - host metadata snapshot - - detection/refusal mechanism - - mutation evidence or non-mutation evidence - - timestamp - - posture update recommendation -2. Ensure the proof packet distinguishes: - - refused before mutation - - blocked before mutation - - detected after attempted mutation - - proof gap -3. Add claim guards so docs/tests cannot say "host interception works" without naming the specific host and proof packet. - -Dependencies: - -- Receipt/proof-gap schema. -- Protected path posture model. -- Quality claim guard script or equivalent repo quality check. - -Validation gate: - -- A bypass result without a proof packet is not a pass. -- A proof packet that cannot distinguish gateway check from downstream execution is evidence theatre. - -## Phase 5: Protected Path Posture Update - -Tasks: - -1. Update posture for `package-manager-local`. -2. Use narrow statuses: - - `unproven` - - `wrapped-path-conformant` - - `raw-sibling-detected` - - `raw-sibling-blocked` - - `proof-gap` - - `stale-host-metadata-refused` -3. Make posture host-specific and fixture-specific. -4. Prevent broad claims like "host bypass is solved." - -Dependencies: - -- Posture store or internal protocol note. -- Claim guards. -- Validation output from phases 2-4. - -Validation gate: - -- Posture cannot advance unless wrapped success, raw sibling refusal/detection, and proof packet all exist for the same host fixture. - -## Phase 6: Claim Guards And Closeout - -Tasks: - -1. Add guards that reject unsupported claims: - - "broad host interception" - - "host bypass solved" - - "raw tools blocked" without host target - - "package-manager protected" without proof packet -2. Require docs to name: - - host target - - fixture id or test family - - wrapped path result - - raw sibling result - - stale metadata refusal behavior -3. Keep `.planning/` scratch out of canonical claims. - -Dependencies: - -- Existing quality claim checks. -- Canonical docs ownership rules. - -Validation gate: - -- Any repo-facing claim about host interception must be backed by host-specific test evidence. - -## Closeout Commands - -Run only after implementation, not during this planning turn: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Add focused gates when implemented: - -```bash -npm run test:package-install-conformance -npm run test:host-bypass:package-manager-local -``` - -If those script names do not exist, the implementation should add or map the focused checks before claiming closeout. - -## Rollback / Stop Conditions - -Stop immediately if: - -1. Package-install conformance is not landed. -2. The wrapped path does not require an exact gateway greenlight. -3. The same greenlight can authorize more than one mutation. -4. Raw sibling mutation succeeds without refusal, block, detection, or proof packet. -5. Host metadata can go stale and still allow a greenlight or gateway check. -6. The receipt cannot distinguish gateway check from downstream package-manager execution. -7. A claim guard allows broad host-interception language from one host fixture. - -Rollback posture to `unproven` if: - -1. Package-manager binary path/version changes without refreshed metadata. -2. The fixture no longer exercises a real raw sibling mutation path. -3. The bypass detector only observes logs after consequence and cannot bind evidence to the protected surface. -4. The proof packet cannot be reconstructed from stored evidence. - -## Smallest Implementation Slice - -Build the smallest slice as: - -1. `package-manager-local` fixture. -2. One wrapped package-install path that succeeds after exact gateway greenlight. -3. One raw sibling package-manager invocation that is refused or detected. -4. One bypass proof packet. -5. One stale host metadata refusal. -6. One claim guard preventing broad host-interception claims. - -Smallest next mechanism to build: **a package-manager-local fixture that proves wrapped install succeeds only after gateway greenlight while the equivalent raw sibling path produces a bypass proof packet or refusal.** diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/RISK.md deleted file mode 100644 index dee36d9..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/RISK.md +++ /dev/null @@ -1,72 +0,0 @@ -# RISK: Host-Specific Bypass Harnesses - -## Invariant At Stake - -A host-specific bypass harness may only prove that one named, configured, installed path resisted named bypass attempts at a recorded freshness/version state. Anything broader is advisory, not Handshake. - -## Threat Model / Premortem - -Six months from now, the failure is not that the x402 bypass harness was useless. The failure is that it got laundered into a broad claim: "host interception is covered." It was not. - -The actual threat is generated automation finding an adjacent mutation path that the harness did not name: another binary on `PATH`, a sibling package manager, a direct MCP call, a CLI subcommand, a token passthrough path, a fixture that reports authority without gateway proof, or a stale tool list that no longer matches the installed host. - -The harness must assume: - -- the automated system can inspect environment shape and choose the easiest reachable mutation path; -- wrapper coverage drifts as hosts upgrade, aliases change, symlinks move, or package managers add subcommands; -- MCP and CLI surfaces expose overlapping authority but different enforcement boundaries; -- source fixtures can fabricate or weaken authority if `sourceAuthority` is not tied to gateway evidence; -- receipts can project evidence from one protected path onto another unless scoped aggressively. - -## Risks - -| Risk | Failure Mode | Required Counter-Evidence | -|---|---|---| -| Stale host tool list | Harness tests old configured tools while new reachable tools exist. | Fresh host inventory with command path, version, checksum or equivalent identity, generated immediately before probe. | -| Wrapper drift | Wrapped binary no longer matches actual invoked binary, alias, shim, or subcommand path. | Resolution proof for every tested command: configured wrapper path, resolved executable path, and gateway-bound invocation path. | -| Raw sibling tool reachability | `npm` is wrapped but `pnpm`, `yarn`, `bun`, `npx`, `corepack`, or direct package-manager shims remain reachable. | Negative bypass probes for sibling package-manager binaries and direct shim execution. | -| MCP/CLI overclaim | Passing CLI bypass tests is treated as MCP protection, or MCP probes are treated as CLI protection. | Separate receipts for MCP tool calls and CLI invocations, with distinct authority boundary labels. | -| `sourceAuthority` weakness | Weak conformance fixtures claim source authority without proving gateway-side evaluation. | Fixture receipts must distinguish conformance-source authority from gateway-probe authority. Weak fixtures cannot support protection claims. | -| Token passthrough | Runtime obtains or reuses a token that lets raw tools mutate outside the gateway. | Tests showing raw token use fails or is quarantined when not bound to exact greenlight and gateway check. | -| Fixture laundering | A fixture produces a green-looking result that is later cited as enforcement evidence. | Fixture output must be marked non-enforcement unless it includes gateway decision, greenlight binding, gateway check, and mutation attempt result. | -| Evidence projection leakage | Evidence from x402 probes is used to imply package-manager, MCP, cloud, or host-wide protection. | Claim schema must bind evidence to action type, host tool, path, version, gateway registry entry, and freshness timestamp. | - -## Validation Gates - -1. **Scope Gate** - Every bypass harness result must name exactly what it covers: host, runtime, installed path, resolved binary, tool version, adapter version, gateway registry entry, action type, and timestamp. - -2. **Freshness Gate** - The harness must fail closed if host inventory is stale, incomplete, or not captured immediately before test execution. - -3. **Reachability Gate** - For package-manager expansion, test the wrapped path and raw sibling paths separately. Passing `x402` probes does not count. - -4. **Gateway Evidence Gate** - A passing result must include proposal, policy decision, one-use greenlight binding, gateway check, execution result or refusal, and proof-gap handling. - -5. **Boundary Label Gate** - Every receipt must label whether it came from fixture conformance, gateway probe, CLI path, MCP path, browser path, or adapter path. - -6. **Overclaim Gate** - Docs, test names, report names, and status summaries must not say "host protected," "interception covered," or "bypass-proof." They may say only: "named configured path resisted named bypass attempts at recorded freshness state." - -## Stop Conditions - -Stop and do not claim protection if: - -- host tool inventory cannot be refreshed; -- raw sibling package-manager reachability is untested; -- wrapper resolution differs from the actual executed binary; -- MCP and CLI evidence are mixed into one claim; -- `sourceAuthority` is fixture-derived without gateway proof; -- token passthrough can mutate without exact greenlight binding; -- a fixture result is cited as gateway enforcement; -- receipts cannot distinguish gateway check from downstream execution; -- evidence from x402 is projected onto package-manager, MCP, CLI, or host-wide claims. - -## Brutal Verdict - -Keep the host-specific bypass harnesses, but narrow the claim hard. They are useful as named-path adversarial probes. They are dangerous as host protection evidence. - -The smallest next mechanism to build: a bypass evidence claim schema that forces every result to bind to `hostToolIdentity`, `resolvedPath`, `adapterVersion`, `gatewayRegistryEntry`, `actionType`, `freshnessTimestamp`, `probeClass`, and `claimScope`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/STRATEGY.md deleted file mode 100644 index cbc9e2f..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/raw/STRATEGY.md +++ /dev/null @@ -1,82 +0,0 @@ -# STRATEGY: Host-Specific Bypass Harnesses - -## Invariant At Stake - -A bypass harness must prove only this: a configured installed protected-action path resisted a named bypass route in a named host/runtime environment. Anything broader becomes evidence theatre. - -## Strategic Sequencing - -1. **Package-manager host harness first** - - Choose local package-manager host after package-install conformance. - - This is the right first host target because package installs are already a protected automated-decision action in the current adapter context, they produce material side effects, and the next adapter plan already wants package-manager material attestation. The host surface is narrow enough to test honestly: `npm`/`pnpm`/`bun` invocation path, wrapper path, raw sibling path, lifecycle script posture, registry/custody source, lockfile/package manifest mutation, and failure-closed behavior. - -2. **x402-hostile harness second** - - x402 hostile probes already exist, so this should become the calibration harness, not the first strategic host claim. - - Use it to prove the harness model can express named bypasses cleanly: raw sibling, MCP direct, token passthrough, wrapper drift, custody source authority, failure closed. But do not let x402 become the category center. x402 exact is a wedge; Handshake is protected actions for automated decision making. - -3. **MCP-host harness third** - - MCP-host comes after the harness contract is boring and repeatable. - - MCP is strategically important, but first MCP harness claims will be easy to overstate. "Protected against MCP bypass" is too broad. The acceptable first MCP claim is closer to: this configured MCP server/tool route denied direct invocation of this protected action unless the gateway-bound contract and one-use greenlight matched. - -## Claim Boundary - -Acceptable claim: - -> In environment `E`, with host `H`, adapter version `A`, gateway policy `P`, and protected action type `T`, Handshake resisted named bypass route `B` and recorded receipt/refusal/proof-gap evidence `R`. - -Unacceptable claim: - -> Handshake protects package managers, MCP, shell, browser, network, or hosts generally. - -For the first package-manager harness, the claim should be: - -> Handshake proves that a configured package-install path cannot mutate the declared package-manager material surface through the named raw/wrapper/sibling bypass routes without exact contract canonicalization, policy decision, one-use greenlight, gateway check, and receipt/proof-gap evidence. - -## 10-Star Bar - -A 10-star host harness has to satisfy all of this: - -1. Names the host, version, OS/runtime, adapter, gateway registry, and protected action type. -2. Defines the protected material surface before execution. -3. Declares every tested bypass route by name. -4. Separates read-only package inspection from package-install mutation. -5. Verifies exact contract canonicalization before policy. -6. Verifies one-use greenlight binding at gateway check. -7. Proves wrapper drift fails closed. -8. Proves raw sibling invocation cannot silently mutate the protected surface. -9. Records refusal, bypass detection, proof gap, or execution receipt distinctly. -10. Emits reconstruction evidence sufficient to replay the decision chain six months later. - -For package-manager specifically, "material surface" should include at minimum: manifest, lockfile, installed artifact tree, lifecycle script execution posture, registry/source/custody metadata, package-manager binary path, and gateway decision/receipt linkage. - -## Cut Lines - -Cut any claim that says "host-wide protection." - -Cut any harness that only tests the happy adapter path. - -Cut any bypass result that says "pass" without distinguishing refusal, gateway denial, quarantine, proof gap, or no-op. - -Cut any test where the package manager can mutate through a raw shell path and Handshake merely notices afterward. That is advisory, not Handshake. - -Cut any x402-first sequencing that makes the company look like an x402 compliance/protocol tool. - -Cut any MCP-first sequencing that claims MCP protection before proving one named MCP tool route in one named runtime. - -Cut any "browser/shell/network/package-manager protection" language unless each is a named host harness with bounded environment evidence. - -## Brutal Verdict - -Keep package-manager host first. - -Use x402-hostile as the proving-ground for harness semantics, not as the category anchor. - -Defer MCP-host until the harness contract can resist overclaiming. - -Smallest next mechanism to build: define the package-manager host harness contract: `HostEnvironment`, `ProtectedMaterialSurface`, `BypassRoute`, `ExpectedGatewayDecision`, and `ReceiptOrProofGapEvidence`. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/synthesis.md deleted file mode 100644 index 14d69cf..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/host-specific-bypass-harnesses/runs/host-specific-bypass-harnesses-20260524T084500Z/synthesis.md +++ /dev/null @@ -1,119 +0,0 @@ -# Chair Synthesis: Host-Specific Bypass Harnesses - -## Invariant At Stake - -Handshake is protected actions for automated decision making. The invariant is exact protected action control, not engineering-agent identity and not host-wide safety. - -A host harness may prove only that a named configured installed path resisted named bypass routes at a recorded freshness state. Anything broader is false precision. - -## Synthesis - -The council converges on package-manager local host first. - -Strategy is right to force the wedge after package-install conformance. Package install is concrete, consequential, and adoption-legible. x402 remains useful as hostile-probe calibration, but it must not become the center of the architecture. - -Architecture is right that the missing primitive is not another probe. The missing primitive is `HostFixtureManifest` v1 plus `BypassProofPacket`. Without those two contracts, probe results become prose confidence and then product overclaim. - -Execution is right to phase this through wrapped path success, raw sibling probes, wrapper integrity, stale metadata refusal, proof packet, posture derivation, and claim guards. The stop conditions are not optional. Raw sibling mutation without refusal or proof gap kills the claim. - -Risk is right that every evidence result must bind host tool identity, resolved path, adapter version, registry entry, action type, freshness timestamp, probe class, and claim scope. If any of those are missing, posture is advisory or proof-gapped. - -Adoption is right that CLI report comes before dashboard. The first user-facing product surface must teach the narrowness of the claim, not hide it. - -## Final Position - -Keep the macro item, but narrow it hard. - -The first deliverable is not "host bypass protection." The first deliverable is: - -For package-manager local host H, protected path T, adapter A, policy P, and freshness state F, Handshake can report whether the configured wrapper is gateway-bound, whether one-use greenlight behavior holds, whether named raw sibling routes bypass control, and what evidence or proof gaps remain. - -That is the product. Everything else is theatre until enforced. - -## Required Mechanisms - -1. `HostFixtureManifest` v1 - - host identity - - environment identity - - adapter identity and version - - protected action type - - protected path - - configured wrapper path - - resolved wrapper path - - raw sibling candidates - - registry entry - - policy identity - - tool list digest - - freshness timestamp - - expected posture - - redaction policy - - non-claims - -2. `BypassProofPacket` - - manifest reference - - probe classes - - probe inputs and outputs - - wrapper integrity - - gateway binding - - freshness decisions - - gateway check result - - downstream execution result - - refusal evidence - - bypass evidence - - proof gaps - - protected-path posture - - redacted projection - - non-claims - -3. Exit states - - `READY` - - `ADVISORY_ONLY` - - `WRAPPER_MISSING` - - `WRAPPER_DRIFTED` - - `GATEWAY_UNBOUND` - - `RAW_SIBLING_MUTATION_POSSIBLE` - - `STALE_PROBE` - - `HOST_TOOL_DIGEST_CHANGED` - - `PROOF_GAP` - -## Antipatterns - -- Treating wrapped path success as package-manager safety. -- Treating fixture probes as establishment custody evidence. -- Treating x402 exact per-call proof as protocol center. -- Treating MCP or CLI reports as enforcement. -- Treating stale probe results as current posture. -- Treating redacted reports as permission to flatten evidence. -- Treating a package-install harness as browser, shell, network, MCP, or platform coverage. -- Treating "agent safety" as the category instead of protected actions for automated decision making. -- Treating one greenlight as reusable authority. -- Treating downstream success as proof that the gateway enforced. - -## Closeout Standard - -This macro closes only when the implementation plan can be validated against: - -- package-install conformance precondition -- manifest schema tests -- wrapped one-use greenlight tests -- raw sibling refusal or proof-gap tests -- wrapper missing and drift tests -- stale metadata tests -- proof packet redaction tests -- protected-path posture tests -- CLI report non-claim tests -- claim guards -- `npm run quality:claims` -- `npm run quality:architecture` -- `npm run format:check` -- `npm run check:repo` - -## Brutal Verdict - -Keep, narrowed. - -The useful primitive is host-specific protected-path posture, not host protection. The first harness should be package-manager local host because it is concrete enough to falsify. If the implementation cannot keep fixture scope, gateway binding, raw sibling posture, freshness, and non-claims intact, cut the claim back to advisory evidence. - -## Smallest Next Mechanism - -Define `HostFixtureManifest` v1 for the package-manager local host harness, with freshness refusal and explicit non-claims, before adding another probe. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/ASSUMPTIONS.md deleted file mode 100644 index 1fd0ee5..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/ASSUMPTIONS.md +++ /dev/null @@ -1,41 +0,0 @@ -# Assumptions - -## Product Assumptions - -- Handshake is protected actions infrastructure for automated decision making. -- x402 exact per-call protected spend is the first wedge. -- Hosted admission and redacted evidence reads are Tier 2 mechanisms. -- Tier 1 kernel authority boundaries remain unchanged. -- Engineering-agent workflows are stress/adoption context, not the product boundary. -- The valid hosted claim is narrow: admit exact protected-call transitions before kernel invocation and expose redacted evidence through tenant-scoped read controls. - -## Source Assumptions - -- Hosted mode already exists as a transport admission seam. -- `HostedCallerVerifier`, `TransitionCallerIdentity`, role checks, freshness checks, and scope checks already happen before body parse/kernel invocation. -- Accepted hosted transitions already store digest/ref evidence rather than raw tokens or raw user headers. -- Evidence read routes already check tenant/org boundaries. -- Generic raw record reads already consult `rawReadPosture`. -- D1/HTTP tests already cover durable protocol surface and local D1 behavior. - -## External Assumptions - -- Cloudflare D1/KV local/dev posture is not production proof. -- Wrangler local/dev behavior and remote/prod behavior must be validated separately. -- Cloudflare D1 bindings, KV bindings, migrations, and remote deployment state require explicit proof. -- Sensitive values belong in Cloudflare secrets, not public vars. -- Readiness may report secret names and presence, never secret values. -- KV consistency limits make it unsuitable as authoritative evidence storage unless limitations are explicit. -- D1 should own structured evidence indexes and records for this plan. - -## Validation Requirements - -- Hosted admission must fail closed when deployment-mode config is absent or inferred. -- Role, scope, freshness, and tenant/org/project mapping must be checked before body parse/kernel invocation. -- Redacted reads must require tenant/org/project entitlement and exact receipt/evidence id. -- Missing and unauthorized records must produce oracle-safe denial. -- Raw reads must obey explicit `rawReadPosture`. -- Readiness must distinguish local/dev, preview, and production posture. -- Secret values must never appear in readiness, receipts, logs, exports, or support bundles. -- Redaction must be proven by fuzzing and read matrices, not wording. -- Hosted claims must be guarded by enforcement evidence. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/CONTEXT.md deleted file mode 100644 index e30621e..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/CONTEXT.md +++ /dev/null @@ -1,29 +0,0 @@ -# Context - -This run is planning-only for the macro item: hosted admission plus redacted evidence plane. - -The hard product frame is protected actions for automated decision making. The first wedge is exact x402 per-call protected action, not general engineering-agent execution control. Engineering agents are relevant as stress and adoption context only. - -The hosted surface must stay narrow. It may admit exact protected-call transitions before kernel invocation and expose redacted evidence records through tenant-scoped read controls. It must not become hosted mutation authority, payment management, settlement, provider custody, general hosted Handshake operation, or compliance/audit theatre. - -The goal path is: - -```text -caller role token --> route admission --> tenant/org/project scope --> protocol transition or redacted read --> durable D1/KV storage --> audit-safe response -``` - -Known source state to preserve: - -- hosted mode already exists as a transport admission seam; -- hosted caller role/freshness/scope checks happen before body parse/kernel invocation; -- accepted hosted transitions store digest/ref evidence, not raw tokens/user headers; -- evidence read routes check tenant/org boundaries; -- generic raw record reads consult rawReadPosture; -- D1/HTTP tests cover durable protocol surface/local D1. - -The macro plan closes the gap between local hosted mechanics and an operated hosted read/admission posture without pretending local D1 tests, provider-neutral identity, or redacted receipts prove production readiness. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/DECISIONS.md deleted file mode 100644 index df21adf..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/DECISIONS.md +++ /dev/null @@ -1,37 +0,0 @@ -# Decisions - -## D1 Owns Structured Evidence - -D1 is the authoritative store for structured evidence indexes and records in this plan. KV may be used only for non-authoritative acceleration, references, cache posture, or derived read support with explicit consistency/audit limitations. - -## Hosted Is Admission And Read Plane Only - -Hosted mode may perform route admission and redacted evidence reads. It does not hold general hosted mutation authority, payment-management authority, settlement authority, provider custody, or compliance certification authority. - -## Deployment Mode Is Mandatory - -Hosted behavior must declare deployment mode: `local-dev`, `test`, `preview`, or `production`. Promoted hosted behavior cannot run from inferred defaults. - -## Admission Roles Are Not Read Entitlements - -Transition admission identity and evidence read entitlement are separate. A caller admitted to submit a protected transition is not automatically entitled to read evidence. - -## Redacted Evidence Is The Default Read Surface - -The default hosted read path returns redacted evidence only. Raw evidence is unavailable, disabled, gated, or allowed according to explicit `rawReadPosture`. - -## Raw Reads Require Strong Posture - -Raw evidence access, if ever allowed, requires explicit role, scope, purpose, time bounds, tenant/org/project entitlement, and audit evidence. Convention-only raw access is forbidden. - -## Readiness Is Posture, Not Liveness - -Hosted readiness reports enforcement and configuration posture: mode, bindings, secrets presence, vars, migrations, schema, verifier, redaction, retention, export, and unsupported capabilities. It is not a production-readiness badge. - -## Secret Values Are Never Evidence - -Secret names and presence may be reported. Secret values must not appear in readiness, logs, receipts, evidence records, exports, or support bundles. - -## Claim Guard Is A Product Control - -Docs, scripts, and repo-facing claims must not imply hosted operation, production readiness, compliance audit, payment management, settlement, custody, or hosted mutation authority unless enforcement gates exist. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/PLAN.md deleted file mode 100644 index 183b3bb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/PLAN.md +++ /dev/null @@ -1,303 +0,0 @@ -# GSD Macro Plan: Hosted Admission And Redacted Evidence Plane - -## Goal - -Invariant at stake: hosted admission and hosted reads must not become hosted mutation authority, payment management, settlement, provider custody, general Handshake operation, or compliance theatre. - -Build a Tier 2 hosted admission plus redacted evidence plane for exact x402 protected calls: - -```text -caller role token --> route admission --> tenant/org/project scope --> protocol transition or redacted read --> durable D1/KV storage --> audit-safe response -``` - -Permitted product claim after closeout: Handshake admits exact protected-call transitions before body/kernel trust and exposes redacted evidence records through tenant-scoped read controls. - -## Non-Goals - -- No hosted mutation execution authority. -- No hosted payment credential custody beyond gateway-held credential creation already required by exact x402 per-call protected spend. -- No settlement, billing operations, or payment-management product surface. -- No general hosted Handshake operation claim. -- No production-readiness claim until Cloudflare bindings, migrations, secrets, readiness, and redaction matrices are proven. -- No compliance, audit-certification, or retention-policy claim beyond explicit evidence classes and proof gaps. -- No raw evidence read by default. -- No expansion from x402 protected spend into general engineering-agent control. - -## Source Boundary - -Tier 1 kernel boundaries remain intact: - -- operating envelopes authorize attempts, not mutations; -- exact action contracts remain proposed commitments, not execution authority; -- greenlights remain one-use and gateway-bound; -- gateway checks remain the final enforcement point before consequence; -- receipts distinguish proposal, policy decision, gateway check, downstream execution, refusal, and proof gap; -- missing or unavailable evidence is recorded, not smoothed over. - -Hosted surfaces are Tier 2 mechanisms only: - -- route admission before body parse and kernel invocation; -- caller identity verification; -- tenant/org/project-scoped read authorization; -- redacted evidence response shaping; -- durable storage binding and readiness reporting. - -## Current State - -Known source state to preserve: - -- Hosted mode exists as a transport admission seam. -- `HostedCallerVerifier`, `TransitionCallerIdentity`, and role/freshness/scope checks happen before body parse and kernel invocation. -- Accepted hosted transitions store digest/ref evidence, not raw tokens or raw user headers. -- Evidence read routes check tenant/org boundaries. -- Generic raw record reads consult `rawReadPosture`. -- D1/HTTP tests cover durable protocol surface and local D1 behavior. - -Known gaps: - -- No operated deployment-mode config. -- No production org/project/RBAC/read entitlement model beyond provider-neutral identity. -- No retention/export policy or audit reader posture. -- No hosted readiness probe. -- No Cloudflare D1/KV deployment and secrets proof. -- No product-level redaction fuzzing or read-entitlement matrix. -- No hosted claim guard beyond no-hosted wording. - -## Target State - -A hosted admission and redacted evidence plane with these explicit boundaries: - -- Deployment modes: `local-dev`, `test`, `preview`, `production`. -- Config declares verifier strategy, freshness window, admitted roles, admitted scopes, tenant source, D1/KV bindings, secret names, public vars, raw read posture, redaction profiles, retention posture, export posture, and readiness expectations. -- Admission is deny-by-default when hosted behavior would run with inferred authority defaults. -- Reader authorization is separate from transition admission. -- Roles are explicit: `viewer`, `auditor`, `operator`, `rawEvidenceReader`. -- Scopes are exact: `evidence:redacted:read`, `evidence:raw:request`, `evidence:raw:read`, `evidence:export:create`, `evidence:retention:admin`, `hosted:readiness:read`. -- D1 owns structured evidence indexes and records. -- KV is non-authoritative unless consistency and audit limits are explicitly documented. -- Redacted reads accept exact receipt/evidence identifiers, tenant/org/project scope, and read entitlement. -- Raw reads are unavailable, disabled, gated, or allowed only through `rawReadPosture`. -- Readiness reports state, not secrets: mode, binding presence, secret names/presence, vars, D1 local vs remote posture, migration/schema status, verifier posture, redaction profile, retention/export posture, and unsupported capabilities. -- SDK/CLI/MCP clients are read-only by default and label authority class, mutation posture, gateway-authority posture, and raw-evidence posture. - -## Assumptions - -- Cloudflare D1/KV local/dev proof is not production proof. -- Wrangler local/dev and remote/prod posture must be validated separately. -- Sensitive values live in Cloudflare secrets, not public vars. -- Readiness may report secret names and presence, never values. -- KV must not become authoritative evidence storage unless consistency and audit limitations are explicit. -- D1 owns structured evidence indexes and records for this plan. -- Hosted admission cannot infer production behavior from missing config. -- Evidence reads must avoid missing-vs-cross-tenant oracles. -- Redaction correctness requires fuzzing and matrix tests, not snapshot-only confidence. -- Engineering agents remain stress/adoption context, not the product boundary. - -## Decisions - -1. Keep the wedge as exact x402 per-call protected actions. -2. Treat hosted admission and redacted evidence reads as Tier 2 mechanisms. -3. Add deployment-mode config before adding broader hosted surfaces. -4. Split transition roles from read entitlements. -5. Make redacted evidence the default read plane. -6. Keep raw evidence unavailable or gated by explicit posture, purpose, time bounds, and audit. -7. Use D1 as the authoritative structured evidence store. -8. Use KV only for non-authoritative acceleration or references with explicit limitations. -9. Add readiness as a posture report, not a liveness badge. -10. Add claim guards so docs and scripts cannot claim hosted operation beyond enforcement. - -## Phases - -### Phase 0 - Boundary And Claim Lock - -Codify the hosted claim boundary and stop hosted language from implying production operation, mutation authority, payment management, custody, settlement, or compliance-grade audit. - -Outputs: - -- hosted claim guard; -- forbidden claim list; -- docs wording updates if needed; -- validation that Tier 1 kernel claims remain unchanged. - -### Phase 1 - Deployment-Mode Admission Config - -Add operated deployment-mode config for hosted admission. - -Outputs: - -- `deploymentMode` with `local-dev`, `test`, `preview`, `production`; -- verifier strategy declaration; -- role/scope/freshness config; -- tenant/org/project source config; -- deny-by-default behavior for missing hosted authority config. - -### Phase 2 - Reader Authorization Boundary - -Split admission identity from evidence reader entitlement. - -Outputs: - -- read roles and scopes; -- tenant/org/project predicates on every read path; -- oracle-safe denial responses; -- SDK/CLI/MCP read-only posture labels. - -### Phase 3 - Redacted Evidence Contract And Raw Posture - -Define the redacted evidence response contract and harden raw-read posture. - -Outputs: - -- redacted evidence schema; -- receipt-id-only read input; -- raw read states: `unavailable`, `disabled`, `gated`, `allowed`; -- raw access purpose/time-bound audit requirements; -- proof-gap responses for unavailable evidence. - -### Phase 4 - D1/KV Durable Posture And Readiness - -Prove D1/KV binding posture and expose hosted readiness. - -Outputs: - -- D1 structured evidence index ownership; -- KV non-authoritative posture; -- local/dev vs remote/prod D1 status; -- migration/schema proof; -- secret presence reporting without values; -- readiness states: `active`, `configured_but_unverified`, `missing`, `disabled`, `read_only`, `not_promoted`. - -### Phase 5 - Retention, Export, And Redaction Proof - -Make evidence lifecycle explicit without claiming compliance certification. - -Outputs: - -- retention classes; -- export creation scope and receipt; -- redacted support bundle contract; -- redaction fuzz tests; -- product-level read matrix. - -## Task Graph - -```text -P0 claim boundary - -> P1 deployment-mode admission config - -> P2 reader authorization boundary - -> P3 redacted evidence contract - -> P3 rawReadPosture hardening - -> P4 D1/KV readiness - -> P4 secrets posture - -> P5 retention/export posture - -> P5 redaction fuzzing - -> P5 SDK/CLI/MCP read posture - -> P5 hosted closeout guard -``` - -Critical path: - -```text -deployment mode --> deny-by-default hosted config --> tenant/org/project read predicate --> redacted evidence schema --> D1 authoritative evidence proof --> readiness posture --> redaction/read matrix --> claim guard -``` - -## Risks And Mitigations - -- Auth bypass: deny-by-default admission, freshness checks, exact role/scope allowlist. -- Caller identity overreach: provider-neutral identity cannot imply org/project entitlement without mapping. -- Token/email leakage: store digest/ref evidence only and fuzz redaction. -- Cross-tenant read leak: tenant/org/project keying plus read predicates. -- Missing-vs-cross-tenant oracle: same denial shape for missing and unauthorized records. -- Raw record exfiltration: default unavailable/disabled posture, gated role/scope/purpose/time-bound audit. -- D1 config drift: readiness reports local/remote D1 mode, binding, migration, and schema status. -- Secret leakage: readiness reports secret names/presence only. -- Hosted theatre: claim guard blocks production/general-hosted/compliance wording until gates pass. -- Replay/status risk: replay rejection remains explicit evidence. -- Retention risk: retention class and proof-gap language required before export/read claims. - -## Validation Gates - -Required gates before claiming the plan complete: - -- Hosted admission rejects missing deployment-mode config in hosted paths. -- Hosted admission checks caller role, freshness, scope, tenant/org/project mapping before body parse/kernel invocation. -- Accepted hosted transitions store digest/ref evidence only. -- Redacted evidence reads require receipt id and tenant/org/project entitlement. -- Cross-tenant and missing records are oracle-safe. -- Raw reads obey `rawReadPosture`. -- D1 owns structured evidence indexes/records. -- KV posture is explicitly non-authoritative. -- Readiness reports Cloudflare binding, migration, schema, and secret presence without leaking values. -- Wrangler local/dev proof and remote/prod proof are separately labeled. -- Redaction fuzzing covers tokens, headers, emails, authorization strings, cookies, payment hints, and provider metadata. -- Claim guard rejects hosted mutation authority, hosted payment management, settlement, custody, production readiness, compliance audit, and general hosted Handshake claims. - -Suggested closeout commands: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -npm test -- --run hosted -npm test -- --run d1 -npm test -- --run evidence -npm test -- --run redaction -``` - -## Cut Lines - -Cut or defer: - -- full RBAC administration UI; -- payment management; -- settlement support; -- provider custody; -- general hosted Handshake operation; -- compliance certification; -- raw evidence browsing; -- hosted mutation orchestration; -- write-capable SDK/CLI/MCP clients; -- multi-provider production deployment automation. - -Keep: - -- deployment-mode config; -- route admission; -- tenant/org/project read boundary; -- redacted evidence contract; -- raw-read posture; -- D1/KV readiness; -- secret-safe readiness; -- redaction fuzzing; -- hosted claim guard. - -## Rollback / Stop Conditions - -Stop implementation or rollback the slice if: - -- hosted behavior can run with inferred authority defaults; -- redacted reads accept broad query filters instead of exact receipt ids; -- raw evidence is controlled only by convention; -- hosted readiness passes with in-memory or stub storage in a promoted mode; -- secret values appear in readiness, logs, receipts, exports, or support bundles; -- clients bypass reader authorization; -- export is a dump of receipts without redaction, entitlement, and audit posture; -- marketing/docs claim hosted operation beyond enforcement; -- Cloudflare local D1 tests are treated as production proof. - -## Smallest Next Action - -Add the deployment-mode hosted admission config and claim guard first: hosted routes must fail closed unless mode, verifier strategy, freshness, role/scope policy, tenant source, D1 binding posture, raw-read posture, and secret-name declarations are explicit. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/RISKS.md deleted file mode 100644 index 9520c32..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/RISKS.md +++ /dev/null @@ -1,18 +0,0 @@ -# Risk Register - -| Risk | Failure Mode | Impact | Mitigation | Validation | -|---|---|---:|---|---| -| Hosted auth bypass | Route accepts hosted transition without explicit deployment/verifier/role/scope config | Critical | Deny-by-default hosted config | Missing-config rejection tests | -| Caller identity overreach | Provider-neutral identity becomes org/project entitlement | Critical | Explicit tenant/org/project mapping | Cross-scope admission tests | -| Body trust before admission | Parser/kernel observes unadmitted request | Critical | Admission before body parse/kernel invocation | Route-order tests | -| Token/header leakage | Raw auth material appears in receipt/readiness/log/export | Critical | Digest/ref evidence only, redaction schema | Redaction fuzzing | -| Cross-tenant evidence leak | Read route misses tenant/org/project predicate | Critical | Storage keying plus read predicate | Tenant matrix tests | -| Missing-vs-unauthorized oracle | Response distinguishes absent record from cross-tenant record | High | Oracle-safe denial | Negative read matrix | -| Raw evidence exfiltration | Raw reads allowed by role name or convention | Critical | `rawReadPosture` with scope/purpose/time/audit | Raw posture tests | -| D1 production drift | Local D1 proof treated as remote/prod proof | High | Readiness labels local/remote and migration/schema status | Wrangler local and remote proof gates | -| KV authority creep | KV becomes evidence source of truth | High | D1 authoritative decision, KV limitation docs | Storage contract tests | -| Secret leakage | Readiness exposes secret values or dynamic env dump | Critical | Secret names/presence only | Snapshot and fuzz checks | -| Hosted theatre | Readiness says ready while storage/verifier/secrets are stubs | High | `configured_but_unverified`, `not_promoted`, `missing` states | Readiness fixture matrix | -| Claim overreach | Docs imply hosted Handshake, compliance audit, custody, or production operation | High | Claim guard | `quality:claims` | -| Export overreach | Export dumps raw receipts without entitlement/redaction/audit | High | Export scope, redaction, receipt, proof gaps | Export contract tests | -| Retention theatre | Retention language exceeds implemented lifecycle | Medium | Retention classes and proof gaps | Retention matrix | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/TASKS.jsonl deleted file mode 100644 index f2f2487..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/TASKS.jsonl +++ /dev/null @@ -1,12 +0,0 @@ -{"id":"HOSTED-001","priority":"P0","phase":"Phase 0","title":"Lock hosted claim boundary","owner":"product-architecture","rationale":"Hosted admission/read surfaces must not imply mutation authority, production operation, payment management, custody, settlement, or compliance audit.","depends_on":[],"acceptance":["Forbidden hosted claims are enumerated","Permitted claim is limited to exact protected-call admission and redacted tenant-scoped reads","Tier 1 kernel language remains unchanged"],"candidate_paths":["AGENTS.md","README.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","scripts/quality"],"non_goals":["Implement hosted runtime","Add payment management","Claim production readiness"]} -{"id":"HOSTED-002","priority":"P0","phase":"Phase 1","title":"Add explicit deployment-mode hosted admission config","owner":"runtime-protocol","rationale":"Hosted behavior must not run from inferred authority defaults.","depends_on":["HOSTED-001"],"acceptance":["deploymentMode supports local-dev test preview production","Hosted routes fail closed when required config is missing","Verifier strategy freshness roles scopes and tenant source are explicit"],"candidate_paths":["src/hosted","src/http","src/protocol","tests/hosted"],"non_goals":["Cloudflare deployment automation","RBAC admin UI","General hosted operation"]} -{"id":"HOSTED-003","priority":"P0","phase":"Phase 1","title":"Prove admission happens before body parse and kernel invocation","owner":"runtime-protocol","rationale":"The hosted seam is only meaningful if unadmitted requests cannot reach body trust or kernel state.","depends_on":["HOSTED-002"],"acceptance":["Role freshness scope and tenant checks run before body parsing","Rejected requests leave refusal/proof-gap evidence as appropriate","Tests fail if parser or kernel is invoked before admission"],"candidate_paths":["src/http","src/hosted","tests/http","tests/hosted"],"non_goals":["Change Tier 1 policy semantics","Add new action types"]} -{"id":"HOSTED-004","priority":"P0","phase":"Phase 2","title":"Split transition admission from evidence read entitlement","owner":"authorization","rationale":"A caller admitted to submit a transition must not automatically read evidence.","depends_on":["HOSTED-002"],"acceptance":["Read roles viewer auditor operator rawEvidenceReader are modeled","Read scopes are exact and separate from admission scopes","Tenant org project predicates gate every read"],"candidate_paths":["src/evidence","src/hosted","src/http","tests/evidence"],"non_goals":["Full production RBAC console","Human persona modeling"]} -{"id":"HOSTED-005","priority":"P0","phase":"Phase 2","title":"Make evidence read denial oracle-safe","owner":"authorization","rationale":"Missing-vs-cross-tenant distinctions can leak evidence existence.","depends_on":["HOSTED-004"],"acceptance":["Unauthorized and missing reads share safe denial shape","Logs/receipts preserve internal reason without leaking to caller","Read matrix covers same-tenant cross-tenant missing and malformed ids"],"candidate_paths":["src/evidence","src/http","tests/evidence"],"non_goals":["User-facing audit dashboard","Broad evidence search"]} -{"id":"HOSTED-006","priority":"P0","phase":"Phase 3","title":"Define redacted evidence response contract","owner":"evidence-plane","rationale":"Redacted evidence must be a typed contract, not ad hoc response shaping.","depends_on":["HOSTED-004"],"acceptance":["Redacted reads accept exact receipt/evidence id only","Response distinguishes stored redacted unavailable refused and proof-gap fields","Tokens headers emails cookies and payment hints are excluded or redacted"],"candidate_paths":["src/evidence","src/protocol","tests/evidence","tests/redaction"],"non_goals":["Raw evidence browsing","Compliance report format"]} -{"id":"HOSTED-007","priority":"P0","phase":"Phase 3","title":"Harden rawReadPosture","owner":"evidence-plane","rationale":"Raw evidence is the highest-leakage surface and must not be controlled by convention.","depends_on":["HOSTED-006"],"acceptance":["States unavailable disabled gated allowed are enforced","Raw reads require explicit role scope purpose time bound and audit when gated/allowed","Default posture blocks raw reads"],"candidate_paths":["src/evidence","src/http","tests/evidence"],"non_goals":["Make raw access easy","Support bundle raw dumps"]} -{"id":"HOSTED-008","priority":"P1","phase":"Phase 4","title":"Codify D1 authoritative and KV non-authoritative storage posture","owner":"storage","rationale":"KV must not become authoritative evidence storage without explicit consistency/audit limits.","depends_on":["HOSTED-006"],"acceptance":["D1 owns structured evidence indexes and records","KV usage is documented and tested as non-authoritative","Storage contract rejects promoted mode without D1 binding proof"],"candidate_paths":["src/storage","src/evidence","tests/d1","docs/internal/protocol-notes.md"],"non_goals":["Replace D1 with KV","Build analytics warehouse"]} -{"id":"HOSTED-009","priority":"P1","phase":"Phase 4","title":"Add hosted readiness posture probe","owner":"operations","rationale":"Readiness must report enforcement posture, not process liveness or marketing readiness.","depends_on":["HOSTED-002","HOSTED-008"],"acceptance":["Readiness reports mode bindings secrets names/presence vars local-vs-remote D1 migration schema verifier redaction retention export","Readiness states include active configured_but_unverified missing disabled read_only not_promoted","Secret values are never emitted"],"candidate_paths":["src/hosted","src/http","src/storage","tests/readiness"],"non_goals":["Production SLA monitor","Secret discovery by env dump"]} -{"id":"HOSTED-010","priority":"P1","phase":"Phase 5","title":"Add retention export and support-bundle posture","owner":"evidence-plane","rationale":"Audit-safe reads need explicit lifecycle and export limits without compliance theatre.","depends_on":["HOSTED-006","HOSTED-007"],"acceptance":["Retention classes are explicit","Export requires exact scope and creates receipt/proof-gap evidence","Support bundle is redacted only"],"candidate_paths":["src/evidence","src/export","tests/evidence","docs/internal/decisions.md"],"non_goals":["Compliance certification","Raw receipt dump export"]} -{"id":"HOSTED-011","priority":"P1","phase":"Phase 5","title":"Add product-level redaction fuzzing and read matrices","owner":"quality","rationale":"Redaction safety and entitlement safety need adversarial tests, not snapshot confidence.","depends_on":["HOSTED-005","HOSTED-006","HOSTED-007"],"acceptance":["Fuzz cases include tokens headers emails authorization strings cookies payment hints provider metadata","Read matrix covers roles scopes tenants orgs projects raw posture and missing records","Failures block hosted claim closeout"],"candidate_paths":["tests/redaction","tests/evidence","scripts/quality"],"non_goals":["Visual review QA","Manual-only audit"]} -{"id":"HOSTED-012","priority":"P1","phase":"Phase 5","title":"Expose read-only SDK CLI MCP client posture labels","owner":"developer-experience","rationale":"Clients must not launder read-plane access into gateway authority or mutation capability.","depends_on":["HOSTED-004","HOSTED-009"],"acceptance":["Clients are read-only by default","Output labels authority class mutation none gateway authority not held raw access disabled unavailable or configured","Clients cannot bypass reader authorization"],"candidate_paths":["src/sdk","src/cli","src/mcp","tests/sdk","tests/cli"],"non_goals":["Write-capable hosted client","Operator dashboard"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/VALIDATION.md deleted file mode 100644 index 856ddbe..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/VALIDATION.md +++ /dev/null @@ -1,62 +0,0 @@ -# Validation Matrix - -| Gate | What Must Be Proven | Evidence | -|---|---|---| -| Hosted deployment mode | Hosted paths fail closed without explicit mode/config | Config tests | -| Admission ordering | Role/freshness/scope/tenant checks happen before body parse/kernel invocation | Route-order tests | -| Exact x402 boundary | Hosted plan remains exact per-call protected action only | Claim guard and protocol tests | -| Digest/ref storage | Hosted transitions do not store raw tokens/user headers | Receipt fixture tests and redaction fuzzing | -| Reader authorization | Evidence reads require tenant/org/project entitlement | Read matrix tests | -| Oracle-safe denial | Missing and unauthorized evidence reads do not leak record existence | Negative read tests | -| Raw-read posture | Raw reads obey unavailable/disabled/gated/allowed states | Raw posture tests | -| D1 authority | D1 owns structured evidence indexes/records | Storage contract tests | -| KV limits | KV is non-authoritative or explicitly limitation-bound | Storage posture tests | -| Cloudflare bindings | D1/KV binding and migration posture are reported separately for local/dev and remote/prod | Wrangler proof artifacts | -| Secrets posture | Secret names/presence are reported, never values | Readiness redaction tests | -| Readiness posture | Readiness returns active/configured_but_unverified/missing/disabled/read_only/not_promoted accurately | Readiness matrix | -| Retention/export | Retention class and export behavior are scoped, redacted, receipted, and proof-gap aware | Retention/export tests | -| Client posture | SDK/CLI/MCP clients are read-only by default and label authority class | Client output tests | -| Claim safety | Hosted claims do not exceed enforcement | Claim guard | - -# Closeout Commands - -Planning-only expected closeout command set: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -npm test -- --run hosted -npm test -- --run evidence -npm test -- --run redaction -npm test -- --run d1 -npm test -- --run readiness -``` - -Cloudflare posture proof must be separated: - -```bash -wrangler d1 migrations list --local -wrangler d1 migrations list --remote -wrangler d1 execute --local --command "select 1" -wrangler d1 execute --remote --command "select 1" -wrangler secret list -``` - -These commands are validation targets, not evidence in this planning run. - -# Closeout Bar - -The slice is not complete until the repo can answer: - -- who attempted the hosted transition; -- what exact protected x402 call was admitted; -- whether admission happened before body/kernel trust; -- which tenant/org/project owned the transition; -- what was stored, redacted, unavailable, or refused; -- whether raw access was blocked, gated, or allowed; -- whether D1/KV bindings and migrations were configured; -- whether secrets were present without exposing values; -- whether export/reconstruction is possible within declared limits; -- whether product claims match enforcement. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/input.md deleted file mode 100644 index bf0cb20..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/input.md +++ /dev/null @@ -1,156 +0,0 @@ -# Macro Plan Input: Hosted Admission And Redacted Evidence Plane - -Run id: hosted-admission-redacted-evidence-plane-20260524T075941Z -Date: 2026-05-24 - -## Hard Frame - -Handshake is protected actions for automated decision making. Engineering-agent workflows are a stress/adoption context, not the product boundary. x402 exact per-call paid HTTP is the first protected-action wedge, not the protocol. - -This is planning only. Do not edit source, tests, docs outside this planning run, package metadata, or previously staged files. - -## Goal - -Plan how to turn local HTTP/D1 capabilities into an operated boundary only after caller custody, reader authorization, durable storage posture, and evidence redaction are real. - -Mechanism target: - -```text -caller role token --> route admission --> tenant/org/project scope --> protocol transition or redacted read --> durable D1/KV storage --> audit-safe response -``` - -## Current Source Grounding - -Canonical posture: - -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` says hosted admission and redacted evidence is critical path item 3, after custody proof and terminal verifier trust plane. -- `docs/internal/decisions.md` says HTTP admission, caller custody, OpenAPI projection, and route-scope resolution are protocol transport seams. They may model deployment-mode custody and caller roles, but they do not prove hosted operation, production org auth, provider enforcement, or customer gateway installation. -- `docs/internal/decisions.md` says local HTTP and SDK evidence reads are redacted diagnostic projections, not hosted audit/search product surfaces. The generic raw record route must enforce `rawReadPosture`. -- `README.md` and `docs/internal/protocol-notes.md` explicitly do not claim hosted operation. - -Current source anchors: - -- `src/http/LANE.md` -- `src/http/app.ts` -- `src/http/app-options.ts` -- `src/http/admission/caller-auth.ts` -- `src/http/admission/hosted-caller-identity.ts` -- `src/http/admission/index.ts` -- `src/http/admission/request-context.ts` -- `src/http/handlers/evidence-read.ts` -- `src/http/handlers/internal-record-read.ts` -- `src/http/routes/evidence-read-route-registry.ts` -- `src/http/routes/transition-route-registry.ts` -- `src/http/routes/transition-scope-resolvers.ts` -- `src/http/store/resolution.ts` -- `src/storage/d1` -- `migrations/` -- `test/http/http.test.ts` -- `test/http/d1-http.test.ts` -- `test/sdk/role-clients.test.ts` -- `test/mcp/mcp-resource-redaction.test.ts` -- `src/surfaces/boundary-manifest.ts` - -Landed behavior: - -- Hosted mode exists as a transport admission seam. -- `HostedCallerVerifier` verifies caller identity server-side. -- `TransitionCallerIdentity` binds caller identity ref, subject digest, tenant/org, custody roles, provider ref, auth/session/service credential digests, expiry, revocation epoch, and claims digest. -- Hosted admission checks role, freshness, and tenant/org scope before transition body parsing and kernel invocation. -- Accepted hosted transitions store only caller digest/ref evidence, not raw bearer tokens or user-identifying headers. -- Evidence read routes check hosted tenant/org boundaries before returning projections. -- Generic raw record reads consult protocol object `rawReadPosture`, and internal-only records return not found. -- D1/HTTP tests cover durable protocol surface behavior and local D1 evidence paths. - -Current gaps: - -- No deployment-mode admission config that proves an operated hosted product boundary. -- No production org/project/RBAC/read entitlement model beyond provider-neutral hosted caller identity. -- No retention/export policy or audit-reader posture. -- No hosted readiness probe that states exactly which hosted claims are active. -- No operated Cloudflare D1/KV deployment proof, migration/readiness proof, or secrets posture. -- No proof that hosted evidence responses are safe under redaction fuzzing and reader-role matrices at product level. -- No hosted claim guard beyond current local no-hosted-operation wording. - -## Official Source Constraints - -Use official source constraints only as planning constraints: - -- Cloudflare Workers secrets docs: secrets are encrypted text bindings for sensitive values; do not use `vars` for secrets; deployed secrets can be configured with Wrangler and validated through required secrets configuration. -- Cloudflare Workers environment variable docs: non-secret text/JSON variables are runtime bindings and are not encrypted; with Node compatibility, values may be exposed through `process.env`. -- Cloudflare D1 docs: D1 is accessed from Workers through environment bindings such as `env.DB`; Workers need configured D1 bindings. -- Cloudflare Wrangler configuration docs: D1 database bindings require binding name, database name, and database id. -- Cloudflare D1 getting-started docs: local and remote/production D1 configuration differ; production deployment requires remote database configuration. - -Do not claim Cloudflare deployment, org auth, secrets hygiene, D1 production readiness, or hosted operation until implementation verifies the actual config, migrations, secrets, admission, read authorization, and response redaction. - -## Required Perspectives - -Produce five independent raw perspectives before chair synthesis: - -1. Strategy: product posture, hosted claim boundary, sequencing after custody/verifier, x402-first implications. -2. Architecture: admission config, role/read models, scope, durable storage, redacted routes, raw-read posture, readiness probe. -3. Execution: implementation slices, candidate files/tests, closeout commands, dependency graph. -4. Risk/Security: auth bypass, token leakage, tenant leakage, raw record exfiltration, D1/secret/config drift, hosted theatre. -5. Adoption/DevEx: operator setup, SDK/CLI read clients, readiness output, error affordances, support/audit workflow. - -## Chair Outputs - -Create: - -- `PLAN.md` -- `CONTEXT.md` -- `ASSUMPTIONS.md` -- `DECISIONS.md` -- `RISKS.md` -- `VALIDATION.md` -- `TASKS.jsonl` -- `runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/synthesis.md` - -The final `PLAN.md` must include: - -- Goal -- Non-Goals -- Source Boundary -- Current State -- Target State -- Assumptions -- Decisions -- Phases -- Task Graph -- Risks And Mitigations -- Validation Gates -- Cut Lines -- Rollback / Stop Conditions -- Smallest Next Action - -## Must-Haves - -- Hosted admission is not authority. It authenticates/contextualizes callers before protocol transitions and redacted reads. -- Route admission must happen before body parsing or kernel invocation for mutating transitions. -- Reader roles must be distinct from control-plane/runtime/gateway/review roles where product semantics require it. -- Raw records must remain gated by `rawReadPosture`; internal-only objects must not be revealed through public/hosted reads. -- Evidence responses must be projection-owned and redaction-tested, not generic raw-record dumps. -- Hosted readiness must state active claims and non-claims explicitly. -- Cloudflare/D1/secrets claims require official-source-informed deployment checks, not local harness evidence alone. - -## Antipatterns To Reject - -- Hosted dashboard before custody, verifier, admission, and redacted reads are real. -- Treating hosted caller identity as principal authority or greenlight. -- Treating HTTP transport as hosted operation. -- Treating D1 local tests as production deployment readiness. -- Exposing raw protocol records because the caller has a control-plane token. -- Returning different errors for missing vs cross-tenant anchors. -- Storing raw bearer tokens, emails, secrets, or provider tokens in protocol records. -- Reader role overreach that allows evidence exfiltration. -- Claiming provider/customer gateway custody from hosted route admission. - -## Closeout Expectations - -Planning closeout is successful when every required output exists, `TASKS.jsonl` parses, required plan sections exist, source working tree remains untouched, and the plan states validation commands for eventual implementation. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ADOPTION.md deleted file mode 100644 index 594a4bb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ADOPTION.md +++ /dev/null @@ -1,217 +0,0 @@ -# ADOPTION Perspective - -## Invariant At Stake - -Hosted operation must not imply hosted authority. The product may expose admission status and redacted evidence reads, but CLI/SDK/MCP surfaces must not become mutation paths unless separately contracted, promoted, and gateway-enforced. - -## Adoption / DevEx Position - -The adoption wedge should be: "I can install the hosted evidence plane, run one readiness command, and know exactly what Handshake is enforcing, what it is only observing, and what evidence is redacted, unavailable, retained, or exportable." - -Do not sell this as hosted Handshake execution yet. Sell it as hosted admission plus evidence-read posture. - -## Operator Setup - -The operator path should be boring and explicit: - -1. Provision hosted admission endpoint. -2. Bind D1 database. -3. Apply migrations. -4. Register role/scope policy. -5. Configure secrets. -6. Configure evidence redaction policy. -7. Configure raw-read posture. -8. Configure retention/export posture. -9. Run readiness. -10. Only then expose read clients. - -Setup should produce a machine-readable readiness document and a human-readable report. Every setup step must say whether it is: - -- active -- configured_but_unverified -- missing -- disabled -- read_only -- not_promoted - -The most important DevEx rule: never make operators infer posture from successful deploy logs. - -## SDK / CLI Read Clients - -CLI, SDK, and MCP clients should be evidence/read-only by default. - -Required client affordances: - -- handshake evidence status -- handshake evidence readiness -- handshake evidence get -- handshake evidence search --redacted -- handshake evidence export --redacted -- handshake admission status -- handshake raw-read posture -- handshake retention status - -Every command should visibly label its authority class: - -```text -Authority: read-only evidence surface -Mutation: none -Gateway authority: not held by this client -Raw evidence access: disabled / unavailable / separately configured -``` - -SDK methods should mirror that posture. No method names like approve, greenlight, admit, mutate, execute, or grant unless the surface has been separately promoted into an enforcement path. - -## Readiness Output - -Readiness is the adoption centerpiece. It should answer: "What exactly is active?" - -Minimum readiness fields: - -```json -{ - "hostedAdmission": { - "status": "active", - "endpoint": "configured", - "operationClaim": "not_claimed" - }, - "roleScopeChecks": { - "status": "active", - "lastVerifiedAt": "timestamp", - "failureMode": "deny" - }, - "d1": { - "binding": "active", - "migrations": "applied", - "schemaVersion": "..." - }, - "secretPosture": { - "status": "configured", - "rawValuesExposed": false, - "rotationEvidence": "missing|present" - }, - "redactedReads": { - "status": "active", - "policyVersion": "...", - "sampleCheck": "passed" - }, - "rawReads": { - "status": "disabled", - "reason": "not_promoted" - }, - "retentionExport": { - "retention": "configured", - "redactedExport": "active", - "rawExport": "disabled" - }, - "readiness": { - "status": "ready_for_evidence_reads", - "notReadyFor": ["hosted_execution_claim", "mutation_authority"] - } -} -``` - -The key product move: readiness should name what is not true. That prevents hosted evidence from being laundered into hosted operation. - -## Error Affordances - -Errors should be posture-revealing, not generic. - -Examples: - -- D1_BINDING_MISSING: "Evidence reads cannot be reconstructed because no D1 binding is active." -- MIGRATION_NOT_APPLIED: "Evidence store exists but schema version is not admitted." -- SECRET_POSTURE_UNVERIFIED: "Hosted admission cannot prove secret handling posture." -- RAW_READ_NOT_PROMOTED: "Raw reads are disabled. This client only exposes redacted evidence." -- ROLE_SCOPE_DENIED: "Caller is authenticated but does not hold the required evidence-read scope." -- HOSTED_OPERATION_NOT_CLAIMED: "This deployment supports hosted admission/evidence reads, not hosted execution authority." - -Every error should include: - -- failed check -- expected state -- observed state -- whether the system failed closed -- next operator action -- audit receipt or readiness event id, if available - -## Support / Audit Workflow - -Support should never require raw secret access or privileged mutation. - -A good support bundle should include: - -- readiness report -- schema version -- D1 binding status, not credentials -- policy version -- redaction policy version -- role/scope decision trace -- failed check ids -- retention/export posture -- sampled redacted receipt ids -- explicit raw-read posture -- timestamped environment identity - -Support workflow: - -1. Operator runs handshake evidence support-bundle --redacted. -2. Bundle excludes raw secrets and raw evidence by default. -3. Bundle includes enough posture evidence to prove whether the failure is setup, policy, read authorization, migration, or product limitation. -4. Raw-read escalation is a separate audited path, not a support convenience. - -## What A 10-Star Product Feels Like - -The operator can tell, within five minutes, whether hosted Handshake is actually doing anything consequential. - -A 10-star experience feels like: - -- the first readiness report is brutally clear; -- every command says whether it is read-only or authority-bearing; -- no dashboard copy overclaims hosted execution; -- redacted evidence reads are useful without exposing raw sensitive payloads; -- broken D1, stale migrations, missing scopes, and disabled raw reads are diagnosed directly; -- support can debug posture without asking for secrets; -- audit can reconstruct why a caller saw redacted evidence and why they could not see raw evidence; -- the system repeatedly says "not promoted" where a weaker product would imply "coming soon" or silently expose capability. - -## Cut Lines - -Cut from this plan: - -- hosted execution claims; -- mutation commands in CLI/SDK/MCP; -- approval or greenlight APIs; -- raw evidence reads by default; -- dashboards that summarize posture without exact readiness fields; -- support workflows that require secrets; -- "secure by default" language without concrete checks; -- retention/export claims without verifiable config; -- MCP tools that can mutate admission, policy, retention, migration, or redaction state. - -## Adoption Risks - -The main adoption risk is that users will interpret "hosted admission" as "hosted Handshake operation." The product must fight that confusion in command names, readiness output, docs, errors, and dashboard labels. - -The second risk is frustration if redacted reads are too thin. The answer is not raw access by default. The answer is better redacted evidence shape, clearer proof gaps, and explicit raw-read escalation posture. - -## Validation Gates - -Before this plan is executable, require: - -- readiness output proves admission without claiming operation; -- CLI/SDK/MCP commands are read-only by inspection and tests; -- redaction tests prove sensitive fields are removed; -- raw-read posture is explicit and disabled unless configured; -- D1 migration failure produces a clear not-ready state; -- role/scope denial is distinguishable from missing auth; -- retention/export status appears in readiness and support bundles; -- support bundle contains no secrets or raw evidence. - -## Brutal Verdict - -Keep, but narrow. - -The adoption product is not "hosted Handshake." It is "hosted admission readiness plus redacted evidence reads." That is a useful wedge because it gives operators proof without prematurely creating a new authority surface. - -Smallest next mechanism to build: a single readiness contract that enumerates admission, D1, migration, role/scope, secret posture, redaction, raw-read posture, retention/export, and explicitly says hosted_operation_claim: false. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ARCH.md deleted file mode 100644 index 277f054..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/ARCH.md +++ /dev/null @@ -1,205 +0,0 @@ -# ARCH Perspective - -## Invariant At Stake - -Hosted admission must prove only that a caller may enter the hosted service path. It must not become execution authority, evidence authority, raw-read authority, or proof that downstream storage/deployment posture is safe. - -## Architecture Position - -The plan should define a hosted evidence plane with three hard boundaries: - -1. Admission boundary: caller identity, role, freshness, and declared scope checked before body parse or kernel invocation. -2. Read entitlement boundary: redacted evidence reads authorized by tenant/org, role, scope, and production RBAC rules. -3. Storage/deployment boundary: D1/KV bindings, secrets, vars, retention, export, and readiness are explicitly configured and provable per deployment mode. - -Hosted admission is only the door. The read model and storage posture decide what the caller can see. - -## Admission Config - -Add an explicit deployment-mode admission configuration, likely: - -- local-dev -- test -- preview -- production - -Each mode should declare: - -- accepted issuer/verifier strategy; -- required freshness window; -- allowed roles; -- allowed scopes; -- tenant/org source; -- whether raw reads are impossible, disabled, or gated; -- required D1/KV bindings; -- required secret names; -- required public vars; -- readiness expectations. - -Do not infer production posture from local tests. Local D1 and remote D1 are different authority surfaces. - -## Role And Read Models - -Split roles from read entitlements. - -Roles answer: "who is this caller?" - -Read entitlements answer: "what evidence shape may this caller retrieve for this tenant/org/scope?" - -Minimum model: - -- viewer: redacted evidence only; -- auditor: expanded redacted evidence plus proof-gap/refusal metadata; -- operator: operational readiness/status only, no raw evidence by default; -- rawEvidenceReader: exceptional entitlement, never implied by hosted admission. - -Production RBAC must be a first-class policy input, not scattered route conditionals. - -## Scope Model - -Scopes should be exact capabilities, not vague access labels. - -Candidate scopes: - -- evidence:redacted:read -- evidence:raw:request -- evidence:raw:read -- evidence:export:create -- evidence:retention:admin -- hosted:readiness:read - -A caller with evidence:redacted:read cannot get raw fields through alternate route parameters, export, readiness payloads, debug responses, or error messages. - -## Durable Storage Posture - -D1 should own structured evidence indexes and redacted read records. - -KV should only be used where eventual consistency is acceptable, such as readiness markers, deployment metadata, or non-authoritative cache state. Do not put raw authority-bearing evidence in KV unless the plan explicitly accepts its consistency and audit limits. - -Retention/export needs a concrete posture: - -- retention class per evidence type; -- redacted export format; -- raw export disabled unless explicitly entitled; -- export receipt records; -- proof-gap behavior when export cannot verify completeness. - -## Redacted Routes - -Redacted routes must bind every read to: - -- tenant/org; -- caller identity; -- role; -- scope; -- evidence record id/query; -- redaction profile; -- storage binding used; -- receipt/read audit event. - -Routes should never return "best effort" evidence without labeling proof gaps. If a redaction rule cannot be applied deterministically, fail closed or return a proof gap envelope. - -## Raw-Read Posture - -Keep rawReadPosture, but make it production-visible and route-enforced. - -States should be explicit: - -- unavailable: raw evidence is not stored or not reachable in this deployment. -- disabled: raw evidence exists but reads are not allowed. -- gated: raw reads require separate entitlement and audit. -- allowed: only for tightly scoped internal/test modes, preferably never production default. - -A raw-read posture flag is not enough. The route must enforce it before storage access. - -## Readiness Probe - -Hosted readiness should verify configuration, not leak evidence. - -It should report: - -- deployment mode; -- D1 binding presence; -- KV binding presence if required; -- required secrets configured, names only, never values; -- required vars configured; -- local vs remote D1 posture; -- migration/schema version; -- admission verifier configured; -- redaction profiles loaded; -- retention/export config loaded. - -It should not prove that a caller may read evidence. It proves the hosted plane is configured enough to evaluate admission and reads. - -## Storage And Deployment Config - -The plan must add Cloudflare-specific proof: - -- wrangler.toml D1 binding names match source expectations; -- preview and production D1 databases are distinct; -- local tests do not masquerade as remote proof; -- secrets are configured through Cloudflare secrets, not vars; -- non-secret config uses vars; -- KV namespaces are explicitly bound per environment; -- deployment docs show exact commands/checks for local and remote D1. - -Do not accept "tests pass locally" as hosted readiness. - -## Import And Source Ownership - -Keep ownership boring: - -- admission config types live with hosted ingress/admission code; -- read entitlement policy lives near evidence read routes, not inside storage adapters; -- D1/KV binding validation lives in hosted platform config; -- redaction profiles live with evidence serialization; -- raw-read posture lives with evidence access policy; -- readiness probe composes config checks but owns no policy. - -No route should import kernel internals just to answer hosted read requests. - -## Risks - -- Admission becomes ambient evidence authority. -- Production RBAC is bolted onto routes after the fact. -- Raw reads leak through export, debug, readiness, or error envelopes. -- Local D1 tests create false confidence for remote Cloudflare deployment. -- Secrets are accidentally modeled as vars. -- KV is used for authoritative evidence because it is convenient. -- Redaction is unit-tested but not fuzzed at product boundary. - -## Validation Gates - -- Hosted request with valid identity but missing read scope is refused before evidence access. -- Hosted request with valid admission but wrong tenant/org cannot read redacted evidence. -- Raw evidence read fails unless posture and entitlement both allow it. -- Readiness fails when required D1/KV bindings are absent. -- Readiness reports secret presence without exposing secret values. -- Remote D1 deployment proof is separate from local D1 test proof. -- Redaction fuzz tests assert forbidden raw fields never appear in route bodies, export bodies, errors, logs, or readiness output. - -## Cut Lines - -Cut from this macro plan: - -- new dashboard UX; -- broad audit analytics; -- generalized compliance exports; -- mutation authority; -- gateway greenlight changes; -- multi-runtime adapter expansion; -- raw evidence browsing UI. - -Keep the wedge narrow: hosted admission plus redacted evidence reads plus deployment posture proof. - -## Brutal Verdict - -Keep the initiative, but narrow it. - -The current source appears to have the right early boundary: admission before body parse/kernel invocation and redacted reads with tenant/org checks. The missing pieces are production hardening, not product expansion. - -Hosted admission is not authority. Redacted evidence access is its own entitlement plane. Raw reads are exceptional. Cloudflare deployment proof is a separate gate from local D1 correctness. - -## Smallest Next Mechanism - -Define a typed HostedAdmissionConfig plus ReadEntitlementPolicy that makes deployment mode, role, scope, tenant/org binding, raw-read posture, and required Cloudflare bindings explicit before adding any new route surface. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/EXECUTION.md deleted file mode 100644 index 47579d4..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/EXECUTION.md +++ /dev/null @@ -1,370 +0,0 @@ -# EXECUTION Perspective - -## Invariant At Stake - -Hosted operation must not turn redacted evidence reads into ambient authority. Admission, storage, read authorization, redaction, export, and claims all need explicit boundaries, or this becomes advisory evidence hosting rather than Handshake enforcement support. - -## Ordered Implementation Slices - -### 1. Deployment-Mode Admission Config - -Goal: make hosted/self-hosted/local admission behavior explicit before touching storage or reads. - -Candidate paths: - -- src/admission/* -- src/hosted/* -- src/config/* -- tests/admission/*.test.ts -- docs/internal/protocol-notes.md - -Work: - -- Add a typed deployment mode: local | self_hosted | hosted. -- Require hosted mode to declare admission authority holder, storage backend, read policy, retention policy, and raw-read posture. -- Refuse startup/readiness if hosted mode has implicit defaults for protected fields. -- Ensure deployment mode is evidence metadata, not permission. - -Tests: - -- hosted mode fails closed on missing read policy. -- local mode cannot accidentally expose hosted-read behavior. -- mode is captured in admission/readiness evidence. - -Stop condition: any hosted behavior can run with inferred authority defaults. - -### 2. Reader Authorization Boundary - -Goal: every redacted evidence read must pass a reader authorization check bound to evidence scope. - -Candidate paths: - -- src/evidence/read* -- src/readers/* -- src/auth/* -- src/protocol/* -- tests/evidence/read-authorization.test.ts - -Work: - -- Define EvidenceReadRequest, EvidenceReader, EvidenceReadDecision. -- Bind reader authorization to tenant/workspace, action contract id, receipt id, evidence class, redaction profile, and export purpose. -- Return refusal/proof gap for unreadable evidence rather than silently omitting. -- Log read decision separately from mutation receipt. - -Tests: - -- unauthorized reader cannot read redacted evidence. -- authorized reader cannot widen from receipt-level to workspace-level. -- read refusal is reconstructable. - -Stop condition: any redacted evidence read path accepts only a receipt id and returns data without reader context. - -### 3. rawReadPosture Hardening - -Goal: raw evidence access must be explicitly disabled, break-glass, or delegated to a storage-side authority. Never implicit. - -Candidate paths: - -- src/evidence/redaction* -- src/evidence/raw* -- src/protocol/evidence* -- tests/evidence/raw-read-posture.test.ts - -Work: - -- Make rawReadPosture an enum: disabled | storage_only | break_glass. -- Fail hosted mode unless raw reads are disabled or guarded by explicit break-glass policy. -- Make raw-read attempts produce refusal or proof-gap evidence. -- Ensure redacted reads cannot include raw fields through nested payloads or metadata. - -Tests: - -- hosted mode rejects rawReadPosture: allowed. -- raw evidence is absent from SDK/CLI read clients. -- fuzzed nested objects cannot leak raw payloads. - -Stop condition: raw read behavior is controlled by caller convention rather than schema/state. - -### 4. D1/KV Deployment Readiness - -Goal: hosted persistence must prove schema, namespace, migration, and consistency posture before claiming readiness. - -Candidate paths: - -- src/storage/d1* -- src/storage/kv* -- src/hosted/readiness* -- wrangler.toml -- migrations/* -- tests/storage/*.test.ts - -Work: - -- Add readiness checks for D1 schema version, KV namespace binding, receipt/evidence indexes, retention clock, and migration status. -- Separate write-store readiness from read-plane readiness. -- Record unavailable storage as readiness refusal, not degraded success. -- Add fixture-backed storage contract tests. - -Tests: - -- readiness fails with missing D1 binding. -- readiness fails with missing KV namespace. -- storage adapter round-trips redacted evidence only. -- migration version mismatch blocks hosted admission. - -Stop condition: hosted readiness can pass with in-memory or stub persistence. - -### 5. Secrets Posture - -Goal: hosted admission must not depend on undeclared secrets or leak secret-derived material into evidence. - -Candidate paths: - -- src/secrets/* -- src/config/secrets* -- src/hosted/readiness* -- tests/secrets/*.test.ts -- docs/internal/decisions.md - -Work: - -- Define required secret names per deployment mode. -- Add startup/readiness validation for present-but-not-logged secrets. -- Redact secret-like values in evidence and read responses. -- Prevent SDK/CLI from printing secret-bearing config. - -Tests: - -- missing hosted secret fails readiness. -- evidence redaction catches token/key/env patterns. -- logs/read responses do not include secret values. - -Stop condition: hosted mode can boot while discovering secrets dynamically from environment without declared posture. - -### 6. Retention And Export - -Goal: redacted evidence is useful only if retention/export rules are explicit and auditable. - -Candidate paths: - -- src/evidence/retention* -- src/evidence/export* -- src/storage/* -- tests/evidence/retention-export.test.ts - -Work: - -- Add retentionPolicyId, expiry, legal-hold posture, and export profile to evidence metadata. -- Implement redacted export only; raw export requires break-glass refusal/review path. -- Add export receipts distinct from execution receipts. -- Make expired evidence return tombstone/proof gap, not silent 404. - -Tests: - -- expired evidence is unavailable with reconstructable tombstone. -- export cannot widen redaction profile. -- raw export is refused in hosted mode unless break-glass path exists. - -Stop condition: export is just "dump stored receipts." - -### 7. Hosted Readiness Probe - -Goal: expose a probe that says whether hosted admission/read plane can enforce boundaries now. - -Candidate paths: - -- src/hosted/readiness* -- src/http/* -- src/cloudflare/* -- tests/hosted/readiness.test.ts - -Work: - -- Probe admission config, storage, read auth, redaction profile, raw posture, retention, secrets, and claim guard versions. -- Return machine-readable failed gates. -- Keep probe read-only. -- Ensure probe does not disclose secrets or raw evidence. - -Tests: - -- each missing subsystem maps to a named readiness failure. -- readiness cannot pass when redaction fuzz suite is disabled from claim guard metadata. -- probe response is safe for operator display. - -Stop condition: readiness reports "ok" based only on process health. - -### 8. Redaction Fuzzing - -Goal: prove redaction survives nested payloads, unknown keys, arrays, metadata, and future schema drift. - -Candidate paths: - -- src/evidence/redaction* -- tests/evidence/redaction-fuzz.test.ts -- tests/fixtures/evidence/* - -Work: - -- Add property/fuzz tests for secret-like strings, raw payload fields, nested command outputs, env names, URLs with credentials, tokens, and stack traces. -- Assert redacted output preserves structure enough for reconstruction without leaking raw values. -- Add regression corpus for known dangerous shapes. - -Tests: - -- no raw payload field survives. -- no known secret pattern survives. -- redaction is deterministic for canonical evidence. - -Stop condition: redaction is only snapshot-tested on happy-path receipts. - -### 9. SDK/CLI/Read Client Posture - -Goal: clients must expose redacted evidence reads without implying hosted mutation authority or raw evidence access. - -Candidate paths: - -- packages/sdk/* -- packages/cli/* -- src/client/* -- tests/sdk/*.test.ts -- tests/cli/*.test.ts - -Work: - -- Add read client methods that require reader context and requested redaction profile. -- Avoid generic getReceiptRaw or readEvidence(any) surfaces. -- CLI should show refusal/proof-gap/read-decision state explicitly. -- Client docs must say hosted read plane is not hosted execution authority. - -Tests: - -- CLI cannot request raw evidence in hosted mode. -- SDK method requires reader identity/scope. -- client output distinguishes redacted receipt, read refusal, proof gap, and expired evidence. - -Stop condition: SDK/CLI adds convenience methods that bypass the reader authorization model. - -### 10. Claim Guards - -Goal: repo claims must not say hosted operation exists until all enforcement and evidence gates pass. - -Candidate paths: - -- scripts/quality/* -- docs/internal/* -- README.md -- QUALITY.md -- tests/quality/*.test.ts - -Work: - -- Add claim guard terms for hosted, managed, cloud, evidence plane, redacted read, and raw evidence. -- Permit only narrow language until readiness, auth, redaction fuzzing, storage, and retention/export gates exist. -- Require docs to distinguish hosted admission seam from hosted operation. -- Add CI/local quality command coverage. - -Tests: - -- forbidden hosted claims fail quality checks. -- allowed guarded language passes. -- README cannot claim hosted operation without linking readiness/read authorization posture. - -Stop condition: marketing or README claims outpace gateway/read-plane enforcement. - -## Dependency Graph - -```text -deployment-mode config - -> reader authorization - -> rawReadPosture hardening - -> D1/KV readiness - -> secrets posture - -> retention/export - -> hosted readiness probe - -> SDK/CLI/read client posture - -> claim guards - -redaction fuzzing - -> rawReadPosture hardening - -> hosted readiness probe - -> claim guards - -D1/KV readiness - -> retention/export - -> hosted readiness probe - -reader authorization - -> SDK/CLI/read client posture - -> retention/export -``` - -## Parallelizable Work - -Can run in parallel after deployment-mode config lands: - -- reader authorization schema/design -- redaction fuzz corpus -- D1/KV readiness adapter planning -- secrets posture validation -- claim guard vocabulary draft - -Must stay serialized: - -- rawReadPosture hardening before SDK/CLI raw-read behavior -- storage readiness before hosted readiness probe -- retention/export before external export claims -- final claim guards after all enforcement gates are named - -## Closeout Commands - -Candidate closeout gates: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Focused test candidates: - -```bash -npm test -- admission -npm test -- evidence -npm test -- storage -npm test -- hosted -npm test -- sdk -npm test -- cli -``` - -## Rollback / Stop Conditions - -Stop immediately if: - -- hosted mode can pass readiness with stub or local storage. -- redacted evidence reads do not require reader authorization. -- raw evidence is reachable through SDK, CLI, export, debug, or metadata. -- readiness proves process liveness instead of enforcement readiness. -- docs claim hosted operation before D1/KV, secrets, read auth, retention/export, and redaction fuzzing are gated. -- receipts blur execution evidence, read evidence, export evidence, and proof gaps. - -Rollback line: - -- keep hosted admission seam and redacted evidence reads as local/self-hosted primitives. -- do not expose hosted mode or hosted claims until readiness and claim guards pass. - -## Traps - -- Hosted admission can become a product claim without hosted enforcement. -- Redacted read clients can become ambient workspace observability. -- Raw evidence can leak through metadata, stack traces, debug fields, export paths, or CLI formatting. -- D1/KV bindings can exist while schema/index/readiness posture is unproven. -- Retention can delete evidence and destroy reconstructability unless tombstones/proof gaps survive. -- SDK convenience methods can erase the reader authorization boundary. -- Readiness probes often lie by checking uptime instead of enforcement gates. -- Claim guards must police docs and names, not just README prose. - -## Smallest Next Mechanism - -Build the deployment-mode admission config first: one typed hosted-mode object that fails closed unless reader policy, storage backend, rawReadPosture, secrets posture, and retention policy are explicitly declared. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/RISK.md deleted file mode 100644 index 166d706..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/RISK.md +++ /dev/null @@ -1,88 +0,0 @@ -# RISK Perspective - -## Invariant At Stake - -Hosted mode must not turn evidence reads or admission checks into ambient authority. Caller identity evidence, redacted receipts, and hosted verifier status are not permission unless the hosted boundary enforces role, freshness, scope, tenant, and raw-read posture server-side. - -## Risk Findings - -| Risk | Failure mode | Required control | -| --- | --- | --- | -| Auth bypass | Hosted endpoint becomes a second path around local verifier/gateway checks. | One hosted admission verifier, deny-by-default, no fallback to advisory mode. | -| Caller identity overreach | Caller-supplied digest/ref is treated as authority instead of evidence. | Digest/ref is evidence only; authorization derives from verified issuer, tenant, role, scope, freshness, and policy version. | -| Token/email leakage | Receipts expose bearer tokens, emails, headers, OAuth claims, webhook payloads, or secret-like refs. | Redaction schema with denylisted fields, typed secret markers, email hashing policy, and snapshot tests. | -| Cross-tenant leaks | Evidence read APIs return receipts from another org through guessed IDs, shared indexes, or weak filters. | Tenant/org boundary must be part of the storage key and every read predicate; no app-layer-only filtering. | -| Missing-vs-cross-tenant oracle | 404 missing vs 403 forbidden lets callers enumerate foreign receipt IDs. | Normalize unauthorized and nonexistent reads unless caller has tenant-scoped index permission. | -| Raw record exfiltration | rawReadPosture becomes a boolean escape hatch for full receipt payloads. | Raw reads require explicit role, purpose, time-bound scope, audit receipt, and field-level allowlist. | -| D1 config drift | Local D1 schema, bindings, migrations, or seed data differ from production. | Migration gate must prove local and production migration state, binding name, and schema hash alignment. | -| Secrets via process.env | Worker code accidentally depends on Node-style env or source-defined secrets. | Cloudflare env binding only; static check banning secret literals and process.env in worker/runtime paths. | -| Hosted theatre | Hosted verifier records "checked" but mutation/evidence access can still proceed through local/raw/sibling route. | Plan must identify every hosted and non-hosted ingress and mark bypass posture for each. | -| Replay/status risk | Stale verifier status or copied caller evidence authorizes later reads/admissions. | Nonce or timestamp freshness, policy version binding, single-use admission where consequential, replay receipt on rejection. | -| Retention risk | Evidence plane stores too much raw payload forever. | Retention class per evidence type, redaction-before-persist where possible, deletion/export policy, proof-gap when raw evidence is unavailable. | - -## Recommended Plan Shape - -1. Define Hosted Admission Contract. - Inputs: caller credential, caller identity digest/ref, tenant/org, requested action/evidence scope, freshness window, policy version, rawReadPosture. - Outputs: allow/refuse/review/quarantine plus reason code and receipt reference. - Non-output: no mutation permission, no proof of downstream execution. - -2. Build Redacted Evidence Read Model. - Separate redactedEvidenceRead from rawEvidenceRead. - Redacted reads are default and tenant-scoped. - Raw reads are exceptional, audited, scoped, and purpose-bound. - -3. Close Oracle And Exfiltration Paths. - Same response posture for missing and unauthorized records unless index authorization is proven. - No raw receipt fetch by ID without tenant-bound authorization. - No caller-controlled projection fields. - -4. Add Cloudflare Deployment Proof. - D1 binding proof. - Migration state proof. - Secret binding proof. - Production-vs-local config divergence recorded explicitly. - -## Cut Lines - -- Cut any plan that treats caller identity digest as authorization. -- Cut any read API that can return raw records by default. -- Cut any hosted verifier that does not enumerate bypass posture. -- Cut any production claim without Cloudflare binding and D1 migration proof. -- Cut process.env dependency from worker/runtime code. -- Cut separate error semantics that expose whether a foreign receipt exists. - -## Validation Gates - -- Auth matrix: tenant x role x scope x freshness x rawReadPosture. -- Cross-tenant negative tests using valid foreign IDs. -- Missing-vs-forbidden response equivalence tests. -- Redaction snapshot tests for tokens, emails, headers, secrets, env names, webhook bodies. -- Raw-read audit tests proving every raw access creates evidence. -- Replay tests for stale caller evidence and reused status. -- D1 migration drift check for local and production binding names/schema hashes. -- Static scan blocking secret literals and process.env in hosted worker paths. -- Hosted bypass test proving unwrapped local/sibling reads cannot access protected evidence. - -## Antipatterns - -- Hosted mode as a trust label instead of an enforced boundary. -- Redacted evidence implemented as UI filtering. -- Caller identity stored as a digest with no issuer, freshness, or tenant binding. -- Returning 403 for foreign records and 404 for missing records. -- Raw read as admin convenience. -- Production readiness based on local Wrangler success. -- Secrets in vars, source, logs, receipt metadata, or test fixtures. -- Receipts that do not distinguish admission check, evidence read, raw read, and downstream execution. - -## Blocked Checks - -- No filesystem, source, config, migration, or test verification was performed per instruction. -- Product-level hosted deployment proof remains unverified. -- Existing read authorization model remains unverified. - -## Brutal Verdict - -Narrow and keep, but only if hosted mode is treated as a new protected ingress, not a deployment flavor. The dangerous part is not transport; it is evidence authority moving server-side without a precise read contract. - -Smallest next mechanism to build: a tenant-bound EvidenceReadAuthorization contract with redacted vs raw posture, freshness, role/scope checks, oracle-safe denial semantics, and mandatory audit receipt for every raw read. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/STRATEGY.md deleted file mode 100644 index 30c80c8..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/raw/STRATEGY.md +++ /dev/null @@ -1,139 +0,0 @@ -# STRATEGY Perspective - -## Invariant At Stake - -Hosted Handshake must not turn transport admission plus redacted storage into a product claim that exceeds enforcement. If hosted mode cannot prove caller admission, tenant-scoped evidence reads, redaction posture, deployment binding correctness, and secret handling, then it is a demo seam, not an operated evidence plane. - -## Product Posture - -The product posture should be narrow: hosted admission and redacted evidence plane for exact x402-protected calls, not "hosted Handshake" broadly. - -The wedge is not engineering-agent workflow control yet. Engineering agents remain a stress case. The first marketable primitive is: a remote caller can attempt an exact paid/protected call, Handshake admits or rejects the caller before request body trust, records only digest/ref caller evidence, and exposes evidence reads through tenant/org/project-scoped entitlement. - -x402 per-call enforcement forces a clean version of Handshake's doctrine: one exact call, one admission boundary, one evidence posture, no ambient authority. - -## Hosted Claim Boundary - -Permitted claim: - -> Handshake hosted mode can admit exact protected calls before kernel invocation and expose redacted evidence records through tenant-scoped read controls. - -Forbidden claims until proven: - -- Hosted production readiness. -- Full organization RBAC. -- Compliance-grade evidence retention. -- Secret-safe deployment. -- Cloudflare durable deployment proof. -- General hosted execution control for engineering agents. -- Raw evidence safety unless raw-read posture is explicitly enforced and tested. -- "Auditable" unless export, retention, redaction, and access evidence survive reconstruction. - -If the hosted claim guard does not exist, product copy will overreach. That is strategy debt, not docs cleanup. - -## Sequencing After Custody/Verifier - -The next macro sequence should be: - -1. Operated deployment mode. - Define local/test/hosted deployment modes, required bindings, secret sources, readiness checks, and failure behavior. - -2. Tenant/org/project/read entitlement model. - Make evidence reads impossible without explicit tenant/org/project authority. This is the product boundary for hosted evidence. - -3. Redacted evidence contract. - Define what is stored as digest/ref only, what is never stored, what rawReadPosture permits, and what proof gaps are recorded. - -4. Cloudflare D1/KV deployment proof. - Prove the hosted runtime can actually bind D1/KV correctly under remote configuration. Local D1 tests are not production proof. - -5. Hosted readiness probe. - Add a readiness surface that verifies mode, bindings, migrations/schema posture, secret availability by reference, and evidence-plane availability without leaking sensitive values. - -6. Product-level redaction fuzzing. - Fuzz evidence ingestion and reads for token-like, secret-like, header-like, and body-like leaks. - -7. Hosted claim guard. - Add automated guardrails against README/docs/product claims that exceed the current hosted proof. - -## x402-First Implications - -x402 should stay first because it forces exact per-call admission. Do not dilute it into general account auth, agent auth, or workflow approval. - -Strategically, x402 means: - -- The protected action is the call, not the customer journey. -- Admission happens before body parsing and kernel invocation. -- Evidence must prove admission/refusal posture without storing caller secrets. -- Pricing/payment is useful only if it strengthens exact-call control. -- Hosted mode must reject vague "session permission" language. - -The danger is turning x402 into a payment feature. The strategic value is not payment. The value is exact, externalized, per-call admission with reconstructable redacted evidence. - -## Cut Lines - -Cut from this macro plan: - -- General engineering-agent dashboards. -- Human review UI polish. -- Broad compliance language. -- Multi-cloud support. -- Full enterprise RBAC. -- Workflow orchestration. -- Raw evidence browsing by default. -- Any claim that hosted mode controls downstream business success. -- Any "agent auth" positioning. -- Any architecture that depends on Cloudflare vars for sensitive values. - -Keep only what proves hosted admission and redacted evidence under operated deployment constraints. - -## Success Criteria - -This plan succeeds when Handshake can prove: - -- Hosted mode refuses requests before body parsing/kernel invocation when caller role, freshness, or scope fails. -- Caller evidence is digest/ref only unless rawReadPosture explicitly permits otherwise. -- Evidence reads are tenant/org/project scoped and denied by default. -- Cloudflare D1/KV bindings are configured and tested in remote deployment posture, not only local durable tests. -- Sensitive values use Cloudflare secrets, not vars. -- Readiness probe reports binding/config posture without leaking sensitive data. -- Retention/export policy is explicit, even if minimal. -- Product docs cannot claim more than the hosted proof supports. -- Redaction fuzzing catches secret-like evidence leaks. -- Failures become refusals or proof gaps, not smoothed-over success records. - -## Risks - -The main risk is evidence theatre: hosted mode records something, but cannot later prove whether admission, redaction, tenant entitlement, and deployment posture were correct. - -The second risk is market theatre: calling this "hosted Handshake" before it handles production deployment and read entitlements. That invites enterprise expectations before the primitive is hard. - -The third risk is x402 dilution: selling payment instead of exact admission. Payment rails are distribution; exact-call enforcement is the product. - -## 10-Star Bar - -A 10-star version lets a skeptical org inspect one x402 protected call and answer: - -- Who attempted the call? -- Was the caller admitted before body/kernel trust? -- Which tenant/org/project owned the evidence? -- What exact evidence was stored? -- What was redacted, referenced, or deliberately unavailable? -- Was raw evidence blocked unless explicitly permitted? -- Were Cloudflare bindings and secrets configured in operated hosted mode? -- Could this be exported or reconstructed later? -- Did the product claim exactly match the enforced behavior? - -If any answer depends on "trust the host runtime," the bar is not met. - -## Brutal Verdict - -Keep the hosted admission and redacted evidence plane. - -Narrow the claim. - -Sequence it after custody/verifier, but before broader hosted product language. - -Make x402 the first exact-call proof surface, not a payment story. - -Smallest next mechanism to build: an operated hosted deployment-mode contract plus readiness probe that validates D1/KV bindings, secret posture, mode config, and evidence-plane availability without parsing protected request bodies or leaking sensitive values. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/synthesis.md deleted file mode 100644 index 5754e41..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/hosted-admission-redacted-evidence-plane/runs/hosted-admission-redacted-evidence-plane-20260524T075941Z/synthesis.md +++ /dev/null @@ -1,68 +0,0 @@ -# Chair Synthesis: Hosted Admission And Redacted Evidence Plane - -## Invariant At Stake - -Hosted admission and hosted reads must remain evidence-plane mechanisms. They cannot become hosted mutation authority, payment management, settlement, provider custody, general hosted Handshake operation, or audit/compliance theatre. - -The core invariant is still exact protected action control: - -```text -vague intent is not authority -generated orchestration is not authority -hosted admission is not authority to mutate -redacted evidence is not proof of downstream success -readiness is not production proof -``` - -## Perspective Reconciliation - -STRATEGY is right to narrow the claim. The market/product claim must be hosted admission plus redacted evidence for exact x402-protected calls, not hosted Handshake. The necessary sequence is deployment mode, read entitlement, redaction contract, Cloudflare durable proof, readiness, redaction fuzzing, and claim guard. - -ARCH is right about the three boundaries: admission, read entitlement, and storage/deployment. The plan adopts deployment modes, explicit verifier/read config, separated roles/scopes, D1 authority, KV limitation, rawReadPosture, and readiness posture. - -EXECUTION is right about stop conditions. The plan fails if hosted behavior runs with inferred authority defaults, if raw reads are convention-controlled, if readiness passes against stubs, if export is a receipt dump, or if clients bypass reader authorization. - -RISK is right that the dangerous failures are not abstract. They are auth bypass, identity overreach, token leakage, cross-tenant leakage, oracle leaks, raw exfiltration, D1 drift, secret leakage, hosted theatre, replay/status confusion, and retention theatre. The mitigation set is now mapped into validation gates. - -ADOPTION is right that the operator path must be small: provision endpoint, bind D1, migrate, register role/scope policy, configure secrets/redaction/raw-read/retention-export, run readiness, expose read clients. The useful operator answer is what is enforcing, observing, redacted, unavailable, retained, and exportable. - -## 10-Star Bar - -A 10-star implementation can answer, from durable evidence and safe hosted reads: - -- who attempted the hosted transition; -- whether admission happened before body parse and kernel invocation; -- which tenant/org/project owned the attempt; -- what exact x402 protected call was admitted; -- what evidence was stored as digest/ref; -- what evidence was redacted; -- what evidence is unavailable; -- what raw evidence is blocked, gated, or allowed; -- whether D1 bindings, migrations, and schema are configured; -- whether KV is non-authoritative; -- whether required secrets are present without revealing values; -- whether export/reconstruction is possible within declared limits; -- whether the public claim matches enforcement. - -## Antipatterns - -- Hosted readiness passes because the process is alive. -- Local D1 tests are treated as Cloudflare production proof. -- Provider-neutral identity becomes tenant/org/project entitlement. -- A transition caller automatically becomes an evidence reader. -- Redacted read APIs accept broad filters instead of exact receipt/evidence ids. -- Raw reads are guarded by naming convention. -- KV becomes the de facto evidence source of truth. -- Readiness dumps `process.env` or secret values. -- Export is a raw receipt dump. -- SDK/CLI/MCP clients imply gateway authority. -- Docs say hosted Handshake when the system only admits transitions and serves redacted reads. -- Compliance language appears before retention/export/audit posture exists. - -## Final Verdict - -Keep, but narrow. - -This is a valid Tier 2 macro plan only if it remains hosted admission plus redacted evidence plane for exact x402 per-call protected actions. The plan should not promote hosted mutation authority, general engineering-agent execution control, payment management, custody, settlement, production readiness, or compliance audit. - -The smallest next mechanism is explicit deployment-mode hosted admission config with fail-closed defaults and a hosted claim guard. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/ASSUMPTIONS.md deleted file mode 100644 index 918c7db..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/ASSUMPTIONS.md +++ /dev/null @@ -1,51 +0,0 @@ -# Assumptions - -## Release Assumptions - -- The package remains public npm package `handshake-protocol-kernel`. -- The version for this macro starts from current source version `0.2.4`, but implementation must verify whether that version is publishable, already published, or needs incrementing. -- `package.json` remains the source of npm package identity. -- `server.json` remains the source of MCP Registry metadata. -- MCP Registry publication is separate from npm publication. -- Clean install verification must run against the public package artifact, not the local checkout. - -## Authority Assumptions - -- Publication is not an authority path. -- Installation is not authorization. -- MCP discoverability is not trust. -- Registry namespace verification is not policy authorization. -- Package provenance is artifact provenance, not runtime enforcement proof. -- CLI/MCP successful startup is runtime availability proof, not mutation proof. -- x402 exact per-call proves a narrow protected-action pattern, not all protected actions. - -## Operational Assumptions - -- Trusted publishing/OIDC is preferred over long-lived npm tokens. -- Any token path requires explicit 2FA and bypass-risk posture. -- Provenance may be available under supported npm trusted publishing conditions. -- Missing provenance support is a proof gap unless release policy explicitly blocks publication. -- MCP Registry preview instability may require blocking or recording preview proof gaps. - -## Documentation Assumptions - -- Public docs must describe Handshake as protected actions for automated decision making. -- Engineering-agent language may be retained only as a domain example or first wedge. -- Public docs must state that publication distributes package and metadata surfaces only. -- Public docs must not imply hosted operation, marketplace review, settlement, payment management, custody, trust, or host-wide enforcement. - -## Proof Gap Assumptions - -The following are proof gaps until evidenced: - -- npm account ownership posture -- namespace ownership posture -- 2FA/token posture -- OIDC/trusted publishing posture -- provenance availability -- actual npm publication for exact version -- clean install from public npm -- MCP Registry namespace auth -- MCP Registry metadata acceptance -- post-registry discoverability -- rollback/deprecation readiness diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/CONTEXT.md deleted file mode 100644 index f9ff6a8..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/CONTEXT.md +++ /dev/null @@ -1,67 +0,0 @@ -# Context: Public Distribution And Publication - -## Invariant At Stake - -Public distribution must not launder publication into authority. - -Handshake is protected actions for automated decision making. Publication can distribute package artifacts, proposal/evidence/read surfaces, and source-owned metadata. It cannot create permission, policy, greenlights, gateway checks, mutation authority, custody, settlement, payment handling, certification, trust, hosted operation, or host-wide enforcement. - -## Macro Item - -Public Distribution And Publication - -## Run - -`public-distribution-publication-20260524T090500Z` - -## Current Package Surface - -The current package is `handshake-protocol-kernel` at version `0.2.4`. - -The package declares MCP name `io.github.joelchan/handshake-protocol-kernel`. - -Public exports currently include root, conformance, runtime, SDK, role clients, CLI, MCP, experimental, and package metadata surfaces. - -Installed commands currently include: - -- `handshake` -- `handshake-mcp` -- package-name bin pointing to the MCP server - -Packaged files currently include bin/source/dist/server metadata/readme/quality/structure/internal docs. - -## Current Registry Surface - -`server.json` targets MCP Registry schema `2025-12-11`. - -It describes npm stdio package metadata and must remain non-authority. - -MCP Registry is preview metadata infrastructure. It does not host npm artifacts and does not make security, trust, enforcement, marketplace, payment, or custody guarantees. - -## Current Check Surface - -Existing scripts already verify parts of the release boundary: - -- package pack shape -- required files -- forbidden paths -- `private: false` -- MCP name sync -- bin shebangs -- CLI schema non-authority smoke -- MCP stdio official client smoke -- no raw `PaymentPayload` or `SIGNATURE` leakage - -These checks are necessary but not complete. They do not by themselves prove account posture, actual npm publication, clean install from the public registry, provenance, MCP Registry acceptance, or post-registry discoverability. - -## Canon Drift To Resolve Later - -README/docs already describe package entrypoints and MCP metadata, but some canon still uses older engineering-agent phrasing. - -That drift is a release blocker for this macro item because the hard invariant is broader: protected actions for automated decision making. Engineering-agent actions may remain a first domain or wedge, but cannot be the product center. - -## Strategy Boundary - -Do not use the cleanest proof surface as a first-market claim. - -x402 exact per-call is the first proof wedge because it is narrow, per-call, inspectable, and easy to test. It is not the protocol center. The protocol center is exact contract, one-use greenlight, gateway check, receipt/refusal/proof-gap, isolation, and bypass posture for protected actions. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/DECISIONS.md deleted file mode 100644 index a0c0ebb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/DECISIONS.md +++ /dev/null @@ -1,47 +0,0 @@ -# Decisions - -## D-001: Publication Is Non-Authority - -Publication distributes package artifacts, source-owned metadata, and proposal/evidence/read surfaces. It does not create authority, decisions, greenlights, gateway checks, mutations, custody, hosted operation, certification, settlement, payment management, trust, or host-wide enforcement. - -## D-002: Protected Actions Are The Product Center - -Handshake is protected actions for automated decision making. Engineering-agent actions are a first domain, not the full product definition. - -## D-003: x402 Is First Proof Wedge Only - -x402 exact per-call is the first proof wedge because it is narrow, per-call, and inspectable. It must not become the protocol center in package, registry, or README language. - -## D-004: Release States Must Be Separate - -The release lifecycle must distinguish: - -- `ready_to_publish` -- `actually_published` -- `registry_discoverable` - -No state can imply the next one. - -## D-005: Release Proof Must Be Structured - -The release must produce or update a source-owned `PackageReleaseProof` shape with package shape, account/namespace, publish operation, provenance, registry discoverability, runtime smoke, authority boundary, and proof gaps. - -## D-006: Release Manifest Before Publish - -A release manifest must exist before npm publish. It must identify exact package, version, tag, expected pack contents, public entrypoints, account posture, provenance posture, authority-boundary false fields, and stop conditions. - -## D-007: Post-Publish Receipt After Publish - -A post-publish verification receipt must exist after npm publish. It must prove clean install, installed bins, installed exports, non-authority behavior, and any proof gaps. - -## D-008: MCP Registry Is Metadata Only - -MCP Registry publication must be treated as metadata/discoverability. It is not artifact hosting, certification, trust establishment, policy enforcement, or marketplace approval. - -## D-009: Public Claims Must Be Cut To Enforced Reality - -Any claim that exceeds package metadata, installability, proposal/evidence/read surfaces, or source-owned checks must be removed or rewritten. - -## D-010: Risky Publish Credentials Cannot Be Silent - -Long-lived token publish, bypass-2FA token usage, missing 2FA, unavailable provenance, or unknown namespace auth must be explicit blocker/proof-gap states, not hidden release details. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/PLAN.md deleted file mode 100644 index 0796844..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/PLAN.md +++ /dev/null @@ -1,296 +0,0 @@ -# GSD Macro Plan: Public Distribution And Publication - -## Goal - -Make Handshake publicly installable and discoverable as a non-authority protocol kernel for protected actions in automated decision making. - -The release must prove package shape, published entrypoints, MCP metadata, installability, runtime smoke behavior, provenance posture, and authority boundaries. Publication distributes proposal, evidence, read surfaces, and source-owned metadata only. Publication does not create authority, policy decisions, greenlights, gateway checks, mutations, custody, hosted operation, marketplace certification, settlement, payment management, trust, or host-wide enforcement. - -x402 exact per-call remains the first proof wedge. It is not the protocol center. - -## Non-Goals - -- Do not broaden Handshake into engineering-agent-only infrastructure. -- Do not claim npm publication creates enforcement. -- Do not claim MCP Registry listing creates trust, certification, security review, custody, or hosted operation. -- Do not add marketplace, settlement, payment management, or host-wide enforcement claims. -- Do not publish with stale engineering-agent-only canon unresolved. -- Do not treat local dry-run evidence as proof of public installability. -- Do not treat a registry metadata entry as proof that package artifacts are safe. - -## Source Boundary - -Authoritative source for this macro item is limited to current tracked repo surfaces and official publication constraints summarized for this run. - -Current source surfaces: - -- `package.json` -- `server.json` -- `scripts/check-package-surface.mjs` -- `scripts/check-published-entrypoints.mjs` -- `README.md` -- `QUALITY.md` -- `STRUCTURE.md` -- `docs/internal/decisions.md` -- `docs/internal/protocol-notes.md` - -Scratch planning files are not source authority. This macro plan may guide work, but implementation must land through tracked source, checks, and receipts. - -Official publication constraints: - -- npm publication publishes installable package artifacts by name and version. -- `npm pack --dry-run --json` is the local package-content inspection gate. -- `package.json` `name` and `version` identify the publishable package. -- `exports` defines public entrypoints and blocks arbitrary package entrypoints. -- `bin` installs commands and Node bins must use a Node shebang. -- `files` constrains package contents. -- Trusted publishing/OIDC is preferred over long-lived tokens and can generate provenance for public packages under supported conditions. -- 2FA/token posture must be explicit; bypass-2FA tokens are risky. -- MCP Registry is preview, hosts metadata rather than artifacts, uses `server.json`, requires public install methods, and for npm ownership verification requires `package.json#mcpName` to match `server.json#name`. - -## Current State - -The package currently declares: - -- package name `handshake-protocol-kernel` -- version `0.2.4` -- `mcpName` `io.github.joelchan/handshake-protocol-kernel` -- root, conformance, runtime, SDK, role client, CLI, MCP, experimental, and package metadata exports -- bins `handshake`, `handshake-mcp`, and a package-name bin pointing to the MCP server -- files covering bins, source, dist, `server.json`, README, quality/structure docs, and internal docs - -`server.json` currently uses MCP Registry schema `2025-12-11`, npm stdio package metadata, and a non-authority description. - -Existing checks cover: - -- npm pack dry-run JSON inspection -- required packaged files -- forbidden packaged paths -- `private: false` -- `mcpName` and `server.json#name` sync -- Node shebangs for bins -- CLI schema non-authority smoke -- MCP stdio official client smoke -- no raw `PaymentPayload` or `SIGNATURE` leakage in published entrypoints - -Known source drift: - -- README/docs already describe package entrypoints and MCP metadata. -- Current canon still contains older engineering-agent phrasing that must be corrected before publication. - -## Target State - -A release is ready only when there is a source-owned release proof that separates: - -- `ready_to_publish`: local package contract, pack evidence, metadata checks, runtime smoke, account/namespace posture, provenance posture, and authority-boundary checks have passed. -- `actually_published`: npm publish has occurred for the exact package/version and post-publish clean-install smoke has passed. -- `registry_discoverable`: MCP Registry metadata has been accepted and post-registry discoverability checks have passed, without implying artifact trust or enforcement. - -The target proof object is `PackageReleaseProof` with: - -- `packageShapeProof` -- `accountNamespaceProof` -- `publishOperationProof` -- `provenanceProof` -- `registryDiscoverabilityProof` -- `runtimeSmokeProof` -- `authorityBoundary` -- `proofGaps` - -`authorityBoundary` must explicitly record false/non-authority fields for: - -- createsAuthority -- createsPolicyDecision -- createsGreenlight -- performsGatewayCheck -- performsMutation -- holdsCustody -- hostsOperation -- certifiesMarketplace -- managesSettlement -- managesPayment -- establishesTrust -- enforcesHostWidePolicy - -## Assumptions - -- npm is the first artifact registry for the public package. -- MCP Registry is a preview discoverability surface, not an enforcement or trust root. -- The publishable package remains public and installable by package name. -- Publication receipt must distinguish local readiness, npm publication, post-publish install, MCP Registry metadata, and post-registry discoverability. -- x402 exact per-call is used as the first proof wedge only. -- Existing scripts are close enough to extend, but not sufficient until older engineering-agent-only canon is removed from public-facing claims. -- Any missing account, OIDC, 2FA, provenance, or namespace proof is a proof gap, not a release success. - -## Decisions - -1. Public distribution is a publication/readiness problem, not an authority primitive. -2. `ready_to_publish`, `actually_published`, and `registry_discoverable` are separate release states. -3. A release manifest must exist before publish; a post-publish verification receipt must exist after publish. -4. MCP Registry metadata must use non-authority wording and must not imply certification, trust, hosted operation, or enforcement. -5. npm trusted publishing/OIDC is preferred; long-lived token publishing requires explicit risk acceptance and proof-gap recording. -6. Clean install smoke after npm publish is mandatory before claiming public installability. -7. Publication checks must fail on package leakage, public export overexposure, stale metadata, missing provenance posture, or engineering-agent-only framing. -8. Rollback posture is deprecate/unpublish-within-registry-policy where possible, plus documentation correction; publication cannot be silently erased from downstream consumers. - -## Phases - -### Phase 1: Local Readiness Contract - -Define the release proof shape and readiness states. Align package metadata, docs, and checks to the protected-actions-for-automated-decision-making invariant. - -### Phase 2: npm Preflight - -Run dry-run package inspection, public export review, bin shebang checks, CLI/MCP smoke, metadata sync, dependency/install-script review, and authority-boundary wording checks. - -### Phase 3: npm Publish - -Publish only from an exact version/tag with explicit account, 2FA/token, and provenance posture. Record publish operation evidence and proof gaps. - -### Phase 4: Post-npm Verification - -Perform clean install by package name and version. Verify bins, exported entrypoints, proposal/evidence/read behavior, and non-authority messaging from installed artifacts. - -### Phase 5: MCP Registry Preflight - -Verify `server.json`, namespace auth, install method metadata, npm ownership sync, preview-status language, and non-certification claims. - -### Phase 6: MCP Registry Publication - -Submit registry metadata only after npm post-publish verification passes. Record registry operation evidence separately from npm artifact evidence. - -### Phase 7: Post-registry Verification - -Verify discoverability, install instructions, metadata drift, and preview limitations. Record `registry_discoverable` only if the metadata is findable and still non-authority. - -## Task Graph - -- `PD-01` has no dependencies. -- `PD-02` depends on `PD-01`. -- `PD-03` depends on `PD-01`. -- `PD-04` depends on `PD-02` and `PD-03`. -- `PD-05` depends on `PD-04`. -- `PD-06` depends on `PD-05`. -- `PD-07` depends on `PD-06`. -- `PD-08` depends on `PD-07`. -- `PD-09` depends on `PD-08`. -- `PD-10` depends on `PD-09`. -- `PD-11` depends on `PD-10`. -- `PD-12` depends on `PD-11`. - -## Risks And Mitigations - -- Package leakage: enforce pack dry-run forbidden paths and required files. -- Dist/source mismatch: smoke installed artifacts, not just source checkout paths. -- Public exports overexpose authority internals: review `exports` as public API, not convenience. -- Bins imply mutation: smoke CLI/MCP messaging for proposal/evidence/read posture only. -- Registry overclaims trust: constrain `server.json` and docs to metadata/discoverability. -- Token/2FA/provenance gaps: record account posture before publish and block silent token fallback. -- Namespace ownership gaps: require `mcpName`/`server.json#name` sync and namespace auth evidence. -- Metadata drift: compare package metadata, server metadata, README, and published install instructions. -- Node runtime failures: clean install smoke bins and exported entrypoints. -- Unexpected install scripts/dependencies: inspect package scripts and dependency surface before publish. -- Rollback/deprecation gaps: predefine stop/deprecate/correction procedure before publish. -- MCP preview instability: record registry proof gaps and never make enforcement claims from registry availability. - -## Validation Gates - -Local gates: - -- `npm pack --dry-run --json` evidence captured. -- Required files present in pack contents. -- Forbidden paths absent from pack contents. -- `private` is false. -- `package.json#mcpName` equals `server.json#name`. -- Node bins use Node shebangs. -- CLI schema smoke proves non-authority posture. -- MCP stdio smoke works through official client path. -- Raw `PaymentPayload` and `SIGNATURE` are not exposed through published entrypoints. -- Public docs no longer frame Handshake as engineering-agent-only infrastructure. - -Pre-publish gates: - -- version/tag are exact. -- account namespace ownership is evidenced. -- 2FA/token posture is explicit. -- provenance posture is explicit. -- rollback/deprecation posture is written. -- release manifest exists. - -Post-publish gates: - -- clean install by package name and version succeeds. -- installed bins run. -- installed exports resolve. -- proposal/evidence/read surfaces work without implying mutation authority. -- publication receipt distinguishes local, npm, provenance, runtime, and proof-gap evidence. - -Registry gates: - -- `server.json` uses public install methods only. -- registry wording is metadata/discoverability only. -- namespace auth evidence exists or is recorded as a blocker. -- registry acceptance is recorded separately from package artifact evidence. -- post-registry discoverability is verified without trust/certification claims. - -## Cut Lines - -Cut any claim that publication: - -- creates authority -- makes policy decisions -- creates greenlights -- performs gateway checks -- causes mutation -- holds custody -- hosts operation -- certifies trust -- manages settlement or payment -- enforces host-wide policy - -Cut any release path that: - -- relies on long-lived token publish without explicit risk recording -- treats MCP Registry as artifact validation -- treats x402 as protocol center -- keeps engineering-agent-only public framing -- cannot distinguish readiness from actual publication -- cannot reconstruct what was published, by whom, under which version/provenance posture - -## Rollback / Stop Conditions - -Stop before npm publish if: - -- pack contents include forbidden paths. -- public exports expose unstable authority internals. -- docs or metadata imply enforcement through publication. -- account/2FA/provenance posture is unknown. -- version/tag is ambiguous. -- release manifest is missing. -- clean local smoke fails. - -Stop after npm publish and before registry submission if: - -- clean install fails. -- installed bins fail. -- installed artifacts drift from source-owned metadata. -- post-publish receipt cannot be produced. -- non-authority messaging fails from installed artifacts. - -Stop after registry submission if: - -- registry metadata implies trust, certification, hosted operation, settlement, payment, or enforcement. -- namespace auth fails. -- discoverability cannot be verified. -- preview instability prevents a reliable registry receipt. - -Rollback posture: - -- prefer immediate correction release for package metadata or docs drift. -- use npm deprecation for unsafe or misleading versions where appropriate. -- use registry metadata correction/removal where supported. -- record every failed publish, deprecation, correction, and unresolved proof gap. - -## Smallest Next Action - -Define the `PackageReleaseProof` and release-state contract in source-owned docs/checks, with explicit false authority-boundary fields and proof-gap recording before any publish command is considered. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/RISKS.md deleted file mode 100644 index 3263d78..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/RISKS.md +++ /dev/null @@ -1,18 +0,0 @@ -# Risks - -| ID | Risk | Failure Mode | Mitigation | Stop Condition | -| --- | --- | --- | --- | --- | -| R-001 | Package leakage | Pack includes scratch plans, secrets, internal junk, or unintended source | Keep `npm pack --dry-run --json` as hard gate with required and forbidden path checks | Any forbidden path appears | -| R-002 | Dist/source mismatch | Local source passes but installed package fails | Clean install exact package/version after publish | Installed bins or exports fail | -| R-003 | Export overexposure | Public `exports` expose authority internals or unstable control surfaces | Review exports as public API and block arbitrary entrypoints | Export implies enforceable authority without gateway | -| R-004 | Bin overclaim | CLI or MCP bin language implies mutation or enforcement | Smoke installed bins for proposal/evidence/read posture | Bin says or implies publication-created authority | -| R-005 | Registry trust laundering | MCP Registry listing is described as certification or trust | Constrain registry language to metadata and discoverability | Metadata implies trust, certification, or security review | -| R-006 | Token/2FA weakness | Publish relies on risky long-lived or bypass-2FA credentials | Prefer OIDC trusted publishing; record credential posture | Account posture unknown or risky path unaccepted | -| R-007 | Missing provenance | Artifact provenance cannot be shown | Use trusted publishing where supported; otherwise record proof gap | Release policy requires provenance and proof is missing | -| R-008 | Namespace mismatch | `package.json#mcpName` and `server.json#name` drift | Keep sync check hard-gated | Names differ | -| R-009 | Metadata drift | README, package metadata, server metadata, and docs contradict | Add/reuse checks and manual release review | Public text reverts to engineering-agent-only center | -| R-010 | Install-script/dependency surprise | Package install runs unexpected lifecycle behavior or pulls broad dependencies | Inspect scripts/dependencies before publish | Unexpected mutation-capable install behavior appears | -| R-011 | Rollback fantasy | Bad release cannot be erased from consumers | Predefine deprecate/correction path | No rollback/deprecation posture exists | -| R-012 | MCP preview instability | Registry behavior changes or acceptance is unavailable | Treat registry as optional discoverability with proof gaps | Registry instability blocks reliable metadata receipt | -| R-013 | x402 center drift | Package language makes x402 the protocol center | Keep x402 as first proof wedge only | Public docs overfit Handshake to x402 | -| R-014 | Evidence theatre | Receipt conflates local checks, publish operation, registry metadata, and runtime success | Use separate proof sections and state transitions | Receipt cannot reconstruct state chain | diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/TASKS.jsonl deleted file mode 100644 index aef20b2..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/TASKS.jsonl +++ /dev/null @@ -1,12 +0,0 @@ -{"id":"PD-01","priority":"P0","phase":"local-readiness","title":"Define release-state and PackageReleaseProof contract","owner":"GSD executor","rationale":"Publication needs a structured proof boundary before any publish operation, or readiness will be confused with authority.","depends_on":[],"acceptance":["States ready_to_publish, actually_published, and registry_discoverable are distinct","PackageReleaseProof includes packageShapeProof, accountNamespaceProof, publishOperationProof, provenanceProof, registryDiscoverabilityProof, runtimeSmokeProof, authorityBoundary, and proofGaps","authorityBoundary contains explicit false fields for non-authority claims"],"candidate_paths":["docs/internal/decisions.md","docs/internal/protocol-notes.md","scripts/check-published-entrypoints.mjs"],"non_goals":["Do not publish","Do not create gateway enforcement","Do not add hosted operation"]} -{"id":"PD-02","priority":"P0","phase":"local-readiness","title":"Remove engineering-agent-only public framing","owner":"GSD executor","rationale":"The hard invariant is protected actions for automated decision making; engineering agents are a domain wedge, not the product center.","depends_on":["PD-01"],"acceptance":["README and package-facing docs use protected-actions framing","Engineering-agent language is limited to wedge/example status","x402 exact per-call is described as first proof wedge only"],"candidate_paths":["README.md","docs/internal/decisions.md","docs/internal/protocol-notes.md","server.json"],"non_goals":["Do not broaden into generic auth","Do not reposition x402 as protocol center","Do not rewrite unrelated docs"]} -{"id":"PD-03","priority":"P0","phase":"local-readiness","title":"Harden non-authority publication wording","owner":"GSD executor","rationale":"Package and registry metadata must not imply authority, policy decisions, greenlights, gateway checks, mutation, custody, trust, settlement, or hosted operation.","depends_on":["PD-01"],"acceptance":["server.json remains metadata-only","README states publication does not create authority","CLI/MCP descriptions avoid mutation or enforcement claims"],"candidate_paths":["server.json","README.md","package.json","src"],"non_goals":["Do not add enforcement implementation","Do not add marketplace claims","Do not add payment management claims"]} -{"id":"PD-04","priority":"P0","phase":"npm-preflight","title":"Extend package surface checks for authority-boundary claims","owner":"GSD executor","rationale":"Existing package checks cover shape but not the full publication authority boundary.","depends_on":["PD-02","PD-03"],"acceptance":["Pack dry-run remains mandatory","Forbidden path checks remain mandatory","Checks fail on authority-overclaiming metadata or public text","Checks preserve no raw PaymentPayload or SIGNATURE leakage"],"candidate_paths":["scripts/check-package-surface.mjs","scripts/check-published-entrypoints.mjs","package.json","server.json"],"non_goals":["Do not publish","Do not inspect private npm account state in source","Do not certify downstream security"]} -{"id":"PD-05","priority":"P0","phase":"npm-preflight","title":"Create release manifest preflight requirements","owner":"GSD executor","rationale":"A publish operation without an exact manifest is not reconstructable six months later.","depends_on":["PD-04"],"acceptance":["Manifest records package name, version, tag, pack evidence, exports, bins, account posture, provenance posture, authority boundary, stop conditions, and proof gaps","Manifest separates local readiness from publish evidence","Manifest blocks unknown credential posture"],"candidate_paths":["docs/internal/protocol-notes.md","scripts","package.json"],"non_goals":["Do not store secrets","Do not publish","Do not mark actually_published"]} -{"id":"PD-06","priority":"P0","phase":"npm-preflight","title":"Verify npm account, 2FA, token, and provenance posture","owner":"release operator","rationale":"Credential posture is part of publication risk; silent fallback to risky tokens is unacceptable.","depends_on":["PD-05"],"acceptance":["OIDC/trusted publishing availability is recorded","2FA/token posture is recorded","Bypass-2FA token usage is blocked or explicitly recorded as rejected risk","Provenance support is recorded or proof gap is named"],"candidate_paths":["release manifest","npm account configuration","CI publication configuration"],"non_goals":["Do not commit secrets","Do not bypass 2FA silently","Do not treat provenance as runtime enforcement"]} -{"id":"PD-07","priority":"P0","phase":"npm-publish","title":"Publish exact npm package version only after preflight passes","owner":"release operator","rationale":"Publication mutates public artifact state and must be tied to exact package/version/provenance evidence.","depends_on":["PD-06"],"acceptance":["Publish uses exact package version and tag","Publish operation evidence is captured","Failure does not advance actually_published","Provenance evidence or proof gap is recorded"],"candidate_paths":["package.json","release manifest","npm publish output"],"non_goals":["Do not submit MCP Registry metadata yet","Do not claim registry discoverability","Do not claim enforcement"]} -{"id":"PD-08","priority":"P0","phase":"post-npm-smoke","title":"Run clean install smoke against public npm artifact","owner":"GSD executor","rationale":"Local source success does not prove public installability or installed runtime behavior.","depends_on":["PD-07"],"acceptance":["Clean install by package name and version succeeds","Installed handshake bin runs","Installed handshake-mcp bin runs","Installed package-name bin runs","Installed exports resolve","Installed messaging remains non-authority"],"candidate_paths":["published package","dist","bin","exports"],"non_goals":["Do not rely on local checkout","Do not mutate protected surfaces","Do not infer downstream business success"]} -{"id":"PD-09","priority":"P0","phase":"post-npm-smoke","title":"Write post-publish verification receipt","owner":"GSD executor","rationale":"The receipt must distinguish package shape, publish operation, provenance, install smoke, and proof gaps.","depends_on":["PD-08"],"acceptance":["Receipt marks actually_published only after clean install passes","Receipt records proof gaps separately","Receipt preserves authorityBoundary false fields","Receipt is reconstructable from source-owned evidence"],"candidate_paths":["docs/internal/protocol-notes.md","release manifest","post-publish receipt"],"non_goals":["Do not claim MCP discoverability","Do not erase failed publish attempts","Do not merge registry evidence into npm evidence"]} -{"id":"PD-10","priority":"P1","phase":"mcp-registry-preflight","title":"Verify MCP Registry metadata and namespace posture","owner":"release operator","rationale":"MCP Registry is metadata/discoverability only and requires namespace/package-name alignment.","depends_on":["PD-09"],"acceptance":["server.json uses public install methods","package.json mcpName matches server.json name","Namespace auth evidence exists or blocks","Registry wording stays metadata-only","Preview limitations are recorded"],"candidate_paths":["server.json","package.json","README.md","MCP Registry submission metadata"],"non_goals":["Do not imply registry certification","Do not host artifacts in registry","Do not claim enforcement"]} -{"id":"PD-11","priority":"P1","phase":"mcp-registry-publish","title":"Submit MCP Registry metadata after npm proof passes","owner":"release operator","rationale":"Registry submission before npm artifact verification would create discoverability for an unproven package.","depends_on":["PD-10"],"acceptance":["Registry submission evidence is captured","Failure does not advance registry_discoverable","Registry operation evidence is separate from npm publish evidence"],"candidate_paths":["server.json","MCP Registry submission output","post-publish receipt"],"non_goals":["Do not republish npm package","Do not claim trust","Do not claim marketplace approval"]} -{"id":"PD-12","priority":"P1","phase":"post-registry-smoke","title":"Verify registry discoverability and finalize release support bundle","owner":"GSD executor","rationale":"Discoverability must be evidenced and packaged with explicit readiness statuses and proof gaps.","depends_on":["PD-11"],"acceptance":["Registry listing is discoverable","Listing install instructions match source-owned metadata","Support bundle uses allowed readiness statuses","registry_discoverable is set only after verification","MCP preview instability is recorded if present"],"candidate_paths":["server.json","README.md","support bundle","release receipt"],"non_goals":["Do not claim host-wide enforcement","Do not claim payment or settlement management","Do not certify downstream aggregators"]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/VALIDATION.md deleted file mode 100644 index 4a2cdfb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/VALIDATION.md +++ /dev/null @@ -1,97 +0,0 @@ -# Validation - -## Invariant Gate - -A release passes only if every public surface preserves this statement: - -Handshake is protected actions for automated decision making. Publication distributes package artifacts, proposal/evidence/read surfaces, and source-owned metadata. Publication does not create authority, policy decisions, greenlights, gateway checks, mutations, custody, hosted operation, marketplace certification, settlement, payment management, trust, or host-wide enforcement. - -## Local Readiness Gates - -- Package identity is explicit: name, version, `mcpName`. -- `server.json#name` matches `package.json#mcpName`. -- `server.json` uses MCP Registry schema `2025-12-11`. -- `server.json` describes npm stdio install metadata only. -- `package.json#private` is false. -- `exports` are reviewed as the public interface. -- `bin` entries point to Node-shebang executables. -- `files` allow required publication files and exclude forbidden paths. -- `npm pack --dry-run --json` evidence is captured. -- CLI schema smoke proves non-authority behavior. -- MCP stdio smoke proves runtime startup through official client path. -- Published entrypoints do not leak raw `PaymentPayload` or `SIGNATURE`. - -## Documentation Gates - -- README/package/server metadata do not frame Handshake as engineering-agent-only infrastructure. -- Engineering-agent language is limited to a domain example or wedge. -- x402 exact per-call is described as first proof wedge, not protocol center. -- Public docs do not imply publication-created authority. -- Public docs do not imply MCP Registry trust, certification, security review, custody, settlement, payment management, hosted operation, or enforcement. - -## npm Preflight Gates - -- Exact version/tag is chosen. -- Release manifest exists. -- Account ownership posture is recorded. -- 2FA/token posture is recorded. -- OIDC/trusted publishing posture is recorded. -- Provenance posture is recorded. -- Rollback/deprecation posture is recorded. -- Known proof gaps are explicit. - -## npm Publish Gates - -- Publish command uses exact intended package/version/tag. -- Publish operation evidence is captured. -- Provenance evidence is captured or proof gap recorded. -- Failure does not advance `actually_published`. - -## Post-npm Gates - -- Clean install by package name and exact version succeeds. -- Installed `handshake` bin runs. -- Installed `handshake-mcp` bin runs. -- Installed package-name bin runs. -- Installed exports resolve. -- Proposal/evidence/read surfaces operate without implying mutation authority. -- Post-publish receipt exists. -- `actually_published` is set only after clean install smoke passes. - -## MCP Registry Preflight Gates - -- npm package metadata is public and installable. -- `package.json#mcpName` equals `server.json#name`. -- Namespace auth evidence exists or blocks. -- Install methods are public. -- Registry wording is metadata/discoverability only. -- Preview limitations are stated. - -## MCP Registry Post Gates - -- Registry metadata submission evidence is captured. -- Discoverability is verified. -- Registry listing does not imply artifact trust or enforcement. -- `registry_discoverable` is set only after post-registry verification. -- Any registry preview instability is recorded as proof gap. - -## Release Status Vocabulary - -Allowed readiness statuses: - -- `ready:proposal-mode` -- `ready:gateway-mode` -- `blocked:metadata` -- `blocked:runtime` -- `blocked:mcp-stdio` -- `blocked:package-contents` -- `blocked:namespace-auth` -- `blocked:provenance` -- `preview:unsupported-enforcement` - -Forbidden status implications: - -- no status may imply publication-created authority -- no status may imply MCP Registry certification -- no status may imply gateway enforcement unless a gateway check actually exists and is evidenced -- no status may imply payment or settlement management diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/input.md deleted file mode 100644 index 1eda42a..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/input.md +++ /dev/null @@ -1,153 +0,0 @@ -# Input: Public Distribution And Publication - -## Hard Frame - -Handshake is protected actions for automated decision making, not engineering-agent-only infrastructure. - -x402 exact per-call is the first proof wedge, not the protocol center. - -Public distribution means packaging and publishing proposal/evidence/read surfaces and source-owned metadata. It does not create authority, gateway custody, hosted operation, marketplace trust, certification, settlement, payment management, or host-wide enforcement. - -CLI/MCP/SDK publication is distribution, not enforcement. Any command, server, package metadata, or registry listing must keep the boundary: - -```text -proposal/read/evidence surface != policy decision -proposal/read/evidence surface != greenlight -proposal/read/evidence surface != gateway check -proposal/read/evidence surface != mutation -proposal/read/evidence surface != receipt export -proposal/read/evidence surface != hosted verifier trust -``` - -## Current Source State - -Tracked source already has a publishable package boundary: - -- `package.json` - - name: `handshake-protocol-kernel` - - version: `0.2.4` - - `mcpName`: `io.github.joelchan/handshake-protocol-kernel` - - bin commands: - - `handshake` -> `bin/handshake` - - `handshake-mcp` -> `bin/handshake-mcp` - - `handshake-protocol-kernel` -> `bin/handshake-mcp` - - exports: - - `.` - - `./conformance` - - `./runtime` - - `./sdk/role-clients` - - `./cli` - - `./mcp` - - `./experimental` - - `./package.json` - - files include `bin`, `src`, `dist`, `server.json`, repo canon, and compact internal docs. - -- `server.json` - - schema: `https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json` - - name: `io.github.joelchan/handshake-protocol-kernel` - - package: npm/stdio `handshake-protocol-kernel` version `0.2.4` - - description explicitly says proposal/evidence only and no policy, greenlight, gateway check, mutation, receipt export, authority certificate, provider custody, hosted operation, or broad MCP protection. - -- `scripts/check-package-surface.mjs` - - runs `npm pack --dry-run --json` - - verifies required files - - rejects package leakage of `.planning/`, `.agents/`, tests, old docs trees, `.DS_Store`, and other forbidden paths - - rejects `package.json#private === true` - -- `scripts/check-published-entrypoints.mjs` - - asserts `package.json#mcpName` matches `server.json#name` - - asserts `server.json` version/package metadata matches `package.json` - - asserts bin wrappers exist and use Node shebangs - - smoke-tests `node bin/handshake schema` - - smoke-tests `bin/handshake-mcp` through the official MCP client SDK - - confirms CLI/MCP outputs do not create authority, greenlight, gateway check, mutation, raw records, credential material, receipt export, or certificate mint. - -Current local package docs: - -- `README.md` describes packaged CLI/MCP entrypoints and MCP Registry metadata. -- `docs/internal/decisions.md` records package boundary decision. -- `.planning/codebase/STACK.md` and `.planning/codebase/INTEGRATIONS.md` record publication posture as scratch mapper outputs. - -## Official External Source Constraints - -Use these source constraints in the plan: - -- npm publish docs: - - `npm publish` publishes a package installable by name. - - npm defaults to the public registry unless registry config/scope changes it. - - `npm pack --dry-run` is the way to inspect what will be included before publication. - - `npm publish` has `access`, `dry-run`, `otp`, `provenance`, and `provenance-file` configuration surfaces. - - Source: https://docs.npmjs.com/cli/publish/ - -- npm pack docs: - - `npm pack --dry-run --json` can report what would be packed without creating changes and can output JSON. - - Source: https://docs.npmjs.com/cli/v11/commands/npm-pack - -- npm package.json docs: - - `name` and `version` are required identifiers for publishable packages. - - `exports` defines the public interface and prevents arbitrary entrypoints outside exports. - - `bin` installs executable commands and bin files should start with `#!/usr/bin/env node`. - - `files` controls what is included. - - Source: https://docs.npmjs.com/cli/v11/configuring-npm/package-json - -- npm trusted publishing docs: - - trusted publishing uses short-lived scoped OIDC credentials and avoids long-lived publish tokens. - - npm recommends restricting traditional token access after trusted publishing is configured. - - trusted publishing can automatically generate provenance for public packages from public repositories under supported conditions. - - Source: https://docs.npmjs.com/trusted-publishers/ - -- npm access token / 2FA docs: - - granular tokens can be scoped and can bypass 2FA only if configured. - - bypassing 2FA should not be used when fully enforced 2FA is required. - - `Require two-factor authentication and disallow tokens` prevents granular token publishing. - - Sources: - - https://docs.npmjs.com/about-access-tokens/ - - https://docs.npmjs.com/requiring-2fa-for-package-publishing-and-settings-modification/ - -- MCP Registry docs: - - the official MCP Registry is currently preview and may have breaking changes or data resets before GA. - - it hosts metadata, not package artifacts. - - server metadata lives in standardized `server.json`. - - npm package metadata in `server.json` uses `registryType: "npm"` and package identifier/version/transport. - - npm package ownership verification requires `package.json#mcpName` to match `server.json#name`. - - the registry supports only public installation methods / public servers and does not support private servers. - - namespace authentication determines allowed server names. - - the registry focuses on namespace authentication and metadata hosting; underlying package registries and downstream aggregators handle broader security scanning/curation. - - Sources: - - https://modelcontextprotocol.io/registry/about - - https://modelcontextprotocol.io/registry/quickstart - - https://modelcontextprotocol.io/registry/package-types - - https://modelcontextprotocol.io/registry/authentication - - https://modelcontextprotocol.io/registry/github-actions - -## Planning Question - -Create a macro plan for public distribution and publication that makes the package actually release-ready without overclaiming authority. - -The plan must cover: - -- npm package release readiness; -- MCP Registry publication readiness; -- source-owned package metadata and schema validation; -- CLI/MCP/SDK public-surface boundaries; -- provenance/trusted publishing posture; -- 2FA/token posture; -- dry-run and post-publish verification; -- release rollback/deprecation posture; -- support/readiness bundle; -- versioning/tagging/registry drift; -- docs and claim guards; -- end criteria for "ready to publish" versus "published"; -- what a 10-star publication surface looks like; -- antipatterns to avoid. - -## Required Output Properties - -- The plan must keep CLI/MCP/SDK as proposal/evidence/read surfaces unless paired with actual gateway enforcement. -- The plan must not imply npm or MCP Registry publication is trust, certification, marketplace status, hosted operation, custody, or authority. -- The plan must separate package shape proof, account/namespace proof, publish operation proof, provenance proof, registry discoverability proof, and runtime smoke proof. -- The plan must be executable slice-by-slice. -- The plan must name validation gates and closeout commands. -- The plan must include external-source decisions and cut lines. -- The plan must include non-goals and stop conditions. -- The plan must not implement source changes. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ADOPTION.md deleted file mode 100644 index 1cab9c2..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ADOPTION.md +++ /dev/null @@ -1,211 +0,0 @@ -# ADOPTION: Public Distribution And Publication - -## Invariant At Stake - -Public distribution must not convert a proposal/evidence surface into an authority claim. If npm, CLI, MCP, README, or support output implies enforcement without a blocking gateway check, this is advisory, not Handshake. - -## First Install/Test-Drive Flow - -### npm user - -The first-run path should prove three things fast: - -1. The package installs by public name. -2. The CLI/bin exports work on the supported Node runtime. -3. A user can generate or inspect an exact protected-action proposal without believing mutation is enforced. - -Recommended flow: - -```bash -npm install -npx --version -npx doctor -npx demo x402 -npx support-bundle --dry-run -``` - -The demo should show: - -- exact per-call action contract; -- policy decision shape; -- evidence/receipt shape; -- explicit statement that no real mutation occurred; -- explicit statement that enforcement requires a gateway integration. - -Do not make the first demo depend on hosted accounts, secrets, payment credentials, or real x402 traffic. - -### MCP user - -The MCP path should prove stdio startup and read/proposal capability only: - -```json -{ - "mcpServers": { - "handshake": { - "command": "npx", - "args": ["", "mcp"] - } - } -} -``` - -Expected first MCP actions: - -- `handshake.readiness`; -- `handshake.describeCatalog`; -- `handshake.proposeAction`; -- `handshake.renderEvidence`; -- `handshake.supportBundle`. - -Avoid MCP tools named as if they execute protected work unless they really perform gateway-blocked enforcement. Prefer `propose*`, `inspect*`, `explain*`, `read*`, `render*`. - -## README/Quickstart Posture - -The README should open with a tight boundary: - -> Handshake turns consequential automated actions into exact proposed action contracts, policy decisions, gateway checks, and reconstructable evidence. This package provides public SDK, CLI, MCP, and readiness surfaces. Enforcement exists only where a blocking gateway check is integrated before mutation. - -The quickstart should separate: - -- **Proposal/read mode:** CLI, MCP, SDK can form contracts and evidence. -- **Gateway mode:** protected mutation is blocked unless an exact greenlight is checked at the gateway. -- **Preview status:** package is public/preview; enforcement coverage is intentionally narrow. - -The x402 wedge should be framed as the first proof path: - -> The first packaged wedge is exact per-call x402 authorization evidence. Handshake is not x402-only; x402 is the first narrow protected-action surface used to prove contract binding, one-use greenlights, and receipt evidence. - -## CLI/MCP Expectations And Non-Claims - -### CLI may claim - -- creates exact action proposals; -- canonicalizes known action contracts; -- runs readiness checks; -- emits support bundles; -- validates package/MCP metadata; -- demonstrates x402 per-call contract/evidence flow; -- shows whether a gateway is configured. - -### CLI must not claim - -- "protects your agents" by itself; -- "enforces MCP tools" broadly; -- "secures payments" generally; -- "manages x402 payments"; -- "approves actions" unless policy decision semantics are exact; -- "blocks mutation" unless the command is paired with a real gateway check. - -### MCP may claim - -- exposes proposal/read/evidence tools to MCP clients; -- lets an agent inspect catalog, policy posture, and receipts; -- can participate in review flows. - -### MCP must not claim - -- that stdio itself is the enforcement boundary; -- that MCP registration protects tools; -- that an agent cannot bypass it; -- that all CLI/MCP actions are protected; -- that a rendered plan is permission. - -If MCP can propose but not block, say so directly: - -> This MCP server is a proposal and evidence surface. It does not enforce protected mutation unless the downstream gateway checks the exact greenlight before consequence. - -## Support Bundle/Readiness Report - -The support bundle should be boring, local, and redacted by default. - -It should include: - -- package name/version; -- Node version and platform; -- binary resolution; -- export resolution; -- package files included; -- `server.json` presence and parse result; -- MCP stdio smoke result; -- namespace/auth status where relevant; -- provenance status; -- preview/GA status; -- configured gateway status; -- action catalog version; -- x402 demo readiness; -- last readiness failure code; -- redaction summary. - -It should not include: - -- secrets; -- raw env vars; -- payment credentials; -- private keys; -- full filesystem listings; -- hosted account tokens; -- mutation payloads unless explicitly redacted. - -Readiness status should be explicit: - -- `ready:proposal-mode` -- `ready:gateway-mode` -- `blocked:metadata` -- `blocked:runtime` -- `blocked:mcp-stdio` -- `blocked:package-contents` -- `blocked:namespace-auth` -- `blocked:provenance` -- `preview:unsupported-enforcement` - -## Error Message Guidance - -| Failure | Message Shape | -|---|---| -| Namespace auth | `Namespace authorization failed for . Publish/install identity could not be verified. This blocks public distribution readiness, not local proposal-mode use.` | -| Metadata | `Package metadata is incomplete: missing . npm/MCP users need stable name, version, bin, exports, files, and preview status before public install can be trusted.` | -| Provenance | `Package provenance is missing or unverifiable. Public publication can proceed only as preview if this is intentional; otherwise fix provenance before release.` | -| Package contents | `Published files do not include required runtime assets: . The package may install but cannot provide the documented CLI/MCP surface.` | -| Node runtime | `Unsupported Node runtime: detected , requires . Handshake cannot guarantee CLI/MCP behavior on this runtime.` | -| MCP metadata/server.json | `MCP Registry metadata is invalid: . This blocks registry readiness, not npm install by name.` | -| MCP stdio smoke | `MCP stdio smoke failed before capability registration: . The server is not ready for MCP clients.` | -| Gateway missing | `No blocking gateway configured. CLI/MCP/SDK are available in proposal/evidence mode only.` | -| x402 demo unavailable | `x402 per-call demo is unavailable: . This does not mean Handshake is x402-only; it means the first public proof wedge is not ready.` | - -Error messages should say what is blocked and what is still usable. Do not collapse metadata failure, enforcement failure, and demo failure into one vague "setup failed." - -## 10-Star First Public Package Experience - -A 10-star first package experience looks like this: - -- `npm install` works by name without private registry assumptions. -- `npx doctor` gives a crisp readiness report in under a few seconds. -- MCP users can paste one config block and get a successful stdio smoke. -- The first demo produces an exact x402 per-call proposal/evidence artifact without requiring real money movement. -- Every screen distinguishes proposal, policy decision, gateway check, execution result, refusal, and proof gap. -- README tells users exactly what is enforced today and what is only preview/proposal mode. -- Package contents match docs: bins, exports, server metadata, examples, and support command all work. -- Failure messages are actionable and scoped. -- No hosted operation is implied. -- No broad "agent security" claim appears before gateway enforcement exists. - -## What To Avoid - -Avoid: - -- naming commands `approve`, `execute`, `protect`, or `enforce` unless they actually bind to gateway checks; -- presenting MCP as the enforcement point; -- making x402 read as the whole product; -- making Handshake sound like payment management; -- claiming engineering-agent-only scope in public positioning; -- implying hosted control plane dependency; -- using "trust," "secure," "policy," or "approval" without exact mechanism; -- showing a review UI that is not bound to the exact action contract; -- letting support output imply downstream business success; -- hiding preview limitations behind friendly onboarding copy. - -## Brutal Verdict - -Keep public distribution narrow. The package should make Handshake feel easy to try, but hard to misunderstand. Public DevEx wins only if users can install, inspect, propose, and verify readiness while clearly seeing that real protection begins at the gateway check. - -Smallest next mechanism to build: a single `doctor`/readiness contract that reports `proposal-mode` versus `gateway-mode` and drives the README, CLI, MCP smoke, and support bundle from the same status vocabulary. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ARCH.md deleted file mode 100644 index 001d477..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/ARCH.md +++ /dev/null @@ -1,201 +0,0 @@ -# ARCH: Public Distribution And Publication - -## Invariant At Stake - -Publication must never be confused with authority. - -Public Distribution And Publication is a distribution/read surface for proposal, evidence, metadata, and installability. It must not create policy, greenlights, gateway checks, mutation rights, custody, hosted operation, marketplace certification, or broad enforcement claims. If publication can be interpreted as "installed equals authorized," the architecture has already failed. - -## Architecture Guidance - -### Package Release Proof Object - -Define a durable `PackageReleaseProof` as a receipt bundle, not a trust badge. - -```ts -type PackageReleaseProof = { - proofId: string; - releaseId: string; - packageName: string; - version: string; - packageManager: "npm"; - createdAt: string; - - packageShapeProof: PackageShapeProof; - accountNamespaceProof: AccountNamespaceProof; - publishOperationProof: PublishOperationProof; - provenanceProof: ProvenanceProof; - registryDiscoverabilityProof: RegistryDiscoverabilityProof; - runtimeSmokeProof: RuntimeSmokeProof; - - releaseManifestDigest: string; - postPublishVerificationDigest?: string; - - authorityBoundary: { - createsPolicy: false; - createsGreenlight: false; - createsGatewayCheck: false; - performsMutation: false; - holdsCustody: false; - certifiesThirdParty: false; - }; - - proofGaps: ProofGap[]; -}; -``` - -This object proves only that a package was shaped, published, discoverable, and smoke-tested under declared constraints. It does not prove that any downstream protected action is authorized or safe. - -### Split Proofs - -Do not collapse release evidence into one "published successfully" flag. That is evidence theatre. - -Use separate proofs: - -- `PackageShapeProof`: npm dry-run pack JSON, files included, exports, bins, package name, version, `mcpName`, `server.json`, license/readme presence, no undeclared source leakage. -- `AccountNamespaceProof`: npm org/user ownership, MCP namespace authorization, `mcpName` matching registry server name, explicit account/2FA/token posture. -- `PublishOperationProof`: exact package/version attempted, actor, CI run, command class, environment, dry-run predecessor, publish result, package digest. -- `ProvenanceProof`: OIDC/trusted publishing status, provenance bundle URL/digest, CI provider identity, source commit, build workflow identity. -- `RegistryDiscoverabilityProof`: MCP Registry preview metadata accepted, `server.json` present, public install method valid, namespace/auth checks passed, metadata not artifact-hosting. -- `RuntimeSmokeProof`: installed-from-packed or installed-from-registry package executes CLI/MCP in non-authority mode only. - -Each proof must carry `verifiedAt`, `source`, `digest`, `result`, and `proofGaps`. - -### Release Manifest - -Create a release manifest that is generated before publish and immutable after publish. - -It should bind: - -- source commit; -- package name/version; -- npm package shape; -- packed tarball digest; -- export map; -- bin map; -- MCP server metadata; -- `server.json` digest; -- expected public install command; -- expected non-authority smoke commands; -- intended registry namespace/name; -- explicit authority boundary. - -The manifest is not a greenlight. It is the expected release contract for publication evidence. - -### Post-Publish Verification Receipts - -After publish, create a separate receipt comparing public reality against the release manifest. - -It should verify: - -- npm package exists at exact version; -- installed package digest or contents match expected release shape; -- CLI bins resolve and run non-authority commands; -- SDK exports expose only allowed public APIs; -- MCP metadata resolves and advertises only proposal/evidence/read tools; -- registry metadata points to npm install method; -- provenance is present or a proof gap is recorded; -- deprecation status is correct; -- no hidden publish-time files appeared. - -If the manifest and public package diverge, record a proof gap or quarantine release status. Do not silently "fix docs." - -### CLI / MCP / SDK Boundaries - -Public package surfaces must be boring and non-authoritative. - -Allowed: - -- inspect release metadata; -- validate local config; -- render proposal/evidence/read surfaces; -- emit candidate action contracts; -- verify receipts; -- run smoke checks; -- explain authority boundaries. - -Forbidden unless gateway-bound: - -- mutate protected surfaces; -- create greenlights; -- evaluate policy as final authority; -- perform gateway checks; -- hold secrets for downstream mutation; -- execute protected actions directly; -- imply certification or marketplace approval. - -CLI bins should have names that do not imply hosted authority. MCP tools must be classified as `read`, `validate`, `propose`, or `receipt`. If a tool can mutate, it does not belong in this publication package unless it is a gateway adapter with exact greenlight verification. - -### Metadata Validation - -Metadata validation should be treated as release blocking. - -Validate: - -- `package.json` `name`, `version`, `files`, `exports`, `bin`; -- `mcpName` presence and match to MCP Registry server name; -- `server.json` schema and install method; -- npm pack dry-run JSON against allowlist; -- registry namespace ownership; -- public install command; -- README claims against authority boundary; -- no package metadata says or implies "approval," "enforcement," "certified," or "trusted" unless the mechanism exists. - -Metadata is not marketing. Metadata is an install-time contract surface. - -### Provenance And Secret Posture - -Preferred path: trusted publishing with OIDC and provenance. - -Architecture posture: - -- publish from CI, not a local machine; -- no long-lived npm token when trusted publishing is available; -- if token publishing is used, record token class, 2FA posture, expiry, storage boundary, and rotation plan; -- provenance absence is a proof gap, not a warning buried in logs; -- package digest must bind to source commit and release manifest; -- CI identity must be explicit. - -A package published with an opaque token and no provenance can still be distributed, but it cannot carry strong release proof. - -### Rollback, Deprecation, Versioning - -Do not design rollback as "delete the bad version." npm publication is append-heavy in practice and unpublish has constraints. - -Use: - -- immutable version receipts; -- deprecation receipts for bad versions; -- replacement version receipts; -- registry metadata update receipts; -- release status: `active`, `deprecated`, `quarantined`, `superseded`; -- semver policy separating public API changes from metadata-only corrections; -- documented refusal to reuse versions. - -A rollback is a new evidence event. It does not erase the bad release. - -### Import / Export Guard Architecture - -Guard the package boundary like an authority boundary. - -Use checks that install or inspect the packed artifact, not just source paths. - -Guard against: - -- exporting internal policy/gateway modules; -- exporting mutation-capable adapters by accident; -- bins reaching private source paths; -- wildcard exports; -- package files including `.planning`, internal reports, secrets, fixtures with credentials, or unpublished authority code; -- MCP tools exposing hidden mutation handlers; -- SDK import paths bypassing intended public APIs. - -The test posture should be: "Can an external consumer import or invoke anything that sounds like authority?" If yes, block release. - -## Brutal Verdict - -Keep the publication macro item, but narrow it hard. - -This is not the "public Handshake platform." It is release evidence for public package distribution and registry discoverability. The first wedge is x402 exact per-call because it gives a clean proof surface, not because x402 is the protocol center. The product remains protected actions for automated decision making. - -Smallest next mechanism to build: a release manifest plus post-publish verification receipt that proves package shape, metadata, provenance posture, registry discoverability, and non-authority runtime behavior for one exact package version. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/EXECUTION.md deleted file mode 100644 index c1e7a47..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/EXECUTION.md +++ /dev/null @@ -1,303 +0,0 @@ -# EXECUTION: Public Distribution And Publication - -## Invariant At Stake - -Publication must distribute proposal/evidence/read surfaces only. It must not imply gateway enforcement, execution authority, or protected mutation control until those paths are actually enforced. - -# Execution Plan: Public Distribution And Publication - -## Phase 0: Local Source Readiness - -Tasks: - -1. Confirm package surface is intentional: - ```bash - npm run build - node scripts/check-package-surface.mjs - node scripts/check-published-entrypoints.mjs - ``` - -2. Confirm repo quality gates: - ```bash - npm run format:check - npm run check:repo - ``` - -3. Confirm package metadata: - - `package.json` has correct `name`, `version`, `description`, `license`, `repository`, `bin`, `files`, `exports`. - - `bin` wrappers point only at built distributable files. - - `dist/` contains every exported runtime entrypoint. - - README package install docs match the actual package name and command shape. - - No `.planning/` paths leak into repo-facing package docs or package metadata. - -Dry-run gate: - -```bash -npm pack --dry-run --json -``` - -Stop conditions: - -- Unexpected files in packed tarball. -- Missing `dist` bundle or bin wrapper. -- Package docs claim enforcement, authority, gateway checks, or mutation protection beyond the implemented package. -- Any check script fails. - -## Phase 1: NPM Publication Preflight - -Tasks: - -1. Confirm npm identity and registry: - ```bash - npm whoami - npm config get registry - npm view version - ``` - -2. Confirm version uniqueness: - ```bash - npm view @ version - ``` - - Expected: not found for a new version. - -3. Confirm 2FA/token posture: - - Prefer npm trusted publishing with provenance from CI. - - If using local publish, verify account 2FA is enabled and token scope is minimal. - - Do not use broad long-lived automation tokens unless there is no CI alternative. - -4. Run publish dry-run: - ```bash - npm publish --dry-run --access public - ``` - -CI/release gate: - -- Release must run from a clean git tag matching `package.json` version. -- CI must run build, package-surface checks, published-entrypoint checks, format, and repo check before publish. -- Trusted publishing/provenance should be required for the real publish job: - ```bash - npm publish --access public --provenance - ``` - -Stop conditions: - -- `npm whoami` is wrong. -- Registry is not `https://registry.npmjs.org/`. -- Version already exists. -- Provenance/trusted publishing is unavailable but release policy requires it. -- Dry-run tarball differs from expected package surface. - -Rollback posture: - -- npm versions are effectively immutable. -- If a bad version publishes, immediately deprecate it: - ```bash - npm deprecate @ "Do not use: publication error. Upgrade to ." - ``` -- Publish a corrected patch version. Do not attempt to pretend the bad artifact never existed. - -## Phase 2: NPM Publish - -Tasks: - -1. Create and push release tag only after all local gates pass: - ```bash - git status --short - git tag v - git push origin v - ``` - -2. Publish through CI trusted publishing, or locally only if explicitly accepted: - ```bash - npm publish --access public --provenance - ``` - -3. Capture evidence: - ```bash - npm view @ --json - npm view @ dist.integrity - npm view @ dist.tarball - ``` - -Stop conditions: - -- Dirty worktree before tag. -- CI quality gates fail. -- Publish succeeds but package metadata does not match intended version, tarball, or entrypoints. - -## Phase 3: Post-NPM Smoke Tests - -Tasks: - -1. Install from npm in a clean temp project: - ```bash - mkdir -p /tmp/handshake-npm-smoke - cd /tmp/handshake-npm-smoke - npm init -y - npm install @ - ``` - -2. Verify package import surface: - ```bash - node -e "import('').then(m => console.log(Object.keys(m).sort()))" - ``` - -3. Verify bin wrapper: - ```bash - npx --help - ``` - -4. Verify published entrypoint assumptions: - ```bash - node -e "import('/').then(() => console.log('ok'))" - ``` - -Stop conditions: - -- Installed package cannot import. -- Bin wrapper fails. -- Public entrypoints differ from README or check scripts. -- Help/docs imply authority enforcement where only read/proposal/evidence publication exists. - -## Phase 4: MCP Registry Preflight - -Tasks: - -1. Validate `server.json` shape: - - `mcpName` is stable and namespace-qualified. - - Package reference points to the published npm package and exact version range policy. - - Public install/preview commands match the npm package. - - Description is distribution-scoped, not enforcement-scoped. - - Registry metadata does not claim gateway authority unless the package actually performs gateway checks. - -2. Validate with the official MCP Registry publisher/validator once pinned: - ```bash - mcp-publisher validate server.json - ``` - -3. Preview rendered registry listing if supported: - ```bash - mcp-publisher preview server.json - ``` - -Stop conditions: - -- `server.json` package reference does not match the npm-published package. -- `mcpName`/namespace conflicts or is not owned. -- Public install command fails in a clean environment. -- Registry listing claims Handshake provides enforcement authority through publication alone. - -## Phase 5: MCP Registry Publish - -Tasks: - -1. Authenticate with the registry using the intended namespace owner. -2. Publish the validated `server.json`: - ```bash - mcp-publisher publish server.json - ``` - -3. Capture registry publish evidence: - ```bash - curl -s - ``` - -Stop conditions: - -- Namespace ownership is not verified. -- Registry publish points at unpublished or wrong npm version. -- Registry generated install command does not work. -- Registry listing cannot be reconstructed from `server.json`. - -Rollback posture: - -- If registry metadata is wrong, publish a corrected registry update if the registry supports replacement. -- If package artifact is wrong, deprecate npm version and update registry to point at the corrected patch. -- If namespace is wrong, halt. Do not create a second public identity without an explicit naming decision. - -## Phase 6: Post-Registry Smoke Tests - -Tasks: - -1. Search registry by name: - ```bash - curl -s "?q=" - ``` - -2. Fetch registry server record: - ```bash - curl -s "/" - ``` - -3. Install exactly as public users would: - ```bash - - ``` - -4. Verify MCP server startup/read surfaces: - ```bash - --help - ``` - -5. Confirm registry metadata agrees with npm: - - package name - - version/range - - bin command - - README link - - source repo - - license - - description - -Stop conditions: - -- Registry search cannot find the server after propagation window. -- Registry API returns stale or mismatched metadata. -- Public install command fails. -- MCP startup path differs from package docs. - -## Docs And Claim Guards Needed Later - -Likely updates when implementing: - -- README: add install, CLI/bin, MCP install, and smoke-test examples. -- `docs/internal/decisions.md`: record that publication distributes proposal/evidence/read surfaces, not authority. -- `docs/internal/protocol-notes.md`: clarify published package boundary versus gateway enforcement boundary. -- Claim guard: reject README/docs language that says publication "enforces," "authorizes," "secures mutations," or "approves actions" unless tied to implemented gateway checks. -- Package guard: ensure `.planning/`, internal-only reports, local scratch files, and unpublished source paths cannot enter npm tarball. -- Entry-point guard: ensure README-documented imports and bin commands are present in built `dist`. - -## Task Dependency Graph - -```mermaid -graph TD - A["Local build"] --> B["Package surface checks"] - B --> C["Published entrypoint checks"] - C --> D["Repo quality gates"] - D --> E["npm pack dry-run"] - E --> F["npm publish dry-run"] - F --> G["CI trusted publishing gate"] - G --> H["npm publish"] - H --> I["npm install smoke test"] - I --> J["MCP server.json validation"] - J --> K["MCP Registry preview"] - K --> L["MCP Registry publish"] - L --> M["Registry API/search verification"] - M --> N["Public install smoke test"] - N --> O["Closeout evidence recorded"] -``` - -## Closeout Commands - -```bash -npm view @ --json -npm install @ -npx --help -curl -s "?q=" -curl -s "/" -npm run check:repo -``` - -Brutal verdict: keep the publication plan narrow. npm and MCP Registry make Handshake installable and inspectable; they do not create authority. Any copy, registry metadata, or release note that implies gateway enforcement from publication alone is advisory theatre. - -Smallest next mechanism to build: a single release preflight script that runs build, package-surface checks, published-entrypoint checks, `npm pack --dry-run --json`, and fails on forbidden authority claims in package-facing docs. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/RISK.md deleted file mode 100644 index 744ea7b..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/RISK.md +++ /dev/null @@ -1,30 +0,0 @@ -# RISK: Public Distribution And Publication - -## Invariant At Stake - -Publishing must not convert proposal, evidence, or read surfaces into implied authority. Public distribution is only acceptable if the package cannot leak protected internals, cannot mutate protected surfaces, cannot imply gateway enforcement where none exists, and can be reconstructed after publication. - -| Risk | Failure Mode | Mitigation | Validation Evidence | Stop Condition | -|---|---|---|---|---| -| Package leaks planning, test, secret, or internal source | npm tarball includes `.planning/`, fixtures with raw receipts, test credentials, internal docs, local env files, or unpublished gateway/signer code. | Use explicit `files` allowlist. Add tarball inspection gate. Block `.planning/`, `test`, `fixtures`, `.env*`, internal docs, raw receipt samples, credential references, and private adapters unless intentionally public. | `npm pack --dry-run` artifact list reviewed and committed as release evidence. Automated denylist check passes against packed tarball, not repo tree. | Any unreviewed internal, planning, credential, raw record, or protected adapter file appears in package contents. | -| Dist/source mismatch | Published `dist` does not match reviewed source; stale build ships hidden behavior, broken APIs, or authority internals removed from source. | Clean build before pack. Verify source-to-dist mapping. Require generated declaration files and JS output to be regenerated from current commit. | Build hash, `git diff --exit-code` after build, packed `dist` file inventory, and smoke import from packed tarball. | Build creates uncommitted drift, packed `dist` differs from current source expectations, or source maps reveal private paths. | -| Public exports overexpose authority internals | `exports` exposes signer primitives, gateway acceptance internals, raw receipt stores, credential resolution internals, or mutation helpers. Downstream users can treat internals as supported authority APIs. | Export only proposal, evidence, read, and metadata surfaces. Keep signer/gateway/credential/raw-record modules private. Add export-boundary tests. | `package.json exports` audit. Type-level import tests prove internal paths are unavailable. Runtime import attempts fail for private modules. | Any public import path exposes greenlight minting, signer material, gateway verification internals, raw receipt mutation, credential access, or receipt-export authority. | -| Bins imply mutation or enforcement | CLI names or help text imply it can approve, enforce, mutate, publish receipts authoritatively, or operate as a gateway when it only reads/proposes/validates metadata. | Rename or scope bins to read/proposal/evidence operations. CLI help must state it does not grant authority or execute protected mutations. Remove mutation-like commands. | `--help` snapshots. CLI command inventory. Smoke test proving no command mutates protected surfaces or emits greenlight-like authority. | Any bin verb such as `approve`, `greenlight`, `enforce`, `execute`, `gateway`, `export-receipt`, or equivalent exists without real gateway-bound enforcement. | -| MCP Registry listing overclaims trust/certification | Registry metadata makes users believe listing certifies code safety, authority correctness, or official enforcement. This is review theatre. | Metadata must say MCP Registry hosts metadata, not artifacts, and does not certify safety. Claims limited to package identity, capabilities, and install path. | Registry preview text reviewed against claim checklist. No "certified," "trusted," "secure," "approved," or "enforced" claims unless mechanically true. | Listing implies registry approval, safety certification, authority enforcement, or audited gateway behavior. | -| npm token, 2FA, or provenance failures | Publish uses weak token, missing 2FA, no provenance, wrong account, or local machine credentials that cannot be audited. | Use npm automation token with least privilege, account 2FA enforced, provenance enabled where supported, and publish from controlled CI if possible. | npm account/package settings screenshot or command output. Provenance visible on published package. Token scope documented. | 2FA disabled, provenance absent without explicit exception, broad personal token used, or publish path cannot be reconstructed. | -| Namespace/account ownership gaps | Package name or scope is controlled by the wrong account, individual owner, stale org, or ambiguous namespace. Attackers or future maintainers can publish lookalikes or take over ownership. | Publish under owned org scope. Require at least two maintainers with explicit ownership. Reserve related names if necessary. Document owner transfer process. | npm owner list, org scope verification, package access settings, MCP Registry namespace ownership proof. | Scope ownership is unclear, single-person account is sole owner, or package name can be confused with an unowned sibling. | -| Version/metadata drift | npm package, Git tag, MCP metadata, README, and registry preview describe different capabilities. Users install one thing and read another. | Version from one source of truth. Release checklist updates package metadata, README, registry metadata, changelog, and tag together. | Git tag matches package version. Packed README matches repository README or intentional release README. MCP metadata references same version/package. | Any published metadata claims capabilities not present in the packed package, or package version cannot be tied to a commit. | -| Post-publish package does not run under Node | Package imports fail due to ESM/CJS mismatch, missing files, wrong `types`, unsupported Node version, bad bin shebangs, or absent runtime dependencies. | Test from packed tarball in a clean temp project under supported Node versions. Verify import, require if supported, bin execution, and type resolution. | Clean install smoke logs from packed tarball. Node version matrix. `npm pack` install test, CLI help test, TypeScript compile test. | Any supported Node runtime cannot import the package, execute bins, or resolve types from the packed artifact. | -| Downstream install executes unexpected scripts or dependencies | Install triggers lifecycle scripts, dependency postinstall behavior, native builds, network calls, telemetry, or dependency confusion. | Avoid lifecycle scripts. Minimize dependencies. Pin/lock release dependencies. Audit transitive scripts. Prefer zero-dependency public core if feasible. | `npm pack` manifest inspection. Dependency tree review. `npm install --ignore-scripts` and normal install comparison. Script inventory is empty or justified. | Any install-time script, native build, network behavior, telemetry, or unexplained transitive dependency appears. | -| Rollback/deprecation gaps | Bad package ships and there is no tested unpublish/deprecate path, no advisory language, no replacement version, and no way to warn downstream users. | Predefine rollback playbook: deprecate version, publish patched version, update registry metadata, tag incident note, and revoke affected tokens if needed. | Dry-run rollback checklist. npm deprecation command prepared. Owner permissions verified. Incident template exists. | Maintainers cannot deprecate, cannot publish a patched version, or cannot update registry metadata promptly. | -| External registry preview instability | MCP Registry preview behavior changes, metadata rendering drifts, validation accepts unsafe claims, or listing breaks after external changes. | Treat registry preview as unstable external display, not canonical truth. Keep canonical package metadata and docs in repo. Re-validate preview before publication and after changes. | Preview screenshot or exported metadata captured at release time. Post-publish registry check. Drift issue filed if rendered claims differ. | Registry preview renders misleading capability, trust, install, or certification claims, or cannot be verified before publication. | - -## Brutal Verdict - -Keep the publication plan only if publication is treated as distribution of non-authority surfaces. Cut any CLI, MCP metadata, export, README phrase, or package file that lets a downstream user infer mutation authority, receipt export authority, gateway enforcement, signer access, or certification. - -The highest-risk failure is not a broken install. It is a package that looks like Handshake authority while only shipping advisory surfaces. That would publish the theatre as product. - -## Smallest Next Mechanism To Build - -Add a release gate that inspects the packed tarball, public exports, bin help text, and registry metadata preview, then fails on authority leakage, mutation implication, internal file exposure, provenance gaps, or metadata overclaim. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/STRATEGY.md deleted file mode 100644 index acdcf5a..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/raw/STRATEGY.md +++ /dev/null @@ -1,177 +0,0 @@ -# STRATEGY: Public Distribution And Publication - -## Invariant At Stake - -Public distribution must not launder installability into authority. A published package, MCP listing, CLI, SDK, or metadata file can make Handshake easier to inspect and install. It cannot prove enforcement, gateway custody, hosted operation, certification, marketplace trust, settlement, or host-wide control. - -## Strategic Posture - -This macro item succeeds only if publication makes the protocol kernel legible, installable, inspectable, and verifiable without overstating what has been enforced. - -Handshake should be presented as: - -> protected actions for automated decision making, with exact per-call x402 as the first proof wedge. - -Not: - -> agent auth, a payment network, a hosted enforcement layer, an MCP trust system, or a certification authority. - -x402 is the proof wedge because it gives a concrete, high-signal surface: exact per-call consequence, declared contract, explicit evidence, and verifiable refusal/proof-gap posture. It is not the protocol center. - -## Ready-To-Publish vs Actually Published - -**Ready-to-publish** means the repo can prove the package shape locally: - -- `handshake-protocol-kernel` has correct `name`, `version`, `exports`, `bin`, `files`, `server.json`, and `mcpName`. -- `npm pack --dry-run` contents match the intended public surface. -- Published entrypoints resolve from the packed artifact, not just local source. -- CLI/MCP/SDK entrypoints work from the package artifact. -- `server.json#name` and `package.json#mcpName` match MCP Registry requirements. -- README and public docs describe distribution as distribution, not enforcement. -- Security posture is documented: trusted publishing/OIDC preferred, npm 2FA/token posture explicit. -- No planning scratch, internal labels, stale claims, or non-public dependency assumptions leak into the package. - -**Actually published** means external systems now carry the public surface: - -- npm package version is published and installable by name. -- Fresh install from npm works in a clean environment. -- CLI bin executes from installed package. -- SDK/package exports resolve from installed package. -- MCP server metadata is accepted by the preview registry using public install methods. -- Post-publish evidence confirms npm contents and registry metadata match source-owned metadata. -- Docs distinguish "listed/installable" from "trusted/enforced/certified." - -Ready-to-publish is a local evidence state. Actually published is an external distribution state. Do not collapse them. - -## Sequencing - -1. **Local Package Contract** - Freeze the intended public package shape: `package.json`, `exports`, `bin`, `files`, `server.json`, `mcpName`, README install commands, and public claim language. - -2. **Pack Evidence** - Run pack dry-run and artifact-level entrypoint checks. The question is not "does the repo build?" The question is "does the artifact contain only the intended public surface and still work when consumed externally?" - -3. **Security Posture** - Decide and document publish auth: trusted publishing/OIDC preferred; if not available, npm 2FA/token posture must be explicit. Long-lived token publishing should be treated as a risk exception, not normal posture. - -4. **npm Publish** - Publish `handshake-protocol-kernel` by exact version. npm is the artifact distribution authority for package installability, not a Handshake authority boundary. - -5. **Clean Install Verification** - Verify install by package name from npm. Check imports, bins, package metadata, and any published entrypoint behavior from a clean project. - -6. **MCP Registry Submission** - Submit metadata only after npm install works. MCP Registry hosts metadata, not package artifacts. Its preview status and namespace checks do not certify code or enforcement. - -7. **Post-Publish Evidence** - Capture the public install commands, resolved version, npm package contents, registry metadata, and known limitations. This becomes the publication receipt. - -## Product Claim Boundaries - -Allowed claims: - -- Public protocol kernel package. -- Installable CLI/MCP/SDK distribution surface. -- Source-owned metadata for npm and MCP Registry. -- Exact per-call x402 proof wedge. -- Public read surfaces for proposal, evidence, and protocol inspection. -- Metadata and artifact checks that make the package reconstructable. - -Forbidden or unsafe claims: - -- "Handshake enforces protected actions" unless a gateway check actually enforces. -- "MCP Registry trust" or "certified server." -- "Marketplace trust." -- "Hosted Handshake." -- "Payment management." -- "Settlement." -- "Host-wide enforcement." -- "Secure by MCP listing." -- "Agent auth." -- "Approval system." -- "Auditable" unless the published artifact includes enough source-owned evidence to reconstruct the chain being claimed. - -## 10-Star Publication Surface - -A 10-star publication surface is boring, exact, and hard to misread: - -- One npm package with clear package name, version, exports, bins, and files. -- One `server.json` whose identity matches `package.json#mcpName`. -- README install path that starts from npm install by name. -- Public examples that exercise exact protected-action proposal/evidence/read surfaces. -- CLI help text that does not imply gateway custody. -- SDK exports that expose kernel primitives, not hosted authority. -- MCP metadata that points to public install methods only. -- Security section covering trusted publishing/OIDC, npm 2FA, token posture, and registry-preview limitations. -- Post-publish verification notes showing clean install and entrypoint checks. -- Claim boundary section saying explicitly what publication does not provide. - -The public surface should make the narrow wedge look inevitable because it is precise, not because it sounds broad. - -## What To Cut - -Cut anything that implies authority where there is only distribution: - -- Hosted enforcement language. -- "Trust," "secure," or "certified" phrasing tied to npm or MCP Registry. -- Marketplace positioning. -- Payment network or settlement language. -- Claims that CLI/MCP/SDK publication means gateway enforcement. -- Internal planning-stage names in public package shape. -- Scratch `.planning/` references. -- Demo copy that makes x402 sound like the whole protocol. -- Any registry language that treats metadata validation as code validation. -- Any "agent infrastructure" framing that narrows the category back to engineering agents only. - -## Success Criteria - -The macro item is complete when: - -- Local package artifact is inspectable and matches intended public files. -- npm published version is installable by package name. -- Published exports and bins work from clean install. -- MCP Registry metadata is accepted or, if blocked by preview constraints, the blocker is recorded as an external distribution proof gap. -- Public docs state exact claim boundaries. -- x402 is presented as first proof wedge, not protocol center. -- Post-publish evidence records artifact, metadata, install, entrypoint, and limitation checks. -- No public surface claims gateway enforcement, hosted custody, certification, marketplace trust, settlement, or host-wide authority unless that mechanism actually exists. - -## End Criteria - -End the macro when there is a publication receipt with: - -- package name and version; -- npm install verification; -- pack contents verification; -- published entrypoint verification; -- MCP Registry submission or proof-gap status; -- public docs claim-boundary check; -- security posture note; -- list of intentionally unsupported claims. - -If any one of those is missing, the item is not done. It may be ready-to-publish, partially published, or blocked, but not complete. - -## Antipatterns - -- Treating `npm publish` as product validation. -- Treating MCP Registry acceptance as trust. -- Publishing before clean artifact checks. -- Publishing metadata that points to non-public install methods. -- Letting README language outrun the package's actual authority boundary. -- Using x402 as brand center instead of proof wedge. -- Calling CLI/MCP/SDK publication "enforcement." -- Hiding npm token or 2FA posture as operational detail. -- Shipping broad category language without a narrow reconstructable proof surface. -- Letting package exports expose unstable internals because "it is just distribution." - -## Brutal Verdict - -Keep the macro item, but narrow it hard. - -This is not "launch Handshake." -This is not "stand up enforcement." -This is not "become trusted infrastructure." - -This is publication of the protocol kernel's proposal/evidence/read surface, with x402 exact per-call as the first proof wedge, through npm artifact distribution and MCP metadata distribution. - -Smallest next mechanism to build: a publication receipt checklist that separates `ready_to_publish`, `npm_published`, `mcp_registry_listed`, and `post_publish_verified`, with explicit proof gaps for anything not externally verified. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/synthesis.md deleted file mode 100644 index 3162f2a..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/public-distribution-publication/runs/public-distribution-publication-20260524T090500Z/synthesis.md +++ /dev/null @@ -1,122 +0,0 @@ -# Synthesis: Public Distribution And Publication - -## Invariant At Stake - -Publication must not become ambient authority wearing package metadata. - -Handshake is protected actions for automated decision making. Public distribution can make the protocol kernel installable and discoverable, but it cannot authorize protected actions. It cannot create a policy decision, greenlight, gateway check, mutation, custody path, hosted operation, settlement path, payment manager, trust root, certification mark, or host-wide enforcement boundary. - -## Chair Synthesis - -The perspectives converge on one severe release model: - -1. Prove local package shape before publication. -2. Prove credential, namespace, and provenance posture before mutation of public package state. -3. Publish npm artifact only from an exact manifest. -4. Verify clean install from public npm before any registry discoverability work. -5. Submit MCP Registry metadata only after npm artifact proof exists. -6. Verify registry discoverability as metadata only. -7. Record every gap instead of smoothing it into release success. - -The strategic correction is important: x402 exact per-call is the first proof wedge, not the center. The center is protected action control for automated decision making: exact contract, one-use greenlight, gateway check, receipt/refusal/proof-gap, isolation, and bypass posture. - -## Adopted Model - -Use three separate release states: - -- `ready_to_publish` -- `actually_published` -- `registry_discoverable` - -A local pack dry-run can support `ready_to_publish`. It cannot support `actually_published`. - -An npm publish operation can support `actually_published` only after clean install smoke passes. - -An MCP Registry submission can support `registry_discoverable` only after post-registry verification passes. It cannot support trust, certification, artifact safety, or enforcement. - -## Required Proof Shape - -The release proof should be structured as `PackageReleaseProof`: - -- `packageShapeProof` -- `accountNamespaceProof` -- `publishOperationProof` -- `provenanceProof` -- `registryDiscoverabilityProof` -- `runtimeSmokeProof` -- `authorityBoundary` -- `proofGaps` - -The `authorityBoundary` must make false claims explicit: - -- `createsAuthority: false` -- `createsPolicyDecision: false` -- `createsGreenlight: false` -- `performsGatewayCheck: false` -- `performsMutation: false` -- `holdsCustody: false` -- `hostsOperation: false` -- `certifiesMarketplace: false` -- `managesSettlement: false` -- `managesPayment: false` -- `establishesTrust: false` -- `enforcesHostWidePolicy: false` - -## Release Sequence - -1. Local readiness contract -2. npm preflight -3. npm publish -4. post-npm clean install smoke -5. MCP Registry preflight -6. MCP Registry metadata submission -7. post-registry discoverability smoke - -This sequence prevents a common failure: making a package discoverable before the artifact and its public claims have survived installation from the public registry. - -## Risk Synthesis - -The largest risks are not mechanical publication failures. The largest risks are semantic boundary failures: - -- package metadata implies authority -- docs narrow Handshake to engineering agents -- x402 becomes the protocol center -- MCP Registry listing is treated as trust -- provenance is confused with runtime enforcement -- clean install is skipped -- a release receipt conflates local checks, npm publish, registry metadata, and runtime smoke - -Those are not wording nits. They are product-boundary failures. - -## Adoption Synthesis - -The first public install/test-drive should prove: - -- package can be installed -- bins can start -- exports resolve -- proposal/evidence/read surfaces are available -- non-authority boundaries are visible -- proof gaps are explicit - -It should not require a team to integrate every protected-action gateway up front. - -Allowed support statuses: - -- `ready:proposal-mode` -- `ready:gateway-mode` -- `blocked:metadata` -- `blocked:runtime` -- `blocked:mcp-stdio` -- `blocked:package-contents` -- `blocked:namespace-auth` -- `blocked:provenance` -- `preview:unsupported-enforcement` - -## Brutal Verdict - -Keep the publication plan, but narrow its claims. - -Public distribution is useful only if it makes Handshake installable, inspectable, and reconstructable without pretending to enforce anything by existing in npm or MCP Registry. Any implementation that treats publication as trust, authority, certification, or gateway enforcement is advisory theatre, not Handshake. - -Smallest next mechanism: define the `PackageReleaseProof` and release-state contract with explicit authority-boundary false fields before any publish operation. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/ASSUMPTIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/ASSUMPTIONS.md deleted file mode 100644 index 366e3da..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/ASSUMPTIONS.md +++ /dev/null @@ -1,35 +0,0 @@ -# Assumptions: Terminal Verifier Trust Plane - -## Product Assumptions - -- The externally useful question is evidence portability for protected automated actions, not payment settlement or generalized identity. -- x402 is the first wedge because exact per-call paid HTTP is concrete and auditable. -- Engineering-agent workflows remain an adoption/stress context, not the product boundary. - -## Architecture Assumptions - -- Existing certificate verification can be extended with a read model instead of replaced. -- `AuthorityCertificate` remains terminal evidence and should not acquire permission semantics. -- Issuer/key/status data can begin as local deterministic protocol records before durable service storage exists. -- A native verifier key-set model is required before JWKS projection. -- Hosted verifier responses can be redacted through an explicit allowlist. - -## Security Assumptions - -- Unknown issuer, unknown key, unauthorized role, revoked key, stale key, malformed key material, algorithm mismatch, and status unavailable must fail closed. -- Status unavailable is a `proof_gap`, not a reason to treat old evidence as verified. -- Hosted verification must not fetch arbitrary remote trust material. -- Public key discovery does not prove trust. - -## Execution Assumptions - -- Candidate implementation paths stay near authority-certificate protocol, CLI certificate handling, HTTP routes, and existing tests. -- Existing quality gates remain authoritative. -- The plan should not introduce source paths, package names, or CI labels from `.planning/` scratch terms. -- If exact test commands differ, implementers should use repo-native focused equivalents and record the substitution. - -## User-Owned Open Questions - -- Which hosted route naming convention should become canonical? -- Should initial status records live entirely in protocol fixtures/local config, or behind an HTTP-backed read provider? -- Which x402 receiver/auditor integration should be the first external proof target? diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/CONTEXT.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/CONTEXT.md deleted file mode 100644 index 1a60bbd..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/CONTEXT.md +++ /dev/null @@ -1,63 +0,0 @@ -# Context: Terminal Verifier Trust Plane - -## Invariant At Stake - -`AuthorityCertificate` is terminal evidence. It is not permission, identity, settlement, approval, actor trust, certification, compliance, or downstream business success. - -## Product Frame - -Handshake is protected actions for automated decision making. Engineering-agent workflows are stress and adoption context, not the product boundary. - -The first wedge is x402 exact per-call paid HTTP because it creates a crisp protected-action evidence question: did this exact per-call action produce terminal evidence that can be verified without trusting the caller's narrative? - -## Current Source State - -- Certificate minting is limited to terminal evidence kinds: `receipt`, `durable_refusal`, `proof_gap`, `replay_refusal`. -- Verification already checks schema, digests, signed-over binding, algorithm prefix, pinned trust keys, signer roles, artifact kinds, gateway admission binding, and terminal binding. -- Production rejects HMAC. -- Trust material is local/pinned with active/retired keys. -- CLI verification is non-mutating and evidence-plane only. - -## Missing Trust Plane - -The current verifier has enough local mechanics to become portable, but lacks: - -- issuer read model; -- key version read model; -- role/status/time-window model; -- status/revocation records; -- native verifier key-set projection; -- JWKS projection; -- hosted verifier; -- redacted verification response; -- explicit status unavailable and revoked failure model; -- claim guard around validity semantics. - -## Plane Separation - -Evidence plane: - -- `AuthorityCertificate`; -- terminal artifact kind; -- signed-over binding; -- gateway admission binding; -- terminal binding; -- receipt/refusal/proof-gap/replay evidence. - -Discovery plane: - -- metadata; -- native verifier key-set; -- JWKS projection; -- status endpoint address; -- hosted verifier endpoint address. - -Trust decision plane: - -- pinned issuer/key acceptance; -- signer role acceptance; -- key version status; -- revocation/status record interpretation; -- caller-owned decision about whether a verifier is trusted. - -JWKS sits in discovery. It does not create trust. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/DECISIONS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/DECISIONS.md deleted file mode 100644 index 1e5ddc9..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/DECISIONS.md +++ /dev/null @@ -1,29 +0,0 @@ -# Decisions: Terminal Verifier Trust Plane - -## D1: AuthorityCertificate Semantics Stay Narrow - -`AuthorityCertificate` proves terminal evidence binding only. It does not prove approval, authorization, payment, settlement, trust, certification, compliance, or success. - -## D2: Verification Result Must Be Structured - -No boolean-only `isValid()` surface. Verification result must separate crypto validity, trusted signer, key status, role status, artifact match, gateway binding, terminal binding, status/revocation, and audit projection. - -## D3: Native Verifier Key Set Precedes JWKS - -The protocol-owned verifier key set is the authority-bearing read model. JWKS is an interoperability projection of public key material only. - -## D4: Discovery Is Not Trust - -Metadata and `jwks_uri` help locate public key material. They do not establish issuer trust, role authorization, status acceptance, or certificate validity. - -## D5: Hosted Verifier Is Non-Mutating - -Hosted verification may parse, validate, redact, and report. It must not mutate certificate state, status records, receipt stores, gateway records, or audit state. - -## D6: Fail Closed On Status Ambiguity - -Revoked, stale, unknown, and status-unavailable states cannot produce verified. Status unavailable should produce `proof_gap` with explicit failure reason. - -## D7: x402 Is Profile, Not Root Protocol - -x402 exact per-call paid HTTP is the first evidence profile built on top of the trust plane. It must not redefine `AuthorityCertificate` semantics. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/PLAN.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/PLAN.md deleted file mode 100644 index 5f38c8f..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/PLAN.md +++ /dev/null @@ -1,301 +0,0 @@ -# Plan: Terminal Verifier Trust Plane - -## Goal - -Invariant at stake: `AuthorityCertificate` must remain terminal evidence for protected automated actions, not permission, identity, settlement, certification, or downstream success. - -Build a Terminal Verifier Trust Plane that lets external receivers, auditors, SDKs, CLI users, MCP tools, and hosted verifier clients answer one narrow question: - -Does this `AuthorityCertificate` verify against pinned or published verifier trust material, current issuer/key/status records, and the exact terminal artifact binding it claims? - -The first protected-action wedge is x402 exact per-call paid HTTP, but the trust plane must stay protocol-owned and evidence-plane first. x402 is the adoption stress case, not the root protocol. - -## Non-Goals - -- Do not make `AuthorityCertificate` an approval, authorization, payment receipt, settlement proof, actor identity, compliance badge, certificate authority artifact, or proof that the principal understood the action. -- Do not make JWKS discovery a trust decision. -- Do not fetch certificate-supplied `jwks_uri` values. -- Do not expose raw receipts, gateway credentials, secrets, principal-private context, policy internals, or mutable audit state through hosted verification. -- Do not build a clearing house, settlement network, or general CA. -- Do not make hosted verification mutate certificate, receipt, issuer, key, or status state. -- Do not expose boolean-only `isValid()` APIs. - -## Source Boundary - -Canonical and candidate source areas: - -- `src/protocol/areas/authority-certificate/` -- `src/cli/certificate.ts` -- `src/http` -- existing authority-certificate protocol tests -- new verifier/key/status/http/cli tests near existing test ownership - -Planning source hierarchy: - -1. This run input and official constraints. -2. Tracked repo canon: `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`. -3. Current source and tests. -4. `.planning/` as scratch only. - -External standards are constraint sources, not inherited product semantics: - -- RFC 7517: JWK/JWK Set are key representations; protect non-public key material. -- RFC 7515: JWS signing, validation, and protected key identifiers inform trust-binding checks. -- RFC 8414: `jwks_uri` can point to a JWK Set document; OAuth semantics are not inherited. -- RFC 7009: borrow endpoint security and ambiguity lessons only; OAuth token revocation is not certificate revocation. - -## Current State - -Implemented source state: - -- `createAuthorityCertificate()` mints terminal evidence for only `receipt`, `durable_refusal`, `proof_gap`, and `replay_refusal`. -- `verifyAuthorityCertificate()` checks schema, envelope digest, signing input digest, signed-over binding, algorithm prefix, pinned trust keys, signer roles, required artifact kinds, gateway admission binding, and terminal binding. -- Production rejects HMAC. -- Trust material is local and pinned with active/retired keys. -- CLI `cert verify` is evidence-plane only and non-mutating. - -Known gaps: - -- No verifier key-set/JWKS projection. -- No issuer/signer role/key version read model. -- No certificate status/revocation record model. -- No hosted verification route. -- No redacted hosted verification response. -- No explicit stale/revoked/status-unavailable failure model. -- No claim guard that prevents "valid" from meaning approved, paid, settled, trusted, certified, authorized, or compliant. - -## Target State - -Terminal verifier clients can submit or inspect an `AuthorityCertificate` and receive a structured non-mutating verification response that separates: - -- schema validity; -- cryptographic validity; -- signing input digest match; -- signed-over artifact binding; -- trusted issuer/key presence; -- signer role allowability; -- key version status and time window; -- required artifact kind match; -- gateway admission binding; -- terminal artifact binding; -- status/revocation result; -- replay refusal or proof-gap evidence; -- redacted audit projection; -- failure reasons. - -Hosted routes expose: - -- verifier metadata; -- verifier key-set projection; -- JWKS projection; -- certificate status lookup; -- hosted certificate verification. - -The verifier key set is the native model. JWKS is only a projection for interoperability. - -All public and SDK language says `verified`, `refused`, or `proof_gap`, never `authorized`, `approved`, `paid`, `settled`, `certified`, `trusted`, `compliant`, or bare `valid`. - -## Assumptions - -- Existing certificate creation and verification functions are stable enough to extend without redesigning terminal certificate semantics. -- Local pinned verification remains the root trust posture; hosted verification is a projection and convenience surface. -- Status records can be represented as append-only or immutable read records even if their storage implementation is initially in-memory or file-backed. -- x402 evidence profile can wait until verifier primitives exist. -- Production HMAC rejection remains mandatory. -- Status unavailable must fail closed as `proof_gap`, not silently degrade to verified. - -## Decisions - -1. Separate planes: - - evidence plane: `AuthorityCertificate` and terminal artifact verification; - - discovery plane: metadata, verifier key set, JWKS projection; - - trust decision plane: pinned/local or caller-owned acceptance of issuer/key/status records. -2. Add protocol-owned models: - - `AuthorityCertificateIssuer`; - - `AuthorityCertificateKeyVersion`; - - `AuthorityCertificateStatusRecord`; - - `AuthorityCertificateVerificationRequest`; - - `AuthorityCertificateVerificationResponse`. -3. Treat JWKS as projection: - - native verifier key-set model owns issuer, role, algorithm, key version, status, and time window; - - JWKS only emits public key material and integrity-protected identifiers compatible with RFC 7517 and RFC 7515 expectations. -4. Hosted verifier is audit-safe: - - deterministic parse; - - request size limits; - - rate limits where route infrastructure supports them; - - no arbitrary remote key fetching; - - no mutation; - - redacted response only. -5. Verification response is structured: - - no boolean-only API; - - explicit failure reasons; - - explicit stale, revoked, unknown, and status-unavailable outcomes. -6. x402 arrives after verifier trust plane: - - first prove `AuthorityCertificate` portability; - - then define exact per-call paid HTTP evidence profile. - -## Phases - -### Phase 0: Claim Guard And Vocabulary Fence - -Add product and code claim guards that make terminal evidence semantics mechanically hard to blur. Ban or flag certificate language that implies approval, authorization, paid status, settlement, actor trust, certification, compliance, or downstream success. - -Exit when `quality:claims` fails on forbidden verifier/certificate claims and current approved wording says terminal evidence only. - -### Phase 1: Trust Read Model - -Introduce issuer, key version, role, algorithm, status, and validity-window read models near authority-certificate protocol ownership. Keep them deterministic and local-first. Require verification to distinguish unknown issuer, unknown key, role mismatch, retired key, revoked key, stale key, and algorithm mismatch. - -Exit when pinned local verification can consume the new read model without changing current terminal artifact semantics. - -### Phase 2: Verifier Key Set And JWKS Projection - -Create native verifier key-set projection first, then a JWKS projection from it. Public JWKS must include only public material and protected identifiers; it must not carry private key material or imply trust. - -Exit when malformed JWK, duplicate keys, algorithm confusion, unknown key, retired key, and role mismatch negative tests fail closed. - -### Phase 3: Status And Revocation Records - -Add status records for certificate/key/issuer verification posture. Model active, retired, revoked, stale, unknown, and status-unavailable distinctly. Status unavailable returns `proof_gap` and prevents verified outcome. - -Exit when revoked/stale/status-outage tests fail closed and responses preserve ambiguity instead of smoothing it. - -### Phase 4: Verification Request And Response Projection - -Define `AuthorityCertificateVerificationRequest` and `AuthorityCertificateVerificationResponse`. Response must separate crypto validity, trusted signer, role/key status, artifact match, gateway binding, terminal binding, status/revocation, and redacted audit projection. - -Exit when CLI and protocol tests prove no boolean-only `isValid()` style surface is introduced. - -### Phase 5: Hosted Verifier Routes - -Add non-mutating hosted routes for metadata, key-set/JWKS, status, and verify. Hosted verification must not fetch arbitrary `jwks_uri`, must reject oversized payloads, must redact sensitive material, and must never mutate receipt/status/certificate state. - -Exit when hosted route tests cover payload size, malformed input, redaction, no raw leak, unknown issuer, revoked key, status outage, and deterministic refusal/proof-gap responses. - -### Phase 6: CLI / SDK / MCP Parity - -Update CLI evidence-plane output to match structured verification results. SDK/MCP-facing surfaces should expose the same categories without a boolean-only shortcut. Keep all surfaces non-mutating. - -Exit when CLI parity tests confirm local and hosted-style response projections preserve the same semantic boundaries. - -### Phase 7: x402 Evidence Profile - -Define the x402 exact per-call paid HTTP evidence profile on top of the verifier trust plane. The profile states what exact protected-action evidence an `AuthorityCertificate` proves or fails to prove for a single paid HTTP call. - -Exit when an external x402 receiver/auditor can ask whether a certificate verifies against published verifier keys/current status and what exact evidence it proves, without treating it as settlement or payment success. - -## Task Graph - -```text -T0 claim guard - -> T1 trust read model - -> T2 key-set projection - -> T3 JWKS projection - -> T4 status records - -> T5 verification response - -> T6 hosted metadata/status routes - -> T7 hosted verify route - -> T8 CLI parity - -> T9 x402 evidence profile -T10 quality gates depends on all implementation tasks -``` - -## Risks And Mitigations - -- Risk: "valid certificate" becomes market shorthand for approved/paid/trusted. - Mitigation: claim guard, API naming discipline, structured result categories, no boolean-only API. -- Risk: JWKS discovery is mistaken for trust. - Mitigation: native key-set model owns trust posture; JWKS docs and tests call it projection only; verifier never fetches certificate-supplied trust. -- Risk: hosted verification leaks raw evidence. - Mitigation: redaction allowlist, negative raw-leak tests, no raw receipt/gateway credential/principal-private fields in response. -- Risk: status outage silently verifies stale evidence. - Mitigation: status unavailable maps to `proof_gap` and fail-closed verification. -- Risk: role/key/version drift creates ambient authority. - Mitigation: signed-over key identifiers, issuer/key/role/algorithm/status/time-window checks, retired/revoked handling. -- Risk: x402 profile broadens into settlement or payment attestation. - Mitigation: profile limited to exact per-call protected-action evidence and terminal certificate verification. - -## Validation Gates - -Required closeout commands: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -Required focused checks: - -```bash -npm test -- authority-certificate -npm test -- verifier -npm test -- certificate -npm test -- http -npm test -- cli -``` - -If exact script names differ, use the repo's existing equivalent focused test selectors and record the substitution. - -Required test coverage: - -- schema-invalid certificate; -- malformed JWK; -- duplicate keys; -- algorithm confusion; -- unknown issuer; -- unknown key version; -- unauthorized signer role; -- retired key; -- revoked key; -- stale key; -- status unavailable; -- missing required artifact kind; -- gateway admission mismatch; -- terminal binding mismatch; -- tenant or issuer mismatch; -- oversized hosted verify payload; -- hosted route raw leak attempt; -- arbitrary `jwks_uri` rejection; -- replay refusal terminal evidence; -- proof gap terminal evidence; -- x402 evidence profile does not imply paid/settled/success. - -## Cut Lines - -Cut before implementation if the plan requires: - -- hosted verifier mutation; -- remote trust fetching from certificate-supplied URLs; -- public exposure of raw receipts or gateway credentials; -- certificate semantics beyond terminal evidence; -- boolean-only validity API; -- x402 settlement/payment-success claims; -- OAuth revocation semantics as certificate revocation semantics. - -Cut scope for first implementation if needed: - -- defer x402 profile until verifier routes and response model are stable; -- defer full SDK/MCP wrappers until CLI parity is proven; -- ship native verifier key-set before JWKS; -- ship local status records before hosted status route; -- ship hosted verify after redaction tests exist. - -## Rollback / Stop Conditions - -Stop and redesign if: - -- any verifier path can return verified while status is revoked, stale, unknown, or unavailable; -- hosted verification mutates state; -- a response leaks raw receipt, gateway credential, secret, or principal-private context; -- JWKS projection becomes the authority source; -- public wording says certificate means approved, authorized, paid, settled, trusted, certified, compliant, or successful; -- one key or greenlight can validate multiple unbound terminal artifacts; -- gateway admission and terminal artifact evidence cannot be distinguished in response output. - -Rollback by disabling hosted routes and preserving local pinned verification if route safety or redaction fails. - -## Smallest Next Action - -Implement the claim guard and vocabulary fence for `AuthorityCertificate` validity semantics, then add the protocol-owned trust read model behind existing local verification. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/RISKS.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/RISKS.md deleted file mode 100644 index 4a113cf..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/RISKS.md +++ /dev/null @@ -1,43 +0,0 @@ -# Risks: Terminal Verifier Trust Plane - -## R1: Validity Meaning Drift - -Risk: users and APIs collapse certificate verifies into approved, paid, trusted, or settled. - -Mitigation: claim guard, API naming constraints, structured response, docs wording, negative wording tests. - -## R2: JWKS As Fake Authority - -Risk: consumers treat key discovery as trust. - -Mitigation: native verifier key-set model; JWKS projection docs; no certificate-supplied `jwks_uri`; explicit issuer/key/status checks. - -## R3: Hosted Verification Leaks Sensitive Evidence - -Risk: hosted response exposes raw receipts, gateway credentials, principal-private context, policy internals, or secrets. - -Mitigation: allowlisted response projection, redaction tests, raw-leak golden negatives. - -## R4: Status Ambiguity Becomes Success - -Risk: status outage or unknown status gets treated as valid. - -Mitigation: status unavailable maps to `proof_gap`; stale/revoked/unknown fail closed. - -## R5: Algorithm Or Key Confusion - -Risk: malformed JWK, duplicate key IDs, algorithm prefix confusion, or retired key drift lets the wrong signer pass. - -Mitigation: deterministic parsing, duplicate rejection, protected key identifiers, algorithm allowlist, key version status checks. - -## R6: Hosted Route Becomes Mutation Channel - -Risk: verify/status endpoints mutate state or become audit side effects. - -Mitigation: route contract says non-mutating; tests assert no write calls; observability must not alter certificate/status meaning. - -## R7: x402 Overclaims - -Risk: x402 evidence profile implies paid, settled, delivered, or business-success proof. - -Mitigation: profile language limited to exact protected-action evidence and terminal certificate verification. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/TASKS.jsonl b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/TASKS.jsonl deleted file mode 100644 index 08aa3b9..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/TASKS.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"id":"T0","priority":"P0","phase":"Phase 0","title":"Add AuthorityCertificate claim guard","owner":"protocol","rationale":"Prevent terminal evidence from drifting into approval, payment, settlement, trust, certification, compliance, or success claims.","depends_on":[],"acceptance":["Forbidden validity/approval/payment/trust terms fail claim checks in certificate/verifier-facing docs and user-facing strings.","Approved wording states AuthorityCertificate is terminal evidence only.","quality:claims passes with the new guard."],"candidate_paths":["docs/internal/decisions.md","docs/internal/protocol-notes.md","src/protocol/areas/authority-certificate/","scripts/"],"non_goals":["Do not change certificate minting semantics.","Do not add hosted routes."]} -{"id":"T1","priority":"P0","phase":"Phase 1","title":"Introduce authority certificate issuer and key version read model","owner":"protocol","rationale":"Verification needs protocol-owned issuer/key/role/algorithm/status/time-window records instead of ad hoc pinned key shape.","depends_on":["T0"],"acceptance":["Models exist for issuer, key version, signer role, algorithm, status, and validity window.","Existing local pinned verification consumes or adapts to the read model.","Unknown issuer, unknown key, role mismatch, retired key, and algorithm mismatch are distinct outcomes."],"candidate_paths":["src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not expose JWKS yet.","Do not fetch remote keys."]} -{"id":"T2","priority":"P0","phase":"Phase 2","title":"Create native verifier key-set projection","owner":"protocol","rationale":"JWKS must be a projection from a native trust model, not the authority source.","depends_on":["T1"],"acceptance":["Native verifier key-set projection exposes only allowed public metadata and key material.","Projection includes issuer, key id/version, role, algorithm, status, and time-window fields where appropriate.","Private key material is never projected."],"candidate_paths":["src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not claim key discovery establishes trust.","Do not implement hosted metadata yet."]} -{"id":"T3","priority":"P0","phase":"Phase 2","title":"Add JWKS projection from verifier key set","owner":"protocol","rationale":"External verifiers need RFC 7517-compatible public key representation without inheriting OAuth or CA semantics.","depends_on":["T2"],"acceptance":["JWKS emits public key material only.","Duplicate key ids, malformed JWK material, and algorithm confusion have negative tests.","Docs or protocol comments state JWKS is projection, not trust."],"candidate_paths":["src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not publish private key material.","Do not accept certificate-supplied jwks_uri as authority."]} -{"id":"T4","priority":"P0","phase":"Phase 3","title":"Add authority certificate status records","owner":"protocol","rationale":"Verification must fail closed on revoked, stale, unknown, and status-unavailable states.","depends_on":["T1"],"acceptance":["Status record model represents active, retired, revoked, stale, unknown, and unavailable outcomes.","Revoked and stale cannot return verified.","Status unavailable returns proof_gap with explicit reason."],"candidate_paths":["src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not borrow OAuth token revocation semantics wholesale.","Do not make status lookup mutating."]} -{"id":"T5","priority":"P0","phase":"Phase 4","title":"Define structured verification request and response","owner":"protocol","rationale":"Consumers need audit-safe categories, not a boolean validity shortcut.","depends_on":["T2","T3","T4"],"acceptance":["Request and response models exist for authority certificate verification.","Response separates schema, crypto, signer trust, role, key status, artifact match, gateway binding, terminal binding, status, and failure reasons.","No boolean-only isValid-style API is introduced."],"candidate_paths":["src/protocol/areas/authority-certificate/","src/cli/certificate.ts","tests/"],"non_goals":["Do not expose raw receipts or secrets.","Do not imply authorization or payment success."]} -{"id":"T6","priority":"P1","phase":"Phase 5","title":"Add hosted verifier metadata, key-set, JWKS, and status routes","owner":"http","rationale":"External auditors and receivers need non-mutating discovery and status surfaces before hosted verification.","depends_on":["T3","T4"],"acceptance":["Routes expose metadata, native key-set projection, JWKS projection, and status lookup.","Routes are non-mutating and redacted.","Metadata may include jwks_uri but does not inherit OAuth semantics or establish trust."],"candidate_paths":["src/http","src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not add verify route side effects.","Do not fetch remote trust material."]} -{"id":"T7","priority":"P1","phase":"Phase 5","title":"Add hosted certificate verification route","owner":"http","rationale":"Hosted verifier must answer the external evidence question without becoming a mutation or leakage channel.","depends_on":["T5","T6"],"acceptance":["Route deterministically parses bounded requests.","Oversized, malformed, unknown issuer, revoked, stale, and status-unavailable cases fail closed.","Response is redacted and excludes raw receipts, gateway credentials, secrets, and principal-private context."],"candidate_paths":["src/http","src/protocol/areas/authority-certificate/","tests/"],"non_goals":["Do not mutate certificate, receipt, key, issuer, or status state.","Do not return authorized, approved, paid, settled, trusted, certified, or compliant."]} -{"id":"T8","priority":"P1","phase":"Phase 6","title":"Update CLI verification output for structured parity","owner":"cli","rationale":"CLI, SDK, and MCP verification surfaces must preserve evidence-plane semantics consistently.","depends_on":["T5"],"acceptance":["CLI cert verify reports structured categories matching protocol response.","CLI remains non-mutating.","CLI does not expose boolean-only validity language."],"candidate_paths":["src/cli/certificate.ts","tests/"],"non_goals":["Do not add mutation commands.","Do not make CLI output settlement or payment proof."]} -{"id":"T9","priority":"P2","phase":"Phase 7","title":"Define x402 exact per-call evidence profile","owner":"protocol","rationale":"x402 is the first protected-action wedge and needs a narrow evidence profile after verifier primitives exist.","depends_on":["T7","T8"],"acceptance":["Profile states what AuthorityCertificate proves and fails to prove for one exact paid HTTP call.","Profile does not claim settlement, payment success, delivery, authorization, or compliance.","External receiver/auditor flow can verify certificate against published keys/current status and inspect exact protected-action evidence."],"candidate_paths":["src/protocol/areas/authority-certificate/","docs/internal/protocol-notes.md","tests/"],"non_goals":["Do not create a payment clearing house.","Do not generalize beyond exact per-call protected-action evidence."]} -{"id":"T10","priority":"P0","phase":"Quality","title":"Run closeout quality and architecture gates","owner":"verification","rationale":"The trust plane is only credible if claim, architecture, formatting, focused tests, and repo checks all pass.","depends_on":["T0","T1","T2","T3","T4","T5","T6","T7","T8","T9"],"acceptance":["quality:claims passes.","quality:architecture passes.","format:check passes.","check:repo passes.","Focused authority-certificate, verifier, certificate, http, and cli tests pass or substitutions are recorded."],"candidate_paths":["package.json","tests/","docs/internal/decisions.md"],"non_goals":["Do not implement additional product scope during closeout.","Do not clean unrelated dirty worktree drift."]} diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/VALIDATION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/VALIDATION.md deleted file mode 100644 index 3982775..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/VALIDATION.md +++ /dev/null @@ -1,73 +0,0 @@ -# Validation: Terminal Verifier Trust Plane - -## Quality Gates - -Run before closeout: - -```bash -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -## Focused Test Gates - -Use repo-native focused selectors for: - -```bash -npm test -- authority-certificate -npm test -- verifier -npm test -- certificate -npm test -- http -npm test -- cli -``` - -## Required Negative Tests - -- schema-invalid certificate refuses; -- malformed JWK refuses; -- duplicate key IDs refuse; -- algorithm mismatch refuses; -- HMAC production verification refuses; -- unknown issuer refuses; -- unknown key version refuses; -- unauthorized signer role refuses; -- retired key refuses or reports retired according to policy; -- revoked key refuses; -- stale key refuses; -- status unavailable returns `proof_gap`; -- required artifact kind mismatch refuses; -- gateway admission binding mismatch refuses; -- terminal artifact binding mismatch refuses; -- tenant mismatch refuses; -- oversized hosted verify payload refuses; -- arbitrary `jwks_uri` input is ignored or rejected; -- hosted response excludes raw receipts; -- hosted response excludes gateway credentials; -- hosted response excludes principal-private context; -- x402 profile does not imply paid, settled, or downstream success. - -## Required Positive Tests - -- local pinned active issuer/key verifies terminal `receipt` evidence; -- local pinned active issuer/key verifies `durable_refusal`; -- local pinned active issuer/key verifies `proof_gap`; -- local pinned active issuer/key verifies `replay_refusal`; -- native verifier key-set projection exposes active public key metadata; -- JWKS projection emits public key material only; -- hosted verify returns redacted structured response; -- CLI output matches structured verification categories. - -## Closeout Evidence - -A closeout is credible only if it records: - -- exact commands run; -- focused test results; -- claim guard result; -- architecture guard result; -- formatting result; -- repo check result; -- any substituted test commands; -- unresolved proof gaps. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/input.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/input.md deleted file mode 100644 index 88a3ae1..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/input.md +++ /dev/null @@ -1,144 +0,0 @@ -# Macro Plan Input: Terminal Verifier Trust Plane - -Run id: terminal-verifier-trust-plane-20260524T074226Z -Date: 2026-05-24 - -## Hard Frame - -Handshake is protected actions for automated decision making. Engineering-agent workflows are a current stress case and adoption context, not the product boundary. x402 exact per-call paid HTTP is the first protected-action wedge, not the protocol. - -This plan is planning only. Do not edit source, tests, docs outside this planning run, package metadata, or previously staged files. Each perspective worker may write only its assigned raw output file. If a worker cannot comply, it must write a BLOCKED note in its assigned file only. - -## Goal - -Plan the terminal verifier trust plane that makes terminal `AuthorityCertificate` evidence portable without turning it into permission, identity, settlement, marketplace certification, or clearing-house language. - -Mechanism target: - -```text -terminal evidence --> AuthorityCertificate --> verifier key set --> revocation/status check --> verification response --> audit-safe projection -``` - -## Current Source Grounding - -Canonical posture: - -- `.planning/macro/DEFERRED-INTEGRATE-ELIMINATE.md` says terminal verification is critical path item 2, after claim boundary cleanup and customer-owned gateway custody proof. -- `.planning/macro/active/claim-boundary-cleanup/PLAN.md` makes category wording a P0 claim boundary: protected actions for automated decision making, x402 first wedge, engineering agents only adoption context/threat model. -- `.planning/macro/active/customer-owned-gateway-custody-proof/PLAN.md` requires credential custody proof before hosted claims. -- `docs/internal/decisions.md` states `AuthorityCertificate` is local terminal signed evidence only, not greenlight, gateway check, mutation proof, identity, settlement, marketplace status, or hosted trust. -- `docs/internal/protocol-notes.md` says cross-org JWKS, revocation, hosted verify APIs, marketplace certification, and provider custody remain outside the local foundation. - -Source anchors: - -- `src/protocol/areas/authority-certificate/schemas.ts` -- `src/protocol/areas/authority-certificate/signing.ts` -- `src/protocol/areas/authority-certificate/transitions.ts` -- `src/protocol/areas/authority-certificate/verify.ts` -- `src/cli/certificate.ts` -- `src/surfaces/boundary-manifest.ts` -- `test/protocol/authority-certificate.test.ts` -- `test/cli/cli-evidence.test.ts` -- `test/sdk/role-clients.test.ts` -- `test/mcp/mcp-resource-redaction.test.ts` -- `test/architecture/claim-boundary.test.ts` -- `test/architecture/root-exports.test.ts` -- `test/architecture/import-posture.test.ts` - -Current landed behavior: - -- `createAuthorityCertificate()` mints terminal evidence only for receipt, durable refusal, proof gap, or replay refusal terminals. -- Certificate signing input excludes signatures/signingInputDigest and includes terminal, envelope, artifacts, verification policy, consumer bindings, extensions, and emittedAt. -- `verifyAuthorityCertificate()` validates schema, envelope digest, signing input digest, signature signed-over binding, algorithm prefix, pinned trust keys, signer roles, required artifact kinds, gateway admission binding, and terminal binding. -- Production verification rejects `hmac-sha256`; HMAC is dev-only behind `allowDevHmac`. -- Trust material is local/pinned: keys have `keyIdentityRef`, optional `signerRole`, algorithm, public key or HMAC secret, and status `active|retired`. -- CLI `cert verify` is evidence-plane only. It verifies supplied certificate material against supplied trust material without minting, mutation, protocol-store access, or raw dumps. - -Current gaps to plan: - -- No verifier key-set projection or JWKS-compatible public-key surface. -- No issuer/signer role/key version/read model beyond local trust material. -- No revocation or status record for certificates/signers/key material. -- No hosted verifier route. -- No route admission, reader authorization, retention, or redacted response plane for hosted verification. -- No stale-key, revoked-key, unknown-key, wrong-issuer, wrong-envelope, or status-unavailable failure model beyond local `trust_key_missing` and `trust_key_inactive`. -- No public claim guard that "valid certificate" means terminal evidence verified at a time/status boundary, not permission, identity, settlement, certification, or final business success. - -## Official Source Constraints - -Use these only as planning constraints; do not invent compatibility claims without implementation and tests: - -- RFC 7517 defines JWK/JWK Set as JSON representations of cryptographic keys and key sets. It explicitly requires protection for non-public key material. -- RFC 7515 defines JWS signing/validation concepts, key identification, and integrity-protected header considerations. -- RFC 8414 defines `jwks_uri` as metadata for a URL pointing to a JWK Set document. -- RFC 7009 is OAuth token revocation, not a certificate revocation standard. Its transferable lesson is security posture: revocation/status endpoints need trustworthy discovery, HTTPS/authentication, and careful failure handling. - -Open question for the plan: whether Handshake should implement a JWKS-compatible public-key projection now or a Handshake-native verifier key-set first, with JWKS compatibility as a later adapter. The answer must preserve modularity and not make OAuth/JWT semantics part of the protocol unless explicitly implemented. - -## Required Perspectives - -Produce five independent raw perspectives before chair synthesis: - -1. Strategy: trust-plane product posture, category boundaries, x402-first-wedge implications, adoption sequence. -2. Architecture: protocol schema/state/route/read-model design, key set/status/revocation, redaction, integration points. -3. Execution: ordered implementation slices, file-level candidates, tests, gates, dependency graph. -4. Risk/Security: threat model, stale key and revocation failure modes, hosted route abuse, response leakage, claim drift. -5. Adoption/DevEx: CLI/SDK/MCP/hosted verifier usage shape, customer integration without boiling the ocean, error affordances. - -## Chair Synthesis Requirements - -Create: - -- `PLAN.md` -- `CONTEXT.md` -- `ASSUMPTIONS.md` -- `DECISIONS.md` -- `RISKS.md` -- `VALIDATION.md` -- `TASKS.jsonl` -- `runs/terminal-verifier-trust-plane-20260524T074226Z/synthesis.md` - -The plan must include: - -- Summary -- Source Grounding -- Non-Goals -- Recommended Architecture -- Phased Implementation -- Validation Gates -- Success Criteria -- End Criteria -- 10-Star Product Bar -- Antipatterns -- Open Questions -- Smallest Next Mechanism - -## Must-Haves - -- Keep `AuthorityCertificate` as terminal evidence, not permission, identity, settlement, certification, or downstream success. -- Separate key discovery from trust decision. A key being visible in a key set is not enough; signer role, issuer/tenant scope, key version, status, revocation, and certificate terminal binding must be evaluated. -- Treat status/revocation failure explicitly. Decide fail-closed vs proof-gap behavior for unavailable status checks. -- Never expose private keys, symmetric keys, HMAC secrets, signing material, raw protocol records, raw custody material, `PaymentPayload`, `PAYMENT-SIGNATURE`, bearer tokens, or mutation credentials. -- Preserve local/offline verification. Hosted verifier is additive, not a replacement for offline pinned verification. -- Keep CLI/MCP/SDK evidence surfaces non-mutating unless a later implementation explicitly promotes a mutation surface through policy/gateway checks. -- Respect the sequence: custody proof first, terminal verifier trust plane second, hosted evidence/admission after both are stable. - -## Antipatterns To Reject - -- Certificate equals approval, identity, settlement, marketplace certification, clearing-house readiness, or downstream success. -- JWKS equals trust. -- Revocation endpoint copied from OAuth semantics without Handshake-specific certificate/status semantics. -- Hosted verification route that returns raw certificate envelopes, raw records, secrets, or operational internals. -- Trust plane that only works if every actor is honest. -- Verifier route that reads or mutates protocol state while claiming to be offline/portable verification. -- CLI/MCP/SDK surfaces that mint certificates or issue authority. -- x402-specific signer fields leaking into generic certificate trust semantics. - -## Closeout Expectations - -Planning closeout is successful when every required output exists, `TASKS.jsonl` parses, required plan sections exist, source working tree remains untouched, and the plan states validation commands for eventual implementation. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ADOPTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ADOPTION.md deleted file mode 100644 index 1af21c8..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ADOPTION.md +++ /dev/null @@ -1,244 +0,0 @@ -# Adoption And DevEx Perspective - -## Invariant At Stake - -Terminal evidence can be portable only if verification remains non-mutating and evidence-plane only. If valid certificate starts meaning permission, identity, settlement, compliance approval, or business success, the verifier becomes authority theatre. - -## Adoption Thesis - -The first wedge is not agent safety. It is verifiable evidence for exact protected paid HTTP actions, starting with x402 per-call payment receipts/refusals/proof gaps as terminal artifacts. - -Customer value should read as: - -> Given this terminal event, can I independently verify that it was signed by a trusted issuer, bound to the exact admitted protected action, not revoked, and safe to project into audit/reporting systems? - -That is narrower, buyable, and easier to integrate than trust infrastructure for agents. - -## Usage Shape - -### CLI - -Primary DevEx loop: - -```bash -handshake cert verify receipt.json \ - --trust-bundle ./handshake-trust.json \ - --status-url https://verifier.example.com/status \ - --required-kind receipt \ - --format json -``` - -Expected outputs: - -- `verified` -- `refused` -- `revoked` -- `stale` -- `status_unavailable` -- `untrusted_issuer` -- `unsupported_algorithm` -- `artifact_kind_mismatch` -- `gateway_binding_mismatch` -- `terminal_binding_mismatch` - -The CLI must never imply mutation authority. No approve, authorize, settle, certify, or clear verbs. - -### SDK - -SDK should expose one boring call: - -```ts -const result = await verifier.verifyAuthorityCertificate({ - certificate, - trustBundle, - requiredArtifactKinds: ["receipt"], - statusPolicy: "fail_closed", -}); -``` - -Result shape must separate: - -- cryptographic validity; -- trusted signer status; -- key version/status; -- artifact kind match; -- gateway admission binding; -- terminal evidence binding; -- revocation/status result; -- audit-safe projection. - -No boolean-only `isValid()`. That invites product misuse. - -### MCP - -MCP tool should be read-only: - -```text -verify_authority_certificate -``` - -It returns structured verification evidence. It must not expose mutation, payment retry, settlement, or permission actions. MCP integration is for hosts that need portable terminal evidence inside workflows, not for granting authority. - -### Hosted Verifier - -Hosted route: - -```http -POST /verify -GET /.well-known/handshake-verifier -GET /jwks.json -GET /status/{certificateId} -``` - -The hosted verifier returns an audit-safe projection, not the full sensitive certificate by default. It should redact principal/runtime/environment details unless explicitly configured. - -## Customer Integration Sequence - -1. Local verification first: customer pins a local trust bundle and verifies sample terminal artifacts from x402 protected calls. -2. Key-set projection: customer consumes issuer/verifier metadata and JWKS-style public keys without learning private trust material. -3. Status checks: customer enables fail-closed revocation/status checks for production audit paths. -4. Hosted verifier: customer points downstream audit/reporting systems at a hosted non-mutating verifier endpoint. -5. Report projection: customer exports redacted verification summaries into finance, risk, support, or compliance systems. - -This sequence avoids boiling the ocean. No runtime replacement, no identity migration, no payment clearing-house posture. - -## Trust Bundle And Key-Set Ergonomics - -Trust bundle needs a human-readable read model: - -```json -{ - "issuer": "acme-handshake", - "environment": "production", - "keys": [ - { - "kid": "2026-05-prod-ed25519-01", - "status": "active", - "roles": ["authority_certificate_signer"], - "notBefore": "2026-05-01T00:00:00Z", - "notAfter": "2026-08-01T00:00:00Z" - } - ] -} -``` - -JWKS projection should expose public key material and key IDs only. It must not expose policy, private authority, settlement state, or customer-sensitive certificate internals. - -Developer affordances needed: - -- `handshake trust inspect` -- `handshake trust diff` -- `handshake trust pin` -- `handshake cert explain` -- `handshake cert verify --why` - -Why failed is mandatory. A cryptographic verifier without explainability will become support debt immediately. - -## Revocation And Status Errors - -Status affordances must be explicit and fail-closed by default for production: - -| Condition | Meaning | Default | -| --- | --- | --- | -| `revoked` | certificate/key/artifact is no longer acceptable evidence | fail | -| `stale` | status freshness exceeded verifier policy | fail | -| `status_unavailable` | verifier cannot determine current status | fail in prod, warn in dev | -| `unknown_kid` | key not in pinned or fetched trust set | fail | -| `retired_key` | key was valid historically but not active now | configurable historical verify | -| `issuer_mismatch` | certificate issuer not in trust bundle | fail | -| `role_mismatch` | signer lacks required certificate-signing role | fail | - -Do not copy RFC 7009 semantics into certificates. Use only the security lesson: revocation/status checks are active controls and must not leak sensitive state casually. - -## Docs And Report Shape - -Docs should be built around evidence questions: - -- What artifact am I verifying? -- Who signed it? -- Which key version signed it? -- What role was the signer allowed to perform? -- What terminal event kind is bound? -- What gateway admission is bound? -- Is the certificate current, stale, revoked, or unverifiable? -- What can I safely project into audit systems? -- What must I not infer? - -Report shape: - -```json -{ - "verification": { - "outcome": "verified", - "verifiedAt": "2026-05-24T00:00:00Z", - "evidencePlaneOnly": true - }, - "certificate": { - "artifactKind": "receipt", - "issuer": "example", - "kid": "2026-05-prod-ed25519-01" - }, - "bindings": { - "gatewayAdmission": "matched", - "terminalEvidence": "matched", - "envelopeDigest": "matched" - }, - "status": { - "state": "active", - "checkedAt": "2026-05-24T00:00:00Z" - }, - "projection": { - "safeForAudit": true, - "redactionsApplied": true - } -} -``` - -## Cut Lines - -Cut: - -- certified payment; -- trusted agent; -- authorized action; -- settlement proof; -- identity verification; -- compliance approval; -- clearing network; -- valid means safe. - -Keep: - -- terminal evidence verified; -- issuer key trusted; -- status checked; -- gateway binding matched; -- audit-safe projection; -- non-mutating verifier. - -## 10-Star Bar - -A 10-star DevEx means a skeptical customer can do this in under 30 minutes: - -1. Verify one sample certificate locally. -2. Inspect why it passed. -3. Break one field and see the exact failure. -4. Rotate/pin a trust key. -5. See stale/revoked/status-unavailable behavior. -6. Call the hosted verifier. -7. Export a redacted audit projection. -8. Explain internally what the verifier does not mean. - -If they cannot explain the non-goals after using it, product language failed. - -## Recommended Plan Shape - -1. Read model and wording guard: issuer/signer role/key version projection and claim guards around valid certificate. -2. Trust bundle and JWKS projection: public key-set projection with pinned/local trust ergonomics. -3. Status and revocation: status records, freshness policy, revoked/stale/status-unavailable outcomes. -4. Hosted verifier: non-mutating verify, metadata, JWKS, and status routes. -5. Audit projection: redacted report objects for downstream systems. - -## Smallest Next Mechanism - -Build a structured verification response type with issuer, key id, signer role, status outcome, binding checks, and an `evidencePlaneOnly: true` projection flag. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ARCH.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ARCH.md deleted file mode 100644 index 7d4d5dc..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/ARCH.md +++ /dev/null @@ -1,186 +0,0 @@ -# Architecture Perspective - -## Invariant At Stake - -`AuthorityCertificate` evidence must be portable without turning into permission. The verifier plane can say this terminal artifact was signed by a recognized evidence signer over this exact envelope and status was acceptable at verification time. It must not say this actor may execute, this identity is trusted, settlement happened, or Handshake certifies the business outcome. - -## Core Boundary - -Separate the system into three planes: - -1. Evidence plane: `AuthorityCertificate` issuance, terminal artifact binding, signature, envelope digest, artifact-kind requirements, gateway admission binding, and terminal binding. -2. Discovery plane: public verifier key set projection, issuer metadata, signer role metadata, key version metadata, and status endpoint discovery. -3. Trust decision plane: local verifier policy over pinned issuers, accepted roles, accepted key versions, required artifact kinds, acceptable status freshness, revocation behavior, and failure mode. - -Key discovery must never imply trust. JWKS can publish public keys. Only local verifier policy decides whether a key, issuer, signer role, and certificate status are acceptable. - -## Protocol Schema And State - -Add protocol-owned models, not route-owned ad hoc shapes: - -- `AuthorityCertificate`: existing signed evidence envelope. Keep terminal-only issuance. -- `AuthorityCertificateIssuer`: stable issuer identifier, evidence-plane service name, metadata URL, supported algorithms, current status. -- `AuthorityCertificateSignerRole`: narrow enum or registry-backed type such as `terminal_evidence_signer`, maybe later `status_signer`. Avoid broad names like `trusted_signer`. -- `AuthorityCertificateKeyVersion`: key id, issuer id, signer role, algorithm, public key material reference, activation time, retirement time, status. -- `AuthorityCertificateStatusRecord`: certificate id or digest, issuer id, status, reason code, observed time, effective time, optional expires time, status signer binding. -- `AuthorityCertificateVerificationRequest`: certificate plus requested policy knobs: required artifact kinds, required issuer, accepted signer roles, freshness budget. -- `AuthorityCertificateVerificationResponse`: evidence-safe result: `valid`, `invalid`, `revoked`, `stale`, `status_unavailable`, `untrusted_issuer`, `untrusted_key`, `unsupported_algorithm`, `artifact_requirement_failed`, `binding_failed`. - -Do not encode approved, authorized, certified, settled, identity verified, or safe to execute in these names. - -## Verifier Key Set Vs JWKS Projection - -There are two different artifacts: - -- Verifier key set: Handshake-native read model with issuer id, signer role, key version, lifecycle state, algorithm, activation/retirement timestamps, and policy-relevant metadata. -- JWKS projection: standards-compatible public-key representation derived from verifier key set. It exposes public verification material and `kid`/algorithm mapping, but it is not the canonical trust model. - -The JWKS endpoint is a public projection, not the source of trust. RFC 7517 gives representation. RFC 7515 gives key identification/signature integrity lessons. RFC 8414-style metadata can advertise `jwks_uri`. None of those documents turn discovery into acceptance. - -## Signer Role And Key Version Model - -Minimum model: - -- `issuerId` -- `keyId` -- `keyVersion` -- `signerRole` -- `algorithm` -- `publicKeyMaterial` -- `status`: `active | retired | revoked` -- `validFrom` -- `retiredAt` -- `revokedAt` -- `rotationReason` - -Verification must require both key match and role match. A key valid for status records must not automatically validate terminal evidence. A retired key may verify historical certificates only if the certificate signing time falls inside the acceptable window and local policy allows historical validation. - -## Certificate Status And Revocation Semantics - -Revocation is evidence-plane invalidation, not OAuth token semantics. RFC 7009 is useful only for transferable security lessons: authenticated revocation, ambiguous public responses where appropriate, replay resistance, and privacy-preserving status behavior. - -Recommended status values: - -- `good` -- `revoked` -- `superseded` -- `unknown` -- `stale` -- `issuer_unavailable` - -Verification must fail closed for live trust decisions when status is unavailable or stale. For audit-only reconstruction, it may return a redacted `status_unavailable` result with enough metadata to explain the gap. - -Status records should be append-only and separately signed or gateway-recorded. Do not silently mutate certificate validity in place. - -## Hosted Verifier Route Boundaries - -Allowed: - -- accept certificate verification input; -- fetch/project local issuer key material; -- check pinned trust material; -- check revocation/status; -- return audit-safe verification result; -- optionally emit receipt/proof-gap for verification-attempt observability if later scoped. - -Forbidden: - -- mint new authority; -- authorize mutation; -- settle payment; -- certify identity; -- imply principal approval; -- infer business success; -- accept arbitrary remote JWKS as trusted without local policy; -- expose full terminal receipts when caller is not entitled to them. - -Suggested routes: - -- `GET /.well-known/handshake-authority-certificate` -- `GET /authority-certificates/jwks.json` -- `POST /authority-certificates/verify` -- `GET /authority-certificates/status/:certificateDigest` - -## Redaction And Audit-Safe Projection - -Default response should include: - -- verification result; -- issuer id; -- key id / key version; -- signer role; -- artifact kinds observed; -- envelope digest; -- terminal evidence kind; -- status result; -- status checked at; -- failure reason code; -- redacted proof-gap markers. - -Default response should exclude: - -- secrets; -- full receipt payloads; -- raw gateway credentials; -- principal private context; -- settlement internals; -- downstream execution details not signed into the certificate; -- unrelated terminal artifacts. - -If full evidence is needed, require a separate entitlement path. Hosted verification must not become a receipt exfiltration endpoint. - -## CLI, SDK, And MCP Integration Points - -CLI: - -- `cert verify` remains non-mutating. -- Add flags for `--issuer`, `--jwks-uri`, `--trust-policy`, `--required-artifact-kind`, `--status-url`, `--allow-stale=false`. -- Output must say certificate evidence valid, not authorized. - -SDK: - -- provide `verifyAuthorityCertificate`; -- provide `loadVerifierKeySet`; -- provide `projectVerifierKeySetToJwks`; -- provide `checkAuthorityCertificateStatus`; -- keep policy explicit: no default remote trust. - -MCP: - -- expose read-only tools only: `handshake.certificate.verify`, `handshake.certificate.status`, `handshake.issuer.metadata`, `handshake.issuer.jwks`; -- tool descriptions must state non-mutating evidence verification; -- do not expose certificate verification as approval or gateway admission. - -## Source Ownership - -Recommended ownership should stay near existing source areas, not generic helper buckets: - -- `src/protocol/areas/authority-certificate/` for canonical schema and verifier extensions; -- `src/protocol/areas/authority-certificate/status.ts` for status and revocation schema; -- `src/protocol/areas/authority-certificate/key-set.ts` for Handshake-native key set model and JWKS projection; -- `src/http/...` for metadata and verifier route adapters when hosted is promoted; -- `src/cli/certificate.ts` for CLI surface; -- SDK/evidence clients for non-mutating helpers. - -Keep RFC-specific projection code at the boundary. Do not let JWKS types invade internal trust semantics. - -## Import Posture - -Accept standards libraries for JWK/JWKS parsing only if boring, maintained, and testable. Do not import a general auth framework that smuggles OAuth, identity-provider, token-introspection, or permission semantics into the model. - -Internal verification policy should remain Handshake-owned. External specs give wire formats, not authority semantics. - -## Validation Gates - -- A valid certificate cannot authorize a new gateway mutation. -- Verification fails when signer role is wrong even if signature is valid. -- Verification fails when a key is discovered through JWKS but not pinned by local trust policy. -- Retired key verifies only historical certificates inside allowed policy window. -- Revoked certificate returns revoked, not invalid generic. -- Status unavailable is distinct from bad signature. -- Hosted verifier never returns full private receipt fields by default. -- CLI/SDK/MCP copy never says permission, approval, identity, settlement, or certified. - -## Smallest Next Mechanism - -Define `VerifierKeySet`, `AuthorityCertificateStatusRecord`, and `AuthorityCertificateVerificationResponse` as protocol-owned types. Make JWKS a projection from that model rather than the trust model itself. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/EXECUTION.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/EXECUTION.md deleted file mode 100644 index 5a1fdee..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/EXECUTION.md +++ /dev/null @@ -1,284 +0,0 @@ -# Execution Perspective - -## Invariant At Stake - -Terminal certificate evidence may become portable, but it must not become permission, identity, settlement, certification, or downstream success. The verifier can answer only: this terminal evidence is structurally and cryptographically consistent with this pinned verifier trust posture and status record. - -## Ordered Slices - -### Slice 0 - Claim Guard Before Code - -Goal: prevent implementation from smuggling product claims into names, docs, routes, CLI output, or tests. - -Candidate paths: - -- `docs/internal/decisions.md` -- `docs/internal/protocol-notes.md` -- `README.md` -- `src/**/authority-certificate*` -- `src/**/cert*` -- `test/**/authority-certificate*` -- `scripts/**/quality*claims*` - -Execution: - -1. Add or update internal wording that says verifier responses are evidence-plane only. -2. Ban language like certified, trusted agent, authorized, approved, settled, cleared, identity verified. -3. Make CLI and hosted verifier response wording use evidence-valid phrasing, not authority phrasing. - -Stop if existing product copy treats a valid certificate as authority. - -### Slice 1 - Issuer / Signer / Key Version Read Model - -Goal: expose trust posture used during verification without changing verification semantics. - -Candidate source paths: - -- `src/protocol/areas/authority-certificate/schemas.ts` -- `src/protocol/areas/authority-certificate/verify.ts` -- `src/protocol/areas/authority-certificate/key-set.ts` - -Candidate tests: - -- `test/protocol/authority-certificate.test.ts` -- `test/protocol/authority-certificate-verifier.test.ts` -- `test/protocol/verifier-trust.test.ts` - -Implement: - -- `VerifierTrustKey` -- `VerifierKeyStatus = active | retired | revoked` -- `VerifierSignerRole` -- `VerifierKeyVersion` -- `VerifierTrustSnapshot` -- deterministic lookup by issuer, key id, algorithm, role, and status. - -Validation gates: - -- active signing key verifies; -- retired key verifies only when allowed by explicit historical semantics; -- revoked key does not verify once status slice lands; -- unknown key id fails closed; -- role mismatch fails closed. - -Trap: `issuer` is local verifier namespace, not legal identity. - -### Slice 2 - RFC 7517 JWKS Projection - -Goal: publish or expose public verifier keys as a JWK Set projection of local pinned trust material. - -Candidate source paths: - -- `src/protocol/areas/authority-certificate/key-set.ts` -- `src/protocol/areas/authority-certificate/jwks.ts` -- `src/http/verifier-metadata.ts` - -Candidate tests: - -- `test/protocol/verifier-key-set.test.ts` -- `test/http/verifier-metadata.test.ts` - -Implement: - -- `toPublicJwkSet(trustSnapshot)`; -- public members only: `kty`, `kid`, `alg`, `use` or `key_ops` if locally modeled; -- private material exclusion; -- stable ordering by `kid`; -- optional metadata projection with `jwks_uri` following RFC 8414 shape without claiming OAuth/OIDC semantics. - -Validation gates: - -- serialized JWKS contains no private fields; -- HMAC keys are rejected from production projection; -- unsupported algorithms fail closed; -- duplicate `kid` fails closed; -- active and retired public keys can appear if historical portability requires it; -- revoked keys are either excluded or status-marked only in status plane, not silently trusted. - -### Slice 3 - Revocation / Status Record - -Goal: add verifier-owned status plane for terminal certificates and signer keys. - -Candidate source paths: - -- `src/protocol/areas/authority-certificate/status.ts` -- `src/protocol/areas/authority-certificate/verify.ts` -- `src/protocol/store/` only if existing store ownership fits. - -Candidate tests: - -- `test/protocol/certificate-status.test.ts` -- `test/protocol/authority-certificate-revocation.test.ts` - -Implement: - -- `CertificateStatusRecord`; -- statuses: `active`, `revoked`, `stale`, `unknown`, `status_unavailable`; -- revocation reason codes as controlled enum; -- status lookup result included in verification response; -- fail-closed behavior for required online status when unavailable; -- local/in-memory status adapter first unless existing durable storage abstraction fits. - -Validation gates: - -- revoked certificate fails verification; -- stale certificate fails or returns non-valid response based on explicit policy; -- status unavailable fails closed when status is required; -- no RFC 7009 certificate semantics. - -### Slice 4 - Verification Response Projection - -Goal: create an audit-safe response object separate from internal verifier diagnostics. - -Candidate source paths: - -- `src/protocol/areas/authority-certificate/verification-response.ts` -- `src/protocol/areas/authority-certificate/verify.ts` -- `src/cli/certificate.ts` -- `src/http/authority-certificate-verifier.ts` - -Candidate tests: - -- `test/protocol/authority-certificate-verification-response.test.ts` -- `test/cli/cli-evidence.test.ts` - -Implement response fields: - -- `result: valid | invalid | revoked | stale | status_unavailable` -- `artifactKind` -- `envelopeDigest` -- `terminalEvidenceBinding` -- `gatewayAdmissionBinding` -- `issuer` -- `kid` -- `signerRole` -- `keyVersion` -- `statusCheckedAt` -- `verificationCheckedAt` -- `failureReasons[]` -- `auditWarnings[]` - -Validation gates: - -- response never exposes private key material; -- response never says permission, authorization, settlement, or certification; -- response distinguishes gateway admission binding from downstream execution evidence; -- missing evidence is a proof gap, not successful verification. - -### Slice 5 - Hosted Verifier Route - -Goal: non-mutating hosted verifier endpoint that accepts a certificate and returns the audit-safe projection. - -Candidate source paths: - -- `src/http/authority-certificate-verifier.ts` -- `src/http/routes/authority-certificate.ts` -- `src/http/server.ts` -- `src/http/verifier-metadata.ts` - -Candidate tests: - -- `test/http/authority-certificate-verifier.test.ts` -- `test/integration/authority-certificate-verifier-route.test.ts` - -Implement: - -- `GET /.well-known/handshake-verifier`; -- `GET /verifier/jwks.json`; -- `POST /verifier/authority-certificates/verify`; -- request size limits; -- schema validation; -- no mutation, minting, admission, or policy greenlight creation. - -Validation gates: - -- malformed certificate returns invalid projection, not crash; -- oversized request rejected; -- route cannot create or update status records; -- unavailable status store produces explicit `status_unavailable`; -- hosted response matches protocol verifier response. - -### Slice 6 - CLI Parity - -Goal: CLI and hosted verifier share the same verifier core and response projection. - -Candidate paths: - -- `src/cli/certificate.ts` -- `src/cli/index.ts` -- `src/protocol/areas/authority-certificate/verify.ts` - -Candidate tests: - -- `test/cli/cli-evidence.test.ts` -- `test/integration/cert-verify-smoke.test.ts` - -Validation gates: - -- CLI rejects HMAC production certificates; -- CLI valid output does not imply authority; -- CLI and hosted route produce equivalent projection for same certificate/trust/status fixture. - -### Slice 7 - Claim / Architecture Quality Gate - -Goal: make forbidden semantics hard to regress. - -Candidate paths: - -- `scripts/check-claims*.mjs` -- `test/architecture/claim-boundary.test.ts` -- `docs/internal/protocol-notes.md` - -Validation: - -- guard forbidden strings near verifier/certificate routes; -- fixture tests prove response wording; -- docs state terminal verifier trust plane is evidence portability only. - -## Dependency Graph - -```text -Slice 0 Claim Guard - -> Slice 1 Trust Read Model - -> Slice 2 JWKS Projection - -> Slice 3 Status Record - -> Slice 4 Verification Response Projection - -> Slice 5 Hosted Verifier Route - -> Slice 6 CLI Parity - -> Slice 7 Quality Gate -``` - -Parallelizable after Slice 1: - -- JWKS projection and status record can proceed independently. -- Hosted route and CLI parity can proceed in parallel after Slice 4. -- Claim guard can start immediately and continue through all slices. -- Tests for fixtures can be prepared in parallel once response schema is fixed. - -## Closeout Commands - -```bash -npm run test -- test/protocol/authority-certificate.test.ts -npm run test -- test/protocol/authority-certificate-verifier.test.ts test/protocol/verifier-key-set.test.ts test/protocol/certificate-status.test.ts -npm run test -- test/http/authority-certificate-verifier.test.ts test/cli/cli-evidence.test.ts -npm run quality:claims -npm run quality:architecture -npm run format:check -npm run check:repo -``` - -## Rollback / Stop Conditions - -Stop implementation if: - -- verifier response implies authorization, identity, settlement, or certification; -- JWKS projection exposes private or symmetric key material; -- revocation/status check silently degrades to valid; -- route creates greenlights, admissions, receipts, or mutations; -- certificate validity is treated as downstream business success; -- one verifier key can satisfy multiple roles without explicit role binding; -- unknown key, unknown issuer, unknown status, or unsupported algorithm passes open. - -## Smallest Next Mechanism - -Add the verifier trust read model and public JWKS projection tests first: pinned key input, deterministic public JWK Set output, no private/HMAC material, stable key id/role/version metadata, and no change to existing `AuthorityCertificate` verification semantics. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/RISK.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/RISK.md deleted file mode 100644 index d39c8d3..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/RISK.md +++ /dev/null @@ -1,104 +0,0 @@ -# Risk And Security Perspective - -## Invariant At Stake - -A terminal `AuthorityCertificate` is portable evidence, not permission. Verification must never imply authority, identity, settlement, compliance certification, clearing-house status, or downstream business success. - -## Risk Posture - -- Stale key: fail closed unless the certificate proves it was signed during an accepted key validity window and status data is available for that window. -- Revoked key: refuse verification with a precise reason such as `revoked_signing_key` or `revoked_issuer_keyset`, not generic invalidity. -- Status outage: return `proof_gap` or `status_unavailable`; never return `valid`. -- Unknown issuer, tenant, role, or key version: refuse, not warn. -- Raw evidence exposure: never return full terminal evidence from hosted verification; return audit-safe projections only. -- Hosted verifier abuse: rate-limit, size-limit, require deterministic parsing, reject recursive fetches, and never fetch arbitrary `jwks_uri` supplied by a certificate. -- Replay/tamper: certificate verification must bind envelope digest, signing input digest, artifact kind, terminal event id, gateway admission id, and issuer key version. -- OAuth/JWKS confusion: use JWK/JWKS only as key representation. Do not import OAuth authorization, token revocation, introspection, identity provider, or bearer-token language. -- x402 overfitting: x402 is the first protected-action wedge, not verifier ontology. Keep action kind, gateway binding, and evidence projection generic. -- Claim drift: guard all docs/CLI/API strings so valid certificate means only signature, binding, status, and projection checks passed. - -## Required Security Mechanisms - -### Issuer / Verifier Read Model - -- `issuer_id` -- `tenant_scope` -- `signer_role` -- `key_id` -- `key_version` -- `key_status: active | retired | revoked` -- `valid_from` -- `valid_until` -- `revoked_at` -- `revocation_reason` -- `allowed_artifact_kinds` - -### Verifier Key Set Projection - -- Publish public verification keys as RFC 7517 JWK Set. -- Protect non-public key material by never placing it in projections, logs, fixtures, or snapshots. -- Treat `kid` as selector metadata, not proof of trust. -- Bind accepted keys to local/pinned issuer trust configuration. - -### Status / Revocation Check - -- Local status record first. -- Optional hosted status endpoint later. -- No OAuth revocation semantics. RFC 7009 contributes only security lessons: authenticated status changes, non-leaky responses, replay resistance, and clear client behavior. -- Verification must distinguish `revoked`, `unknown`, `retired_outside_window`, and `status_unavailable`. - -### Hosted Verification Response - -Response states: - -- `verified` -- `refused` -- `proof_gap` - -Never return authorized, approved, paid, settled, certified, trusted, or compliant. - -Include only redacted projection: - -- certificate id; -- issuer id; -- key version; -- artifact kinds; -- terminal evidence kind; -- gateway binding presence; -- status result; -- refusal/proof-gap reason. - -### Admission / Terminal Binding - -Verification remains invalid unless the certificate binds both exact gateway admission evidence and exact terminal evidence artifact. A certificate without gateway binding is evidence-plane residue, not Handshake evidence. - -## Validation Gates - -- Golden tests for active, retired-valid-window, retired-outside-window, revoked, unknown key, wrong role, wrong tenant, wrong artifact kind. -- Hosted verifier tests for oversized payloads, malformed JWK, bad key id, duplicate keys, algorithm confusion, and arbitrary `jwks_uri` injection. -- Claim-guard tests banning permission/identity/settlement/certification language in CLI, API responses, docs, and examples. -- Redaction tests proving raw terminal evidence and non-public key material never appear in hosted responses. -- Status-outage tests proving verifier returns proof gap/status unavailable, not verified. -- Replay tests proving reused certificate material cannot validate against a different terminal artifact, gateway admission, tenant, or artifact kind. -- x402 regression tests proving x402 examples do not leak into generic verifier schemas. - -## Antipatterns To Cut - -- Valid certificate means the action was allowed. -- JWKS means OAuth trust. -- Revocation endpoint means OAuth token revocation. -- Hosted verifier is a source of authority. -- Retired key is always invalid. -- Status unavailable but signature valid, so pass. -- Return raw evidence so integrators can inspect it. -- Use x402 names in core verifier schema. -- Trust any `jwks_uri` referenced by the certificate. -- One verifier response doubles as audit receipt and business success proof. - -## Brutal Verdict - -Keep the terminal verifier trust plane, but narrow it hard: it verifies evidence binding and key/status posture only. Anything broader is trust confusion. The dangerous failure is not bad cryptography; it is letting a portable evidence artifact become ambient authority wearing certificate language. - -## Smallest Next Mechanism - -Build a local issuer/key-status read model plus verifier result enum `verified | refused | proof_gap`, with stale/revoked/status-unavailable tests before any hosted route. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/STRATEGY.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/STRATEGY.md deleted file mode 100644 index a515f71..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/raw/STRATEGY.md +++ /dev/null @@ -1,145 +0,0 @@ -# Strategy Perspective - -## Invariant At Stake - -Portable terminal evidence must not become portable permission. An `AuthorityCertificate` can prove that Handshake recorded terminal evidence for an exact action contract under a pinned verifier trust set. It must not imply identity, settlement, compliance, certification, business success, or authority to mutate anything. - -## Strategy Posture - -Handshake should position this work as an evidence portability layer for protected automated actions, starting with x402 exact per-call paid HTTP. The wedge is not "x402 support." The wedge is that paid HTTP calls are consequential, frequent, atomic, externally observable, and naturally require proof that an exact call was greenlit or refused before consequence. - -The verifier trust plane should make terminal evidence portable across systems without expanding Handshake's role. Handshake issues and verifies evidence. It does not become a payment processor, identity provider, certificate authority, compliance auditor, or clearing house. - -## Category Boundaries - -Keep: - -- `AuthorityCertificate` as signed terminal evidence. -- Verifier key sets as public trust material. -- Revocation/status as evidence freshness and trust-state checks. -- Verification response as an audit-safe projection. -- x402 as the first protected-action surface. - -Cut: - -- certificate means approved; -- certificate means paid; -- certificate means the principal authorized all downstream effects; -- certificate means the actor is trusted; -- certificate means settlement succeeded; -- certificate means compliance; -- certificate authority language unless Handshake intentionally accepts CA expectations, liability, lifecycle, audits, and revocation semantics. - -Preferred language: - -- terminal evidence certificate; -- evidence verifier; -- verifier key set; -- certificate status; -- audit-safe verification response; -- protected action evidence. - -Avoid: - -- trust network; -- identity layer; -- payment certification; -- settlement proof; -- authorization certificate; -- approved certificate; -- clearing house. - -## x402-First Wedge Implications - -x402 is strategically useful because it forces exactness: - -- one paid HTTP request; -- one gateway admission; -- one terminal outcome; -- one receipt/refusal/proof gap; -- one certificate; -- one verifier response. - -That maps cleanly onto Handshake's core primitive. - -x402 is also dangerous because the market will try to pull Handshake into protocol claims: payment validity, payer identity, merchant trust, settlement finality, and dispute resolution. Reject that pull. Handshake's job is to prove whether the automated actor had a gateway-bound terminal evidence record for the exact protected call. Payment protocol semantics remain outside the product boundary. - -The product claim should be: - -> For x402-protected automated calls, Handshake makes the terminal evidence portable: what exact action was proposed, what terminal evidence exists, which verifier key signed it, whether the certificate is currently verifiable, and what must remain unknown. - -## Adoption Sequence - -1. Local verifier model: add issuer/signer role/key-version read models over existing pinned trust material. No hosted route yet. Prove the trust vocabulary without network product surface. -2. Public key-set projection: expose RFC 7517-shaped JWK Set projection for active and retired verifier public keys. Protect non-public material. Include key ids and signer roles without turning this into identity. -3. Status and revocation records: add certificate status records: `active`, `revoked`, `stale`, `unknown`, `status_unavailable`. Treat unavailable status as a verification failure unless explicitly configured otherwise. -4. Verification response plane: return redacted, audit-safe verification responses with certificate digest, terminal evidence kind, issuer, signer role, key id/version, status, checked-at, artifact checks, gateway binding, terminal binding, and explicit non-claims. -5. Hosted verifier route: add a read-only route that verifies submitted certificates against projected key set and status store. It must be non-mutating and must not mint authority. -6. x402 integration profile: define the minimal verification profile an x402 receiver or auditor needs: exact paid-call contract digest, terminal evidence kind, gateway admission binding, certificate status, and proof-gap handling. - -## Cut Lines - -- Do not build settlement proof. -- Do not build principal identity assertions. -- Do not build merchant reputation. -- Do not build generalized credentials. -- Do not build org-wide trust federation. -- Do not allow verification response consumers to treat `valid` as safe to execute. -- Do not use RFC 7009 semantics directly. Borrow only the security lesson: revocation/status endpoints require careful authentication, denial-of-service posture, and status ambiguity handling. -- Do not expose raw receipts if the verifier response can answer the audit question with redaction. - -## Assumptions - -- x402 paid HTTP calls remain atomic enough to model as one protected action attempt. -- The current certificate signing model already binds terminal evidence to envelope digest, signing input digest, signer role, gateway admission, and terminal artifact kind. -- Local pinned trust material is acceptable for the next phase but not sufficient for external verifier adoption. -- External consumers need portable evidence, not raw internal receipt stores. -- Revocation/status is about trust in certificate evidence, not undoing the underlying action. - -## Dependencies - -- Stable certificate schema and digest canonicalization. -- Public-key signing path suitable for production. -- Key id and key version model. -- Signer role model. -- Issuer model. -- Status store with revocation reason and checked-at timestamps. -- Audit-safe redaction policy. -- Claim guard copy and tests preventing overstatement. -- x402 action-contract profile defining required fields and evidence expectations. - -## Risks - -- `valid: true` becomes authorization theatre if the response does not say what validity means. -- Hosted verifier becomes a de facto trust authority if product language drifts. -- Revocation gets misread as payment cancellation. -- x402 positioning gets mistaken for protocol infrastructure rather than protected-action enforcement. -- Status-unavailable handling becomes a soft pass under adoption pressure. -- Key rotation breaks old audits if retired keys are not verifiable with clear status. -- Redaction strips too much, making the response useless for reconstruction. -- Redaction strips too little, leaking principal, action, or business-sensitive data. - -## Validation Gates - -- A certificate with a valid signature but revoked status must fail verification. -- A certificate signed by a retired-but-allowed key must verify only according to explicit policy. -- A certificate with unknown key id must fail. -- A certificate with valid signature but missing required terminal artifact kind must fail. -- A certificate with valid receipt evidence but no gateway admission binding must fail. -- A certificate with proof-gap terminal evidence must verify as a proof gap, not as success. -- Hosted verifier must be read-only and non-mutating. -- Verification response must include explicit non-claims. -- Claim guard must reject valid certificate means approved/paid/authorized/settled/certified. -- x402 profile must prove one protected paid-call attempt, not generalized payment legitimacy. - -## 10-Star Bar - -A 10-star version makes an external x402 receiver or auditor comfortable asking one narrow question: - -> Does this submitted terminal evidence certificate verify against Handshake's published verifier keys and current status policy, and what exact protected-action evidence does it prove or fail to prove? - -The answer is deterministic, redacted, reconstructable, and boring. It includes enough evidence to audit the exact protected action attempt. It refuses to imply authority. It survives key rotation. It handles revocation and stale status explicitly. It treats proof gaps as first-class outcomes. It makes overclaiming hard in code, docs, and API shape. - -## Smallest Next Mechanism - -Build the verifier read model and response contract first: issuer, signer role, key id/version, active/retired status, certificate status, verification result, terminal evidence projection, and explicit non-claims. Then expose the same model through a JWKS projection and only after that through a hosted verifier route. diff --git a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/synthesis.md b/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/synthesis.md deleted file mode 100644 index 84f8ceb..0000000 --- a/.planning/macro/archive/implemented-sprints/2026-05-24-tier2-macro-closeout/terminal-verifier-trust-plane/runs/terminal-verifier-trust-plane-20260524T074226Z/synthesis.md +++ /dev/null @@ -1,75 +0,0 @@ -# Synthesis: Terminal Verifier Trust Plane - -## Chair Read - -The perspectives converge on one hard boundary: the trust plane must make `AuthorityCertificate` portable without letting portability become authority. - -The weak version of this initiative would publish keys, add a hosted `/verify`, and market certificates as proof that an x402 call was paid or approved. That is advisory theatre. The strong version separates evidence, discovery, and trust decision planes, then gives external receivers a structured answer about exact terminal evidence. - -## Coherent Sequence - -The correct order is: - -1. Claim guard. -2. Trust read model. -3. Native key-set projection. -4. JWKS projection. -5. Status/revocation records. -6. Structured verification response. -7. Hosted discovery/status routes. -8. Hosted verify route. -9. CLI/SDK/MCP parity. -10. x402 evidence profile. - -This order is chosen because hosted verification before status semantics would produce false confidence, and JWKS before native key-set would turn projection into authority. x402 must wait until certificate verification cannot be confused with payment settlement. - -## Key Reconciliations - -Strategy wanted external portability for x402 receivers and auditors. Architecture required plane separation and protocol-owned read models. Execution proposed slices near existing authority-certificate, CLI, HTTP, and tests. Risk forced fail-closed status and redaction. Adoption required CLI/SDK/MCP surfaces without boolean validity shortcuts. - -The merged plan keeps the strategic wedge but makes architecture and risk constraints the gate. x402 is not allowed to define certificate meaning. - -## Chosen Primitive - -The primitive is structured terminal evidence verification: - -- exact certificate; -- exact terminal artifact kind; -- exact signed-over binding; -- exact issuer/key/role/status model; -- exact gateway admission binding; -- exact terminal binding; -- explicit refusal or proof gap when evidence is missing, stale, revoked, or unavailable. - -## Boundaries Preserved - -- Vague intent is not authority. -- Generated action is not permission. -- `AuthorityCertificate` is not greenlight. -- JWKS is not trust. -- Hosted verifier is not mutation. -- Verification is not settlement. -- Redacted audit response is not raw receipt disclosure. - -## Main Product Cut - -Cut every claim that says or implies: - -- certificate means approved; -- certificate means paid; -- certificate means settled; -- certificate means the actor is trusted; -- certificate means compliance; -- certificate means downstream success; -- JWKS means the verifier is trusted. - -The acceptable language is narrower: certificate verifies, refuses, or produces a proof gap against a declared verifier trust plane. - -## Readiness To Execute - -The plan is ready to execute if the team accepts two user-owned decisions: - -- hosted route naming convention; -- initial storage/read-provider posture for status records. - -Neither blocks Phase 0 or Phase 1. The smallest next mechanism is the claim guard followed by the issuer/key-version read model. diff --git a/.planning/tier2/00-canon-alignment.md b/.planning/tier2/00-canon-alignment.md deleted file mode 100644 index 0e46cb1..0000000 --- a/.planning/tier2/00-canon-alignment.md +++ /dev/null @@ -1,127 +0,0 @@ -# Canon Alignment - -Status: planning scratch, revised 2026-05-19. - -## Invariant at stake - -Tier 2 must extend the protocol kernel without changing the primitive. It must -not smuggle hosted claims, provider claims, or broad x402 payment claims into a -self-hosted proof. - -## Canon facts from `/docs/internal` - -### Product kernel - -`docs/internal/decisions.md` defines the current product kernel as: - -```text -exact action contract --> exact policy decision --> one-use gateway-bound greenlight --> gateway check before mutation --> receipt, refusal, or proof gap -``` - -It also defines the first bought product as Handshake Protected Actions: an -integration kit and receipt experience for one coding-agent workflow executing -one protected production-adjacent action through gateway-checked action -contracts. - -### Hosted boundary - -`docs/internal/decisions.md` says HTTP admission and caller custody may model -deployment-mode custody and caller roles, but they do not prove hosted -operation, production org auth, provider enforcement, or customer gateway -installation. - -A hosted claim requires: - -- a real deployment boundary; -- a credential custody model; -- a customer or provider gateway check; -- receipts that distinguish gateway check evidence from downstream execution - evidence. - -### Extension boundary - -`docs/internal/protocol-kernel-architecture.md` defines the forward extension -path: - -- self-hosted operation adds installable protected-action loops around the - kernel; -- hosted operation adds policy management, receipt retention, search, rollout, - audit, and recovery operations around the same kernel; -- bilateral ecosystem operation may add negotiation and linked agreements, but - every obligation still becomes its own action contract, policy decision, - greenlight, gateway check, and receipt/refusal/proof-gap chain. - -### Gateway policy lifecycle - -The same architecture doc says self-hosted installs can use local versioned -gateway policy, and hosted operation can distribute hosted versioned policy to -gateways. Enforcement remains at the gateway in both cases. - -### Evidence boundary - -`docs/internal/protocol-notes.md` requires receipts to distinguish: - -- proposal evidence; -- policy decision evidence; -- gateway check evidence; -- mutation attempt evidence; -- downstream finality evidence; -- proof gaps. - -Missing or ambiguous evidence is `ProofGap`, not success. - -## Correction to the first draft - -The first draft over-indexed on local product parts. That is not enough. - -The corrected design starts from a tier ladder: - -```text -Tier 1: protocol kernel proves the authority state machine -Tier 2: self-hosted Protected Actions proves one installed customer-owned path -Tier 3: hosted operation manages policy, retention, audit, rollout, and recovery -Tier 4: provider/customer gateway integrations make enforcement native at the - protected system boundary -``` - -The x402 example is useful only because wallet signing gives a clean mutation -boundary. It is not the product category. - -## Design constraints - -Tier 2 must preserve these constraints: - -- The agent may propose. It cannot authorize. -- The customer-owned gateway holds or controls signing authority. -- Policy is versioned before action time. -- The contract pins x402 evidence and gateway policy version. -- The greenlight is exact, one-use, gateway-bound, and expires. -- The gateway checks pinned and current policy, contract digest, params digest, - idempotency, isolation, and protected path posture before signing. -- The receipt can later move into Tier 3 retention/search without changing its - evidentiary meaning. -- Tier 4 provider work must make the gateway check native or provider-certified; - it cannot be a later observer. - -## Non-claims - -Tier 2 must not claim: - -- hosted operation; -- provider-side enforcement; -- generic x402 payment control; -- universal agent governance; -- wallet custody product; -- settlement finality; -- downstream business success; -- control over raw sibling tools or credentials outside the installed path. - -## Smallest next mechanism - -Define a migration-ready `x402_payment.exact` protected action family whose -records are already suitable for future hosted policy distribution and -provider-gateway attestation. diff --git a/.planning/tier2/01-source-study.md b/.planning/tier2/01-source-study.md deleted file mode 100644 index 185e427..0000000 --- a/.planning/tier2/01-source-study.md +++ /dev/null @@ -1,157 +0,0 @@ -# Source Study - -Status: planning scratch, revised 2026-05-19. - -## Invariant at stake - -Source evidence must separate what x402 proves from what Handshake proves. -x402 can prove payment-protocol facts. Handshake must prove principal authority -over a generated agent's consequential payment attempt. - -## Internal source anchors - -### `docs/internal/protocol-definition.md` - -Authority exists only when: - -- runtime or generated-execution evidence produced the candidate; -- the candidate matched catalog, envelope, and gateway records; -- the candidate was canonicalized into an exact `ActionContract`; -- policy greenlit that exact contract; -- the `Greenlight` is unexpired, unconsumed, and `maxUses: 1`; -- no active `IsolationState` blocks policy or gateway execution; -- the gateway owns or controls the mutation credential; -- the gateway checks the exact greenlight before mutation. - -For x402, the mutation credential is wallet signing authority. - -### `docs/internal/protocol-kernel-architecture.md` - -The kernel already has the required object chain: - -```text -ToolCapability -ActionType -GatewayRegistryEntry -OperatingEnvelope -RuntimeExecution -GeneratedExecutionGraph -IntentCompilationRecord -CandidateAction -ActionContract -PolicyDecision -Greenlight -GatewayCheckAttempt -MutationAttempt -Receipt -Refusal -ProofGap -IsolationState -RecoveryRecommendation -``` - -Tier 2 should map x402 into this chain instead of adding a new protocol core. - -### `docs/internal/protocol-layman.md` - -The plain-language guide gives the product translation Tier 2 should preserve: - -```text -one exact work order -one decision -one-use pass -one gateway check -one receipt, refusal, or proof gap -``` - -For x402: - -```text -one exact payment contract -one decision -one-use greenlight -one wallet gateway check -one receipt, refusal, or proof gap -``` - -### `docs/internal/decisions.md` - -The first bought product is Protected Actions: one workflow, one protected -production-adjacent action class, one gateway check, one policy file, one -receipt timeline. - -That implies Tier 2 x402 should design for a buying path, not just a demo path. - -## X402 primary-source facts - -Primary sources: - -- x402 HTTP 402 docs: - -- x402 buyer quickstart: - -- x402 facilitator docs: - -- x402 V1 to V2 migration guide: - -- x402 GitHub repository: - - -### Payment flow - -x402 V2 uses: - -- `PAYMENT-REQUIRED`: server to client, base64 `PaymentRequired`; -- `PAYMENT-SIGNATURE`: client to server, base64 `PaymentPayload`; -- `PAYMENT-RESPONSE`: server to client, base64 settlement response. - -The buyer receives a 402, selects accepted payment details, creates and signs a -payment payload, retries the request with `PAYMENT-SIGNATURE`, and receives -resource/settlement evidence through the server response. - -Handshake's authority boundary is before `PAYMENT-SIGNATURE` exists. - -### Buyer SDK pressure - -The buyer quickstart shows private-key-backed signers loaded from environment -variables such as `EVM_PRIVATE_KEY` and clients that automatically retry paid -requests. That is correct x402 ergonomics, but it is the danger case for -Handshake: generated code can make a paid request look like an ordinary HTTP -call. - -Tier 2 must invert that path. Generated code may produce a candidate. Only the -customer-owned gateway may create the payment signature. - -### Facilitator boundary - -The facilitator verifies and settles payments for servers and does not hold -buyer funds. Facilitator responses are downstream evidence. They do not decide -whether the principal authorized the agent to sign. - -### Version drift - -x402 V2 changed headers and network identifiers. Contracts must pin x402 -version and header evidence rather than letting the gateway infer compatibility -at signing time. - -## Design conclusion - -x402 is a strong Tier 2 proof because the mutation is crisp: - -```text -PAYMENT-SIGNATURE created by wallet authority -``` - -But x402 should not determine the Handshake architecture. The architecture is: - -```text -protected action authority chain now -hosted operation around the same chain later -provider gateway attestation around the same chain after that -``` - -## Smallest next mechanism - -Map `PAYMENT-REQUIRED` into `ActionContract.parameters` and make -`PAYMENT-SIGNATURE` creation a `GatewayCheckAttempt` outcome, never a runtime -helper outcome. diff --git a/.planning/tier2/02-users-and-tier-pathway.md b/.planning/tier2/02-users-and-tier-pathway.md deleted file mode 100644 index 5c7aaa5..0000000 --- a/.planning/tier2/02-users-and-tier-pathway.md +++ /dev/null @@ -1,258 +0,0 @@ -# Users And Tier Pathway - -Status: planning scratch, revised 2026-05-19. - -## Invariant at stake - -User-type design cannot become persona theatre. Each user type must map to a -real authority, evidence, adoption, or recovery job in the protocol chain. - -## User types - -### 1. Agent workflow owner - -Who: engineer or team lead letting a coding agent perform useful work. - -Job: get agent productivity without handing the agent mutation authority. - -Needs: - -- a way for generated work to produce exact candidates; -- fast local feedback when a candidate is refused; -- proof that a successful action used the gateway path; -- no requirement to understand every protocol object on day one. - -Tier implication: - -- Tier 2 must feel like an installable protected-action loop. -- Tier 3 can centralize policy and receipts for multiple workflows. -- Tier 4 matters when their provider or platform can enforce natively. - -### 2. Protected path owner - -Who: engineer, platform owner, security owner, or wallet owner who controls the -credential or mutation path. - -Job: ensure the agent cannot mutate outside declared bounds. - -Needs: - -- custody posture: who holds the credential; -- gateway policy version; -- exact contract fields; -- replay and drift refusal; -- isolation after divergence. - -Tier implication: - -- Tier 2 must keep credential authority outside the agent. -- Tier 3 must manage policy rollout without broadening authority. -- Tier 4 must make provider-side enforcement real, not advisory. - -### 3. Policy owner - -Who: person or team responsible for deciding which exact actions may proceed. - -Job: turn operating limits into machine-checkable decisions. - -Needs: - -- versioned policy packs; -- deterministic evaluation; -- refusal reasons; -- review hooks tied to exact contract digests; -- budget windows treated as attempt bounds, not permission. - -Tier implication: - -- Tier 2 uses local versioned policy. -- Tier 3 hosts policy management and distribution. -- Tier 4 requires policy contracts the provider gateway can verify or honor. - -### 4. Reviewer or auditor - -Who: operator, security reviewer, compliance reviewer, incident responder, or -future maintainer reconstructing what happened. - -Job: determine what was controlled, what was observed, and what is unknown. - -Needs: - -- receipt timeline; -- refusal history; -- proof gaps; -- gateway check evidence; -- downstream finality evidence; -- links between related obligations. - -Tier implication: - -- Tier 2 must produce local reconstruction truth. -- Tier 3 adds retention, search, audit, and recovery workflows. -- Tier 4 adds provider attestations or native evidence. - -### 5. Provider partner - -Who: wallet provider, deployment provider, package registry, CI provider, cloud -provider, data API provider, or agent runtime vendor. - -Job: make Handshake enforcement native enough that customers do not have to rely -on wrappers or logs. - -Needs: - -- stable contract and gateway check semantics; -- versioned gateway policy contract; -- conformance expectations; -- evidence exchange format; -- clear non-claim boundaries. - -Tier implication: - -- Tier 2 should expose the shape providers will later need. -- Tier 3 can operate policy and evidence across orgs. -- Tier 4 is reached only when the provider/customer gateway can block mutation - before consequence. - -### 6. Resource seller in the x402 example - -Who: x402 seller, data/API provider, or facilitator-adjacent service. - -Job: publish payment requirements and fulfill paid resources. - -Needs: - -- no dependency on Handshake to sell through x402; -- clear buyer-side evidence requirements; -- optional signed offer/receipt support treated as evidence; -- no assumption that seller approval equals principal consent. - -Tier implication: - -- Tier 2 buyer-side proof should not require seller cooperation beyond standard - x402. -- Tier 4 may later support provider-native receipt or offer attestation, but it - still cannot authorize the buyer's principal. - -## Tier ladder - -### Tier 1: protocol kernel - -User promise: - -```text -There is a coherent authority state machine. -``` - -What exists: - -- exact contracts; -- policy decisions; -- one-use greenlights; -- gateway checks; -- receipts/refusals/proof gaps; -- isolation and recovery primitives. - -What it cannot claim: - -- installed customer path; -- hosted operation; -- provider enforcement. - -### Tier 2: self-hosted Protected Actions - -User promise: - -```text -This installed customer-owned path is gateway-checked. -``` - -For x402: - -```text -The agent can propose a paid request. -The customer-owned wallet gateway creates PAYMENT-SIGNATURE only after exact -greenlight verification. -``` - -Tier 2 must produce objects that Tier 3 can host later: - -- versioned policy pack; -- gateway registry entry; -- protected path posture; -- receipts and proof gaps; -- recovery recommendations; -- conformance results. - -### Tier 3: hosted operation - -User promise: - -```text -Handshake can operate policy, evidence, audit, rollout, and recovery across -installed protected paths. -``` - -Tier 3 adds: - -- hosted policy management; -- policy distribution to gateways; -- gateway enrollment and health; -- receipt retention and search; -- audit workflows; -- recovery workflows; -- rollout controls; -- org-level installation posture. - -Tier 3 must not move enforcement away from the gateway. Hosted policy is not a -mutation credential. - -### Tier 4: provider-integrated enforcement - -User promise: - -```text -The protected system's own gateway or provider-certified boundary can enforce -Handshake-compatible checks before mutation. -``` - -Tier 4 adds: - -- provider/customer gateway contract; -- native or certified pre-mutation check; -- provider evidence attestation; -- conformance profile; -- bilateral or ecosystem records when multiple principals coordinate. - -Tier 4 is not "more connectors." It is a stronger enforcement location. - -## X402 ladder - -```text -Tier 2: - customer-owned wallet gateway signs after local policy greenlight - -Tier 3: - hosted Handshake manages wallet-gateway policy, receipts, rollout, recovery, - and audit across teams - -Tier 4: - wallet provider, x402 client provider, or payment infrastructure provider - implements or certifies the gateway check before signing -``` - -## Design requirements by user type - -| User type | Tier 2 proof | Tier 3 growth | Tier 4 endpoint | -| --- | --- | --- | --- | -| Agent workflow owner | agent cannot spend directly | many workflows managed | provider runtime cannot bypass | -| Protected path owner | gateway owns signer | policy rollout and health | native provider enforcement | -| Policy owner | local deterministic policy | hosted policy distribution | provider-verifiable policy contract | -| Reviewer/auditor | local receipt timeline | retained/searchable evidence | provider attestation | -| Provider partner | clear gateway semantics | operational integration | certified enforcement | -| x402 seller | standard x402 compatibility | richer evidence intake | signed offers/receipts as evidence | - -## Smallest next mechanism - -Design Tier 2 records so every object has a Tier 3 owner and a Tier 4 -attestation path before source implementation begins. diff --git a/.planning/tier2/03-x402-architecture.md b/.planning/tier2/03-x402-architecture.md deleted file mode 100644 index 0facd48..0000000 --- a/.planning/tier2/03-x402-architecture.md +++ /dev/null @@ -1,205 +0,0 @@ -# X402 Architecture - -Status: planning scratch, revised 2026-05-19. - -## Invariant at stake - -The x402 transaction is valid Tier 2 only if the wallet gateway is the first -component that can create `PAYMENT-SIGNATURE`. If generated code can sign, the -architecture is advisory, not Handshake. - -## Role model - -```text -principal - owns intent and operating envelope - -agent runtime - generates execution evidence and proposes payment candidate - -policy owner - defines versioned local policy in Tier 2 - defines hosted policy in Tier 3 - -wallet gateway owner - owns or controls signing authority - -x402 seller - returns PAYMENT-REQUIRED and fulfills resource if payment is accepted - -facilitator - verifies/settles x402 payment for the seller when used -``` - -Authority stays with the principal's policy and wallet gateway. The seller and -facilitator provide payment-protocol evidence, not principal authority. - -## Kernel mapping - -| Kernel object | X402 mapping | Tier 3/4 continuity | -| --- | --- | --- | -| `ToolCapability` | generated request capability and raw x402/wallet reachability posture | hosted install inventory; provider runtime claims | -| `ActionType` | `x402_payment.exact` | stable action family for policy and provider profiles | -| `GatewayRegistryEntry` | customer-owned wallet gateway, custody mode, policy version | hosted gateway enrollment; provider gateway registration | -| `OperatingEnvelope` | agent, runtime, allowed resource, network, asset, gateway, budget bounds | hosted policy pack and org rollout | -| `RuntimeExecution` | generated request attempt and 402 discovery evidence | retained execution evidence | -| `GeneratedExecutionGraph` | graph node showing paid request proposal, no signer node | hosted replay and review | -| `IntentCompilationRecord` | conversion of vague intent into candidate payment | compiler quality and refusal analytics | -| `CandidateAction` | proposed exact x402 payment | candidate review and policy evaluation | -| `ActionContract` | canonical x402 V2 payment contract | stable evidence object across tiers | -| `PolicyDecision` | deterministic local/hosted decision | hosted policy distribution | -| `Greenlight` | one-use wallet-gateway-bound pass | provider-verifiable authority token | -| `GatewayCheckAttempt` | pre-signature wallet verification | provider/customer enforcement evidence | -| `MutationAttempt` | payment signature creation and paid retry | downstream operation reconciliation | -| `Receipt` | reconstructed chain and x402 evidence | retention, search, audit | -| `Refusal` | no authority/no signature evidence | policy tuning and recovery | -| `ProofGap` | missing settlement/receipt/finality/idempotency evidence | recovery and audit queue | -| `IsolationState` | future block after signer exposure or divergence | org-level containment | - -## Contract shape - -The first implementation should use generic `ActionContract.parameters`, not a -new protocol primitive. - -```yaml -actionType: x402_payment.exact -x402Version: 2 -request: - method: GET - url: https://seller.example/data - headersDigest: sha256:... - bodyDigest: null -paymentRequired: - rawHeaderDigest: sha256:... - decodedDigest: sha256:... - selectedPaymentDetailsDigest: sha256:... - scheme: exact - network: eip155:84532 - asset: usdc - maxAmountRequired: "1000" - payTo: "0x..." - resource: https://seller.example/data - facilitatorUrl: https://... - timeoutSeconds: 60 -extensions: - paymentIdentifier: - required: true - valueDigest: sha256:... - signedOffer: - posture: optional_evidence - offerDigest: sha256:... -gateway: - gatewayId: gateway_wallet_local_... - policyVersion: x402-policy-v1 - custodyMode: customer_owned - authorityHolder: wallet_gateway -idempotency: - key: x402-attempt-... - retryScopeDigest: sha256:... -evidence: - requirePaymentResponse: true - requireSettlementEvidence: true - signedReceipt: optional_evidence -``` - -Important: `maxAmountRequired` is x402 terminology. In the `exact` scheme, the -contract still represents one fixed payment requirement selected before signing. - -## Authority sequence - -```mermaid -sequenceDiagram - participant A as Agent runtime - participant K as Handshake kernel - participant P as Policy - participant G as Wallet gateway - participant S as x402 seller - participant F as Facilitator - - A->>S: request paid resource without payment - S-->>A: 402 + PAYMENT-REQUIRED - A->>K: record runtime evidence and candidate - K->>K: canonicalize ActionContract - K->>P: evaluate exact contract - P-->>K: Greenlight or Refusal - K-->>G: one-use gateway-bound greenlight - G->>K: verify contract, policy, idempotency, isolation - G->>S: retry with PAYMENT-SIGNATURE only if verified - S->>F: verify/settle when facilitator is used - F-->>S: verification/settlement evidence - S-->>G: resource or 402 + PAYMENT-RESPONSE when available - G->>K: record mutation attempt, receipt, refusal, or proof gap -``` - -## Tier 2 requirements - -Tier 2 is acceptable only when it proves: - -- generated code cannot access the signer in the protected path; -- candidate payment is exact and canonicalized; -- policy can refuse before authority exists; -- greenlight is one-use, gateway-bound, and consumed; -- wallet gateway signs only after the exact check; -- replay, mismatch, drift, and isolation refuse before signature; -- receipt distinguishes gateway check from x402 settlement/resource evidence; -- raw sibling authority is reported as unsafe posture, not silently ignored. - -## Tier 3 migration requirements - -The Tier 2 architecture must leave these migration seams intact: - -- policy pack can move from local file to hosted versioned distribution; -- receipt file can move to hosted retention without changing meaning; -- gateway registration can move to hosted enrollment without moving signing - authority into the agent; -- refusal/proof-gap records can move into hosted audit and recovery queues; -- install posture can become org-level health without claiming universal - enforcement. - -Tier 3 adds operation around the same chain. It must not create a hosted bypass -around the gateway. - -## Tier 4 migration requirements - -The Tier 4 path is provider-native or provider-certified enforcement. - -For x402 this could mean: - -- wallet provider implements the Handshake-compatible gateway check before - signing; -- x402 client provider offers a mode where payment signing calls require a - verified Handshake greenlight; -- payment infrastructure provider emits attestable evidence for settlement and - signed receipt support; -- agent runtime provider blocks raw signer access and exposes generated - execution evidence suitable for Handshake. - -Tier 4 is reached only when the provider or customer gateway can block mutation. -If it only logs after signing, it is not Tier 4. - -## Architecture decisions - -### Decision 1: x402 is a proof lens, not the product category - -Keep x402 because the signature boundary is concrete. Do not turn Tier 2 into a -payment product. - -### Decision 2: buyer-side first - -The first proof is buyer-side because the authority question is principal spend. -Seller middleware and facilitator behavior are downstream evidence. - -### Decision 3: exact scheme first - -Start with x402 V2 `exact`. Treat `upto` as a future hostile fixture because the -seller can determine actual usage after signature. - -### Decision 4: policy before operation, operation before ecosystem - -Tier 2 proves local policy and gateway enforcement. Tier 3 operates it across -orgs. Tier 4 moves enforcement into provider/customer boundaries. - -## Smallest next mechanism - -Build a fake-signing wallet gateway fixture whose records are shaped exactly as -Tier 3 hosted retention and Tier 4 provider attestation would need them. diff --git a/.planning/tier2/04-spec-and-doubt-review.md b/.planning/tier2/04-spec-and-doubt-review.md deleted file mode 100644 index 4c5c52d..0000000 --- a/.planning/tier2/04-spec-and-doubt-review.md +++ /dev/null @@ -1,195 +0,0 @@ -# Spec And Doubt Review - -Status: planning scratch, revised 2026-05-19. - -## Invariant at stake - -The design must be strong enough that a Tier 2 proof can grow into hosted and -provider-integrated Handshake without renaming local demo artifacts into product -truth. - -## Spec - -### Objective - -Design the Tier 2 x402 protected spend proof as the first self-hosted instance -of Handshake Protected Actions. - -Success means: - -- one coding-agent workflow can propose an exact x402 payment; -- the wallet gateway, not the agent, holds signing authority; -- policy can greenlight/refuse the exact payment; -- the gateway creates `PAYMENT-SIGNATURE` only after exact one-use verification; -- the resulting records are suitable for Tier 3 hosted operation and Tier 4 - provider-gateway integration. - -### Commands - -No source implementation in this packet. When implementation begins, repo canon -requires: - -```bash -npm run check:types -npm run lint -npm run test -git diff --check -``` - -Full gate: - -```bash -npm run check:repo -``` - -### Future source ownership - -Do not implement directly from this scratch packet without a follow-up source -plan. - -Expected ownership if implemented: - -- `src/runtime/x402-payment`: generated-execution evidence and candidate - proposal only; -- `src/adapters/x402-wallet-gateway`: reference wallet gateway fixture that - signs only after verified gateway check; -- `src/conformance/x402-payment`: hostile checks for replay, drift, raw signer - exposure, and proof gaps; -- `test/runtime`, `test/adapters`, `test/conformance`: focused evidence tests. - -### Code style - -Use protocol nouns that describe authority: - -```ts -recordX402PaymentCandidate(...) -proposeX402PaymentContract(...) -evaluateX402PaymentPolicy(...) -recordWalletGatewayCheck(...) -recordX402PaymentReceipt(...) -``` - -Avoid names that imply more than mechanism: - -```text -safePayment -trustedAgentPayment -approvedSpend -secureX402Fetch -proveSettlement -``` - -### Testing strategy - -The first behavioral proof should use deterministic fake signing before real -funds. - -Required hostile checks: - -- no greenlight -> no payment signature; -- wrong contract digest -> no payment signature; -- wrong gateway -> no payment signature; -- expired greenlight -> no payment signature; -- replayed greenlight -> no second signature; -- changed `PAYMENT-REQUIRED` -> no payment signature; -- active isolation -> no payment signature; -- raw signer visible to agent -> unsafe posture and refusal/quarantine; -- missing `PAYMENT-RESPONSE` -> proof gap, not success; -- `upto` offered -> refusal until final amount evidence is designed. - -### Boundaries - -Always: - -- preserve exact contract binding; -- keep signer authority out of generated code; -- record refusals and proof gaps as product outcomes; -- design records for Tier 3 retention and Tier 4 attestation. - -Ask first: - -- adding x402 dependencies; -- adding source paths; -- moving scratch planning into canon; -- running real testnet/mainnet payment flows. - -Never: - -- give generated code private keys; -- infer authority from x402 seller/facilitator evidence; -- claim hosted operation without deployment/custody/gateway proof; -- claim provider enforcement without provider/customer pre-mutation check. - -## Doubt review - -This is a degraded in-session adversarial pass, not a fresh-context or -cross-model review. Subagents and external model CLIs were not invoked in this -turn. - -### Claim: "Tier 2 x402 creates a path to Tier 3/4." - -Issue: only true if Tier 2 records already carry policy version, gateway -identity, custody mode, contract digest, idempotency posture, receipt evidence, -proof gaps, and install posture. - -Resolution: revised architecture makes Tier 3/4 continuity a design requirement, -not a follow-up. - -### Claim: "User types are addressed." - -Issue: generic personas would be theatre. User types must map to authority jobs. - -Resolution: user types are defined by protocol responsibility: workflow owner, -protected path owner, policy owner, auditor, provider partner, and x402 seller. - -### Claim: "The x402 buyer flow is enough." - -Issue: official x402 buyer docs optimize for automatic payment after 402. That -is the exact bypass risk for generated code. - -Resolution: the buyer flow is used as threat pressure. Handshake inverts it: -generated code proposes; wallet gateway signs after exact check. - -### Claim: "Tier 3 is just hosted UI." - -Issue: that repeats the prior misalignment. Hosted operation is not presentation. - -Resolution: Tier 3 is policy management, distribution, receipt retention, -search, rollout, audit, and recovery around the same authority chain. - -### Claim: "Tier 4 is more integrations." - -Issue: more integrations can still be advisory. - -Resolution: Tier 4 requires provider/customer gateway enforcement before -mutation or provider-native evidence compatible with the gateway chain. - -## Design verdict - -Keep: - -- x402 buyer-side exact payment as first proof lens; -- wallet gateway as authority holder; -- local versioned policy in Tier 2; -- Tier 3 hosted operation around the same chain; -- Tier 4 provider/customer gateway enforcement as the end state. - -Cut: - -- local adapter as product center; -- payment-product language; -- seller/facilitator ambitions; -- generic "agent commerce"; -- broad "x402 protection" claims. - -Redesign: - -- records must be migration-ready from the first Tier 2 fixture; -- user types must be responsibility types, not marketing personas; -- receipt structure must serve future retention/search/audit without changing - evidence meaning. - -## Smallest next mechanism - -Before source implementation, write the `x402_payment.exact` record contract and -conformance checklist as a Tier 2 -> Tier 3 -> Tier 4 compatibility matrix. diff --git a/.planning/tier2/README.md b/.planning/tier2/README.md deleted file mode 100644 index 7344b1e..0000000 --- a/.planning/tier2/README.md +++ /dev/null @@ -1,144 +0,0 @@ -# Tier 2 Protocol Usability And Clearing-House Research Packet - -Status: planning scratch, revised 2026-05-21 after gsd-map-codebase refresh. - -This packet records the current Tier 2/Tier 3 architecture thinking around -protocol-facing usability and the longer clearing-house thesis. It is scratch, -not repo canon. - -The important correction is that no adapter family defines the protocol shape. -`x402_payment.exact`, preview deploy, package install, and repo write are proof -profiles or reference protected action families. The product center remains a -protected action path for automated decision-making: - -```text -observed consequential attempt --> exact action contract --> policy decision --> one-use gateway-bound greenlight --> gateway check before mutation --> receipt, refusal, proof gap, isolation, or recovery evidence -``` - -The clearing-house thesis extends that same loop into a future evidence layer: - -```text -protected action path --> gateway-checked authority evidence --> local terminal AuthorityCertificate evidence --> hosted evidence navigation and policy operation --> cross-org verification and ecosystem clearing -``` - -Doctrine realignment (autoreason pass_02): [tiered-product-doctrine.md](../strategy/tiered-product-doctrine.md) v0.3.1 — protocol remains Layer 8 authority proof; adapter profiles do not become the product center. - -Crypto / signing (autoreason pass_03): [authority-certificate-foundation.md](../strategy/authority-certificate-foundation.md) — Ed25519 over `signingInput`; local `AuthorityCertificate` minting and offline pinned-key verification are now landed source behavior. Older docs **06–09** target language is historical planning context only. Do not reschedule K-D9-K-D12 as unfinished local foundation work, and do not convert local certificate verification into hosted trust, provider custody, marketplace certification, or cross-org clearing. - -Files under `.planning/` are scratch. They are not active repo canon. - -## Invariant at stake - -Tier 2 must prove the same authority chain that future hosted and -provider-integrated Handshake must preserve: - -```text -generated execution evidence --> exact action contract --> policy decision --> one-use gateway-bound greenlight --> gateway check before mutation --> receipt, refusal, proof gap, isolation, or recovery evidence -``` - -If Tier 2 only proves a local wrapper, it does not create a credible path to -Tier 3 or Tier 4. - -## Packet - -- `00-canon-alignment.md`: early canon alignment and non-claim boundaries. -- `01-source-study.md`: early source study; useful but x402-centered. -- `02-users-and-tier-pathway.md`: early Tier 2 -> Tier 3 -> Tier 4 pathway. -- `03-x402-architecture.md`: x402 adapter-family study; treat as example only. -- `04-spec-and-doubt-review.md`: early adversarial review and concerns. -- `05-t2-t3-cli-mcp-sdk-architecture-map.md`: self-hosted/hosted activation - map across CLI, MCP, SDK, gateway, and evidence surfaces. -- `06-policy-agent-management-interface-map.md`: current consolidated map for - protocol-facing metadata, challenges, requests, and evidence projections. -- `07-agentic-economy-clearing-house-research.md`: current consolidated - clearing-house research and kernel-now/kernel-needed map. -- `surfaces/`: Tier 2 activation **constitution** (P1–P12 -> MCP/CLI rules) plus - **doc 10 Agent Proof Slice** (Tier 2 activation proof over the landed authority - kernel, with x402 as the worked proof profile, hostile traces, and the current - product-level regression). Not implementation; preserves runtime - ingress as proposal evidence and keeps policy/gateway authority out of the - agent surface. - -## Current Kernel - -The current source kernel already supports the hard local primitive: - -```text -RuntimeExecution / GeneratedExecutionGraph / ToolCallDraft --> IntentCompilationRecord / CandidateAction --> ActionContract --> PolicyDecision --> one-use Greenlight or Refusal --> GatewayCheck --> MutationAttempt / Receipt / Refusal / ProofGap --> reconciliation, recovery, isolation, and redacted evidence projections -``` - -That is enough to prove local authority mechanics. It is not enough to claim a -clearing house. - -## What The Kernel Needs Next For The Vision - -The next required layer is not a new authority primitive. It is a projection and -usability layer that preserves the existing primitive: - -- `ProtectedActionMetadata`: what an automated client may propose, not - permission. -- `ProtectedActionChallenge`: structured refusal/proof-gap navigation, not - negotiation. -- `ProtectedActionRequest`: an external proposal shape that compiles into - runtime evidence and candidate action. -- `AgentTransactionEnvelope`: a redacted evidence projection/export, not - authority. -- Generic protected-path health and receipt timeline across action families, not - package-install-only diagnostics. -- Real runtime adapters, real bypass probes, and customer/provider gateway - custody before installed-path claims. -- Hosted policy management, retention, search, alerts, audit exports, and - reader authorization only in Tier 3. -- Cross-org verification, conformance marks, external verifier signatures, and - ecosystem clearing only in Tier 4. - -## Current APS proof - -`test/product/agent-proof-slice.test.ts` now proves that Tier 2 activation can -sit on the existing adapter framework without adding a protocol primitive: - -```text -generated runtime dispatch --> adapter-specific proposal helper --> generic kernel authority chain --> adapter-owned gateway check --> receipt, refusal, or proof gap --> redacted agent transaction envelope --> terminal AuthorityCertificate -``` - -x402 is the worked proof profile; package install is the non-x402 parity check. -The envelope is read-only, redacted, and unable to mint policy decisions, -greenlights, gateway checks, receipts, exports, certificates, or mutations. -The x402 lane is the official buyer-side `exact` path only: gateway-held -`PaymentPayload` / `PAYMENT-SIGNATURE` creation after `VerifiedGatewayCheck`, -with per-call spend authority and explicit cut lines around hosted/provider -custody, facilitator/seller operation, spend-window ledgers, certification, and -cross-org trust. - -## Smallest next mechanism - -Wrap the product proof in a first-protected-action walkthrough that shows the -same evidence refs without introducing CLI/MCP/hosted clearing-house surface -area. diff --git a/.planning/tier2/surfaces/10-agent-proof-slice.md b/.planning/tier2/surfaces/10-agent-proof-slice.md deleted file mode 100644 index 7b2b526..0000000 --- a/.planning/tier2/surfaces/10-agent-proof-slice.md +++ /dev/null @@ -1,519 +0,0 @@ -# Agent Proof Slice (APS) - Tier 2 Activation Proof - -Status: planning scratch, rewritten 2026-05-20. -Audience: Tier 2 implementers, runtime/gateway integrators, plan-devex-review, -plan-eng-review. -Source anchors: `AGENTS.md`, `README.md`, -`docs/internal/protocol-definition.md`, -`docs/internal/protocol-kernel-architecture.md`, -`.planning/tier2/README.md`, -`.planning/tier2/surfaces/00-surface-design-principles.md`, -`.planning/tier2/surfaces/04-v1-inventory.md`, -`.planning/tier2/06-policy-agent-management-interface-map.md`, -`.planning/codebase/CONCERNS.md`. - -This file is scratch. It is not repo canon, not a public roadmap, and not an -implementation claim. - -## Invariant at stake - -APS must prove that an automated runtime can propose consequential work without -receiving mutation authority, and that the protected gateway remains the only -place where consequence can happen. - -If APS turns into "agent payments", "approval UX", "observability", or a nice -x402 demo, it violates the product kernel. The primitive is still: - -```text -observed generated execution --> exact action contract --> policy decision --> one-use gateway-bound greenlight or refusal --> gateway check before mutation --> receipt, refusal, proof gap, isolation, or recovery evidence -``` - -## Rewrite verdict - -The previous APS draft treated x402 as the Tier 1 product proof and carried -stale blockers around route custody, invented proof scripts, and a package -install comparison that no longer matches the current kernel. Cut that framing. - -APS is now a Tier 2 activation slice over the landed local authority kernel. -x402 remains the worked proof profile because paid HTTP stresses wallet custody, -exact parameter binding, replay, downstream uncertainty, and evidence -reconstruction. It does not define the product. - -## APS thesis - -An agent runtime should be able to: - -1. Observe generated orchestration that attempts a consequential action. -2. Reduce that attempt to a catalog-bound, exact proposed action contract. -3. Receive either a contract handle or a structured refusal/challenge. -4. Hold no install authority, policy authority, gateway authority, wallet key, - mutation credential, or greenlight minting capability. -5. Read redacted evidence after policy/gateway activity. -6. Reconstruct whether the chain ended in receipt, refusal, proof gap, - isolation, or recovery. - -That is enough for a first developer-facing proof. It is not enough to claim -hosted operation, cross-org clearing, broad MCP safety, or an agentic economy -clearing house. - -## APS is not - -- Not a generic x402 payment SDK. -- Not a wallet-hosting product. -- Not an approval screen. -- Not a hosted verifier. -- Not MCP productization. -- Not a CLI product. -- Not package-install certification. -- Not a conformance mark. -- Not a claim that all agent actions are controlled. -- Not a claim that downstream business success is proven. - -## Why x402 remains the worked proof profile - -| Proof profile | Why it belongs | What it does not prove | -| --- | --- | --- | -| `x402_payment.exact` | Exercises money movement, wallet-signature custody, exact paid-HTTP parameters, replay, and downstream proof gaps. | General product scope, hosted wallet custody, session/day spend-window ledgers, provider trust, or universal payment safety. | -| `package_install.npm` | Exercises package-manager bypass, material evidence, lifecycle risk, and supply-chain regression. | Payment semantics, wallet custody, or paid-HTTP proof. | -| preview deploy / repo write | Future reference profiles for cloud/repo mutation paths. | Nothing until an installed gateway path exists. | - -x402 is the best local APS profile because payment consequence is obvious and -gateway custody is testable. It must remain a proof profile, not the product -center. - -## Current architecture snapshot - -The old APS draft had several blockers that are now false. Current source state: - -- Protocol version is `0.2.4`. -- `/v0.2/action-contracts` requires `runtime_evidence` custody. -- Runtime execution, generated graph, tool-call draft, and intent compilation - routes require `runtime_evidence` custody. -- Policy decisions, isolation, breaker decisions, recovery records, and receipt - exports are `control_plane` custody. -- Bypass probes, protected-path posture, gateway checks, and downstream - reconciliation are `gateway_custody`. -- Review artifacts and review decisions are `review_custody`. -- Evidence projections are readable by `review_custody` and `runtime_evidence`; - reads are redacted diagnostics, not authority. -- `ProtectedActionMetadata`, `ProtectedActionRequest`, - `ProtectedActionChallenge`, and `ProtectedActionEvidenceProjection` exist as - non-authority representation schemas. -- Runtime ingress supports wrapped/raw/ambiguous package-install and x402 - dispatch observations. -- The local x402 D1/HTTP proof profile covers proposal, policy, gateway check, - wallet signature after admission, replay refusal, parameter mismatch refusal, - and proof gap recording. -- `AuthorityCertificate` exists as a local terminal-evidence export. It is not - hosted trust, JWKS, revocation, provider custody, or cross-org clearing. - -## Custody matrix - -| Surface | Current custody holder | APS rule | -| --- | --- | --- | -| Tool/action/gateway catalog registration | `control_plane` | Operator/setup only. Never agent-facing authority. | -| Operating envelope registration | `control_plane` | Authorizes attempts, not mutation. | -| Runtime execution evidence | `runtime_evidence` | Agent/runtime may record what generated code attempted. | -| Generated execution graph | `runtime_evidence` | Evidence only; not permission. | -| Tool-call draft creation/transition | `runtime_evidence` | Captures generated dispatch state before contract. | -| Intent compilation | `runtime_evidence` | Emits candidate/refusal boundary; never permission. | -| Action contract proposal | `runtime_evidence` | Produces proposed exact contract; never greenlight. | -| Policy decision / greenlight | `control_plane` | Machine decision layer; greenlight is one-use and gateway-bound. | -| Review artifact / review decision | `review_custody` | Human review evidence bound to exact digests; never gateway authority. | -| Bypass probe / path posture | `gateway_custody` | Gateway-owned protected-path evidence. | -| Gateway check | `gateway_custody` | Final enforcement point before mutation. | -| Surface operation reconciliation | `gateway_custody` | Downstream observation only; no fresh authority. | -| Evidence projection reads | `review_custody` or `runtime_evidence` | Redacted reconstruction only. | - -An APS agent must not be able to call install, policy, greenlight, gateway -check, reconcile, isolation, or receipt-export transitions. - -## The APS happy path - -```text -operator/control_plane: - register tool catalog, action catalog, gateway registry, envelope - -gateway/gateway_custody: - record bypass probes and protected-path posture - -runtime/runtime_evidence: - observe generated x402 dispatch block - create runtime execution evidence - create generated execution graph - create/finalize tool-call draft - compile intent - propose action contract - -control_plane: - evaluate policy - record one-use greenlight or refusal - -gateway/gateway_custody: - verify exact greenlight binding - only then create wallet payment signature / mutation attempt - emit receipt or proof gap - reconcile downstream state if available - -runtime or reviewer: - read redacted evidence projections - optionally verify a local terminal AuthorityCertificate -``` - -The magical developer moment is not "the payment succeeds". It is seeing that -the agent can propose a paid action and read evidence, but the wallet signature -only appears after gateway admission against the exact contract. - -## Developer target - -Primary persona: runtime or gateway engineer integrating Handshake into an -engineering-agent stack. - -Their job is not to become a Handshake protocol expert. Their job is: - -```text -wrap one consequential path --> observe generated dispatch --> propose exact contract --> let policy/gateway own authority --> read reconstructable evidence -``` - -APS is successful when this engineer can explain four things without reading -internal state-machine code: - -1. What generated action was attempted. -2. Why the runtime could propose but not execute. -3. Where the gateway enforced exact authority. -4. What evidence survives if the action is refused, replayed, mismatched, or - downstream proof is missing. - -Target time-to-first-hard-proof for a future public flow: under 10 minutes from -clone/install to a local x402 contract, refusal/proof-gap, receipt timeline, and -terminal evidence verification. The current repo has tests and source APIs, not -yet that public developer command. - -## Public APS shape - -APS should expose four safe surfaces over the current kernel. - -| Surface | Purpose | Non-authority rule | -| --- | --- | --- | -| `ProtectedActionMetadata` | Tell an automated client what it may propose and what evidence/policy shape applies. | Must include `authorityCreated: false`, no greenlight, no gateway check, no mutation. | -| `ProtectedActionRequest` | External proposal envelope that compiles into runtime evidence and candidate action. | Must not bypass intent compilation or canonicalization. | -| `ProtectedActionChallenge` | Structured refusal/proof-gap navigation. | Must not negotiate authority or hide mutation ambiguity. | -| `ProtectedActionEvidenceProjection` / agent transaction envelope | Redacted reconstruction of graph, contract, receipt, idempotency, posture, and proof gaps. | Must never include raw internal records, mutation commands, secrets, or fresh authority. | - -`AuthorityCertificate` can be shown as an optional terminal evidence export once -there is a terminal receipt/refusal/proof-gap/isolation/recovery state. It must -not become a cross-org trust claim in APS. - -## Canonical local x402 request shape - -The APS x402 request should be a representation over the current adapter input, -not a new authority primitive: - -```json -{ - "schemaVersion": "0.2.4", - "tenantId": "tenant_demo", - "organizationId": "org_demo", - "createdAt": "2026-05-20T00:00:00.000Z", - "requestId": "req_x402_demo", - "metadataRef": "pam_x402_demo", - "principalIntentRef": "intent_upgrade_staging", - "generatedCodeOrSpecRef": "codeblock_x402_001", - "runtimeExecutionId": "runexec_001", - "generatedExecutionGraphId": "graph_001", - "generatedExecutionNodeId": "node_001", - "toolCallDraftId": "draft_001", - "actionClass": "x402_payment.exact", - "resourceRef": "x402:https://api.example.test/paid-report:base-sepolia:0xpayee", - "parameters": { - "endpointUrl": "https://api.example.test/paid-report", - "payee": "0xpayee", - "network": "base-sepolia", - "token": "USDC", - "atomicAmount": "1000", - "paymentRequirementsDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "facilitatorRef": "facilitator:local" - }, - "nonSecretParamsSummary": { - "endpointUrl": "https://api.example.test/paid-report", - "payee": "0xpayee", - "network": "base-sepolia", - "token": "USDC", - "atomicAmount": "1000", - "paymentRequirementsDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "facilitatorRef": "facilitator:local" - }, - "secretRefs": {}, - "idempotencyKey": "x402-payment:demo", - "evidenceRefs": ["evidence:x402-payment-required:aaaaaaaaaaaaaaaa"], - "requestedAt": "2026-05-20T00:00:00.000Z", - "authorityCreated": false, - "greenlightRef": null, - "gatewayCheckRef": null, - "mutationAttemptRef": null -} -``` - -The corresponding runtime dispatch observation is narrower and belongs to -runtime ingress: - -```json -{ - "principalIntentRef": "intent_upgrade_staging", - "generatedCodeOrSpecRef": "codeblock_x402_001", - "dispatchBoundaryRef": "runtime-adapter:demo", - "graphNonce": "nonce-demo-001", - "truncationStatus": "complete", - "unobservedRegionRefs": [], - "dispatches": [ - { - "dispatchKind": "wrapped_x402_payment", - "dispatchRef": "dispatch_x402_001", - "generatedCodeOrSpecRef": "codeblock_x402_001", - "dynamicToolConstructionDetected": false, - "lateBoundParameterRefs": [], - "retryOfDispatchRef": null, - "branchRef": null, - "loopIteration": null, - "endpointUrl": "https://api.example.test/paid-report", - "payee": "0xpayee", - "network": "base-sepolia", - "token": "USDC", - "atomicAmount": "1000", - "paymentRequirementsDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "facilitatorRef": "facilitator:local", - "evidenceRefs": ["evidence:x402-payment-required:aaaaaaaaaaaaaaaa"] - } - ], - "evidenceRefs": ["evidence:runtime-transcript:demo"] -} -``` - -These shapes can propose. They cannot evaluate policy, mint a greenlight, run a -gateway check, sign a payment, or mutate a protected surface. - -## Challenge shape - -APS must make refusal and proof gap first-class. Example: - -```json -{ - "schemaVersion": "0.2.4", - "tenantId": "tenant_demo", - "organizationId": "org_demo", - "createdAt": "2026-05-20T00:00:00.000Z", - "challengeId": "challenge_x402_amount_bound", - "phase": "compilation", - "actionContractRef": null, - "refusedObjectRef": "dispatch_x402_001", - "proofGapRef": null, - "reasonCode": "x402_amount_exceeds_call_bound", - "retryability": "terminal", - "commitState": "not_started", - "mutationAttempted": false, - "rawInternalRecordIncluded": false, - "evidenceRefs": ["evidence:x402-payment-required:aaaaaaaaaaaaaaaa"], - "nextStepKind": "recraft_request", - "authorityCreated": false, - "greenlightRef": null, - "gatewayCheckRef": null, - "mutationAttemptRef": null -} -``` - -If downstream payment confirmation is missing after a gateway-admitted attempt, -the challenge/projection must say proof gap. It must not imply downstream -business success. - -## Hostile trace catalog - -APS must preserve these hostile cases as product-facing evidence, even if the -implementation uses existing tests underneath. - -| Case | Required APS outcome | Current anchor | -| --- | --- | --- | -| Agent tries to propose with `control_plane` token | Rejected as wrong custody; proposal is runtime evidence only. | `test/http/http.test.ts` | -| Agent tries to call policy/gateway routes | Rejected as wrong custody. | `test/http/http.test.ts` | -| Wrapped x402 call within bound | Produces runtime evidence and proposed contract only. | `test/runtime/runtime-ingress.test.ts` | -| x402 amount above `maxAtomicAmountPerCall` | Candidate refusal/challenge, no contract. | `src/adapters/x402-payment/action-proposal.ts` | -| Raw sibling x402 payment path | Refusal/challenge or bypass evidence, no greenlight. | `test/runtime/runtime-ingress.test.ts` | -| Ambiguous x402 dispatch | Refusal/challenge, no greenlight. | `test/runtime/runtime-ingress.test.ts` | -| Dynamic tool construction / late-bound parameter refs | Captured as uncertainty; must not silently contract. | `src/runtime/ingress/index.ts` | -| Gateway receives mismatched params | Refusal before wallet signature. | `test/integration/x402-d1-http.test.ts` | -| Greenlight replay | Rejected; no second mutation. | `test/integration/x402-d1-http.test.ts` | -| Downstream proof missing | Proof gap, not receipt theatre. | `test/integration/x402-d1-http.test.ts` | -| Evidence read attempts to expose internals | Redacted projection only. | `test/protocol/representation-contract.test.ts` | -| Terminal evidence certificate tampered | Verification fails. | `test/protocol/authority-certificate.test.ts` | - -## Plan-eng review - -Brutal verdict: keep the slice and narrow the claim. The product-level proof now -exists; the next work is a walkthrough over that proof before any CLI/MCP -surface. - -Execution concerns: - -- Do not build a new control plane for APS. -- Do not add a second x402 adapter path. -- Do not invent `prove:*` scripts that create new authority. A wrapper may only - run or explain the existing product proof. -- Do not expose policy, gateway, install, receipt export, or internal store - APIs to the agent. -- Do not let `ProtectedActionRequest` bypass runtime evidence or intent - compilation. -- Do not let evidence projection reads become raw record reads. -- Do not claim session/day/review spend-window enforcement. Current local - x402 bounds prove atomic amount per call. -- Do not claim hosted gateway custody, provider custody, JWKS, revocation, or - cross-org clearing. - -Completed implementation path: - -1. `test/product/agent-proof-slice.test.ts` stitches x402 runtime ingress, - proposal, policy, gateway, evidence projection, and terminal certificate - verification. -2. Runtime custody can propose and read redacted evidence only. -3. Gateway, policy, wallet, and certificate authority remain outside runtime - custody. -4. Mismatch, replay, raw sibling dispatch, and proof gap produce refusal, - challenge, or evidence, not fake receipts. -5. The next implementation surface may wrap that proof for developer - understanding, but it must not create a new mutation path. - -## Plan-devex review - -Brutal verdict: APS is understandable only if the first developer experience is -"watch authority stay out of the runtime", not "make an x402 payment". - -Developer-facing assets should be ordered like this: - -1. Existing source-owned product regression. -2. One-page local proof walkthrough over that regression. -3. One minimal read-only command wrapping that regression. -4. Optional MCP/SDK convenience after the proof is already stable. - -The first screen or walkthrough must show: - -- observed generated dispatch; -- exact action contract digest; -- policy outcome; -- gateway check outcome; -- payment signature or refusal/proof gap; -- redacted evidence projection; -- terminal certificate verification if terminal evidence exists. - -The walkthrough must not hide: - -- which custody role made each transition; -- that the agent never receives wallet/gateway authority; -- that evidence reads are not execution authority; -- that x402 is only the worked proof profile; -- that hosted/cross-org claims are future. - -## Acceptance tests - -The APS implementation should not duplicate every low-level invariant. It should -compose the source-owned tests into one product story. - -| Layer | Existing proof | APS status | -| --- | --- | --- | -| Route custody | `test/http/http.test.ts` | Covered for role boundaries; APS product proof additionally asserts runtime cannot use authority. | -| Runtime ingress | `test/runtime/runtime-ingress.test.ts` | Covered directly and composed through product proof. | -| x402 D1/HTTP | `test/integration/x402-d1-http.test.ts` | Covered directly; product proof shows signer evidence only after gateway check. | -| Representation | `test/protocol/representation-contract.test.ts` | Covered as non-authority shape; product proof uses redacted envelope projection. | -| Authority certificate | `test/protocol/authority-certificate.test.ts` | Covered directly and composed through product proof as local terminal evidence only. | -| Adapter-backed APS | `test/product/agent-proof-slice.test.ts` | Current product proof: x402 plus package-install parity share the same generic authority/evidence spine. | -| Claim boundary | `test/architecture/claim-boundary.test.ts` | Covered for local/per-call x402 and non-hosted, non-provider, non-cross-org language. | - -## Evidence requirements - -APS remains green only while the product-level proof leaves these reconstructable -references: - -- runtime execution id; -- generated execution graph id; -- tool-call draft id; -- intent compilation id; -- candidate action id or refusal/challenge id; -- action contract id when proposed; -- policy decision id; -- greenlight id only when policy admits; -- gateway check id only when gateway attempts; -- mutation attempt id only when mutation is attempted; -- receipt id when evidence is sufficient; -- proof gap id when evidence is missing or downstream state is ambiguous; -- terminal certificate id only for terminal evidence exports. - -Any missing link is either a refusal or a proof gap. It is not a TODO comment in -the receipt. - -## Product non-claims - -APS must explicitly refuse these claims: - -- "Handshake secures x402 payments" - false. It proves one local protected x402 - path. -- "Handshake is agent auth" - false. It separates principal authority, runtime - evidence, policy, and gateway custody. -- "The agent approved a payment" - false. The agent proposed an exact action; - policy and gateway admitted or refused it. -- "The receipt proves the business outcome" - false unless downstream evidence - exists and is bound. -- "The review screen authorized execution" - false unless it is bound to exact - contract/policy digests and the gateway enforces the greenlight. -- "The certificate proves ecosystem trust" - false in APS. Local terminal - certificate verification is not hosted trust or cross-org clearing. - -## Future surfaces after APS - -Only after the product-level APS proof remains green: - -- SDK wrapper for `ProtectedActionMetadata`, `ProtectedActionRequest`, - `ProtectedActionChallenge`, and redacted evidence projections. -- MCP read/propose surface that follows the v1 inventory and excludes install, - policy, gateway, and mutation tools. -- CLI wrapper for the local proof flow. -- Generic transaction-envelope projection across x402 and package-install. -- Hosted evidence navigation in Tier 3. -- Cross-org verification and clearing-house trust in Tier 4. - -## Current product proof - -`test/product/agent-proof-slice.test.ts` now proves the adapter-backed APS spine: - -```text -generated runtime dispatch --> adapter-specific proposal helper --> generic kernel authority chain --> adapter-owned gateway check --> receipt / refusal / proof gap --> redacted agent transaction envelope projection --> terminal AuthorityCertificate -``` - -The test keeps x402 as the worked proof profile, verifies raw bypass, -parameter-mismatch, replay, and proof-gap branches, and includes package-install -parity to prevent the product proof from becoming payment-specific. - -## Smallest next mechanism - -Add a first-protected-action walkthrough that wraps the product proof without -creating new authority surface: - -```text -run the APS product proof -inspect the generated dispatch, contract, gateway check, envelope, and certificate refs -show that runtime custody could propose/read evidence but could not install, policy, gateway, sign, mutate, or export -``` - -Do that before building any APS CLI, MCP surface, dashboard, hosted verifier, or -clearing-house language. From 525fb7701c8c0e9b68176c297150a5fd00dd01b5 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Mon, 25 May 2026 21:17:12 +0800 Subject: [PATCH 014/144] Add tier 1 projection guardrails --- docs/internal/protocol-notes.md | 10 ++ docs/internal/service-workflow-story.md | 17 ++ src/mcp/x402-proposal.ts | 23 ++- .../areas/credential-custody/transitions.ts | 15 ++ src/protocol/foundation/reason-codes.ts | 1 + .../service-workflow-admission/index.ts | 73 ++++++++ test/architecture/active-vocabulary.test.ts | 20 +++ .../workflow-admission-boundary.test.ts | 151 +++++++++++++++++ test/mcp/mcp-schema-contract.test.ts | 36 ++++ test/mcp/mcp-x402-proposal.test.ts | 37 ++++- test/protocol/credential-custody.test.ts | 156 +++++++++++++++++- 11 files changed, 533 insertions(+), 6 deletions(-) diff --git a/docs/internal/protocol-notes.md b/docs/internal/protocol-notes.md index e65456f..7d73875 100644 --- a/docs/internal/protocol-notes.md +++ b/docs/internal/protocol-notes.md @@ -30,6 +30,11 @@ protected-action clearance -> terminal outcome`. Passport, admission, and handle records are evidence/readback context; they are not identity, policy, greenlight, gateway check, mutation permission, receipt export, terminal certificate, or reusable auth. +- `PrincipalAgentLink` and `ServiceWorkflowContextRefs` are product projection + contracts, not protocol authority primitives. They may provide setup evidence + and proposal metadata, but they cannot approve spend, widen an envelope, + satisfy delegated authority, perform a gateway check, or replace a fresh + exact action contract. - The certificate is terminal evidence, not permission, identity, settlement, hosted trust, or reusable auth. - Public npm availability does not create authority. MCP Registry @@ -132,6 +137,11 @@ Protocol areas may depend on foundation/events/context/store and other area publ - `catalog-envelope`: declared tool, action, gateway, and envelope records; catalog presence is not authorization. Envelopes may carry provider-neutral participant identity bindings, but those bindings are evidence-only links to the opaque principal/agent refs. - `delegated-authority`: redacted principal/agent/runtime/envelope/gateway scoped attempt-authority refs; registering a ref records bounds and evidence expectations only, and creates no policy decision, greenlight, gateway check, mutation authority, or receipt. Revocation and expiry are separate status-transition evidence that creates `authority_ref` isolation without mutating the original ref. - `credential-custody`: opaque gateway credential refs, redacted gateway custody proof packets, and post-gate resolution evidence; no provider clients or secret retrieval API. + Customer or provider gateway custody claims require official external + verification, current custody and resolver posture, time-bounded lease or + rotation evidence, attestation evidence, redaction success, and no raw + credential or payment material. Fixture-local custody remains local proof and + cannot satisfy `customer_gateway_evidence`. - `runtime-evidence`: generated execution evidence; evidence can propose but cannot authorize. - `generated-execution-graph`: normalized generated-code/spec evidence and action candidates. - `tool-call-draft`: opened, streaming, finalized, invalid, or abandoned generated tool-call input state. diff --git a/docs/internal/service-workflow-story.md b/docs/internal/service-workflow-story.md index bcb72ea..4fe4a83 100644 --- a/docs/internal/service-workflow-story.md +++ b/docs/internal/service-workflow-story.md @@ -52,6 +52,18 @@ mintsTerminalCertificate: false freshActionContractRequired: true ``` +The source contract for carrying those five fields is +`ServiceWorkflowContextRefsSchema`. MCP may accept that object as proposal +metadata for one fresh x402 contract. SDK, HTTP, runtime, package-root, and +protocol-public surfaces must not accept that schema as permission or as an +authority shortcut unless a separate package-surface decision and proof gate +are opened. + +`PrincipalAgentLink` is also evidence-only. It may help a hosted service record +which principal scoped which agent for a tenant, organization, project, or +workspace. It is not a bearer credential, reusable auth, spend approval, policy +decision, greenlight, gateway check, receipt, or envelope-widening authority. + ## Protected Action Boundary A service can admit standing evidence into a workflow context. That is still @@ -96,3 +108,8 @@ permission. A new protected action requires a new exact contract. - Do not claim hosted operation, provider custody, settlement finality, marketplace trust, broad runtime containment, or cross-org trust from this surface. +- Do not claim customer gateway custody from local fixture evidence. + `customer_gateway_evidence` requires official external verification, current + custody and resolver posture, lease/rotation or equivalent time-bounded + evidence, attestation evidence, redaction success, and no raw payment or + credential material. diff --git a/src/mcp/x402-proposal.ts b/src/mcp/x402-proposal.ts index b77d401..9fbe245 100644 --- a/src/mcp/x402-proposal.ts +++ b/src/mcp/x402-proposal.ts @@ -1,5 +1,10 @@ import { z } from "zod"; import type { RuntimeClient } from "../sdk/surface-clients"; +import { + ServiceWorkflowContextRefsSchema, + serviceWorkflowContextCorrelationRef, + serviceWorkflowContextEvidenceRefs, +} from "../surfaces/service-workflow-admission"; import { mcpActionContractProposedOutcome, mcpNonContractOutcome, mcpToolResult, type McpToolResult } from "./output"; import { digestMcp, type McpJsonValue } from "./digest"; @@ -102,6 +107,7 @@ export const McpX402PaymentProposalInputSchema = z.strictObject({ retryDetected: z.boolean().default(false), branchDetected: z.boolean().default(false), correlationRef: McpRefSchema.nullable().default(null), + serviceWorkflowContextRefs: ServiceWorkflowContextRefsSchema.optional(), }); export type McpX402PaymentProposalInput = z.input; @@ -366,6 +372,7 @@ async function proposeContract( input.paymentRequiredEvidenceRef, trustedBinding.gatewayReadinessRef, trustedBinding.policyVersionRef, + ...serviceWorkflowEvidenceRefs(input), ...delegatedAuthorityEvidenceRefs(input), ]); const executionBlockDigest = await digestMcp({ @@ -380,6 +387,7 @@ async function proposeContract( providerEnvironmentRef: input.providerEnvironmentRef, selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, selectedPaymentRequirementDigest: input.selectedPaymentRequirementDigest, + serviceWorkflowContextRefs: input.serviceWorkflowContextRefs ?? null, gatewayReadinessDigest: trustedBinding.gatewayReadinessDigest, policyVersionDigest: trustedBinding.policyVersionDigest, }); @@ -476,7 +484,7 @@ async function proposeContract( purposeCode: "x402_paid_request", expectedSideEffectCodes: ["x402_payment_signature_created"], evidenceRefs, - clearingEvidenceRefs: input.correlationRef ? { correlationRef: input.correlationRef } : {}, + clearingEvidenceRefs: clearingEvidenceRefs(input), bounds: { endpointDomain: new URL(input.endpointUrl).hostname, payee: input.payee, @@ -580,6 +588,18 @@ async function proposeContract( ); } +function serviceWorkflowEvidenceRefs(input: ParsedMcpX402PaymentProposalInput): string[] { + return input.serviceWorkflowContextRefs ? serviceWorkflowContextEvidenceRefs(input.serviceWorkflowContextRefs) : []; +} + +function clearingEvidenceRefs(input: ParsedMcpX402PaymentProposalInput): { correlationRef?: string } { + if (input.correlationRef) return { correlationRef: input.correlationRef }; + if (input.serviceWorkflowContextRefs) { + return { correlationRef: serviceWorkflowContextCorrelationRef(input.serviceWorkflowContextRefs) }; + } + return {}; +} + async function deriveMcpX402IdempotencyKey( input: ParsedMcpX402PaymentProposalInput, trustedBinding: McpTrustedProposalBinding | null, @@ -612,6 +632,7 @@ async function deriveMcpX402IdempotencyKey( paymentRequirementsDigest: input.paymentRequirementsDigest, selectedPaymentRequirementIndex: input.selectedPaymentRequirementIndex, selectedPaymentRequirementDigest: input.selectedPaymentRequirementDigest, + serviceWorkflowContextRefs: input.serviceWorkflowContextRefs ?? null, delegatedAuthorityRefId: input.delegatedAuthorityBinding.delegatedAuthorityRefId, delegatedAuthorityRefDigest: input.delegatedAuthorityBinding.delegatedAuthorityRefDigest, delegatedAuthorityPolicyPackRef: input.delegatedAuthorityBinding.policyPackRef, diff --git a/src/protocol/areas/credential-custody/transitions.ts b/src/protocol/areas/credential-custody/transitions.ts index 135d9f6..9b93344 100644 --- a/src/protocol/areas/credential-custody/transitions.ts +++ b/src/protocol/areas/credential-custody/transitions.ts @@ -461,6 +461,21 @@ function assertCustodyProofPacketContext(context: CustodyProofPacketContext): vo 409, ); } + if ( + input.custodyClaimLevel !== "local_fixture" && + (!input.leaseRef || + !input.leaseVersion || + !input.leaseIssuedAt || + !input.leaseExpiresAt || + input.attestationRefs.length === 0 || + input.attestationDigests.length === 0) + ) { + throw new HandshakeProtocolError( + "gateway_custody_proof_customer_evidence_missing", + "Customer/provider custody proof requires current lease and attestation evidence.", + 409, + ); + } if (input.custodyDriftStatus !== "current" || input.resolverDriftStatus !== "current") { throw new HandshakeProtocolError( "gateway_custody_proof_drifted", diff --git a/src/protocol/foundation/reason-codes.ts b/src/protocol/foundation/reason-codes.ts index 7713890..d4ab122 100644 --- a/src/protocol/foundation/reason-codes.ts +++ b/src/protocol/foundation/reason-codes.ts @@ -123,6 +123,7 @@ export const protocolReasonCodes = [ code("gateway_custody_proof_bypass_probe_mismatch", "transition_error", "credential_custody"), code("gateway_custody_proof_external_verification_required", "transition_error", "credential_custody"), code("gateway_custody_proof_fixture_cannot_claim_customer_custody", "transition_error", "credential_custody"), + code("gateway_custody_proof_customer_evidence_missing", "transition_error", "credential_custody"), code("gateway_custody_proof_drifted", "transition_error", "credential_custody"), code("gateway_custody_proof_redaction_failed", "transition_error", "credential_custody"), diff --git a/src/surfaces/service-workflow-admission/index.ts b/src/surfaces/service-workflow-admission/index.ts index d667950..dda078f 100644 --- a/src/surfaces/service-workflow-admission/index.ts +++ b/src/surfaces/service-workflow-admission/index.ts @@ -3,6 +3,7 @@ import { z } from "zod"; const sha256DigestSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/); export const serviceWorkflowAdmissionSchemaVersion = "handshake.service-workflow-admission.v0.1" as const; +export const principalAgentLinkSchemaVersion = "handshake.principal-agent-link.v0.1" as const; export const serviceWorkflowClaimStatuses = ["accepted", "refused", "stale", "proof_gap", "quarantined"] as const; @@ -52,6 +53,53 @@ export const serviceWorkflowAuthorityBoundary = { freshActionContractRequired: true, } as const satisfies ServiceWorkflowAuthorityBoundary; +export const ServiceWorkflowContextRefsSchema = z.strictObject({ + passportPackageDigest: sha256DigestSchema, + passportPresentationId: z.string().min(1), + admissionId: z.string().min(1), + serviceWorkflowHandleId: z.string().min(1), + serviceWorkflowHandleDigest: sha256DigestSchema, +}); + +export type ServiceWorkflowContextRefs = z.infer; + +export const PrincipalAgentLinkSchema = z.strictObject({ + schemaVersion: z.literal(principalAgentLinkSchemaVersion), + principalAgentLinkId: z.string().min(1), + principalAgentLinkDigest: sha256DigestSchema, + tenantId: z.string().min(1), + organizationId: z.string().min(1), + projectId: z.string().min(1).nullable(), + workspaceId: z.string().min(1).nullable(), + principalId: z.string().min(1), + agentId: z.string().min(1), + principalSubjectDigest: sha256DigestSchema, + agentSubjectDigest: sha256DigestSchema, + authProviderRef: z.string().min(1), + linkEvidenceRefs: z.array(z.string().min(1)), + scopeRefs: z.array(z.string().min(1)), + issuedAt: z.string().datetime({ offset: true }), + expiresAt: z.string().datetime({ offset: true }).nullable(), + revokedAt: z.string().datetime({ offset: true }).nullable(), + authorityBoundary: ServiceWorkflowAuthorityBoundarySchema, + createsAuthority: z.literal(false), + createsPolicyDecision: z.literal(false), + createsGreenlight: z.literal(false), + performsGatewayCheck: z.literal(false), + permitsMutation: z.literal(false), + exportsReceipt: z.literal(false), + mintsTerminalCertificate: z.literal(false), + containsCredentialMaterial: z.literal(false), + containsPaymentMaterial: z.literal(false), + widensOperatingEnvelope: z.literal(false), + isReusableAuth: z.literal(false), + isGatewayBinding: z.literal(false), + freshActionContractRequired: z.literal(true), + allowedUse: z.literal("scoped_evidence_for_envelope_setup_and_readback_only"), +}); + +export type PrincipalAgentLink = z.infer; + export const ServiceWorkflowClaimResultSchema = z.strictObject({ claimRef: z.string().min(1), claimDigest: sha256DigestSchema.nullable(), @@ -115,3 +163,28 @@ export type ServiceWorkflowAdmission = z.infer { it("keeps stale receiver vocabulary out of active docs, commands, migrations, and code", async () => { @@ -45,6 +48,23 @@ describe("active vocabulary guard", () => { expect(violations).toEqual([]); }); + + it("keeps badge vocabulary constrained to anti-authority warnings", async () => { + const files = await activeFiles(); + const violations: string[] = []; + + for (const file of files) { + const text = await readFile(join(ROOT, file), "utf8"); + const lines = text.split("\n"); + for (const [index, line] of lines.entries()) { + if (BADGE_AUTHORITY_PATTERN.test(line) && !BADGE_ALLOWED_CONTEXT_PATTERN.test(line)) { + violations.push(`${file}:${index + 1}: badge language lacks anti-authority context`); + } + } + } + + expect(violations).toEqual([]); + }); }); async function activeFiles(): Promise { diff --git a/test/architecture/workflow-admission-boundary.test.ts b/test/architecture/workflow-admission-boundary.test.ts index 066c218..57b4093 100644 --- a/test/architecture/workflow-admission-boundary.test.ts +++ b/test/architecture/workflow-admission-boundary.test.ts @@ -2,8 +2,12 @@ import { describe, expect, it } from "bun:test"; import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; import { join, relative } from "node:path"; import { + PrincipalAgentLinkSchema, ServiceWorkflowAdmissionSchema, + ServiceWorkflowContextRefsSchema, ServiceWorkflowHandleSchema, + serviceWorkflowContextEvidenceRefs, + serviceWorkflowContextRefFromHandle, serviceWorkflowNonAuthorityBoundary, } from "../../src/surfaces/service-workflow-admission"; @@ -18,6 +22,8 @@ const forbiddenAuthorityRoots = ["src/protocol/areas", "src/adapters", "src/runt const workflowSurfaceNames = [ "ServiceWorkflowAdmission", "ServiceWorkflowHandle", + "PrincipalAgentLink", + "ServiceWorkflowContextRefs", "serviceWorkflowHandleId", "serviceWorkflowHandleDigest", "passportPackageDigest", @@ -47,6 +53,81 @@ describe("service workflow admission boundary", () => { expect(admission.runtimePosture[0]?.nativeContainmentClaimed).toBe(false); }); + it("defines service workflow context refs as exact proposal metadata, not authority", () => { + const admission = ServiceWorkflowAdmissionSchema.parse(validAdmission()); + const contextRefs = ServiceWorkflowContextRefsSchema.parse( + serviceWorkflowContextRefFromHandle(admission.serviceWorkflowHandle), + ); + + expect(Object.keys(contextRefs).sort()).toEqual( + [ + "admissionId", + "passportPackageDigest", + "passportPresentationId", + "serviceWorkflowHandleDigest", + "serviceWorkflowHandleId", + ].sort(), + ); + expect(contextRefs).toEqual({ + passportPackageDigest: admission.passportPackageDigest, + passportPresentationId: admission.passportPresentationId, + admissionId: admission.admissionId, + serviceWorkflowHandleId: admission.serviceWorkflowHandle.serviceWorkflowHandleId, + serviceWorkflowHandleDigest: admission.serviceWorkflowHandle.serviceWorkflowHandleDigest, + }); + expect(serviceWorkflowContextEvidenceRefs(contextRefs)).toEqual([ + `service-workflow-context:passport-package:${admission.passportPackageDigest}`, + `service-workflow-context:presentation:${admission.passportPresentationId}`, + `service-workflow-context:admission:${admission.admissionId}`, + `service-workflow-context:handle:${admission.serviceWorkflowHandle.serviceWorkflowHandleId}`, + `service-workflow-context:handle-digest:${admission.serviceWorkflowHandle.serviceWorkflowHandleDigest}`, + ]); + + for (const authorityField of [ + "policyDecisionRef", + "greenlightRef", + "gatewayCheckRef", + "receiptRef", + "authorityCertificateRef", + "gatewayCredentialRef", + "paymentPayloadRef", + ]) { + expect(ServiceWorkflowContextRefsSchema.safeParse({ ...contextRefs, [authorityField]: "x" }).success).toBe(false); + } + }); + + it("defines principal-agent links as scoped evidence, not reusable auth", () => { + const link = PrincipalAgentLinkSchema.parse(validPrincipalAgentLink()); + + expect(link).toMatchObject({ + principalAgentLinkId: "principal-agent-link-1", + tenantId: "tenant_demo", + organizationId: "org_demo", + projectId: "project_demo", + workspaceId: "workspace_demo", + principalId: "principal_demo", + agentId: "agent_demo", + authorityBoundary: serviceWorkflowNonAuthorityBoundary(), + allowedUse: "scoped_evidence_for_envelope_setup_and_readback_only", + freshActionContractRequired: true, + }); + expect(link.createsAuthority).toBe(false); + expect(link.isReusableAuth).toBe(false); + + for (const authorityField of [ + "policyDecisionRef", + "greenlightRef", + "gatewayCheckRef", + "receiptRef", + "gatewayCredentialRef", + "paymentApprovalRef", + ]) { + expect(PrincipalAgentLinkSchema.safeParse({ ...link, [authorityField]: "x" }).success).toBe(false); + } + expect(PrincipalAgentLinkSchema.safeParse({ ...link, createsAuthority: true }).success).toBe(false); + expect(PrincipalAgentLinkSchema.safeParse({ ...link, isReusableAuth: true }).success).toBe(false); + }); + it("rejects attempts to turn admission or handle fields into authority", () => { const admission = validAdmission(); @@ -83,6 +164,32 @@ describe("service workflow admission boundary", () => { for (const file of walkTs(root)) { const text = readFileSync(file, "utf8"); for (const name of workflowSurfaceNames) { + if (name === "ServiceWorkflowContextRefs" && relative(process.cwd(), file) === "src/mcp/x402-proposal.ts") { + continue; + } + if (text.includes(name)) violations.push(`${relative(process.cwd(), file)} mentions ${name}`); + } + } + } + + expect(violations.sort()).toEqual([]); + }); + + it("keeps service workflow context schemas off SDK, HTTP, runtime, root, and protocol-public surfaces", () => { + const guardedRoots = ["src/http", "src/sdk", "src/runtime", "src/protocol/public", "src/index.ts", "package.json"]; + const schemaNames = [ + "PrincipalAgentLinkSchema", + "ServiceWorkflowContextRefsSchema", + "serviceWorkflowContextRefFromHandle", + "serviceWorkflowContextEvidenceRefs", + "serviceWorkflowContextCorrelationRef", + ]; + const violations: string[] = []; + + for (const root of guardedRoots) { + for (const file of walkTsOrConfig(root)) { + const text = readFileSync(file, "utf8"); + for (const name of schemaNames) { if (text.includes(name)) violations.push(`${relative(process.cwd(), file)} mentions ${name}`); } } @@ -153,6 +260,43 @@ function validAdmission() { }; } +function validPrincipalAgentLink() { + return { + schemaVersion: "handshake.principal-agent-link.v0.1", + principalAgentLinkId: "principal-agent-link-1", + principalAgentLinkDigest: sixthDigest, + tenantId: "tenant_demo", + organizationId: "org_demo", + projectId: "project_demo", + workspaceId: "workspace_demo", + principalId: "principal_demo", + agentId: "agent_demo", + principalSubjectDigest: digest, + agentSubjectDigest: secondDigest, + authProviderRef: "auth-provider:clerk", + linkEvidenceRefs: ["evidence:principal-agent-link:setup"], + scopeRefs: ["scope:org:project:workspace"], + issuedAt: "2026-05-25T09:00:00.000Z", + expiresAt: "2026-05-25T10:00:00.000Z", + revokedAt: null, + authorityBoundary: serviceWorkflowNonAuthorityBoundary(), + createsAuthority: false, + createsPolicyDecision: false, + createsGreenlight: false, + performsGatewayCheck: false, + permitsMutation: false, + exportsReceipt: false, + mintsTerminalCertificate: false, + containsCredentialMaterial: false, + containsPaymentMaterial: false, + widensOperatingEnvelope: false, + isReusableAuth: false, + isGatewayBinding: false, + freshActionContractRequired: true, + allowedUse: "scoped_evidence_for_envelope_setup_and_readback_only", + }; +} + function walkTs(root: string): string[] { if (!existsSync(root)) return []; const stat = statSync(root); @@ -169,3 +313,10 @@ function walkTs(root: string): string[] { } return files; } + +function walkTsOrConfig(root: string): string[] { + if (!existsSync(root)) return []; + const stat = statSync(root); + if (stat.isFile()) return /\.(ts|json)$/.test(root) ? [root] : []; + return walkTs(root); +} diff --git a/test/mcp/mcp-schema-contract.test.ts b/test/mcp/mcp-schema-contract.test.ts index 43e30d2..335d33c 100644 --- a/test/mcp/mcp-schema-contract.test.ts +++ b/test/mcp/mcp-schema-contract.test.ts @@ -59,6 +59,32 @@ describe("MCP schema contract", () => { } }); + it("accepts typed service workflow context only as non-authority proposal metadata", () => { + const base = validProposalInput(); + const contextRefs = serviceWorkflowContextRefs(); + expect( + McpX402PaymentProposalInputSchema.safeParse({ ...base, serviceWorkflowContextRefs: contextRefs }).success, + ).toBe(true); + + for (const forbiddenField of [ + "policyDecisionRef", + "greenlightRef", + "gatewayCheckRef", + "receiptRef", + "authorityCertificateRef", + "gatewayCredentialRef", + "paymentApprovalRef", + "signerRef", + ]) { + expect( + McpX402PaymentProposalInputSchema.safeParse({ + ...base, + serviceWorkflowContextRefs: { ...contextRefs, [forbiddenField]: "x" }, + }).success, + ).toBe(false); + } + }); + it("requires explicit x402 request-body and provider posture", () => { const valid = validProposalInput(); expect(McpX402PaymentProposalInputSchema.safeParse(valid).success).toBe(true); @@ -192,6 +218,16 @@ export function validProposalInput() { }; } +export function serviceWorkflowContextRefs() { + return { + passportPackageDigest: digest(21), + passportPresentationId: "passport-presentation-mcp-1", + admissionId: "service-workflow-admission-mcp-1", + serviceWorkflowHandleId: "service-workflow-handle-mcp-1", + serviceWorkflowHandleDigest: digest(22), + }; +} + export function digest(seed: number): `sha256:${string}` { return `sha256:${seed.toString(16).padStart(64, "0")}`; } diff --git a/test/mcp/mcp-x402-proposal.test.ts b/test/mcp/mcp-x402-proposal.test.ts index ca54cd5..80d88ce 100644 --- a/test/mcp/mcp-x402-proposal.test.ts +++ b/test/mcp/mcp-x402-proposal.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; import { proposeMcpX402Payment, type McpRuntimeProposalClient } from "../../src/mcp/x402-proposal"; -import { digest, validProposalInput } from "./mcp-schema-contract.test"; +import { digest, serviceWorkflowContextRefs, validProposalInput } from "./mcp-schema-contract.test"; describe("MCP x402 proposal bridge", () => { it("creates runtime evidence, draft, compilation, and action contract only", async () => { @@ -93,6 +93,40 @@ describe("MCP x402 proposal bridge", () => { ); }); + it("carries typed service workflow context as evidence metadata, not delegated authority", async () => { + const calls: Array<{ name: string; input: unknown }> = []; + const input = { ...validProposalInput(), serviceWorkflowContextRefs: serviceWorkflowContextRefs() }; + + const result = await proposeMcpX402Payment(input, trustedOptions(fakeRuntimeClient(calls))); + + expect(result.isError).toBe(false); + expect(result.structuredContent).toMatchObject({ + outcome: "action_contract_proposed", + authorityCreated: false, + greenlightCreated: false, + gatewayCheckPerformed: false, + mutationAttempted: false, + }); + + const compileCandidate = compileIntentCandidate(calls); + expect(compileCandidate.evidenceRefs).toEqual( + expect.arrayContaining([ + `service-workflow-context:passport-package:${input.serviceWorkflowContextRefs.passportPackageDigest}`, + `service-workflow-context:presentation:${input.serviceWorkflowContextRefs.passportPresentationId}`, + `service-workflow-context:admission:${input.serviceWorkflowContextRefs.admissionId}`, + `service-workflow-context:handle:${input.serviceWorkflowContextRefs.serviceWorkflowHandleId}`, + `service-workflow-context:handle-digest:${input.serviceWorkflowContextRefs.serviceWorkflowHandleDigest}`, + ]), + ); + expect(compileCandidate.clearingEvidenceRefs).toEqual({ + correlationRef: `service-workflow-context:${input.serviceWorkflowContextRefs.serviceWorkflowHandleId}`, + }); + expect(JSON.stringify(compileCandidate.delegatedAuthorityRefs)).not.toContain("serviceWorkflowHandle"); + expect(JSON.stringify(compileCandidate)).not.toContain("greenlightRef"); + expect(JSON.stringify(compileCandidate)).not.toContain("gatewayCheckRef"); + expect(JSON.stringify(compileCandidate)).not.toContain("receiptRef"); + }); + it("refuses stale metadata, not-ready install, offline gateway, unknown gateway, and amount overrun before runtime calls", async () => { for (const [input, options, outcome] of [ [validProposalInput(), { currentMetadataDigest: digest(50) }, "metadata_stale"], @@ -496,6 +530,7 @@ function compileIntentCandidate(calls: Array<{ name: string; input: unknown }>) bounds: Record; delegatedAuthorityRefs: unknown[]; evidenceRefs: string[]; + clearingEvidenceRefs: Record; }; } diff --git a/test/protocol/credential-custody.test.ts b/test/protocol/credential-custody.test.ts index 4ebf9c9..9ab342e 100644 --- a/test/protocol/credential-custody.test.ts +++ b/test/protocol/credential-custody.test.ts @@ -328,6 +328,147 @@ describe("credential custody protocol records", () => { expect(JSON.stringify(packet)).not.toMatch(/private[_-]?key|PAYMENT-SIGNATURE|PaymentPayload|package-token/); }); + it("records customer gateway custody evidence only with official verification and current redacted lease evidence", async () => { + const fixture = makeKernelFixture(); + const credentialRef = await registerFixtureCredentialRef( + fixture, + credentialRefInput({ + gatewayCredentialRefId: "gcr_customer_gateway_token", + custodyStatus: "gateway_held", + providerClass: "customer_gateway_provider", + providerRegistryRef: "provider-registry:customer-gateway", + }), + ); + const posture = await recordGatewayCheckedPosture(fixture, { credentialCustodyStatus: "gateway_held" }); + + const packet = await fixture.kernel.recordGatewayCustodyProofPacket( + custodyProofPacketInput({ + gatewayCredentialRefId: credentialRef.gatewayCredentialRefId, + gatewayCredentialRefDigest: credentialRef.gatewayCredentialRefDigest, + protectedPathPostureId: posture.protectedPathPostureId, + protectedPathPostureDigest: posture.postureDigest, + bypassProbeIds: posture.bypassProbeIds, + bypassProbeDigests: posture.bypassProbeDigests, + custodyClaimLevel: "customer_gateway_evidence", + custodyProviderClass: "customer_gateway_provider", + custodyProviderRegistryRef: "provider-registry:customer-gateway", + externalVerificationStatus: "verified_by_official_source", + attestationRefs: ["attestation:customer-gateway:official"], + attestationDigests: [`sha256:${"7".repeat(64)}`], + redactedAuditRefs: ["audit:redacted:customer-gateway"], + redactedAuditDigest: `sha256:${"8".repeat(64)}`, + }), + ); + + expect(packet).toMatchObject({ + custodyClaimLevel: "customer_gateway_evidence", + credentialCustodyStatus: "gateway_held", + custodyDriftStatus: "current", + resolverDriftStatus: "current", + redactionStatus: "redacted", + externalVerificationStatus: "verified_by_official_source", + secretMaterialIncluded: false, + authorityCreated: false, + } satisfies Partial); + expect(packet.leaseRef).toBe("lease:package-manager-token"); + expect(packet.attestationRefs).toContain("attestation:customer-gateway:official"); + expect(JSON.stringify(packet)).not.toMatch( + /PaymentPayload|PAYMENT-SIGNATURE|private[_-]?key|rawCredentialMaterial|api[_-]?key/, + ); + }); + + it("rejects customer gateway custody claims with fixture custody, stale proof, drift, failed redaction, or missing lease evidence", async () => { + const cases = [ + { + name: "fixture custody", + credential: credentialRefInput({ custodyStatus: "fixture_gateway_held" }), + posture: { credentialCustodyStatus: "fixture_gateway_held" as const }, + packet: { externalVerificationStatus: "verified_by_official_source" as const }, + error: "Fixture custody cannot satisfy customer or provider custody claims", + }, + { + name: "missing external verification", + packet: { externalVerificationStatus: "required_before_live_claim" as const }, + error: "Customer/provider custody proof requires official external verification evidence", + }, + { + name: "custody drift", + packet: { + custodyDriftStatus: "provider_drift" as const, + externalVerificationStatus: "verified_by_official_source" as const, + }, + error: "Gateway custody proof packet cannot be recorded as current when custody or resolver drift is present", + }, + { + name: "resolver drift", + packet: { + resolverDriftStatus: "resolver_drift" as const, + externalVerificationStatus: "verified_by_official_source" as const, + }, + error: "Gateway custody proof packet cannot be recorded as current when custody or resolver drift is present", + }, + { + name: "failed redaction", + packet: { + redactionStatus: "redaction_failed" as const, + externalVerificationStatus: "verified_by_official_source" as const, + }, + error: "Gateway custody proof packet cannot expose failed redaction as usable evidence", + }, + { + name: "missing lease", + packet: { leaseRef: null, externalVerificationStatus: "verified_by_official_source" as const }, + error: "Customer/provider custody proof requires current lease and attestation evidence", + }, + { + name: "missing attestation", + packet: { + attestationRefs: [], + attestationDigests: [], + externalVerificationStatus: "verified_by_official_source" as const, + }, + error: "Customer/provider custody proof requires current lease and attestation evidence", + }, + ]; + + for (const entry of cases) { + const fixture = makeKernelFixture(); + const credentialRef = await registerFixtureCredentialRef( + fixture, + credentialRefInput({ + gatewayCredentialRefId: `gcr_customer_gateway_${entry.name.replaceAll(" ", "_")}`, + custodyStatus: "gateway_held", + providerClass: "customer_gateway_provider", + providerRegistryRef: `provider-registry:customer-gateway:${entry.name.replaceAll(" ", "-")}`, + ...(entry.credential ?? {}), + }), + ); + const posture = await recordGatewayCheckedPosture(fixture, { + credentialCustodyStatus: "gateway_held", + ...(entry.posture ?? {}), + }); + await expect( + fixture.kernel.recordGatewayCustodyProofPacket( + custodyProofPacketInput({ + gatewayCustodyProofPacketId: `gcpp_customer_gateway_${entry.name.replaceAll(" ", "_")}`, + gatewayCredentialRefId: credentialRef.gatewayCredentialRefId, + gatewayCredentialRefDigest: credentialRef.gatewayCredentialRefDigest, + protectedPathPostureId: posture.protectedPathPostureId, + protectedPathPostureDigest: posture.postureDigest, + bypassProbeIds: posture.bypassProbeIds, + bypassProbeDigests: posture.bypassProbeDigests, + custodyClaimLevel: "customer_gateway_evidence", + custodyProviderClass: "customer_gateway_provider", + custodyProviderRegistryRef: `provider-registry:customer-gateway:${entry.name.replaceAll(" ", "-")}`, + attestationRefs: ["attestation:customer-gateway:official"], + attestationDigests: [`sha256:${"7".repeat(64)}`], + ...(entry.packet ?? {}), + }), + ), + ).rejects.toThrow(entry.error); + } + }); + it("changes the custody proof digest when resolver, lease, or attestation material changes", async () => { const fixture = makeKernelFixture(); const credentialRef = await registerFixtureCredentialRef(fixture); @@ -365,9 +506,10 @@ describe("credential custody protocol records", () => { async function registerFixtureCredentialRef( fixture: ReturnType, + input: RegisterGatewayCredentialRefInput = credentialRefInput(), ): Promise { await registerFixtureObjects(fixture); - return fixture.kernel.registerGatewayCredentialRef(credentialRefInput()); + return fixture.kernel.registerGatewayCredentialRef(input); } async function proposeCredentialBoundContract( @@ -395,7 +537,9 @@ async function proposeCredentialBoundContract( return { compilation, contract }; } -function credentialRefInput(): RegisterGatewayCredentialRefInput { +function credentialRefInput( + overrides: Partial = {}, +): RegisterGatewayCredentialRefInput { return { tenantId: "tenant_demo", organizationId: "org_demo", @@ -416,6 +560,7 @@ function credentialRefInput(): RegisterGatewayCredentialRefInput { resolverVersion: "v1", evidenceExpectationRefs: ["evidence:credential-resolution"], expiresAt: futureIso(), + ...overrides, }; } @@ -431,7 +576,10 @@ function credentialBindingFor(credentialRef: GatewayCredentialRef) { }; } -async function recordGatewayCheckedPosture(fixture: ReturnType) { +async function recordGatewayCheckedPosture( + fixture: ReturnType, + overrides: { credentialCustodyStatus?: RegisterGatewayCredentialRefInput["custodyStatus"] } = {}, +) { const bypassProbeIds = await recordSafeBypassProbes(fixture); return fixture.kernel.createProtectedPathPosture({ tenantId: "tenant_demo", @@ -442,7 +590,7 @@ async function recordGatewayCheckedPosture(fixture: ReturnType Date: Tue, 26 May 2026 00:14:59 +0800 Subject: [PATCH 015/144] plan: add a2a negotiation macro plan --- .../A2A_NEGOTIATION_META_META_GOAL.md | 393 ++++++++++++++++++ .../a2a-negotiation/AGENT-HANDOFF.md | 80 ++++ .../a2a-negotiation/ARCHITECTURE.md | 239 +++++++++++ .../macro-plan/a2a-negotiation/EVALUATION.md | 90 ++++ .../a2a-negotiation/EXECUTION-SLICES.md | 172 ++++++++ .../macro-plan/a2a-negotiation/MACRO-PLAN.md | 126 ++++++ .../macro-plan/a2a-negotiation/README.md | 44 ++ .../a2a-negotiation/REVIEW-AUDIT.md | 88 ++++ .../macro-plan/a2a-negotiation/TASKS.jsonl | 6 + .../audits/validation.md | 40 ++ .../chair-synthesis.md | 51 +++ .../input.md | 76 ++++ .../normalized/AGENT.jsonl | 2 + .../normalized/CEO.jsonl | 2 + .../normalized/DESIGN.jsonl | 2 + .../normalized/DEVEX.jsonl | 2 + .../normalized/ENGINEERING.jsonl | 2 + .../raw/AGENT.md | 68 +++ .../raw/CEO.md | 76 ++++ .../raw/DESIGN.md | 90 ++++ .../raw/DEVEX.md | 63 +++ .../raw/ENGINEERING.md | 98 +++++ .../source-snapshot.md | 67 +++ 23 files changed, 1877 insertions(+) create mode 100644 .planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md create mode 100644 .planning/macro-plan/a2a-negotiation/AGENT-HANDOFF.md create mode 100644 .planning/macro-plan/a2a-negotiation/ARCHITECTURE.md create mode 100644 .planning/macro-plan/a2a-negotiation/EVALUATION.md create mode 100644 .planning/macro-plan/a2a-negotiation/EXECUTION-SLICES.md create mode 100644 .planning/macro-plan/a2a-negotiation/MACRO-PLAN.md create mode 100644 .planning/macro-plan/a2a-negotiation/README.md create mode 100644 .planning/macro-plan/a2a-negotiation/REVIEW-AUDIT.md create mode 100644 .planning/macro-plan/a2a-negotiation/TASKS.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/audits/validation.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/chair-synthesis.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/input.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/AGENT.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/CEO.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DESIGN.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DEVEX.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/ENGINEERING.jsonl create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/AGENT.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/CEO.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DESIGN.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DEVEX.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/ENGINEERING.md create mode 100644 .planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/source-snapshot.md diff --git a/.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md b/.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md new file mode 100644 index 0000000..ec57a1d --- /dev/null +++ b/.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md @@ -0,0 +1,393 @@ +# A2A Negotiation Meta-Meta Goal + +Status: run-control goal +Purpose: drive GSD planning from architecture through implementation, +evaluation, and review/audit for agent-to-agent negotiated protected-action +events in Handshake. + +## Invariant At Stake + +Agent-to-agent agreement is not authority. + +Handshake may record, project, and audit negotiated obligations only if every +consequential obligation still becomes its own normal protected-action chain: + +```text +CandidateAction +-> exact ActionContract +-> PolicyDecision / one-use Greenlight or Refusal +-> GatewayCheck before consequence +-> Receipt / Refusal / ReplayRefusal / ProofGap / Isolation +-> optional AuthorityCertificate as terminal evidence only +``` + +No negotiation session, offer, counteroffer, acceptance, linked agreement, +marketplace listing, transcript, certificate, service admission, MCP proposal, +or rendered review surface may create permission, signer use, mutation +authority, settlement finality, cross-org trust, reputation, dispute resolution, +or reusable authorization. + +## Meta-Meta Goal + +Use GSD to plan the complete architecture, implementation, evaluation, and +review/audit path for A2A negotiation in Handshake. + +The output must let a future implementation agent build the first A2A +negotiation slice without inventing: + +- product category or launch claim; +- protocol object shape; +- transition and event lifecycle; +- authority boundary; +- policy hook; +- gateway proof obligation; +- cross-party evidence posture; +- x402 buyer/seller fixture; +- operator/readback surface; +- evaluation matrix; +- review/audit gates; +- stop conditions. + +The planning target is not "generic negotiation." The planning target is: + +```text +agent A and agent B negotiate one obligation; +the accepted obligation binds to one fresh protected-action contract; +each party clears only its own protected surface; +the terminal evidence can be reconstructed without treating agreement as authority. +``` + +## Product Frame + +Category: + +```text +Clearing layer for agent-negotiated protected-action events. +``` + +Primary product object: + +```text +LinkedAgreement +``` + +Economic object: + +```text +Cleared Work Unit +``` + +First proof fixture: + +```text +buyer-agent / seller-agent negotiation over one buyer-side x402_payment.exact +protected action. +``` + +First user: + +```text +agent builder or platform/security owner who wants agents to negotiate paid +work or paid API access without giving either agent ambient spend authority. +``` + +10-star moment: + +```text +The user sees that an accepted A2A offer did not authorize anything by itself; +Handshake bound one accepted obligation to one exact action contract, cleared or +refused it through policy/gateway, and produced receipt/refusal/proof-gap +evidence that both sides can inspect. +``` + +## Source Boundary + +Current source anchors: + +- `docs/internal/protocol-kernel-architecture.md` says bilateral ecosystem + operation may add negotiation and linked agreements, but each party's + obligation must still become its own normal `ActionContract`, policy decision, + greenlight, gateway check, and receipt/refusal/proof-gap chain. +- `docs/internal/protocol-layman.md` says the bilateral object is the agreement + while the enforcement object remains each side's action contract and gateway + check. +- `src/protocol/foundation/schema-core.ts` already exposes + `clearingEvidenceRefs.correlationRef`, `obligationRef`, and + `counterpartyRef`, which are the existing bridge from contracts to + negotiated obligations. +- `src/protocol/events/schemas.ts` owns durable event vocabulary. +- `src/protocol/areas/object-registry/` owns protocol object export and raw-read + posture. +- `src/protocol/kernel.ts` owns transition facade shape. +- `src/protocol/areas/policy-greenlight/sequence-dependencies.ts` owns existing + same-org action sequencing checks. + +Planning scratch, prior chat, memory, and market language are not source truth. +They may inform strategy, but implementation claims must be re-grounded in +current source and tests. + +## Required GSD Flow + +Run this as a GSD planning chain, not as a single chat answer: + +```text +gsd-plan-map +-> gsd-macro-plan +-> gsd-plan-phase +-> implementation slices +-> evaluation suite +-> review/audit chain +``` + +Use `--runtime multi` and `--authority-overlay` because the target involves +multi-agent execution, x402/payment, cross-party evidence, and protected-action +authority. + +The first normal-quality run must not be promoted unless it has durable +architecture, implementation, evaluation, and review artifacts. If subagent or +review-lens execution is unavailable, mark the run `DEGRADED` or +`DEGRADED_UNMAPPED`. + +## Required Skill Roles + +Use skill roles as production pressure, not ceremony: + +| Skill role | Required output | Blocking question | +| --- | --- | --- | +| `handshake-grounding` | source boundary and current non-proofs | Does current source support the claim? | +| `gsd-plan-map` | macro map with authority overlay | Is this the right macro move before implementation? | +| `gsd-macro-plan` | execution-ready macro plan package | Are slices, gates, and handoffs implementable? | +| `api-and-interface-design` | protocol/API/object contracts | Are interfaces hard to misuse and additive? | +| `plan-ceo-review` | market/opening verdict | Does A2A negotiation create market pull or distraction? | +| `plan-eng-review` | architecture and failure-mode review | Can the kernel extension preserve invariants? | +| `plan-devex-review` | first proof and adopter path | Can a builder reach the A2A proof quickly? | +| `plan-design-review` | readback/review surface critique | Can users see agreement vs authority clearly? | +| `plan-agent-review` | multi-agent operability review | Can agents propose without inheriting mutation authority? | +| `security-and-hardening` | cross-party, secret, tenancy, replay review | Do all dangerous paths fail closed? | +| `quality-contract` | acceptance and eval gates | Can bad A2A work fail objective tests? | +| `gsd-code-review` | implementation review | Did code preserve the authority boundary? | +| `gsd-secure-phase` | security review | Are credentials, signers, raw records, and tenancy safe? | +| `gsd-verify-work` | goal-backward completion audit | Does evidence prove the full goal, not a subset? | +| `thermo-nuclear-code-quality-review` | strict claim/maintainability audit | Are claims, names, and exports too broad? | + +## Architecture Deliverables + +The architecture plan must define all of the following before implementation: + +1. new non-authority protocol area: + +```text +src/protocol/areas/negotiation/ +``` + +2. additive records: + +```text +NegotiationSession +NegotiationOffer +NegotiationDecision +LinkedAgreement +AgreementObligationBinding +AgreementStatusTransition +``` + +3. additive events: + +```text +negotiation_session_opened +negotiation_offer_recorded +negotiation_decision_recorded +linked_agreement_recorded +agreement_obligation_bound +agreement_status_changed +``` + +4. object-registry posture: + +```text +exportPosture: transition_evidence +rawReadPosture: audit_read +``` + +5. kernel transition methods: + +```text +openNegotiationSession +recordNegotiationOffer +recordNegotiationDecision +recordLinkedAgreement +bindAgreementObligation +transitionAgreementStatus +``` + +6. policy hook: + +```text +if clearingEvidenceRefs.obligationRef is present, policy must be able to +require a current LinkedAgreement and a matching AgreementObligationBinding. +``` + +7. readback projections: + +```text +NegotiationTimelineProjection +LinkedAgreementProjection +AgreementObligationProjection +``` + +8. no-authority proof: + +```text +offer acceptance creates no PolicyDecision, Greenlight, GatewayCheck, signer +use, mutation, receipt, receipt export, certificate, settlement, or reusable +authorization. +``` + +## Implementation Slices + +The macro plan must split work into implementation slices with proof gates: + +### A2A-001 Source And Schema Foundation + +Create negotiation schemas, inputs, object registry entries, and event enum +additions. No policy or gateway behavior yet. + +Proof gate: records parse, reject malformed variants, and remain +`transition_evidence` only. + +### A2A-002 Transition Lifecycle + +Implement session, offer, decision, linked-agreement, obligation-binding, and +agreement-status transitions. + +Proof gate: acceptance and linked agreement creation do not create authority or +mutation records. + +### A2A-003 Obligation Binding To ActionContract + +Bind one accepted obligation to one existing `ActionContract` through +`clearingEvidenceRefs.obligationRef`, `counterpartyRef`, and digest checks. + +Proof gate: mismatched contract digest, parameters, party, status, expiry, or +counterparty refuses. + +### A2A-004 Policy Integration + +Add policy evaluation support for agreement-backed obligations. + +Proof gate: expired, withdrawn, disputed, superseded, or mismatched agreements +produce policy refusal, not best-effort continuation. + +### A2A-005 x402 Buyer/Seller Fixture + +Prove one buyer-agent/seller-agent negotiation over +`x402_payment.exact`. + +Proof gate: payment material remains behind `VerifiedGatewayCheck`; downstream +finality remains receipt/proof-gap evidence, not settlement. + +### A2A-006 Evidence Readback And Support Packet + +Add redacted negotiation/agreement readback and receipt timeline linkage. + +Proof gate: readback distinguishes accepted terms, bound obligations, action +contracts, policy, gateway, receipt/refusal/proof-gap, and non-claims. + +### A2A-007 Evaluation And Review Closeout + +Run product, protocol, security, agent, and claim audits. + +Proof gate: all P0/P1 findings are fixed, blocked, cut, or explicitly marked +accepted-risk before promotion. + +## Evaluation Suite + +The evaluation plan must include failing and passing cases: + +- offer acceptance does not create authority; +- accepted offer without obligation binding is not executable; +- obligation binding requires exact accepted terms digest; +- obligation binding requires exact action contract digest; +- party mismatch refuses; +- counterparty mismatch refuses; +- expired agreement refuses; +- withdrawn agreement refuses; +- disputed agreement refuses or proof-gaps according to policy; +- superseded offer cannot be accepted; +- stale transcript evidence refuses or proof-gaps; +- replayed greenlight still refuses; +- changed x402 parameters refuse; +- raw sibling payment path is detected/refused or recorded as proof gap; +- downstream x402 finality unknown records proof gap, not success; +- terminal certificate is evidence only; +- cross-org trust remains proof gap unless a separate trust model is proven; +- readback redacts raw terms, secrets, payment material, and signer material; +- receipt timeline can reconstruct agreement -> obligation -> contract -> + policy -> gateway -> terminal outcome. + +## Review And Audit Gates + +No implementation may be called complete until these reviews exist: + +1. CEO review: A2A negotiation opens market access without dragging Handshake + into owning the marketplace. +2. Engineering review: protocol extension is additive, typed, replay-safe, and + isolated from authority overclaim. +3. Security review: cross-party evidence, tenancy, secrets, signers, raw reads, + replay, stale terms, and disputed status fail closed. +4. DevEx review: builder can run the first A2A x402 proof without learning the + whole protocol. +5. Design review: UI/readback makes "agreement is not authority" visible. +6. Agent review: multi-agent runtime can propose and negotiate without raw + mutation tools. +7. Claim audit: docs and examples do not claim marketplace, settlement, + legal-contract, reputation, escrow, cross-org trust, provider custody, or + generic A2A support. +8. Verification audit: tests and generated outputs prove every acceptance gate. + +## Hard Stop Conditions + +Stop and report `BLOCKED` if: + +- the plan treats acceptance as permission; +- the plan lets one agreement authorize multiple mutations; +- the plan lets one party authorize the other party's gateway; +- the plan requires raw signer or payment material outside the gateway; +- the plan depends on cross-org trust before a trust model exists; +- the plan claims settlement, legal contract formation, reputation, dispute + resolution, escrow, marketplace certification, or provider custody; +- the plan cannot bind accepted terms to exact `ActionContract` digests; +- policy cannot refuse stale, expired, withdrawn, disputed, or mismatched + agreement state; +- readback cannot reconstruct the chain six months later; +- implementation requires broad root exports before package-surface gates; +- full review/audit gates are missing. + +## Success Definition + +This meta-meta goal is satisfied when GSD outputs a durable plan package that +contains: + +- source boundary; +- macro map; +- execution-ready macro plan; +- architecture contract; +- implementation slice plan; +- evaluation suite; +- review/audit matrix; +- fresh-agent handoff; +- concrete tasks; +- explicit proof gaps and non-claims; +- status that honestly reflects whether the work is ready for phase planning, + agent execution, or blocked. + +## Smallest Next Mechanism + +Create the GSD macro-map input packet for: + +```text +A2A negotiated protected-action events in Handshake +``` + +with runtime `multi`, authority overlay enabled, and first fixture +`buyer-agent / seller-agent x402_payment.exact`. diff --git a/.planning/macro-plan/a2a-negotiation/AGENT-HANDOFF.md b/.planning/macro-plan/a2a-negotiation/AGENT-HANDOFF.md new file mode 100644 index 0000000..56edb3e --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/AGENT-HANDOFF.md @@ -0,0 +1,80 @@ +# A2A Negotiation Agent Handoff + +Status: ready for detailed phase planning + +## Objective + +Create the detailed `A2A-001 Source And Schema Foundation` phase plan. + +Do not implement source code until the phase plan exists and passes review. + +## Required Reading + +1. `.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md` +2. `.planning/macro-plan/a2a-negotiation/MACRO-PLAN.md` +3. `.planning/macro-plan/a2a-negotiation/ARCHITECTURE.md` +4. `.planning/macro-plan/a2a-negotiation/EXECUTION-SLICES.md` +5. `.planning/macro-plan/a2a-negotiation/EVALUATION.md` +6. `.planning/macro-plan/a2a-negotiation/REVIEW-AUDIT.md` +7. `docs/internal/protocol-kernel-architecture.md` +8. `docs/internal/protocol-layman.md` +9. `src/protocol/foundation/schema-core.ts` +10. `src/protocol/events/schemas.ts` +11. `src/protocol/areas/object-registry/` +12. `src/protocol/kernel.ts` + +## Runtime Profile + +Runtime: Codex or equivalent coding agent. + +Protected-action overlay: mandatory. + +Write scope for phase planning: + +- `.planning/macro-plan/a2a-negotiation/` +- future phase directory chosen by the planner + +Do not edit protocol source during phase planning. + +## First Phase Target + +`A2A-001 Source And Schema Foundation` + +The phase plan must name exact source files, test files, export posture, and +stop conditions for the schema/object/event foundation. + +## Non-Negotiable Boundaries + +- acceptance is not permission; +- linked agreement is not bearer auth; +- obligation binding is not gateway approval; +- terminal certificate is evidence only; +- receipt is not settlement; +- no cross-org trust without a trust model; +- no root exports before package-surface gates; +- no raw terms, secrets, signer material, payment payload, or payment signature + in readback. + +## Stop Conditions + +Stop before implementation if: + +- the phase plan cannot prove no-authority acceptance; +- the phase plan requires broad package exports; +- the phase plan needs cross-org trust; +- x402 raw sibling path is used as success; +- policy hook cannot refuse stale/mismatched agreement state; +- tests cannot detect authority overclaim. + +## Expected Phase Plan Output + +The next agent should produce: + +- `PLAN.md`; +- `TASKS.jsonl`; +- `TEST_PLAN.md`; +- `PROTECTED_ACTION_GATES.md`; +- `REVIEW.md` or review gate plan; +- exact source/test file list; +- verification commands; +- residual proof gaps. diff --git a/.planning/macro-plan/a2a-negotiation/ARCHITECTURE.md b/.planning/macro-plan/a2a-negotiation/ARCHITECTURE.md new file mode 100644 index 0000000..e8dbc33 --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/ARCHITECTURE.md @@ -0,0 +1,239 @@ +# A2A Negotiation Architecture Contract + +Status: planned + +## Invariant + +Negotiation records coordinate obligations. They never issue authority. + +## New Protocol Area + +```text +src/protocol/areas/negotiation/ + schemas.ts + inputs.ts + transitions.ts + guards.ts + artifacts.ts + index.ts +``` + +## Record Contracts + +### NegotiationSession + +Purpose: bounded context for a negotiation between agents or services. + +Required fields: + +- `negotiationSessionId` +- `principalId` +- `initiatingAgentId` +- `partyRefs` +- `allowedActionTypeIds` +- `allowedResourceRefs` +- `sessionDigest` +- `transcriptEvidenceRefs` +- `expiresAt` +- `status` +- non-authority flags + +Non-authority: opening a session creates no agreement and no protected-action +authority. + +### NegotiationOffer + +Purpose: records offered terms and proposed obligations. + +Required fields: + +- `negotiationOfferId` +- `negotiationSessionId` +- `offeredByPartyRef` +- `respondsToOfferId` +- `termsDigest` +- `redactedTermsSummary` +- `proposedObligations` +- `offerDigest` +- `expiresAt` + +Non-authority: an offer is evidence only. + +### NegotiationDecision + +Purpose: records accept, reject, counter, or withdraw decisions over one offer. + +Required fields: + +- `negotiationDecisionId` +- `negotiationSessionId` +- `negotiationOfferId` +- `decidedByPartyRef` +- `decision` +- `decisionDigest` +- `attestationRef` + +Non-authority: acceptance creates no policy decision, greenlight, gateway check, +signer use, mutation, receipt, export, certificate, or reusable authorization. + +### LinkedAgreement + +Purpose: terminal agreement evidence for one accepted offer. + +Required fields: + +- `linkedAgreementId` +- `negotiationSessionId` +- `acceptedOfferId` +- `acceptedDecisionId` +- `acceptedTermsDigest` +- `partyRefs` +- `obligationRefs` +- `agreementDigest` +- `status` +- `expiresAt` + +Non-authority: a linked agreement cannot be used as a bearer token. + +### AgreementObligationBinding + +Purpose: binds one negotiated obligation to one exact `ActionContract`. + +Required fields: + +- `agreementObligationBindingId` +- `linkedAgreementId` +- `obligationRef` +- `responsiblePartyRef` +- `counterpartyRef` +- `actionContractId` +- `actionContractDigest` +- `expectedParamsDigest` +- `bindingDigest` +- `bindingStatus` + +Invariant: one binding points to one contract. One contract can clear at most +one gateway-checked mutation attempt through existing greenlight rules. + +### AgreementStatusTransition + +Purpose: records status changes such as active, withdrawn, expired, disputed, +superseded, or resolved. + +Required fields: + +- `agreementStatusTransitionId` +- `linkedAgreementId` +- `fromStatus` +- `toStatus` +- `reasonCode` +- `transitionDigest` +- `supersededByAgreementId` +- `effectiveAt` + +## Event Additions + +Add to `ContractStreamEventSchema`: + +```text +negotiation_session_opened +negotiation_offer_recorded +negotiation_decision_recorded +linked_agreement_recorded +agreement_obligation_bound +agreement_status_changed +``` + +Partitioning: use organization stream with `negotiation:` and +`agreement:` partition keys first. Do not add a new stream scope until a +query requirement proves it. + +## Object Registry + +All negotiation records: + +```text +exportPosture: "transition_evidence" +rawReadPosture: "audit_read" +``` + +Do not expose raw transcript text, raw terms, secrets, payment payloads, signer +material, or hidden counterparty metadata through raw reads. + +## Kernel Facade + +Add methods: + +```text +openNegotiationSession(input) +recordNegotiationOffer(input) +recordNegotiationDecision(input) +recordLinkedAgreement(input) +bindAgreementObligation(input) +transitionAgreementStatus(input) +``` + +Each transition must commit records with events through the existing recorder +and conflict semantics. + +## Policy Hook + +When `ActionContract.clearingEvidenceRefs.obligationRef` is present, policy can +require: + +- `LinkedAgreement` exists; +- agreement status is active; +- agreement is not expired; +- obligation exists in the accepted terms; +- `AgreementObligationBinding` matches the action contract; +- responsible party and counterparty match; +- contract digest and params digest match expected values; +- required evidence refs are present; +- no active isolation blocks the party, agreement, resource, gateway, or + credential ref. + +Policy refusal reason codes should be specific: + +- `agreement_missing` +- `agreement_not_active` +- `agreement_expired` +- `agreement_disputed` +- `agreement_withdrawn` +- `agreement_superseded` +- `obligation_missing` +- `obligation_binding_missing` +- `obligation_binding_digest_mismatch` +- `obligation_contract_digest_mismatch` +- `obligation_params_mismatch` +- `obligation_party_mismatch` +- `obligation_counterparty_mismatch` + +## Readback Projections + +Add redacted projections: + +```text +NegotiationTimelineProjection +LinkedAgreementProjection +AgreementObligationProjection +``` + +Required readback axes: + +- negotiation status; +- agreement status; +- obligation binding status; +- action contract status; +- policy status; +- gateway status; +- downstream outcome status; +- proof gaps; +- non-claims. + +## Cross-Org Boundary + +The first implementation is same-tenant/org local/reference unless a separate +trust model is admitted. + +Cross-org trust, remote JWKS, portable acceptance, settlement, and marketplace +certification remain proof gaps. diff --git a/.planning/macro-plan/a2a-negotiation/EVALUATION.md b/.planning/macro-plan/a2a-negotiation/EVALUATION.md new file mode 100644 index 0000000..dd8b8d3 --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/EVALUATION.md @@ -0,0 +1,90 @@ +# A2A Negotiation Evaluation Suite + +Status: planned + +## Evaluation Goal + +Bad A2A work must fail objective tests before it can become source truth. + +## Unit And Schema Evals + +- `NegotiationSession` rejects empty parties, unsupported action types, expired + sessions, and missing evidence refs. +- `NegotiationOffer` rejects missing terms digest and obligation refs. +- `NegotiationDecision` rejects acceptance by a non-party. +- `LinkedAgreement` rejects accepted terms digest mismatch. +- `AgreementObligationBinding` rejects missing action contract digest. +- `AgreementStatusTransition` rejects invalid status transitions. + +## Transition Evals + +- opening session emits `negotiation_session_opened`; +- recording offer emits `negotiation_offer_recorded`; +- recording acceptance emits `negotiation_decision_recorded`; +- linked agreement emits `linked_agreement_recorded`; +- binding emits `agreement_obligation_bound`; +- status transition emits `agreement_status_changed`; +- acceptance creates no `policy_decision`, `greenlight`, + `gateway_check_attempt`, `mutation_attempt`, `receipt`, + `receipt_export`, or `authority_certificate`. + +## Policy Evals + +- active exact agreement allows normal policy evaluation to continue; +- missing agreement refuses `agreement_missing`; +- expired agreement refuses `agreement_expired`; +- withdrawn agreement refuses `agreement_withdrawn`; +- disputed agreement refuses `agreement_disputed`; +- superseded agreement refuses `agreement_superseded`; +- missing obligation refuses `obligation_missing`; +- missing binding refuses `obligation_binding_missing`; +- digest mismatch refuses `obligation_contract_digest_mismatch`; +- params mismatch refuses `obligation_params_mismatch`; +- party mismatch refuses `obligation_party_mismatch`; +- counterparty mismatch refuses `obligation_counterparty_mismatch`; +- active isolation still refuses. + +## Gateway And x402 Evals + +- changed x402 amount refuses; +- changed target URL refuses; +- changed selected payment requirement refuses; +- replayed greenlight refuses; +- payment material appears only after verified gateway check; +- downstream finality unknown records proof gap; +- raw sibling payment path is refused, detected, or recorded as proof gap. + +## Readback Evals + +- readback shows negotiation status separately from policy status; +- readback shows gateway status separately from downstream outcome; +- support packet redacts raw terms, secrets, signer material, payment payload, + and payment signature; +- terminal certificate is shown as evidence only; +- proof gaps survive export/readback; +- six-month reconstruction can follow exact refs. + +## Product Evals + +- first fixture output includes JSON and Markdown; +- output names non-claims; +- output shows accepted offer created no authority; +- output shows bound obligation and exact action contract; +- output shows receipt/refusal/proof gap with reason codes; +- output does not claim settlement, marketplace, legal contract, reputation, + cross-org trust, or provider custody. + +## Suggested Commands + +Final command names are deferred to phase planning, but expected gates are: + +```bash +npm run test -- test/protocol/a2a-negotiation.test.ts +npm run test -- test/product/a2a-negotiated-x402.test.ts +npm run quality:claims +npm run quality:architecture +npm run check:repo +``` + +If broad repo gates fail from unrelated dirty work, the closeout must report the +exact blocker and preserve the focused A2A evidence. diff --git a/.planning/macro-plan/a2a-negotiation/EXECUTION-SLICES.md b/.planning/macro-plan/a2a-negotiation/EXECUTION-SLICES.md new file mode 100644 index 0000000..7a7a8ad --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/EXECUTION-SLICES.md @@ -0,0 +1,172 @@ +# A2A Negotiation Execution Slices + +Status: planned + +## A2A-001 Source And Schema Foundation + +Objective: create the non-authority schema foundation. + +Write scope: + +- `src/protocol/areas/negotiation/` +- `src/protocol/areas/object-registry/schemas.ts` +- `src/protocol/areas/object-registry/index.ts` +- `src/protocol/events/schemas.ts` +- focused schema tests + +Proof gates: + +- negotiation records parse and reject malformed variants; +- object registry entries are `transition_evidence` and `audit_read`; +- no policy, greenlight, gateway, mutation, receipt, or certificate records are + created; +- package root exports remain unchanged unless tests admit the surface. + +Stop conditions: + +- any schema field implies bearer authorization; +- raw transcript text becomes raw-readable; +- event names imply execution or settlement. + +## A2A-002 Transition Lifecycle + +Objective: implement session, offer, decision, linked agreement, obligation +binding, and status transitions. + +Write scope: + +- `src/protocol/areas/negotiation/transitions.ts` +- `src/protocol/areas/negotiation/guards.ts` +- `src/protocol/kernel.ts` +- transition route/SDK surfaces only if explicitly admitted +- focused transition tests + +Proof gates: + +- acceptance creates no authority records; +- linked agreement creation creates no authority records; +- status transitions are monotonic or explicitly superseding; +- duplicate acceptance and stale counteroffer paths refuse. + +Stop conditions: + +- acceptance directly calls policy or gateway; +- one linked agreement can bind multiple mutations without per-obligation + contracts; +- one party can authorize another party's gateway. + +## A2A-003 Obligation Binding To ActionContract + +Objective: bind one accepted obligation to one exact action contract. + +Write scope: + +- `src/protocol/areas/negotiation/` +- `src/protocol/areas/action-contract/` only if binding validation requires it +- tests for digest, party, counterparty, params, expiry, and status mismatch + +Proof gates: + +- `clearingEvidenceRefs.obligationRef` must match the binding; +- `counterpartyRef` must match the accepted counterparty; +- `actionContractDigest` and `paramsDigest` must match; +- mismatches refuse before policy greenlight. + +Stop conditions: + +- binding can mutate contract parameters; +- binding can be reused across different contracts; +- stale or withdrawn agreement can bind a fresh contract. + +## A2A-004 Policy Integration + +Objective: make policy aware of agreement-backed obligations. + +Write scope: + +- `src/protocol/areas/policy-greenlight/` +- reason-code registry +- policy tests + +Proof gates: + +- expired, withdrawn, disputed, superseded, missing, stale, or mismatched + agreement state produces policy refusal; +- active agreement with exact binding can proceed to normal greenlight rules; +- isolation still blocks policy and gateway. + +Stop conditions: + +- policy treats agreement as sufficient permission; +- refusal reason is generic or unauditable; +- gateway path can proceed without policy checking agreement state. + +## A2A-005 x402 Buyer/Seller Fixture + +Objective: prove first A2A negotiated protected-spend path. + +Write scope: + +- `examples/a2a-negotiated-x402/` +- product tests +- x402 adapter tests only as needed + +Proof gates: + +- buyer/seller accepted offer creates no authority; +- accepted obligation binds to `x402_payment.exact`; +- changed amount or endpoint refuses; +- replay refuses; +- signer/payment material appears only after `VerifiedGatewayCheck`; +- downstream finality unknown is proof gap, not success. + +Stop conditions: + +- fixture claims broad x402 compatibility; +- fixture claims hosted/provider/customer custody; +- fixture uses raw sibling payment path as success. + +## A2A-006 Evidence Readback And Support Packet + +Objective: make the chain inspectable without leaking raw terms or secrets. + +Write scope: + +- evidence projections; +- CLI/evidence readback only if admitted; +- example output `latest.json` and `latest.md`; +- product tests. + +Proof gates: + +- readback reconstructs agreement -> obligation -> contract -> policy -> + gateway -> receipt/refusal/proof-gap; +- readback distinguishes agreement status from authority status; +- raw terms, secrets, signer material, payment payload, and payment signature + are redacted or absent. + +Stop conditions: + +- support packet implies permission, recovery, or settlement; +- readback merges gateway check and downstream finality. + +## A2A-007 Review, Evaluation, And Closeout + +Objective: prove the implementation and claims. + +Required gates: + +- `npm run quality:claims`; +- `npm run quality:architecture`; +- focused protocol tests; +- focused product tests; +- package-surface tests; +- generated example outputs; +- final code review; +- security review; +- goal-backward verification. + +Promotion: + +- `READY_FOR_AGENT_EXECUTION` only after phase plans, source implementation, + tests, generated outputs, and reviews pass. diff --git a/.planning/macro-plan/a2a-negotiation/MACRO-PLAN.md b/.planning/macro-plan/a2a-negotiation/MACRO-PLAN.md new file mode 100644 index 0000000..e079f73 --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/MACRO-PLAN.md @@ -0,0 +1,126 @@ +# A2A Negotiation Macro Plan + +Status: `READY_FOR_PHASE_PLANNING` +Run: `20260526T000830Z-a2a-negotiation-end2end` + +## Invariant At Stake + +Agent-to-agent agreement is not authority. + +Handshake may coordinate negotiated obligations only if every consequential +obligation is reduced to a fresh exact protected-action contract and then +cleared or refused through policy and gateway enforcement. + +## Product Claim Under Plan + +Allowed future claim after implementation and gates: + +```text +Handshake records, binds, clears, refuses, and reconstructs agent-negotiated +protected-action obligations. +``` + +Forbidden current claim: + +```text +Handshake supports A2A negotiation today. +``` + +Forbidden future overclaims: + +- marketplace operation; +- escrow; +- legal contract formation; +- settlement finality; +- reputation; +- dispute resolution; +- provider/customer custody; +- cross-org trust; +- generic A2A protocol support. + +## Selected Macro Move + +Create a non-authority `negotiation` protocol area: + +```text +NegotiationSession +-> NegotiationOffer +-> NegotiationDecision +-> LinkedAgreement +-> AgreementObligationBinding +-> AgreementStatusTransition +``` + +Then bind each accepted obligation to: + +```text +ActionContract.clearingEvidenceRefs.obligationRef +ActionContract.clearingEvidenceRefs.counterpartyRef +``` + +The binding feeds policy checks. It does not create authority. + +## First Proof + +Buyer-agent/seller-agent negotiation over one buyer-side +`x402_payment.exact` protected action. + +The proof must show: + +1. accepted offer creates no policy decision, greenlight, gateway check, signer + use, mutation, receipt, or certificate; +2. accepted obligation binds to one exact `ActionContract`; +3. policy can refuse mismatch, expiry, withdrawal, dispute, supersession, stale + evidence, changed params, and replay; +4. gateway still owns final enforcement before payment material; +5. receipt/readback separates agreement acceptance from downstream payment + finality. + +## Review Chain + +Inline lens sequence completed: + +```text +plan-ceo-review +-> plan-eng-review +-> plan-design-review +-> plan-devex-review +-> plan-agent-review +-> chair synthesis +-> validation audit +``` + +Review outputs: + +- `runs/20260526T000830Z-a2a-negotiation-end2end/raw/CEO.md` +- `runs/20260526T000830Z-a2a-negotiation-end2end/raw/ENGINEERING.md` +- `runs/20260526T000830Z-a2a-negotiation-end2end/raw/DESIGN.md` +- `runs/20260526T000830Z-a2a-negotiation-end2end/raw/DEVEX.md` +- `runs/20260526T000830Z-a2a-negotiation-end2end/raw/AGENT.md` + +## Key Decisions + +1. Use existing `clearingEvidenceRefs` as the contract bridge. +2. Add new records as `transition_evidence`, not `receipt_evidence` or + authority. +3. Keep public/root exports closed until package-surface tests admit them. +4. Keep first fixture local/reference and x402 buyer-side. +5. Do not solve cross-org trust in the first slice. +6. Treat marketplace and settlement language as explicit non-goals. +7. Make readback show agreement status, policy status, gateway status, and + downstream outcome as separate axes. + +## Blockers Before Implementation + +- A2A-001 phase plan must name exact source files and tests. +- Package export posture must be decided before public API exposure. +- Policy hook shape must be reviewed against existing policy transitions. +- Readback projection must prove redaction before support/export paths. +- Cross-org trust must remain a proof gap unless explicitly admitted later. + +## Final Status + +`READY_FOR_PHASE_PLANNING` + +The next valid step is a detailed phase plan for `A2A-001 Source And Schema +Foundation`. diff --git a/.planning/macro-plan/a2a-negotiation/README.md b/.planning/macro-plan/a2a-negotiation/README.md new file mode 100644 index 0000000..3f2ee1b --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/README.md @@ -0,0 +1,44 @@ +# A2A Negotiation Macro Plan Package + +Run: `20260526T000830Z-a2a-negotiation-end2end` +Status: `READY_FOR_PHASE_PLANNING` + +## Scope + +This package plans the architecture, implementation slices, evaluation suite, +and review/audit gates for agent-to-agent negotiated protected-action events in +Handshake. + +It is derived from: + +- `.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md` +- `runs/20260526T000830Z-a2a-negotiation-end2end/input.md` +- current source anchors listed in the run `source-snapshot.md` +- inline CEO, engineering, design, DevEx, and agent reviews + +## Macro Move + +Add a non-authority negotiation layer where agents can record offers, +decisions, linked agreements, and obligation bindings, while every +consequential obligation still clears through the normal protected-action +lifecycle. + +## Artifact Index + +- `MACRO-PLAN.md`: chair-owned plan, decisions, status, and proof boundaries. +- `ARCHITECTURE.md`: protocol/object/event/policy/readback architecture. +- `EXECUTION-SLICES.md`: ordered implementation slices and proof gates. +- `EVALUATION.md`: failing/passing eval suite and command targets. +- `REVIEW-AUDIT.md`: review, audit, claim, and promotion gates. +- `AGENT-HANDOFF.md`: fresh-agent execution context for detailed phase planning. +- `TASKS.jsonl`: assignable next mechanisms. +- `runs/20260526T000830Z-a2a-negotiation-end2end/`: source snapshot, raw lens + reviews, normalized findings, chair synthesis, validation. + +## Status Meaning + +`READY_FOR_PHASE_PLANNING` means a detailed `A2A-001` phase plan can be written. +It does not mean protocol code is implemented, tested, exported, or launchable. + +This package is not `READY_FOR_AGENT_EXECUTION` because no source implementation +or detailed phase plan has been verified yet. diff --git a/.planning/macro-plan/a2a-negotiation/REVIEW-AUDIT.md b/.planning/macro-plan/a2a-negotiation/REVIEW-AUDIT.md new file mode 100644 index 0000000..13493eb --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/REVIEW-AUDIT.md @@ -0,0 +1,88 @@ +# A2A Negotiation Review And Audit Gates + +Status: planned + +## Required Review Chain + +1. CEO review: + - market-opening value; + - first buyer; + - why Handshake should not own the marketplace; + - cleared work unit thesis. +2. Engineering review: + - schema and transition architecture; + - policy/gateway interaction; + - storage/event/replay behavior; + - package-surface risk. +3. Design review: + - agreement-vs-authority legibility; + - operator readback; + - redacted support packet; + - mobile/detail state. +4. DevEx review: + - time to first A2A proof; + - fixture path; + - errors and reason codes; + - public API/export posture. +5. Agent review: + - runtime profile; + - tool contract; + - write scopes; + - stop conditions; + - protected-action overlay. +6. Security review: + - tenancy; + - cross-party evidence; + - raw read posture; + - secret and signer material; + - replay and stale state. +7. Claim audit: + - docs, examples, README, CLI help, package exports; + - forbidden words and overclaims. +8. Verification audit: + - each requirement mapped to tests, generated outputs, or explicit proof gap. + +## Current Inline Reviews + +This macro package includes inline reviews under: + +```text +runs/20260526T000830Z-a2a-negotiation-end2end/raw/ +``` + +These satisfy phase-planning pressure. They do not replace post-implementation +code review, secure-phase review, or goal-backward verification. + +## P0 Audit Questions + +- Does any record create authority before `PolicyDecision` and `GatewayCheck`? +- Can one accepted offer authorize more than one mutation? +- Can one party authorize another party's gateway? +- Can an agent reach raw x402 payment material? +- Can stale, expired, withdrawn, disputed, or superseded agreement state clear? +- Can readback hide proof gaps? +- Can support/export leak raw terms or secrets? +- Can terminal certificate be mistaken for permission? +- Can public docs claim marketplace, settlement, or legal contract formation? + +## Promotion Gates + +Phase planning may begin when this package exists. + +Implementation may begin only after `A2A-001` has a detailed phase plan. + +Agent execution may begin only after: + +- exact file write scopes exist; +- focused tests are named; +- stop conditions are explicit; +- source branch/worktree state is classified; +- rollback/abandonment criteria exist. + +Launch claims may begin only after: + +- implementation is merged or otherwise source-owned; +- demo outputs are regenerated; +- claim and architecture gates pass; +- support/readback packet exists; +- non-claims are visible. diff --git a/.planning/macro-plan/a2a-negotiation/TASKS.jsonl b/.planning/macro-plan/a2a-negotiation/TASKS.jsonl new file mode 100644 index 0000000..e08d0db --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/TASKS.jsonl @@ -0,0 +1,6 @@ +{"id":"A2A-PLAN-001","status":"ready","title":"Write A2A-001 phase plan","objective":"Create a detailed source-and-schema foundation plan for the negotiation protocol area.","source":["A2A_NEGOTIATION_META_META_GOAL.md","a2a-negotiation/ARCHITECTURE.md","a2a-negotiation/EXECUTION-SLICES.md"],"acceptance":["exact source files named","test files named","no-authority acceptance gate included","package export posture decided or blocked"],"stop_conditions":["requires cross-org trust","requires raw signer/payment material","requires broad root exports before tests"]} +{"id":"A2A-PLAN-002","status":"ready","title":"Specify negotiation schema contracts","objective":"Define field-level contracts for NegotiationSession, NegotiationOffer, NegotiationDecision, LinkedAgreement, AgreementObligationBinding, and AgreementStatusTransition.","source":["a2a-negotiation/ARCHITECTURE.md"],"acceptance":["all schema fields typed","digests and statuses named","redaction posture named","malformed variants listed"],"stop_conditions":["schema implies bearer authority","raw transcript terms become audit-readable"]} +{"id":"A2A-PLAN-003","status":"ready","title":"Specify transition and event tests","objective":"Plan tests for negotiation transitions and contract stream events.","source":["a2a-negotiation/EVALUATION.md"],"acceptance":["event list mapped to tests","acceptance creates no authority test included","duplicate and stale decision tests included"],"stop_conditions":["tests only check happy path","events imply execution or settlement"]} +{"id":"A2A-PLAN-004","status":"ready","title":"Specify obligation binding and policy hook","objective":"Plan exact validation between accepted obligations, AgreementObligationBinding, and ActionContract clearingEvidenceRefs.","source":["a2a-negotiation/ARCHITECTURE.md","a2a-negotiation/EVALUATION.md"],"acceptance":["digest mismatch refusals named","party/counterparty mismatch refusals named","expired/withdrawn/disputed/superseded refusals named"],"stop_conditions":["policy can greenlight without agreement state check","binding mutates contract parameters"]} +{"id":"A2A-PLAN-005","status":"ready","title":"Specify x402 buyer-seller fixture","objective":"Plan the first buyer-agent/seller-agent x402_payment.exact fixture and generated outputs.","source":["a2a-negotiation/EXECUTION-SLICES.md","a2a-negotiation/EVALUATION.md"],"acceptance":["fixture path named","JSON and Markdown outputs planned","changed params and replay cases included","non-claims included"],"stop_conditions":["fixture claims broad x402 compatibility","fixture claims hosted/provider/customer custody","raw sibling payment path used as success"]} +{"id":"A2A-PLAN-006","status":"ready","title":"Specify readback and support packet","objective":"Plan redacted projections that reconstruct agreement to terminal protected-action outcome.","source":["a2a-negotiation/ARCHITECTURE.md","a2a-negotiation/REVIEW-AUDIT.md"],"acceptance":["NegotiationTimelineProjection named","LinkedAgreementProjection named","AgreementObligationProjection named","redaction gates named"],"stop_conditions":["readback merges gateway and downstream finality","support packet implies permission or recovery"]} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/audits/validation.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/audits/validation.md new file mode 100644 index 0000000..f4a6bb8 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/audits/validation.md @@ -0,0 +1,40 @@ +# A2A Negotiation Macro Plan Validation + +Run: `20260526T000830Z-a2a-negotiation-end2end` +Verdict: PASS_FOR_PHASE_PLANNING + +## Checked Requirements + +| Requirement | Evidence | Verdict | +| --- | --- | --- | +| CEO review exists | `raw/CEO.md` | PASS | +| Engineering review exists | `raw/ENGINEERING.md` | PASS | +| Design review exists | `raw/DESIGN.md` | PASS | +| DevEx review exists | `raw/DEVEX.md` | PASS | +| Agent review exists | `raw/AGENT.md` | PASS | +| Normalized findings exist | `normalized/*.jsonl` | PASS | +| Source boundary exists | `source-snapshot.md` | PASS | +| Chair synthesis exists | `chair-synthesis.md` | PASS | +| Architecture plan exists | `../../a2a-negotiation/ARCHITECTURE.md` | PASS | +| Implementation slices exist | `../../a2a-negotiation/EXECUTION-SLICES.md` | PASS | +| Evaluation suite exists | `../../a2a-negotiation/EVALUATION.md` | PASS | +| Review/audit matrix exists | `../../a2a-negotiation/REVIEW-AUDIT.md` | PASS | +| Agent handoff exists | `../../a2a-negotiation/AGENT-HANDOFF.md` | PASS | +| Task list exists | `../../a2a-negotiation/TASKS.jsonl` | PASS | +| Authority boundary preserved | all artifacts repeat agreement is not authority | PASS | + +## Non-Proofs + +- No protocol code has been implemented. +- No tests have been added or run for the future protocol extension. +- No independent subagent review artifacts were produced; lens reviews were run + inline in this thread. +- No cross-org trust model exists. +- No public package exports are approved. + +## Final Status + +`READY_FOR_PHASE_PLANNING` + +The package is sufficient to start detailed phase planning for A2A-001. It is +not sufficient to start autonomous source implementation without a phase plan. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/chair-synthesis.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/chair-synthesis.md new file mode 100644 index 0000000..2a856d3 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/chair-synthesis.md @@ -0,0 +1,51 @@ +# Chair Synthesis: A2A Negotiation Macro Plan + +Run: `20260526T000830Z-a2a-negotiation-end2end` +Status: `READY_FOR_PHASE_PLANNING` + +## Convergence + +All five review lenses converge on the same macro move: + +```text +Add negotiated-obligation evidence and binding records, not negotiation +authority. +``` + +The first proof must be a buyer-agent/seller-agent +`x402_payment.exact` fixture. The agreement is a coordination/readback object. +The enforcement object remains the action contract and gateway check. + +## Accepted Decisions + +1. Add a new `negotiation` protocol area. +2. Add `LinkedAgreement` and `AgreementObligationBinding` as transition + evidence only. +3. Use existing `clearingEvidenceRefs.obligationRef` and `counterpartyRef` to + connect action contracts to negotiated obligations. +4. Keep first proof local/reference, not hosted/cross-org. +5. Require policy refusal for expired, withdrawn, disputed, superseded, stale, + or mismatched agreement state. +6. Defer cross-org trust, marketplace, escrow, reputation, settlement, + provider custody, and legal contract formation. + +## P0 Gates + +- agreement acceptance cannot create authority; +- one agreement cannot authorize multiple mutations; +- one party cannot authorize another party's gateway; +- policy must check agreement state before greenlight; +- gateway must still verify one-use greenlight before payment/signer material; +- readback must separate agreement status, policy status, gateway status, and + downstream finality; +- raw terms, secrets, signer material, and payment material must not leak in + readback or support packets. + +## Plan Status + +`READY_FOR_PHASE_PLANNING` + +Reason: this package contains source boundary, lens reviews, architecture +contract, execution slices, evaluation suite, audit gates, task list, and agent +handoff. It is not `READY_FOR_AGENT_EXECUTION` because implementation phase +plans and source edits have not yet been created or verified. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/input.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/input.md new file mode 100644 index 0000000..489a881 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/input.md @@ -0,0 +1,76 @@ +# A2A Negotiation End-to-End Macro Plan Input + +Run: `20260526T000830Z-a2a-negotiation-end2end` +Source goal: `.planning/macro-plan/A2A_NEGOTIATION_META_META_GOAL.md` +Runtime posture: `multi` +Authority overlay: required +Planner posture: inline lens chain + +## User Objective + +Run the A2A Negotiation Meta-Meta Goal macro plan end to end: + +```text +full planceo review +-> plan-eng review +-> plan-design review +-> plan-devex review +-> plan-agent review +-> execution plan +-> review/audit +-> evaluation +-> commit +``` + +## Target Macro Move + +Plan agent-to-agent negotiated protected-action events in Handshake. + +The move is not generic negotiation. It is the smallest protocol/product layer +where two agents can negotiate an obligation, but accepted terms create no +authority until the obligation binds to a fresh protected-action contract and +clears the normal gateway-enforced lifecycle. + +## First Fixture + +```text +buyer-agent / seller-agent negotiation over one buyer-side x402_payment.exact +protected action +``` + +## Required Invariant + +Agent-to-agent agreement is not authority. + +Each consequential negotiated obligation must still clear through: + +```text +CandidateAction +-> exact ActionContract +-> PolicyDecision / one-use Greenlight or Refusal +-> GatewayCheck before consequence +-> Receipt / Refusal / ReplayRefusal / ProofGap / Isolation +``` + +## Source Boundary + +Canonical source anchors are listed in `source-snapshot.md`. + +This run may use memory and prior strategy only as context. Claims must be +grounded in current source files and the local planning artifact. + +## Review Lenses + +- CEO: market/opening verdict and scope discipline. +- Engineering: protocol architecture, state transitions, policy hook, tests. +- Design: readback workflow and agreement-vs-authority legibility. +- DevEx: first proof path and builder ergonomics. +- Agent: multi-agent runtime suitability and protected-action posture. + +## Promotion Rule + +This run can become `READY_FOR_PHASE_PLANNING` if it creates architecture, +execution slices, evals, review/audit gates, tasks, and a fresh-agent handoff. + +It must not claim `READY_FOR_AGENT_EXECUTION` unless implementation-ready phase +plans, source edits, tests, and independent verification are present. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/AGENT.jsonl b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/AGENT.jsonl new file mode 100644 index 0000000..e43e63e --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/AGENT.jsonl @@ -0,0 +1,2 @@ +{"lens":"AGENT","severity":"P0","finding":"Agent may implement generic negotiation without protected-action clearing.","required_change":"Require slice handoffs with runtime profile, write scopes, tool contract, and stop conditions."} +{"lens":"AGENT","severity":"P1","finding":"Raw x402 payment path would escape the contract boundary.","required_change":"Fixture must prove signer/payment material stays behind VerifiedGatewayCheck."} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/CEO.jsonl b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/CEO.jsonl new file mode 100644 index 0000000..7e5a990 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/CEO.jsonl @@ -0,0 +1,2 @@ +{"lens":"CEO","severity":"P0","finding":"Acceptance must not create authority.","required_change":"Keep LinkedAgreement non-authority and require fresh protected-action contracts for each obligation."} +{"lens":"CEO","severity":"P1","finding":"A2A negotiation can become marketplace sprawl.","required_change":"Keep first proof to buyer-agent/seller-agent x402_payment.exact and cut marketplace, escrow, reputation, and settlement claims."} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DESIGN.jsonl b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DESIGN.jsonl new file mode 100644 index 0000000..e88de7c --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DESIGN.jsonl @@ -0,0 +1,2 @@ +{"lens":"DESIGN","severity":"P0","finding":"Accepted offer can be mistaken for authorized action.","required_change":"Render agreement status separately from policy and gateway status."} +{"lens":"DESIGN","severity":"P1","finding":"Evidence can disappear behind summaries.","required_change":"Every obligation row must expose exact refs and terminal posture."} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DEVEX.jsonl b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DEVEX.jsonl new file mode 100644 index 0000000..1807c51 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/DEVEX.jsonl @@ -0,0 +1,2 @@ +{"lens":"DEVEX","severity":"P0","finding":"Manual protocol assembly blocks first proof.","required_change":"Create a fixture runner for examples/a2a-negotiated-x402 before broad CLI/API work."} +{"lens":"DEVEX","severity":"P1","finding":"Hosted or cross-org dependencies would stall adoption.","required_change":"Keep first proof local/reference with explicit non-claims."} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/ENGINEERING.jsonl b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/ENGINEERING.jsonl new file mode 100644 index 0000000..6bd046a --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/normalized/ENGINEERING.jsonl @@ -0,0 +1,2 @@ +{"lens":"ENGINEERING","severity":"P0","finding":"Cross-org dependencies exceed current same-org sequence dependency support.","required_change":"Treat cross-org trust as proof gap until a trust model exists."} +{"lens":"ENGINEERING","severity":"P0","finding":"Policy must validate agreement state before greenlight.","required_change":"Add agreement-backed obligation policy hook before any gateway path can clear."} diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/AGENT.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/AGENT.md new file mode 100644 index 0000000..85318c1 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/AGENT.md @@ -0,0 +1,68 @@ +# Agent Review: A2A Negotiation + +Status: PROFILE_REQUIRED_BEFORE_AGENT_EXECUTION +Runtime: multi +Protected-action overlay: required + +## Invariant At Stake + +Agents may negotiate, propose, and inspect evidence. They must not inherit raw +mutation, signer, payment, gateway, or cross-party authority from the +negotiation. + +## Execution Shape + +```text +buyer agent +-> receives seller offer +-> proposes acceptance evidence +-> Handshake records linked agreement +-> buyer agent proposes x402_payment.exact CandidateAction +-> Handshake binds obligation to ActionContract +-> policy/gateway decide consequence +``` + +Seller agent may present terms and read terminal evidence. It cannot authorize +buyer spend. Buyer agent cannot authorize seller-side mutation. + +## Agent Plan Contract + +The implementation plan must name: + +- runtime profile: Codex first, multi-host later; +- instruction sources: `AGENTS.md`, meta-meta goal, macro plan, source anchors; +- tool contract: read, propose, fixture-run, test only until gateway slice; +- write scopes: negotiation area, tests, examples, docs; +- stop conditions: authority overclaim, raw signer exposure, cross-org trust + dependency, unsupported broad export; +- evals: no-authority acceptance, binding mismatch, replay, proof gap; +- handoff: one fresh-agent packet per slice. + +## P0/P1 Findings + +P0: Without a runtime profile and fixture packet, a coding agent may implement +generic negotiation instead of protected-action clearing. + +P0: Any plan that asks the agent to call raw x402 payment paths outside a +gateway-protected wrapper must stop. + +P1: If the agent can dynamically construct action types or gateways from +negotiation text, policy must refuse until catalog-bound. + +P1: Parallel agents need disjoint write scopes because protocol schema, +object registry, kernel facade, tests, and examples are tightly coupled. + +## Suitability Matrix + +| Runtime | Posture | Reason | +| --- | --- | --- | +| Codex | `PROFILE_REQUIRED` | Can execute slices with file gates, but needs exact handoff. | +| MCP | `PROTECTED_ACTION_OVERLAY_REQUIRED` | Proposal/evidence only, no authority. | +| x402 | `PROTECTED_ACTION_OVERLAY_REQUIRED` | Payment material must stay behind gateway. | +| Multi-host | `BLOCKED_BY_TRUST_MODEL` | Cross-org trust and host parity are not proven. | + +## Agent Recommendation + +Proceed to phase planning, not autonomous implementation. First produce +`A2A-001` phase plan with source anchors, exact files, tests, and stop +conditions. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/CEO.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/CEO.md new file mode 100644 index 0000000..f0ff707 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/CEO.md @@ -0,0 +1,76 @@ +# CEO Review: A2A Negotiation + +Status: PASS_FOR_PHASE_PLANNING +Mode: selective expansion with hard authority boundary + +## Invariant At Stake + +Handshake wins if it becomes the clearing layer for agent-negotiated work. It +loses if it becomes another marketplace or negotiation chatbot with proof +language attached. + +## Verdict + +Yes, pursue A2A negotiation, but only as negotiated-obligation clearing. + +The commercial object is not "conversation between agents." The commercial +object is a cleared work unit: accepted terms tied to exact protected-action +contracts and terminal evidence. + +## Market Thesis + +Agents will increasingly: + +- buy paid API calls; +- subcontract tasks; +- bid for work; +- deliver work claims; +- request evaluations; +- route payments; +- hand off protected actions across services. + +The market gap is not that agents cannot talk. They can. The gap is that +businesses cannot safely accept automated negotiated obligations without proof +that consequence was cleared inside bounds. + +## Scope Decision + +Keep: + +- `LinkedAgreement` as non-authority evidence. +- `AgreementObligationBinding` as the bridge to exact `ActionContract`s. +- first fixture: buyer-agent/seller-agent over `x402_payment.exact`. +- cleared work unit as economic language. + +Cut: + +- marketplace ownership; +- escrow/settlement; +- legal contract formation; +- generic A2A identity; +- reputation; +- cross-org trust; +- broad dispute resolution. + +## P0/P1 Findings + +P0: If agreement acceptance creates permission, the product becomes ambient +authority wearing a badge. + +P0: If Handshake claims A2A negotiation before the x402 fixture clears through +gateway evidence, the launch claim outruns enforcement. + +P1: If the first product surface leads with negotiation UI instead of terminal +evidence, users will misunderstand what Handshake controls. + +## Recommendation + +Proceed to architecture and phase planning with this product sentence: + +```text +Handshake lets services accept, refuse, and reconstruct agent-negotiated +protected-action obligations. +``` + +Do not promote to implementation until engineering proves exact obligation +binding, policy refusal, replay refusal, and redacted readback. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DESIGN.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DESIGN.md new file mode 100644 index 0000000..680e504 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DESIGN.md @@ -0,0 +1,90 @@ +# Design Review: A2A Negotiation + +Status: PASS_FOR_READBACK_SPEC + +## Invariant At Stake + +The interface must make agreement and authority visually distinct. If users see +"accepted" and infer "authorized," the design is review theatre. + +## Primary User Moment + +The user opens an A2A event and needs to answer: + +```text +What did the agents agree to, which obligations became exact contracts, what +cleared, what refused, and what remains a proof gap? +``` + +## Information Hierarchy + +1. Terminal posture: + - cleared; + - refused; + - proof gap; + - isolated; + - pending contract; + - pending gateway. +2. Agreement posture: + - offer; + - counter; + - accepted; + - withdrawn; + - expired; + - disputed; + - superseded. +3. Obligation bindings: + - obligation ID; + - responsible party; + - counterparty; + - action contract ref; + - digest match posture; + - policy posture; + - gateway posture. +4. Evidence timeline: + - negotiation events; + - action lifecycle; + - terminal receipt/refusal/proof gap. +5. Non-claims: + - acceptance is not permission; + - receipt is not settlement; + - certificate is terminal evidence only. + +## Required Screens Or Projections + +- A2A negotiation timeline. +- Linked agreement detail. +- Obligation binding table. +- Protected action evidence drawer. +- Redacted support packet preview. +- Failure-state readback for mismatch, expiry, dispute, replay, and proof gap. + +## P0/P1 Findings + +P0: Do not render "Accepted" as a success state unless the protected-action +outcome is separately visible. + +P0: Do not combine agreement status and gateway status into one badge. + +P1: Every obligation row needs exact refs. Hover-only evidence is not enough. + +P1: Empty states must explain whether no contract exists, no policy decision +exists, no gateway check exists, or readback is redacted. + +## Design Recommendation + +Use a two-column operational detail: + +```text +left: negotiation and obligation structure +right: protected-action lifecycle and terminal evidence +``` + +The top banner should answer: + +```text +Agreement accepted. Authority not created until each obligation clears. +``` + +The first x402 fixture should show "accepted offer" and "payment action +cleared/refused" as separate rows. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DEVEX.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DEVEX.md new file mode 100644 index 0000000..e68fc77 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/DEVEX.md @@ -0,0 +1,63 @@ +# DevEx Review: A2A Negotiation + +Status: PASS_WITH_FIRST_PROOF_REQUIREMENT + +## Invariant At Stake + +Developers should not need to learn the full kernel to prove the first A2A +path, but the quickstart must not hide the authority boundary. + +## First Developer Job + +An agent builder wants to let a buyer agent accept a seller agent's paid API +offer without giving either agent raw spend authority. + +## First Proof Path + +```text +npm install handshake-protocol-kernel +-> run A2A x402 fixture +-> see accepted offer create no authority +-> bind obligation to x402_payment.exact ActionContract +-> see policy greenlight/refusal +-> see gateway pass/refuse before signer use +-> inspect receipt/refusal/proof-gap readback +``` + +## Required Developer Artifacts + +- one fixture JSON input; +- one fixture Markdown output; +- one support/readback packet; +- one CLI or test command that runs the fixture; +- one failure fixture for stale/changed params; +- one failure fixture for accepted offer without binding. + +## P0/P1 Findings + +P0: A developer must not be asked to assemble protocol records manually for the +first proof. Provide a fixture runner or helper facade. + +P0: Quickstart copy must say "proposal/evidence only" until policy/gateway +transitions are run. + +P1: If the first proof requires hosted operation, customer custody, registry +listing, or cross-org trust, adoption stalls. Keep it local/reference first. + +P1: Errors need reason codes, not prose-only failures. + +## DevEx Recommendation + +Add an example package path before broad API design: + +```text +examples/a2a-negotiated-x402/ + input/ + output/latest.json + output/latest.md + run.ts + README.md +``` + +Then add CLI only after the fixture proves stable. Do not expose public package +root helpers until package-surface tests prove the intended boundary. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/ENGINEERING.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/ENGINEERING.md new file mode 100644 index 0000000..1d8777c --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/raw/ENGINEERING.md @@ -0,0 +1,98 @@ +# Engineering Review: A2A Negotiation + +Status: PASS_WITH_P0_GATES + +## Invariant At Stake + +The protocol extension must be additive and non-authority. Negotiation records +may coordinate obligations, but only `ActionContract`, policy, greenlight, +gateway, and receipt/refusal/proof-gap transitions control consequence. + +## Architecture Verdict + +Add a new protocol area: + +```text +src/protocol/areas/negotiation/ +``` + +Do not mutate `ActionContract` into a negotiation object. Use +`clearingEvidenceRefs.obligationRef` and `counterpartyRef` to connect the +contract to negotiated evidence. + +## Required Schemas + +- `NegotiationSession` +- `NegotiationOffer` +- `NegotiationDecision` +- `LinkedAgreement` +- `AgreementObligationBinding` +- `AgreementStatusTransition` + +Every schema must include tenant/org scope, digest fields, status fields, +expiry where relevant, evidence refs, non-secret summaries, and explicit +authority flags or non-authority posture. + +## Required Events + +- `negotiation_session_opened` +- `negotiation_offer_recorded` +- `negotiation_decision_recorded` +- `linked_agreement_recorded` +- `agreement_obligation_bound` +- `agreement_status_changed` + +## Required Transition Guards + +- one accepted offer per linked agreement; +- accepted offer digest must match linked agreement accepted terms digest; +- obligation binding must match action contract digest; +- responsible party must match principal/agent or accepted participant binding; +- counterparty must match `clearingEvidenceRefs.counterpartyRef`; +- expired, withdrawn, disputed, revoked, or superseded agreement cannot back a + greenlight; +- binding cannot broaden amount, resource, method, endpoint, credential, + gateway, or action type beyond accepted terms; +- agreement status changes must be monotonic or explicitly superseding. + +## P0/P1 Findings + +P0: Cross-org dependencies cannot reuse current same-org sequence dependency +logic. Treat cross-org trust as proof gap until a separate trust model exists. + +P0: A single agreement must not authorize multiple mutations. Each obligation +binding must reference one exact contract, and each greenlight remains one-use. + +P0: Policy must refuse stale or mismatched agreement state before greenlight. + +P1: Object-registry posture must be `transition_evidence` and `audit_read`. +Raw transcript text and secret terms should not be raw-readable. + +P1: Event projections must reconstruct the chain without reading internal-only +stream events directly. + +## Required Tests + +- schema parse/refuse tests; +- transition lifecycle tests; +- no-authority acceptance test; +- obligation binding digest mismatch tests; +- policy refusal tests for expired/withdrawn/disputed/superseded agreements; +- x402 changed parameter and replay refusal tests; +- evidence projection redaction tests; +- root export and package surface tests. + +## Engineering Recommendation + +Implement in seven slices: + +1. schemas and object registry; +2. transition lifecycle; +3. obligation binding; +4. policy hook; +5. x402 fixture; +6. readback projections; +7. audits and claim gates. + +Do not add package root exports until package-surface tests define the intended +public boundary. diff --git a/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/source-snapshot.md b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/source-snapshot.md new file mode 100644 index 0000000..febfd45 --- /dev/null +++ b/.planning/macro-plan/runs/20260526T000830Z-a2a-negotiation-end2end/source-snapshot.md @@ -0,0 +1,67 @@ +# A2A Negotiation Source Snapshot + +Run: `20260526T000830Z-a2a-negotiation-end2end` + +## Worktree Posture + +Branch: `codex/architectural-north-star-simplification` + +The worktree is already heavily dirty with unrelated tracked and untracked work +across `.planning/`, docs, examples, CLI, HTTP, protocol, runtime, storage, +surfaces, x402 protected-tool code, and tests. This run must not revert, +normalize, or stage unrelated edits. + +`.planning/` is ignored by `.gitignore`. New planning files under `.planning/` +must be force-added if the user wants them committed. + +## Canonical Current Anchors + +- `AGENTS.md`: governing invariant that rendered plans, generated code, and + agreement-like artifacts are not authority. +- `README.md`: product kernel, current x402 wedge, MCP proposal/evidence + boundary, package posture, and non-claims. +- `docs/internal/decisions.md`: current product kernel, proof ledger, + expansion admission, and launch-gate posture. +- `docs/internal/protocol-kernel-architecture.md`: protocol transition map, + extension boundary, and bilateral ecosystem note. +- `docs/internal/protocol-layman.md`: plain-language bilateral ecosystem + explanation. +- `src/protocol/foundation/schema-core.ts`: `clearingEvidenceRefs` already + includes `correlationRef`, `obligationRef`, and `counterpartyRef`. +- `src/protocol/events/schemas.ts`: source-owned contract event enum. +- `src/protocol/areas/object-registry/`: object export posture and raw-read + posture. +- `src/protocol/kernel.ts`: transition facade. +- `src/protocol/areas/action-contract/`: exact proposed commitment. +- `src/protocol/areas/policy-greenlight/`: policy decisions, greenlights, and + sequence dependency handling. +- `src/protocol/areas/gateway-gate/`: final enforcement before consequence. + +## Existing Source Truth For Bilateral Operation + +Current docs already permit future negotiation and linked agreements, with the +hard cut line that each party's obligation must still become its own normal +`ActionContract`, policy decision, greenlight, gateway check, and +receipt/refusal/proof-gap chain. + +The current protocol is not a marketplace, escrow system, settlement layer, +legal-contract system, reputation layer, dispute-resolution system, or generic +A2A protocol. + +## Current Non-Proofs + +- No implemented `negotiation` protocol area exists. +- No `LinkedAgreement` or `AgreementObligationBinding` schema exists. +- No negotiation event types exist in `ContractStreamEventSchema`. +- No policy hook validates agreement-backed obligations. +- No cross-org trust model exists. +- No A2A x402 fixture exists. +- No readback projection links agreement -> obligation -> contract -> policy + -> gateway -> terminal outcome. +- No launch claim may say Handshake supports A2A negotiation today. + +## Existing Useful Seam + +`clearingEvidenceRefs.obligationRef` and `counterpartyRef` are the right bridge +from a negotiated obligation to an `ActionContract`. The extension should use +that seam before adding new authority-bearing concepts. From 4946237210172a138b249503907ed46cbb66f29c Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Tue, 26 May 2026 09:41:46 +0800 Subject: [PATCH 016/144] feat(protocol): add negotiation evidence schemas --- src/protocol/areas/negotiation/LANE.md | 79 ++++ src/protocol/areas/negotiation/index.ts | 2 + src/protocol/areas/negotiation/inputs.ts | 8 + src/protocol/areas/negotiation/schemas.ts | 214 ++++++++++ src/protocol/areas/negotiation/types.ts | 3 + src/protocol/areas/object-registry/index.ts | 50 +++ src/protocol/areas/object-registry/schemas.ts | 26 ++ src/protocol/events/schemas.ts | 6 + test/architecture/import-posture.test.ts | 1 + .../negotiation-no-authority-surface.test.ts | 100 +++++ test/protocol/negotiation-events.test.ts | 72 ++++ .../negotiation-object-registry.test.ts | 195 +++++++++ test/protocol/negotiation-schemas.test.ts | 371 ++++++++++++++++++ test/protocol/object-registry.test.ts | 6 + 14 files changed, 1133 insertions(+) create mode 100644 src/protocol/areas/negotiation/LANE.md create mode 100644 src/protocol/areas/negotiation/index.ts create mode 100644 src/protocol/areas/negotiation/inputs.ts create mode 100644 src/protocol/areas/negotiation/schemas.ts create mode 100644 src/protocol/areas/negotiation/types.ts create mode 100644 test/architecture/negotiation-no-authority-surface.test.ts create mode 100644 test/protocol/negotiation-events.test.ts create mode 100644 test/protocol/negotiation-object-registry.test.ts create mode 100644 test/protocol/negotiation-schemas.test.ts diff --git a/src/protocol/areas/negotiation/LANE.md b/src/protocol/areas/negotiation/LANE.md new file mode 100644 index 0000000..1a9eaa3 --- /dev/null +++ b/src/protocol/areas/negotiation/LANE.md @@ -0,0 +1,79 @@ +# Negotiation + +## Authority owner + +The protocol kernel owns negotiation records as transition evidence. + +## Current proof claim + +This area defines strict evidence schemas for `NegotiationSession` records and +related offer, decision, agreement, obligation-binding, and status-transition +records. It does not perform protected-action control transitions. + +## Use cases + +- Record imported A2A-style conversation context as digest-bound evidence. +- Keep party proof posture explicit instead of implying counterparty proof from + an agent or endpoint string. +- Link accepted-offer evidence to local proposed protected-action evidence. + +## Constraints and assumptions + +- External protocol refs are imported evidence only. +- Raw transcripts and raw-readable offer terms are outside this area. +- Agreement and obligation records are local evidence objects, not reusable + permission. +- Protected-action enforcement remains owned by the existing contract, policy, + gate, and terminal-evidence areas. + +## Core components + +- `NegotiationSessionSchema` +- `NegotiationOfferSchema` +- `NegotiationDecisionSchema` +- `LinkedAgreementSchema` +- `AgreementObligationBindingSchema` +- `AgreementStatusTransitionSchema` + +## Failure and scale posture + +Missing, stale, or unverifiable counterparty material is modeled with proof-gap +refs. Sequence and supersession fields preserve later reconstruction without +claiming lifecycle enforcement in this phase. + +## Future package target + +None in A2A-001. This area is not exported through the package root in this +phase. + +## Allowed imports + +- `zod` +- protocol foundation schemas + +## Forbidden imports + +- protected-action control transition areas +- runtime adapters +- HTTP, CLI, MCP, SDK, storage, or package-surface modules + +## Guarding tests + +- `test/protocol/negotiation-schemas.test.ts` +- `test/protocol/negotiation-object-registry.test.ts` +- `test/protocol/negotiation-events.test.ts` +- `test/architecture/negotiation-no-authority-surface.test.ts` + +## Public surface + +Area-local schemas and inferred types only. + +## Extraction trigger + +Extract only after runtime adapters and readback surfaces prove stable imported +evidence shapes without widening the protected-action control path. + +## Scope boundary + +A negotiation record can be referenced by a later local protected-action path. +It cannot replace that path. diff --git a/src/protocol/areas/negotiation/index.ts b/src/protocol/areas/negotiation/index.ts new file mode 100644 index 0000000..c23e749 --- /dev/null +++ b/src/protocol/areas/negotiation/index.ts @@ -0,0 +1,2 @@ +export * from "./schemas"; +export * from "./inputs"; diff --git a/src/protocol/areas/negotiation/inputs.ts b/src/protocol/areas/negotiation/inputs.ts new file mode 100644 index 0000000..8475c8f --- /dev/null +++ b/src/protocol/areas/negotiation/inputs.ts @@ -0,0 +1,8 @@ +export { + AgreementObligationBindingSchema as RecordAgreementObligationBindingInputSchema, + AgreementStatusTransitionSchema as RecordAgreementStatusTransitionInputSchema, + LinkedAgreementSchema as RecordLinkedAgreementInputSchema, + NegotiationDecisionSchema as RecordNegotiationDecisionInputSchema, + NegotiationOfferSchema as RecordNegotiationOfferInputSchema, + NegotiationSessionSchema as RecordNegotiationSessionInputSchema, +} from "./schemas"; diff --git a/src/protocol/areas/negotiation/schemas.ts b/src/protocol/areas/negotiation/schemas.ts new file mode 100644 index 0000000..44c5824 --- /dev/null +++ b/src/protocol/areas/negotiation/schemas.ts @@ -0,0 +1,214 @@ +import { z } from "zod"; +import { + ClearingEvidenceRefsSchema, + DigestSchema, + IdSchema, + IsoDateSchema, + ProtocolBaseSchema, + ReasonCodeSchema, + ResourceRefSchema, +} from "../../foundation/schema-core"; + +export const NegotiationPartyIdentityProofPostureSchema = z.enum([ + "self_attested", + "host_verified_ref", + "proof_gap_recorded", +]); +export type NegotiationPartyIdentityProofPosture = z.infer; + +export const NegotiationPartyBindingSchema = z + .strictObject({ + partyId: IdSchema, + partyRole: z.enum(["initiator", "counterparty", "observer"]), + agentRef: ResourceRefSchema, + organizationRef: ResourceRefSchema.nullable().default(null), + runtimeRef: ResourceRefSchema.nullable().default(null), + endpointRef: ResourceRefSchema.nullable().default(null), + identityProofPosture: NegotiationPartyIdentityProofPostureSchema, + identityEvidenceRefs: z.array(ResourceRefSchema).default([]), + identityProofDigest: DigestSchema.nullable().default(null), + proofGapRefs: z.array(ResourceRefSchema).default([]), + }) + .superRefine((value, ctx) => { + if (value.identityProofPosture === "host_verified_ref" && value.identityEvidenceRefs.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "host verified parties require local identity evidence refs", + path: ["identityEvidenceRefs"], + }); + } + if (value.identityProofPosture === "proof_gap_recorded" && value.proofGapRefs.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "proof-gap parties require proof gap refs", + path: ["proofGapRefs"], + }); + } + }); +export type NegotiationPartyBinding = z.infer; + +export const ExternalProtocolEvidenceRefSchema = z.strictObject({ + protocol: z.enum(["a2a", "acp", "anp", "ap2", "mcp", "runtime_handoff", "other"]), + protocolVersion: z.string().min(1).max(80), + objectKind: z.string().min(1).max(120), + objectRef: ResourceRefSchema, + objectDigest: DigestSchema, + evidencePosture: z.literal("imported_evidence_only"), + evidenceUse: z.enum([ + "conversation_context", + "descriptor_context", + "runtime_context", + "mandate_context_evidence", + "tool_context", + "handoff_context", + "other_context", + ]), + proofGapRefs: z.array(ResourceRefSchema).default([]), +}); +export type ExternalProtocolEvidenceRef = z.infer; + +const OfferVersionRefSchema = IdSchema.refine((value) => !["latest", "current", "unspecified"].includes(value), { + message: "decisions must bind to a specific offer version", +}); + +const disallowedObligationRefPattern = new RegExp( + [ + "greenlight", + "gateway[_:-]?check", + "mutation[_:-]?attempt", + "receipt", + "authority[_:-]?certificate", + "settlement", + "payment", + "signer", + "reusable[_:-]?authority", + ].join("|"), + "i", +); + +const EvidenceRefSchema = z.strictObject({ + refKind: z.enum(["candidate_action", "action_contract", "intent_compilation", "generated_execution_graph"]), + ref: ResourceRefSchema.refine((value) => !disallowedObligationRefPattern.test(value), { + message: "obligation evidence ref cannot point at a control or terminal artifact", + }), + digest: DigestSchema.nullable().default(null), +}); + +export const NegotiationSessionSchema = ProtocolBaseSchema.extend({ + negotiationSessionId: IdSchema, + negotiationSessionDigest: DigestSchema, + subjectResourceRef: ResourceRefSchema, + subjectProtectedActionContextRefs: z.array(ResourceRefSchema).default([]), + runtimePosture: z.enum(["declared_runtime_context", "observed_runtime_evidence", "proof_gap_recorded"]), + parties: z.array(NegotiationPartyBindingSchema).min(1), + generatedCodeOrSpecRefs: z.array(ResourceRefSchema).default([]), + declaredAssumptions: z.array(z.string().min(1).max(500)).default([]), + uncertaintyMarkers: z.array(z.string().min(1).max(500)).default([]), + externalProtocolEvidenceRefs: z.array(ExternalProtocolEvidenceRefSchema).default([]), + clearingEvidenceRefs: ClearingEvidenceRefsSchema, + expiresAt: IsoDateSchema.nullable().default(null), +}); +export type NegotiationSession = z.infer; + +export const NegotiationOfferSchema = ProtocolBaseSchema.extend({ + negotiationOfferId: IdSchema, + negotiationSessionId: IdSchema, + offerVersionId: OfferVersionRefSchema, + offerSequence: z.number().int().positive(), + offeredByPartyId: IdSchema, + previousOfferVersionId: OfferVersionRefSchema.nullable().default(null), + supersedesOfferVersionId: OfferVersionRefSchema.nullable().default(null), + offerContentDigest: DigestSchema, + offerObjectRefs: z.array(ResourceRefSchema).default([]), + offerContentRefs: z.array(ResourceRefSchema).default([]), + proofGapRefs: z.array(ResourceRefSchema).default([]), + externalProtocolEvidenceRefs: z.array(ExternalProtocolEvidenceRefSchema).default([]), + generatedCodeOrSpecRefs: z.array(ResourceRefSchema).default([]), + declaredAssumptions: z.array(z.string().min(1).max(500)).default([]), + uncertaintyMarkers: z.array(z.string().min(1).max(500)).default([]), + clearingEvidenceRefs: ClearingEvidenceRefsSchema, + expiresAt: IsoDateSchema.nullable().default(null), +}).superRefine(requireReconstructionRefs("offer")); +export type NegotiationOffer = z.infer; + +export const NegotiationDecisionSchema = ProtocolBaseSchema.extend({ + negotiationDecisionId: IdSchema, + negotiationSessionId: IdSchema, + decidedOfferVersionId: OfferVersionRefSchema, + decidedOfferSequence: z.number().int().positive(), + decidedByPartyId: IdSchema, + decision: z.enum(["accept", "reject", "counter", "withdraw", "expire"]), + reasonCodes: z.array(ReasonCodeSchema).default([]), + evidenceRefs: z.array(ResourceRefSchema).default([]), + proofGapRefs: z.array(ResourceRefSchema).default([]), + counterOfferVersionId: OfferVersionRefSchema.nullable().default(null), + decisionDigest: DigestSchema, +}); +export type NegotiationDecision = z.infer; + +export const LinkedAgreementSchema = ProtocolBaseSchema.extend({ + linkedAgreementId: IdSchema, + negotiationSessionId: IdSchema, + acceptedOfferVersionId: OfferVersionRefSchema, + acceptedOfferSequence: z.number().int().positive(), + agreementDigest: DigestSchema, + agreementObjectRefs: z.array(ResourceRefSchema).default([]), + agreementContentRefs: z.array(ResourceRefSchema).default([]), + proofGapRefs: z.array(ResourceRefSchema).default([]), + agreementEvidencePosture: z.literal("local_evidence_only"), + clearingEvidenceRefs: ClearingEvidenceRefsSchema, + externalProtocolEvidenceRefs: z.array(ExternalProtocolEvidenceRefSchema).default([]), +}).superRefine(requireReconstructionRefs("agreement")); +export type LinkedAgreement = z.infer; + +export const AgreementObligationBindingSchema = ProtocolBaseSchema.extend({ + agreementObligationBindingId: IdSchema, + linkedAgreementId: IdSchema, + negotiationSessionId: IdSchema, + obligationRef: ResourceRefSchema.refine((value) => !disallowedObligationRefPattern.test(value), { + message: "obligation ref cannot point at a control or terminal artifact", + }), + obligationDigest: DigestSchema.nullable().default(null), + bindingPosture: z.literal("local_evidence_only"), + localProtectedActionEvidenceRefs: z.array(EvidenceRefSchema).min(1), + evidenceRefs: z.array(ResourceRefSchema).default([]), + proofGapRefs: z.array(ResourceRefSchema).default([]), +}); +export type AgreementObligationBinding = z.infer; + +export const AgreementStatusTransitionSchema = ProtocolBaseSchema.extend({ + agreementStatusTransitionId: IdSchema, + linkedAgreementId: IdSchema, + negotiationSessionId: IdSchema, + fromStatus: z.enum(["proposed", "active", "superseded", "expired", "disputed", "resolved", "withdrawn"]), + toStatus: z.enum(["active", "superseded", "expired", "disputed", "resolved", "withdrawn"]), + reasonCodes: z.array(ReasonCodeSchema).default([]), + evidenceRefs: z.array(ResourceRefSchema).default([]), + proofGapRefs: z.array(ResourceRefSchema).default([]), + transitionDigest: DigestSchema, +}); +export type AgreementStatusTransition = z.infer; + +function requireReconstructionRefs(kind: "offer" | "agreement") { + return ( + value: + | Pick + | Pick, + ctx: z.RefinementCtx, + ): void => { + const objectRefs = + kind === "offer" + ? (value as Pick).offerObjectRefs + : (value as Pick).agreementObjectRefs; + const contentRefs = + kind === "offer" + ? (value as Pick).offerContentRefs + : (value as Pick).agreementContentRefs; + if (objectRefs.length > 0 || contentRefs.length > 0 || value.proofGapRefs.length > 0) return; + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${kind} digest requires object refs, content refs, or proof gap refs`, + path: kind === "offer" ? ["offerObjectRefs"] : ["agreementObjectRefs"], + }); + }; +} diff --git a/src/protocol/areas/negotiation/types.ts b/src/protocol/areas/negotiation/types.ts new file mode 100644 index 0000000..19100d9 --- /dev/null +++ b/src/protocol/areas/negotiation/types.ts @@ -0,0 +1,3 @@ +export * from "../../foundation/schema-core"; +export * from "./schemas"; +export * from "./inputs"; diff --git a/src/protocol/areas/object-registry/index.ts b/src/protocol/areas/object-registry/index.ts index b54ed4a..08c57ba 100644 --- a/src/protocol/areas/object-registry/index.ts +++ b/src/protocol/areas/object-registry/index.ts @@ -21,6 +21,14 @@ import { IdempotencyLedgerEntrySchema } from "../idempotency-ledger/schemas"; import { BypassProbeSchema } from "../bypass-probe/schemas"; import { ToolCallDraftSchema } from "../tool-call-draft/schemas"; import { IntentCompilationRecordSchema } from "../intent-compilation/schemas"; +import { + AgreementObligationBindingSchema, + AgreementStatusTransitionSchema, + LinkedAgreementSchema, + NegotiationDecisionSchema, + NegotiationOfferSchema, + NegotiationSessionSchema, +} from "../negotiation/schemas"; import { BreakerDecisionSchema, IsolationStateSchema, type IsolationState } from "../isolation-breaker/schemas"; import { ProtectedSurfaceOperationClaimSchema, @@ -175,6 +183,48 @@ export const protocolObjectRegistry = { "transition_evidence", "audit_read", ), + negotiation_session: entry( + "negotiation_session", + NegotiationSessionSchema, + (record) => record.payload.negotiationSessionId, + "transition_evidence", + "audit_read", + ), + negotiation_offer: entry( + "negotiation_offer", + NegotiationOfferSchema, + (record) => record.payload.negotiationOfferId, + "transition_evidence", + "audit_read", + ), + negotiation_decision: entry( + "negotiation_decision", + NegotiationDecisionSchema, + (record) => record.payload.negotiationDecisionId, + "transition_evidence", + "audit_read", + ), + linked_agreement: entry( + "linked_agreement", + LinkedAgreementSchema, + (record) => record.payload.linkedAgreementId, + "transition_evidence", + "audit_read", + ), + agreement_obligation_binding: entry( + "agreement_obligation_binding", + AgreementObligationBindingSchema, + (record) => record.payload.agreementObligationBindingId, + "transition_evidence", + "audit_read", + ), + agreement_status_transition: entry( + "agreement_status_transition", + AgreementStatusTransitionSchema, + (record) => record.payload.agreementStatusTransitionId, + "transition_evidence", + "audit_read", + ), action_contract: entry( "action_contract", ActionContractSchema, diff --git a/src/protocol/areas/object-registry/schemas.ts b/src/protocol/areas/object-registry/schemas.ts index 325ceb5..d1e1642 100644 --- a/src/protocol/areas/object-registry/schemas.ts +++ b/src/protocol/areas/object-registry/schemas.ts @@ -20,6 +20,14 @@ import { IdempotencyLedgerEntrySchema } from "../idempotency-ledger/schemas"; import { BypassProbeSchema } from "../bypass-probe/schemas"; import { ToolCallDraftSchema } from "../tool-call-draft/schemas"; import { IntentCompilationRecordSchema } from "../intent-compilation/schemas"; +import { + AgreementObligationBindingSchema, + AgreementStatusTransitionSchema, + LinkedAgreementSchema, + NegotiationDecisionSchema, + NegotiationOfferSchema, + NegotiationSessionSchema, +} from "../negotiation/schemas"; import { BreakerDecisionSchema, IsolationStateSchema } from "../isolation-breaker/schemas"; import { ProtectedSurfaceOperationClaimSchema, @@ -53,6 +61,12 @@ export const ProtocolObjectTypeSchema = z.enum([ "tool_call_draft", "protected_path_posture", "intent_compilation", + "negotiation_session", + "negotiation_offer", + "negotiation_decision", + "linked_agreement", + "agreement_obligation_binding", + "agreement_status_transition", "action_contract", "authority_certificate", "policy_decision", @@ -102,6 +116,18 @@ export const ProtocolRecordSchema = z.discriminatedUnion("objectType", [ z.strictObject({ objectType: z.literal("tool_call_draft"), payload: ToolCallDraftSchema }), z.strictObject({ objectType: z.literal("protected_path_posture"), payload: ProtectedPathPostureSchema }), z.strictObject({ objectType: z.literal("intent_compilation"), payload: IntentCompilationRecordSchema }), + z.strictObject({ objectType: z.literal("negotiation_session"), payload: NegotiationSessionSchema }), + z.strictObject({ objectType: z.literal("negotiation_offer"), payload: NegotiationOfferSchema }), + z.strictObject({ objectType: z.literal("negotiation_decision"), payload: NegotiationDecisionSchema }), + z.strictObject({ objectType: z.literal("linked_agreement"), payload: LinkedAgreementSchema }), + z.strictObject({ + objectType: z.literal("agreement_obligation_binding"), + payload: AgreementObligationBindingSchema, + }), + z.strictObject({ + objectType: z.literal("agreement_status_transition"), + payload: AgreementStatusTransitionSchema, + }), z.strictObject({ objectType: z.literal("action_contract"), payload: ActionContractSchema }), z.strictObject({ objectType: z.literal("authority_certificate"), payload: AuthorityCertificateSchema }), z.strictObject({ objectType: z.literal("policy_decision"), payload: PolicyDecisionSchema }), diff --git a/src/protocol/events/schemas.ts b/src/protocol/events/schemas.ts index a0d40c8..6008e17 100644 --- a/src/protocol/events/schemas.ts +++ b/src/protocol/events/schemas.ts @@ -22,6 +22,12 @@ export const ContractStreamEventSchema = ProtocolBaseSchema.extend({ "bypass_probe_recorded", "tool_call_draft_recorded", "protected_path_posture_recorded", + "negotiation_session_recorded", + "negotiation_offer_recorded", + "negotiation_decision_recorded", + "linked_agreement_recorded", + "agreement_obligation_binding_recorded", + "agreement_status_transition_recorded", "action_proposed", "policy_decision_recorded", "action_greenlit", diff --git a/test/architecture/import-posture.test.ts b/test/architecture/import-posture.test.ts index 291b1fa..a2e03d8 100644 --- a/test/architecture/import-posture.test.ts +++ b/test/architecture/import-posture.test.ts @@ -372,6 +372,7 @@ describe("protocol module import posture", () => { "../idempotency-ledger/schemas", "../intent-compilation/schemas", "../isolation-breaker/schemas", + "../negotiation/schemas", "../operation-lifecycle/schemas", "../policy-greenlight/schemas", "../proof-gap/schemas", diff --git a/test/architecture/negotiation-no-authority-surface.test.ts b/test/architecture/negotiation-no-authority-surface.test.ts new file mode 100644 index 0000000..6e11312 --- /dev/null +++ b/test/architecture/negotiation-no-authority-surface.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from "bun:test"; +import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { join, relative } from "node:path"; + +const negotiationRoot = "src/protocol/areas/negotiation"; +const forbiddenAreaSpecifiers = [ + "../policy-greenlight", + "../gateway-gate", + "../receipt-export", + "../authority-certificate", + "../operation-lifecycle", +] as const; +const downstreamSurfaceRoots = [ + "src/cli", + "src/mcp", + "src/http", + "src/sdk", + "src/adapters/x402-payment", + "src/storage", + "src/runtime", +] as const; + +describe("negotiation area authority surface", () => { + it("keeps negotiation schemas from importing protected-action control areas", () => { + const violations: string[] = []; + + for (const file of walkTs(negotiationRoot)) { + const imports = importsFrom(readFileSync(file, "utf8")); + for (const specifier of imports) { + if (forbiddenAreaSpecifiers.some((forbidden) => specifier.startsWith(forbidden))) { + violations.push(`${relative(process.cwd(), file)} imports ${specifier}`); + } + } + } + + expect(violations).toEqual([]); + }); + + it("does not add negotiation transition functions or a transition module", () => { + expect(existsSync(join(negotiationRoot, "transitions.ts"))).toBe(false); + + const exportedFunctions: string[] = []; + for (const file of walkTs(negotiationRoot)) { + const rel = relative(process.cwd(), file); + const text = readFileSync(file, "utf8"); + for (const match of text.matchAll(/export\s+(?:async\s+)?function\s+([A-Za-z0-9_]+)/g)) { + exportedFunctions.push(`${rel}:${match[1]}`); + } + } + + expect(exportedFunctions).toEqual([]); + }); + + it("keeps negotiation out of the package root for this phase", () => { + const rootIndex = readFileSync("src/index.ts", "utf8"); + + expect(rootIndex).not.toContain("negotiation"); + expect(rootIndex).not.toContain("Negotiation"); + }); + + it("keeps downstream product and runtime surfaces from importing negotiation", () => { + const violations: string[] = []; + + for (const root of downstreamSurfaceRoots) { + for (const file of walkTs(root)) { + const imports = importsFrom(readFileSync(file, "utf8")); + for (const specifier of imports) { + if (specifier.includes("protocol/areas/negotiation") || specifier.includes("../negotiation")) { + violations.push(`${relative(process.cwd(), file)} imports ${specifier}`); + } + } + } + } + + expect(violations).toEqual([]); + }); +}); + +function importsFrom(text: string): string[] { + return [...text.matchAll(/(?:import|export)\s+(?:type\s+)?(?:[^"']*?\s+from\s+)?["']([^"']+)["']/g)].map( + (match) => match[1] ?? "", + ); +} + +function walkTs(root: string): string[] { + const files: string[] = []; + if (!existsSync(root)) return files; + + for (const entry of readdirSync(root)) { + const full = join(root, entry); + const stat = statSync(full); + if (stat.isDirectory()) { + files.push(...walkTs(full)); + continue; + } + if (entry.endsWith(".ts")) files.push(full); + } + + return files.sort(); +} diff --git a/test/protocol/negotiation-events.test.ts b/test/protocol/negotiation-events.test.ts new file mode 100644 index 0000000..a1bacf6 --- /dev/null +++ b/test/protocol/negotiation-events.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, it } from "bun:test"; +import { ContractStreamEventSchema } from "../../src/protocol/events/schemas"; + +const digest = `sha256:${"a".repeat(64)}`; + +const negotiationRecordedEvents = [ + "negotiation_session_recorded", + "negotiation_offer_recorded", + "negotiation_decision_recorded", + "linked_agreement_recorded", + "agreement_obligation_binding_recorded", + "agreement_status_transition_recorded", +] as const; + +const authorityShapedEventNames = [ + "negotiation_authorized", + "negotiation_greenlit", + "negotiation_session_opened", + "agreement_obligation_bound", + "agreement_status_changed", + "agreement_executed", + "agreement_settled", + "agreement_certified", +] as const; + +describe("negotiation stream events", () => { + it("accepts recorded-only negotiation events", () => { + for (const eventType of negotiationRecordedEvents) { + expect(ContractStreamEventSchema.parse(validEvent(eventType))).toMatchObject({ + eventType, + streamScope: "run", + objectRefs: ["negotiation_session:negotiation_session_demo"], + }); + } + }); + + it("rejects authority-shaped negotiation events", () => { + for (const eventType of authorityShapedEventNames) { + expect(ContractStreamEventSchema.safeParse(validEvent(eventType)).success).toBe(false); + } + }); + + it("keeps the existing stream scopes unchanged for this schema-only phase", () => { + const streamScopeOptions = ContractStreamEventSchema.shape.streamScope.options; + + expect([...streamScopeOptions].sort()).toEqual(["organization", "protected_surface_resource", "run", "tenant"]); + }); +}); + +function validEvent(eventType: string) { + return { + schemaVersion: "0.2.4", + tenantId: "tenant_demo", + organizationId: "org_demo", + createdAt: "2026-05-26T00:00:00.000Z", + streamEventId: `event:${eventType}`, + streamId: "stream:negotiation-demo", + streamScope: "run", + offset: 0, + partitionKey: "tenant_demo:run_demo", + eventType, + eventTime: "2026-05-26T00:00:00.000Z", + producerRef: "protocol:negotiation-test", + objectRefs: ["negotiation_session:negotiation_session_demo"], + previousEventDigest: null, + eventDigest: digest, + payload: { + negotiationSessionId: "negotiation_session_demo", + evidencePosture: "recorded_only", + }, + }; +} diff --git a/test/protocol/negotiation-object-registry.test.ts b/test/protocol/negotiation-object-registry.test.ts new file mode 100644 index 0000000..81747e2 --- /dev/null +++ b/test/protocol/negotiation-object-registry.test.ts @@ -0,0 +1,195 @@ +import { describe, expect, it } from "bun:test"; +import { + getObjectId, + protocolObjectRegistry, + protocolObjectTypes, + protocolRecordSchemas, +} from "../../src/protocol/areas/object-registry"; +import { ProtocolRecordSchema } from "../../src/protocol/areas/object-registry/schemas"; + +const digest = `sha256:${"a".repeat(64)}`; +const now = "2026-05-26T00:00:00.000Z"; + +const negotiationObjectTypes = [ + "negotiation_session", + "negotiation_offer", + "negotiation_decision", + "linked_agreement", + "agreement_obligation_binding", + "agreement_status_transition", +] as const; + +const expectedIdByType = { + negotiation_session: "negotiation_session_demo", + negotiation_offer: "negotiation_offer_demo", + negotiation_decision: "negotiation_decision_demo", + linked_agreement: "linked_agreement_demo", + agreement_obligation_binding: "agreement_obligation_binding_demo", + agreement_status_transition: "agreement_status_transition_demo", +} satisfies Record<(typeof negotiationObjectTypes)[number], string>; + +describe("negotiation protocol object registry entries", () => { + it("registers every negotiation object type", () => { + for (const objectType of negotiationObjectTypes) { + expect(protocolObjectTypes).toContain(objectType); + expect(protocolObjectRegistry[objectType]).toBeDefined(); + expect(protocolRecordSchemas[objectType]).toBe(protocolObjectRegistry[objectType].schema); + } + }); + + it("keeps negotiation records as transition evidence with audit read posture", () => { + for (const objectType of negotiationObjectTypes) { + const entry = protocolObjectRegistry[objectType]; + expect(entry.exportPosture).toBe("transition_evidence"); + expect(entry.rawReadPosture).toBe("audit_read"); + } + }); + + it("selects negotiation object ids from the negotiation payload itself", () => { + for (const objectType of negotiationObjectTypes) { + const record = ProtocolRecordSchema.parse({ objectType, payload: validPayloads[objectType] }); + + expect(record.objectType).toBe(objectType); + expect(JSON.stringify(record.payload)).toBe(JSON.stringify(validPayloads[objectType])); + expect(getObjectId(record)).toBe(expectedIdByType[objectType]); + } + }); + + it("does not classify negotiation objects as catalog, terminal, control-plane, or internal-only records", () => { + for (const objectType of negotiationObjectTypes) { + const entry = protocolObjectRegistry[objectType]; + + expect(entry.exportPosture).not.toBe("catalog_public"); + expect(entry.exportPosture).not.toBe("receipt_evidence"); + expect(entry.rawReadPosture).not.toBe("control_plane_read"); + expect(entry.rawReadPosture).not.toBe("internal_only"); + } + }); +}); + +const base = { + schemaVersion: "0.2.4", + tenantId: "tenant_demo", + organizationId: "org_demo", + createdAt: now, +} as const; + +const externalRef = { + protocol: "a2a", + protocolVersion: "0.3.0", + objectKind: "Task", + objectRef: "a2a:task:demo", + objectDigest: digest, + evidencePosture: "imported_evidence_only", + evidenceUse: "conversation_context", + proofGapRefs: [], +} as const; + +const validPayloads = { + negotiation_session: { + ...base, + negotiationSessionId: expectedIdByType.negotiation_session, + negotiationSessionDigest: digest, + subjectResourceRef: "resource:repo:demo", + subjectProtectedActionContextRefs: ["candidate_action:candidate_demo"], + runtimePosture: "declared_runtime_context", + parties: [ + { + partyId: "party_initiator", + partyRole: "initiator", + agentRef: "agent:local", + organizationRef: null, + runtimeRef: "runtime:codex", + endpointRef: null, + identityProofPosture: "self_attested", + identityEvidenceRefs: [], + identityProofDigest: null, + proofGapRefs: [], + }, + ], + generatedCodeOrSpecRefs: [], + declaredAssumptions: [], + uncertaintyMarkers: [], + externalProtocolEvidenceRefs: [externalRef], + clearingEvidenceRefs: {}, + expiresAt: null, + }, + negotiation_offer: { + ...base, + negotiationOfferId: expectedIdByType.negotiation_offer, + negotiationSessionId: expectedIdByType.negotiation_session, + offerVersionId: "offer_version_1", + offerSequence: 1, + offeredByPartyId: "party_initiator", + previousOfferVersionId: null, + supersedesOfferVersionId: null, + offerContentDigest: digest, + offerObjectRefs: ["object:offer:v1"], + offerContentRefs: [], + proofGapRefs: [], + externalProtocolEvidenceRefs: [], + generatedCodeOrSpecRefs: [], + declaredAssumptions: [], + uncertaintyMarkers: [], + clearingEvidenceRefs: {}, + expiresAt: null, + }, + negotiation_decision: { + ...base, + negotiationDecisionId: expectedIdByType.negotiation_decision, + negotiationSessionId: expectedIdByType.negotiation_session, + decidedOfferVersionId: "offer_version_1", + decidedOfferSequence: 1, + decidedByPartyId: "party_initiator", + decision: "accept", + reasonCodes: [], + evidenceRefs: ["evidence:decision"], + proofGapRefs: [], + counterOfferVersionId: null, + decisionDigest: digest, + }, + linked_agreement: { + ...base, + linkedAgreementId: expectedIdByType.linked_agreement, + negotiationSessionId: expectedIdByType.negotiation_session, + acceptedOfferVersionId: "offer_version_1", + acceptedOfferSequence: 1, + agreementDigest: digest, + agreementObjectRefs: ["object:agreement:v1"], + agreementContentRefs: [], + proofGapRefs: [], + agreementEvidencePosture: "local_evidence_only", + clearingEvidenceRefs: {}, + externalProtocolEvidenceRefs: [], + }, + agreement_obligation_binding: { + ...base, + agreementObligationBindingId: expectedIdByType.agreement_obligation_binding, + linkedAgreementId: expectedIdByType.linked_agreement, + negotiationSessionId: expectedIdByType.negotiation_session, + obligationRef: "obligation:local-proposed-action", + obligationDigest: digest, + bindingPosture: "local_evidence_only", + localProtectedActionEvidenceRefs: [ + { + refKind: "candidate_action", + ref: "candidate_action:candidate_demo", + digest, + }, + ], + evidenceRefs: [], + proofGapRefs: [], + }, + agreement_status_transition: { + ...base, + agreementStatusTransitionId: expectedIdByType.agreement_status_transition, + linkedAgreementId: expectedIdByType.linked_agreement, + negotiationSessionId: expectedIdByType.negotiation_session, + fromStatus: "active", + toStatus: "disputed", + reasonCodes: ["counterparty_disputed_terms"], + evidenceRefs: ["evidence:status"], + proofGapRefs: [], + transitionDigest: digest, + }, +} as const; diff --git a/test/protocol/negotiation-schemas.test.ts b/test/protocol/negotiation-schemas.test.ts new file mode 100644 index 0000000..45d527f --- /dev/null +++ b/test/protocol/negotiation-schemas.test.ts @@ -0,0 +1,371 @@ +import { describe, expect, it } from "bun:test"; +import { + AgreementObligationBindingSchema, + AgreementStatusTransitionSchema, + ExternalProtocolEvidenceRefSchema, + LinkedAgreementSchema, + NegotiationDecisionSchema, + NegotiationOfferSchema, + NegotiationSessionSchema, + NegotiationPartyBindingSchema, +} from "../../src/protocol/areas/negotiation"; + +const digest = `sha256:${"a".repeat(64)}`; +const otherDigest = `sha256:${"b".repeat(64)}`; +const now = "2026-05-26T00:00:00.000Z"; +const later = "2026-05-27T00:00:00.000Z"; + +const base = { + schemaVersion: "0.2.4", + tenantId: "tenant_demo", + organizationId: "org_demo", + createdAt: now, +} as const; + +describe("negotiation evidence schemas", () => { + it("parses a strict NegotiationSession with explicit party proof posture and imported external evidence", () => { + expect(NegotiationSessionSchema.parse(validSession())).toMatchObject({ + negotiationSessionId: "negotiation_session_demo", + parties: [ + { partyId: "party_initiator", identityProofPosture: "host_verified_ref" }, + { partyId: "party_counterparty", identityProofPosture: "proof_gap_recorded" }, + ], + externalProtocolEvidenceRefs: [{ evidencePosture: "imported_evidence_only" }], + }); + }); + + it("requires verified party identity claims to carry evidence refs", () => { + expect( + NegotiationPartyBindingSchema.safeParse({ + partyId: "party_counterparty", + partyRole: "counterparty", + agentRef: "agent:remote", + identityProofPosture: "host_verified_ref", + identityEvidenceRefs: [], + identityProofDigest: null, + proofGapRefs: [], + }).success, + ).toBe(false); + }); + + it("requires proof-gap party posture to name proof gap refs", () => { + const party = validSession().parties[1]; + expect(NegotiationPartyBindingSchema.safeParse({ ...party, proofGapRefs: [] }).success).toBe(false); + }); + + it("rejects raw transcript or raw-readable term fields on negotiation sessions", () => { + expect( + NegotiationSessionSchema.safeParse({ + ...validSession(), + rawTranscript: "agent A accepted everything", + }).success, + ).toBe(false); + }); + + it("parses offers only when content digests have refs or proof-gap refs", () => { + expect(NegotiationOfferSchema.parse(validOffer())).toMatchObject({ + negotiationOfferId: "negotiation_offer_v1", + offerSequence: 1, + offerContentDigest: digest, + offerObjectRefs: ["object:offer:v1"], + }); + + expect( + NegotiationOfferSchema.safeParse({ + ...validOffer(), + offerObjectRefs: [], + offerContentRefs: [], + proofGapRefs: [], + }).success, + ).toBe(false); + }); + + it("tracks offer sequence and supersession refs without treating raw terms as evidence", () => { + const counterOffer = { + ...validOffer(), + negotiationOfferId: "negotiation_offer_v2", + offerVersionId: "offer_version_2", + offerSequence: 2, + previousOfferVersionId: "offer_version_1", + supersedesOfferVersionId: "offer_version_1", + }; + + expect(NegotiationOfferSchema.parse(counterOffer)).toMatchObject({ + offerSequence: 2, + previousOfferVersionId: "offer_version_1", + supersedesOfferVersionId: "offer_version_1", + }); + expect(NegotiationOfferSchema.safeParse({ ...counterOffer, rawTerms: "pay me later" }).success).toBe(false); + }); + + it("requires decisions to point at one specific offer version", () => { + expect(NegotiationDecisionSchema.parse(validDecision())).toMatchObject({ + decision: "accept", + decidedOfferVersionId: "offer_version_1", + decidedOfferSequence: 1, + }); + + expect( + NegotiationDecisionSchema.safeParse({ + ...validDecision(), + decidedOfferVersionId: "latest", + }).success, + ).toBe(false); + }); + + it("parses linked agreement evidence without accepting receipt or certificate fields", () => { + expect(LinkedAgreementSchema.parse(validAgreement())).toMatchObject({ + linkedAgreementId: "linked_agreement_demo", + acceptedOfferVersionId: "offer_version_1", + agreementEvidencePosture: "local_evidence_only", + }); + + expect( + LinkedAgreementSchema.safeParse({ + ...validAgreement(), + receiptId: "receipt_demo", + }).success, + ).toBe(false); + }); + + it("requires agreement content digests to have object/content refs or proof-gap refs", () => { + expect( + LinkedAgreementSchema.safeParse({ + ...validAgreement(), + agreementObjectRefs: [], + agreementContentRefs: [], + proofGapRefs: [], + }).success, + ).toBe(false); + }); + + it("keeps obligation bindings local evidence only", () => { + expect(AgreementObligationBindingSchema.parse(validObligationBinding())).toMatchObject({ + agreementObligationBindingId: "agreement_obligation_binding_demo", + bindingPosture: "local_evidence_only", + localProtectedActionEvidenceRefs: [{ refKind: "action_contract" }], + }); + }); + + it.each([ + "greenlight", + "gateway_check", + "mutation_attempt", + "receipt", + "authority_certificate", + "settlement", + "payment", + "signer", + "reusable_authority", + ])("rejects authority-shaped obligation refs: %s", (forbiddenKind) => { + expect( + AgreementObligationBindingSchema.safeParse({ + ...validObligationBinding(), + localProtectedActionEvidenceRefs: [ + { + refKind: forbiddenKind, + ref: `${forbiddenKind}:demo`, + digest, + }, + ], + }).success, + ).toBe(false); + }); + + it("parses agreement status transitions as evidence-only lifecycle records", () => { + expect(AgreementStatusTransitionSchema.parse(validStatusTransition())).toMatchObject({ + agreementStatusTransitionId: "agreement_status_transition_demo", + fromStatus: "active", + toStatus: "disputed", + }); + }); + + it("keeps external protocol refs digest-bound and imported evidence only", () => { + expect(ExternalProtocolEvidenceRefSchema.parse(validExternalRef())).toMatchObject({ + protocol: "a2a", + objectKind: "Task", + evidencePosture: "imported_evidence_only", + }); + + expect( + ExternalProtocolEvidenceRefSchema.safeParse({ + ...validExternalRef(), + evidencePosture: "authorization", + }).success, + ).toBe(false); + }); + + it.each(["authorization", "identity_proof", "execution_proof", "settlement", "payment", "receipt", "certificate"])( + "rejects external refs represented as %s", + (evidenceUse) => { + expect( + ExternalProtocolEvidenceRefSchema.safeParse({ + ...validExternalRef(), + evidenceUse, + }).success, + ).toBe(false); + }, + ); + + it.each(["AgentCard", "Task", "Run", "Thread", "Mandate", "Receipt", "tool_call", "handoff"])( + "accepts %s only as imported context evidence", + (objectKind) => { + expect( + ExternalProtocolEvidenceRefSchema.parse({ + ...validExternalRef(), + objectKind, + evidenceUse: "conversation_context", + }), + ).toMatchObject({ objectKind, evidencePosture: "imported_evidence_only" }); + }, + ); +}); + +function validSession() { + return { + ...base, + negotiationSessionId: "negotiation_session_demo", + negotiationSessionDigest: digest, + subjectResourceRef: "resource:repo:demo", + subjectProtectedActionContextRefs: ["candidate_action:candidate_demo"], + runtimePosture: "declared_runtime_context", + parties: [ + { + partyId: "party_initiator", + partyRole: "initiator", + agentRef: "agent:local", + organizationRef: "org:local", + runtimeRef: "runtime:codex", + endpointRef: null, + identityProofPosture: "host_verified_ref", + identityEvidenceRefs: ["identity-evidence:local"], + identityProofDigest: digest, + proofGapRefs: [], + }, + { + partyId: "party_counterparty", + partyRole: "counterparty", + agentRef: "agent:remote", + organizationRef: null, + runtimeRef: "runtime:a2a", + endpointRef: "https://agent.example.test", + identityProofPosture: "proof_gap_recorded", + identityEvidenceRefs: [], + identityProofDigest: null, + proofGapRefs: ["proof_gap:counterparty_identity"], + }, + ], + generatedCodeOrSpecRefs: ["generated_graph:demo"], + declaredAssumptions: ["counterparty endpoint was supplied by runtime evidence"], + uncertaintyMarkers: ["counterparty identity is not locally verified"], + externalProtocolEvidenceRefs: [validExternalRef()], + clearingEvidenceRefs: { correlationRef: "a2a:task:demo" }, + expiresAt: later, + }; +} + +function validExternalRef() { + return { + protocol: "a2a", + protocolVersion: "0.3.0", + objectKind: "Task", + objectRef: "a2a:task:demo", + objectDigest: digest, + evidencePosture: "imported_evidence_only", + evidenceUse: "conversation_context", + proofGapRefs: [], + }; +} + +function validOffer() { + return { + ...base, + negotiationOfferId: "negotiation_offer_v1", + negotiationSessionId: "negotiation_session_demo", + offerVersionId: "offer_version_1", + offerSequence: 1, + offeredByPartyId: "party_initiator", + previousOfferVersionId: null, + supersedesOfferVersionId: null, + offerContentDigest: digest, + offerObjectRefs: ["object:offer:v1"], + offerContentRefs: ["content:offer:v1"], + proofGapRefs: [], + externalProtocolEvidenceRefs: [validExternalRef()], + generatedCodeOrSpecRefs: ["generated_graph:demo"], + declaredAssumptions: ["offer was generated from local planning evidence"], + uncertaintyMarkers: [], + clearingEvidenceRefs: { obligationRef: "obligation:demo" }, + expiresAt: later, + }; +} + +function validDecision() { + return { + ...base, + negotiationDecisionId: "negotiation_decision_demo", + negotiationSessionId: "negotiation_session_demo", + decidedOfferVersionId: "offer_version_1", + decidedOfferSequence: 1, + decidedByPartyId: "party_counterparty", + decision: "accept", + reasonCodes: ["offer_terms_accepted"], + evidenceRefs: ["evidence:decision"], + proofGapRefs: [], + counterOfferVersionId: null, + decisionDigest: digest, + }; +} + +function validAgreement() { + return { + ...base, + linkedAgreementId: "linked_agreement_demo", + negotiationSessionId: "negotiation_session_demo", + acceptedOfferVersionId: "offer_version_1", + acceptedOfferSequence: 1, + agreementDigest: digest, + agreementObjectRefs: ["object:agreement:v1"], + agreementContentRefs: ["content:agreement:v1"], + proofGapRefs: [], + agreementEvidencePosture: "local_evidence_only", + clearingEvidenceRefs: { correlationRef: "agreement:demo" }, + externalProtocolEvidenceRefs: [validExternalRef()], + }; +} + +function validObligationBinding() { + return { + ...base, + agreementObligationBindingId: "agreement_obligation_binding_demo", + linkedAgreementId: "linked_agreement_demo", + negotiationSessionId: "negotiation_session_demo", + obligationRef: "obligation:local-protected-action", + obligationDigest: otherDigest, + bindingPosture: "local_evidence_only", + localProtectedActionEvidenceRefs: [ + { + refKind: "action_contract", + ref: "action_contract:proposed_demo", + digest, + }, + ], + evidenceRefs: ["evidence:obligation-binding"], + proofGapRefs: [], + }; +} + +function validStatusTransition() { + return { + ...base, + agreementStatusTransitionId: "agreement_status_transition_demo", + linkedAgreementId: "linked_agreement_demo", + negotiationSessionId: "negotiation_session_demo", + fromStatus: "active", + toStatus: "disputed", + reasonCodes: ["counterparty_disputed_terms"], + evidenceRefs: ["evidence:status-transition"], + proofGapRefs: [], + transitionDigest: digest, + }; +} diff --git a/test/protocol/object-registry.test.ts b/test/protocol/object-registry.test.ts index 2da4d4f..1f2418f 100644 --- a/test/protocol/object-registry.test.ts +++ b/test/protocol/object-registry.test.ts @@ -31,6 +31,12 @@ const idFields = { tool_call_draft: "toolCallDraftId", protected_path_posture: "protectedPathPostureId", intent_compilation: "intentCompilationId", + negotiation_session: "negotiationSessionId", + negotiation_offer: "negotiationOfferId", + negotiation_decision: "negotiationDecisionId", + linked_agreement: "linkedAgreementId", + agreement_obligation_binding: "agreementObligationBindingId", + agreement_status_transition: "agreementStatusTransitionId", action_contract: "actionContractId", authority_certificate: "authorityCertificateId", policy_decision: "policyDecisionId", From bce7b8eb2ca3e85ed03f4136bea9890b3162007f Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Tue, 26 May 2026 10:01:54 +0800 Subject: [PATCH 017/144] fix(protocol): harden negotiation evidence schemas --- src/protocol/areas/negotiation/schemas.ts | 61 +++++++++++-- .../negotiation-object-registry.test.ts | 12 +++ test/protocol/negotiation-schemas.test.ts | 85 ++++++++++++++++++- 3 files changed, 152 insertions(+), 6 deletions(-) diff --git a/src/protocol/areas/negotiation/schemas.ts b/src/protocol/areas/negotiation/schemas.ts index 44c5824..e8e0cdc 100644 --- a/src/protocol/areas/negotiation/schemas.ts +++ b/src/protocol/areas/negotiation/schemas.ts @@ -67,15 +67,24 @@ export const ExternalProtocolEvidenceRefSchema = z.strictObject({ }); export type ExternalProtocolEvidenceRef = z.infer; -const OfferVersionRefSchema = IdSchema.refine((value) => !["latest", "current", "unspecified"].includes(value), { - message: "decisions must bind to a specific offer version", -}); +const forbiddenOfferVersionAliases = ["latest", "current", "unspecified"] as const; +const OfferVersionRefSchema = IdSchema.refine( + (value) => { + const normalized = value.toLowerCase(); + return !forbiddenOfferVersionAliases.some((alias) => normalized.includes(alias)); + }, + { + message: "offer version refs must bind to a specific offer version", + }, +); const disallowedObligationRefPattern = new RegExp( [ "greenlight", "gateway[_:-]?check", + "gate[_:-]?attempt", "mutation[_:-]?attempt", + "policy[_:-]?decision", "receipt", "authority[_:-]?certificate", "settlement", @@ -94,19 +103,38 @@ const EvidenceRefSchema = z.strictObject({ digest: DigestSchema.nullable().default(null), }); +const NonAuthorityContextRefSchema = ResourceRefSchema.refine((value) => !disallowedObligationRefPattern.test(value), { + message: "negotiation context ref cannot point at a control or terminal artifact", +}); + export const NegotiationSessionSchema = ProtocolBaseSchema.extend({ negotiationSessionId: IdSchema, negotiationSessionDigest: DigestSchema, subjectResourceRef: ResourceRefSchema, - subjectProtectedActionContextRefs: z.array(ResourceRefSchema).default([]), + subjectProtectedActionContextRefs: z.array(NonAuthorityContextRefSchema).default([]), runtimePosture: z.enum(["declared_runtime_context", "observed_runtime_evidence", "proof_gap_recorded"]), - parties: z.array(NegotiationPartyBindingSchema).min(1), + parties: z.array(NegotiationPartyBindingSchema).min(2), generatedCodeOrSpecRefs: z.array(ResourceRefSchema).default([]), declaredAssumptions: z.array(z.string().min(1).max(500)).default([]), uncertaintyMarkers: z.array(z.string().min(1).max(500)).default([]), externalProtocolEvidenceRefs: z.array(ExternalProtocolEvidenceRefSchema).default([]), clearingEvidenceRefs: ClearingEvidenceRefsSchema, expiresAt: IsoDateSchema.nullable().default(null), +}).superRefine((value, ctx) => { + if (!value.parties.some((party) => party.partyRole === "initiator")) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "negotiation sessions require an initiator party", + path: ["parties"], + }); + } + if (!value.parties.some((party) => party.partyRole === "counterparty")) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "negotiation sessions require a counterparty party", + path: ["parties"], + }); + } }); export type NegotiationSession = z.infer; @@ -143,6 +171,21 @@ export const NegotiationDecisionSchema = ProtocolBaseSchema.extend({ proofGapRefs: z.array(ResourceRefSchema).default([]), counterOfferVersionId: OfferVersionRefSchema.nullable().default(null), decisionDigest: DigestSchema, +}).superRefine((value, ctx) => { + if (value.decision === "counter" && value.counterOfferVersionId === null) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "counter decisions require a specific counter offer version", + path: ["counterOfferVersionId"], + }); + } + if (value.decision !== "counter" && value.counterOfferVersionId !== null) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "only counter decisions may reference a counter offer version", + path: ["counterOfferVersionId"], + }); + } }); export type NegotiationDecision = z.infer; @@ -186,6 +229,14 @@ export const AgreementStatusTransitionSchema = ProtocolBaseSchema.extend({ evidenceRefs: z.array(ResourceRefSchema).default([]), proofGapRefs: z.array(ResourceRefSchema).default([]), transitionDigest: DigestSchema, +}).superRefine((value, ctx) => { + if (value.fromStatus === value.toStatus) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "agreement status transitions must change status", + path: ["toStatus"], + }); + } }); export type AgreementStatusTransition = z.infer; diff --git a/test/protocol/negotiation-object-registry.test.ts b/test/protocol/negotiation-object-registry.test.ts index 81747e2..21e8485 100644 --- a/test/protocol/negotiation-object-registry.test.ts +++ b/test/protocol/negotiation-object-registry.test.ts @@ -106,6 +106,18 @@ const validPayloads = { identityProofDigest: null, proofGapRefs: [], }, + { + partyId: "party_counterparty", + partyRole: "counterparty", + agentRef: "agent:remote", + organizationRef: null, + runtimeRef: "runtime:a2a", + endpointRef: "https://agent.example.test", + identityProofPosture: "proof_gap_recorded", + identityEvidenceRefs: [], + identityProofDigest: null, + proofGapRefs: ["proof_gap:counterparty_identity"], + }, ], generatedCodeOrSpecRefs: [], declaredAssumptions: [], diff --git a/test/protocol/negotiation-schemas.test.ts b/test/protocol/negotiation-schemas.test.ts index 45d527f..b9f2b11 100644 --- a/test/protocol/negotiation-schemas.test.ts +++ b/test/protocol/negotiation-schemas.test.ts @@ -53,6 +53,18 @@ describe("negotiation evidence schemas", () => { expect(NegotiationPartyBindingSchema.safeParse({ ...party, proofGapRefs: [] }).success).toBe(false); }); + it("requires sessions to carry both initiator and counterparty evidence", () => { + expect( + NegotiationSessionSchema.safeParse({ ...validSession(), parties: [validSession().parties[0]] }).success, + ).toBe(false); + expect( + NegotiationSessionSchema.safeParse({ + ...validSession(), + parties: [validSession().parties[0], { ...validSession().parties[1], partyRole: "observer" }], + }).success, + ).toBe(false); + }); + it("rejects raw transcript or raw-readable term fields on negotiation sessions", () => { expect( NegotiationSessionSchema.safeParse({ @@ -62,6 +74,18 @@ describe("negotiation evidence schemas", () => { ).toBe(false); }); + it.each(["greenlight:demo", "gate_attempt:demo", "gateway_check:demo", "receipt:demo", "policy_decision:demo"])( + "rejects authority-shaped protected-action context refs: %s", + (contextRef) => { + expect( + NegotiationSessionSchema.safeParse({ + ...validSession(), + subjectProtectedActionContextRefs: [contextRef], + }).success, + ).toBe(false); + }, + ); + it("parses offers only when content digests have refs or proof-gap refs", () => { expect(NegotiationOfferSchema.parse(validOffer())).toMatchObject({ negotiationOfferId: "negotiation_offer_v1", @@ -113,6 +137,51 @@ describe("negotiation evidence schemas", () => { ).toBe(false); }); + it.each(["latest", "Latest", "offer:latest", "offer_current", "offer-unspecified"])( + "rejects non-specific offer version refs: %s", + (offerVersionRef) => { + expect( + NegotiationDecisionSchema.safeParse({ + ...validDecision(), + decidedOfferVersionId: offerVersionRef, + }).success, + ).toBe(false); + expect( + NegotiationOfferSchema.safeParse({ + ...validOffer(), + offerVersionId: offerVersionRef, + }).success, + ).toBe(false); + expect( + LinkedAgreementSchema.safeParse({ + ...validAgreement(), + acceptedOfferVersionId: offerVersionRef, + }).success, + ).toBe(false); + }, + ); + + it("requires counter decisions to bind a specific counter-offer version", () => { + expect(NegotiationDecisionSchema.safeParse({ ...validDecision(), decision: "counter" }).success).toBe(false); + expect( + NegotiationDecisionSchema.parse({ + ...validDecision(), + decision: "counter", + counterOfferVersionId: "offer_version_2", + }), + ).toMatchObject({ + decision: "counter", + counterOfferVersionId: "offer_version_2", + }); + expect( + NegotiationDecisionSchema.safeParse({ + ...validDecision(), + decision: "accept", + counterOfferVersionId: "offer_version_2", + }).success, + ).toBe(false); + }); + it("parses linked agreement evidence without accepting receipt or certificate fields", () => { expect(LinkedAgreementSchema.parse(validAgreement())).toMatchObject({ linkedAgreementId: "linked_agreement_demo", @@ -150,7 +219,9 @@ describe("negotiation evidence schemas", () => { it.each([ "greenlight", "gateway_check", + "gate_attempt", "mutation_attempt", + "policy_decision", "receipt", "authority_certificate", "settlement", @@ -158,12 +229,18 @@ describe("negotiation evidence schemas", () => { "signer", "reusable_authority", ])("rejects authority-shaped obligation refs: %s", (forbiddenKind) => { + expect( + AgreementObligationBindingSchema.safeParse({ + ...validObligationBinding(), + obligationRef: `${forbiddenKind}:demo`, + }).success, + ).toBe(false); expect( AgreementObligationBindingSchema.safeParse({ ...validObligationBinding(), localProtectedActionEvidenceRefs: [ { - refKind: forbiddenKind, + refKind: "action_contract", ref: `${forbiddenKind}:demo`, digest, }, @@ -178,6 +255,12 @@ describe("negotiation evidence schemas", () => { fromStatus: "active", toStatus: "disputed", }); + expect( + AgreementStatusTransitionSchema.safeParse({ + ...validStatusTransition(), + toStatus: validStatusTransition().fromStatus, + }).success, + ).toBe(false); }); it("keeps external protocol refs digest-bound and imported evidence only", () => { From 09630b9a81cbf691e32880dd09664838b392f825 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Tue, 26 May 2026 10:02:22 +0800 Subject: [PATCH 018/144] docs(planning): refresh codebase map --- .planning/codebase/ARCHITECTURE.md | 506 +++++++++++++++-------------- .planning/codebase/CONCERNS.md | 473 +++++++++++++-------------- .planning/codebase/CONVENTIONS.md | 188 ++++------- .planning/codebase/INTEGRATIONS.md | 311 +++++++----------- .planning/codebase/STACK.md | 198 ++++------- .planning/codebase/STRUCTURE.md | 503 +++++++++++++++------------- .planning/codebase/TESTING.md | 324 +++++++++--------- 7 files changed, 1197 insertions(+), 1306 deletions(-) diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md index b14c03f..a16727d 100644 --- a/.planning/codebase/ARCHITECTURE.md +++ b/.planning/codebase/ARCHITECTURE.md @@ -1,308 +1,332 @@ - + # Architecture -**Analysis Date:** 2026-05-25 +**Analysis Date:** 2026-05-26 ## System Overview ```text -Product and integration surfaces -`src/cli`, `src/mcp`, `src/sdk`, `src/http`, `src/runtime`, `src/surfaces` - | - v -HTTP admission and route dispatch -`src/http/app.ts`, `src/http/admission/index.ts`, -`src/http/routes/transition-route-registry.ts`, -`src/http/routes/transition-invokers.ts` - | - v -Protocol authority kernel -`src/protocol/kernel.ts`, `src/protocol/areas/*` - | - v -Protocol store and reconstruction state -`src/protocol/store/port.ts`, `src/storage/*`, `migrations/0001_protocol_kernel.sql` - | - +--> Gateway adapters before mutation - | `src/adapters/x402-payment/wallet-gateway.ts`, - | `src/adapters/package-install/gateway.ts` - | - +--> Evidence projections and read models - `src/protocol/evidence-projections/*`, - `src/http/handlers/evidence-read.ts` +External callers, hosts, package consumers, and local tools + | + |-- HTTP/Worker transport: `src/http/app.ts`, `src/worker.ts` + |-- SDK transport: `src/sdk/client.ts`, `src/sdk/surface-clients/*` + |-- MCP proposal/evidence: `src/mcp/*`, `src/mcp/stdio/*` + |-- CLI readback/operator commands: `src/cli/*`, `bin/handshake` + |-- Published subpaths: `src/adapter-sdk`, `src/hosted-admission`, + | `src/x402-protected-tool`, `src/surfaces/service-workflow-admission` + | + v +Product/readback and admission surfaces + `src/surfaces/boundary-manifest.ts` + `src/surfaces/service-workflow-admission/index.ts` + `src/http/admission/*` + | + v +Protocol authority spine + `src/protocol/kernel.ts` + `src/protocol/areas/*` + `src/protocol/foundation/*` + `src/protocol/events/*` + | + |-- Evidence-only protocol area: + | `src/protocol/areas/negotiation/*` + | + v +Append-only record/event persistence + `src/protocol/store/port.ts` + `src/storage/d1/index.ts` + `src/storage/memory/index.ts` + `migrations/0001_protocol_kernel.sql` + | + v +Gateway adapters and protected surfaces + `src/adapters/*` + `src/protocol/evidence-projections/*` + `src/http/handlers/evidence-read.ts` ``` ## Component Responsibilities | Component | Responsibility | File | |-----------|----------------|------| -| Canonical repo doctrine | Defines current product kernel, authority invariants, and scratch-vs-canon boundaries. | `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` | -| Protocol kernel facade | Coordinates protocol transitions and persists append-only state through the store port. | `src/protocol/kernel.ts` | -| Protocol areas | Own source-level schemas, transition inputs, transition outputs, and state-machine rules for each protected-action primitive. | `src/protocol/areas/*` | -| Policy greenlight area | Produces policy decisions and one-use greenlights without performing gateway checks or mutations. | `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/policy-greenlight/policy-record/index.ts` | -| Gateway gate area | Verifies exact greenlight, contract, idempotency, isolation, path posture, credential binding, and drift before consequence. | `src/protocol/areas/gateway-gate/transitions.ts`, `src/protocol/areas/gateway-gate/artifacts.ts` | -| Runtime ingress | Compiles runtime/tool observations into candidate actions and contracts; it is proposal-only. | `src/runtime/ingress/index.ts`, `src/runtime/ingress/registry.ts` | -| HTTP transport | Enforces caller custody/read admission and dispatches route IDs to kernel transitions. | `src/http/app.ts`, `src/http/admission/index.ts`, `src/http/routes/transition-route-registry.ts`, `src/http/routes/transition-invokers.ts` | -| Gateway adapters | Hold mutation-side integration logic and only execute after a verified gateway check. | `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/package-install/gateway.ts` | -| Evidence projections | Build redacted review/readback models from stored protocol records. | `src/protocol/evidence-projections/projections.ts`, `src/protocol/evidence-projections/assembly.ts` | -| Storage adapters | Implement append-only events, current indexes, greenlight consumption, idempotency ledgers, and scoped reads. | `src/storage/memory/index.ts`, `src/storage/d1/index.ts`, `src/protocol/store/port.ts` | -| Architecture tests | Freeze import posture, package surfaces, surface authority boundaries, and public claims. | `test/architecture/*` | +| Package root | Curated public exports for HTTP app creation, protocol schemas/inputs, SDK client, protocol navigation, gateway verification helpers, and certificate verification. | `src/index.ts` | +| Worker entrypoint | Creates the Hono app and exposes the Cloudflare Worker `fetch` handler. | `src/worker.ts` | +| HTTP app | Registers transition routes, evidence routes, hosted readiness, verifier endpoints, raw internal read endpoint, body limits, security headers, error envelopes, and transition request identity headers. | `src/http/app.ts` | +| HTTP route registry | Declares each `/v0.2/*` transition path, custody role, scope resolver, request schema, response schema, and non-authority summary. | `src/http/routes/transition-route-registry.ts` | +| HTTP transition invokers | Maps route ids to `HandshakeKernel` methods and the composite runtime-ingress proposal bridge. | `src/http/routes/transition-invokers.ts` | +| Hosted admission | Performs provider-neutral caller admission, hosted identity freshness checks, scoped route checks, read entitlement checks, and redacted caller evidence generation. | `src/http/admission/*`, `src/hosted-admission/*` | +| Kernel facade | Owns the authority transition surface and delegates to protocol area transition modules. | `src/protocol/kernel.ts` | +| Protocol areas | Own primitive schemas, inputs, guards, transitions, and local indexes by authority area. | `src/protocol/areas/*` | +| Negotiation evidence area | Records A2A-style negotiation sessions, offers, decisions, linked agreements, obligation bindings, and status transitions as imported/local evidence only. It has schemas and input aliases, no transitions, no root export, and no product/runtime imports. | `src/protocol/areas/negotiation/*` | +| Object registry | Discriminates every durable protocol object type, including the negotiation evidence object types added in commit `4946237`. | `src/protocol/areas/object-registry/schemas.ts` | +| Event schemas | Defines append-only event types, including `negotiation_*_recorded` and `agreement_*_recorded` evidence events. | `src/protocol/events/schemas.ts` | +| Protocol recorder | Builds canonical records, commits records with event chains, retries stream conflicts, and writes transition request context evidence. | `src/protocol/events/records.ts` | +| Store port | Defines atomic protocol persistence, stream reads, current-index reads, one-use greenlight consumption, and gateway-check commit contracts. | `src/protocol/store/port.ts` | +| D1 store | Durable reference `ProtocolStore` implementation using SQL statements and batched commits. | `src/storage/d1/index.ts` | +| Memory store | In-memory `ProtocolStore` fixture and invariant oracle. | `src/storage/memory/index.ts` | +| Runtime ingress | Converts generated dispatch blocks into runtime evidence, generated graph evidence, tool-call drafts, intent compilations, and action-contract proposals without policy or gateway authority. | `src/runtime/ingress/index.ts` | +| Runtime family registry | Names supported runtime dispatch families: package install, x402 payment, and auth.md protected API call. | `src/runtime/ingress/registry.ts` | +| Reference gateways | Demonstrate mutation only after `VerifiedGatewayCheck`, then reconcile downstream evidence or proof gaps. | `src/adapters/*/gateway.ts` | +| x402 wallet gateway | Official x402 exact buyer-side signer path; signer/payment material stays inside the wallet gateway after gate verification. | `src/adapters/x402-payment/wallet-gateway.ts` | +| SDK clients | Invoke public HTTP transition/evidence routes and role-scoped activation clients; clients transport custody, not product authority. | `src/sdk/client.ts`, `src/sdk/surface-clients/*` | +| MCP surface | Model-facing proposal/evidence catalog for `handshake.actions.x402_payment.propose` plus read-only resources. | `src/mcp/*` | +| CLI surface | Local command manifest and JSON evidence/operator commands without gateway, policy, signer, receipt export, or mutation authority. | `src/cli/*` | +| Adapter SDK | Definition-only protected-action adapter pack and install-proposal shape review surface. | `src/adapter-sdk/index.ts` | +| x402 protected tool | Public protected-tool facade/profile/readiness subpath for first normal-agent-tool x402 proposal flow; proposal and profile only. | `src/x402-protected-tool/index.ts` | +| Surfaces manifest | Source-owned surface ids, allowed route families, forbidden imports, forbidden credentials, and required non-authority flags. | `src/surfaces/boundary-manifest.ts` | +| Service workflow projection | Admission, handle, principal-agent link, and context refs as non-authority readback/projection contracts. | `src/surfaces/service-workflow-admission/index.ts` | +| Conformance | Narrow invariant probes for protected mutation adapters and x402 posture checks. | `src/conformance/index.ts` | ## Pattern Overview -**Overall:** Source-owned protocol kernel with narrow transport/adapters, append-only receipts, and redacted projection read models. +**Overall:** Layered protocol authority kernel with port/adapters persistence and constrained proposal/readback surfaces. **Key Characteristics:** -- Authority lives in protocol transitions and gateway checks, not in CLI, SDK, MCP, review UI, runtime ingress, public exports, or generated demos. -- Policy greenlights are exact, one-use, gateway-bound records; they are not execution proof and do not perform mutation. -- Gateway adapters hold the final mutation boundary and must obtain `VerifiedGatewayCheck` evidence before calling an external surface. -- Evidence read models are projections assembled from protocol records; they support review and recovery but do not create authority. -- `.planning/` is scratch; tracked source, root docs, and `docs/internal/*` are the current repo truth. +- Protocol meaning lives in `src/protocol/areas/*`; transports and product surfaces call the kernel or public schemas rather than owning primitive semantics. +- Authority-bearing transitions flow through `HandshakeKernel` in `src/protocol/kernel.ts:100` and `ProtocolRecorder` in `src/protocol/events/records.ts:77`. +- Runtime, MCP, CLI, SDK, hosted admission, adapter SDK, service workflow, and protected-tool surfaces are proposal/readback/setup surfaces unless they explicitly route to a protocol transition. +- Gateway-side mutation adapters must require `VerifiedGatewayCheck` before protected consequence in files such as `src/adapters/x402-payment/wallet-gateway.ts` and `src/adapters/package-install/gateway.ts`. +- The A2A negotiation area from commit `4946237` is evidence-only: `src/protocol/areas/negotiation/schemas.ts` defines records, while `test/architecture/negotiation-no-authority-surface.test.ts` guards against transitions, root export, control-area imports, and downstream surface imports. ## Layers -**Canonical Doctrine:** -- Purpose: Define the current product boundary and the vocabulary future work must obey. -- Location: `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md` -- Contains: Product kernel, decisions, quality rules, source ownership rules, protocol notes. -- Depends on: No source implementation. -- Used by: Planning, implementation, architecture tests, package-surface claims. - -**Surface and Client Layer:** -- Purpose: Expose Handshake through CLI, MCP, SDK role clients, demos, and public package exports without becoming authority. -- Location: `src/cli`, `src/mcp`, `src/sdk`, `src/surfaces`, `src/index.ts`, `src/experimental.ts` -- Contains: Command manifests, MCP server glue, role clients, renderable surfaces, curated package exports, experimental reference fixtures. -- Depends on: Public protocol/surface contracts and HTTP clients. -- Used by: Consumers, examples, package exports, conformance demos. - -**Runtime Proposal Layer:** -- Purpose: Convert runtime/tool observations into intent compilation records and proposed action contracts. -- Location: `src/runtime/ingress/index.ts`, `src/runtime/ingress/families.ts`, `src/runtime/ingress/registry.ts` -- Contains: Proposal-only family registry for `package.install`, `x402_payment.exact`, and `auth.md.protected_api_call`; generated graph and tool-call draft recording. -- Depends on: Protocol kernel transitions that create proposal records. -- Used by: HTTP transition route `runtimeIngress.proposeActionContracts` and demos. - -**Admission and Transport Layer:** -- Purpose: Admit or reject HTTP callers by custody role, entitlement, route metadata, tenant/org scope, and hosted scope posture. -- Location: `src/http/app.ts`, `src/http/admission/index.ts`, `src/http/routes/*`, `src/http/handlers/*` -- Contains: Hono app, transition route registry, transition invokers, evidence read routes, record-read handlers, readiness/verifier handlers. -- Depends on: `src/protocol/kernel.ts`, `src/storage/*`, request headers, route metadata. -- Used by: Cloudflare Worker entry point `src/worker.ts`, SDK/CLI/MCP clients, hosted or local HTTP deployments. - **Protocol Authority Kernel:** -- Purpose: Own the state machine that turns exact contracts into policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, and certificates. -- Location: `src/protocol/kernel.ts`, `src/protocol/areas/*` -- Contains: Source-owned schemas, transition inputs, transition outputs, digest/canonicalization helpers, status transitions, receipts, isolation records. -- Depends on: Protocol store port and protocol-local utilities. -- Used by: HTTP transport, tests, adapters, projection assembly. - -**Gateway Adapter Layer:** -- Purpose: Bridge verified gateway checks to real mutation surfaces. -- Location: `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/package-install/gateway.ts` -- Contains: Adapter-specific gateway execution, credential resolution evidence, official signer custody for x402, package-install surface invocation. -- Depends on: `src/protocol/areas/gateway-gate/artifacts.ts`, kernel gateway-check transitions, adapter-specific mutation APIs. -- Used by: External integration examples and runtime-gateway flows. - -**Persistence Layer:** -- Purpose: Persist append-only events and current-state indexes required for reconstruction and replay protection. -- Location: `src/protocol/store/port.ts`, `src/storage/memory/index.ts`, `src/storage/d1/index.ts`, `src/storage/kv`, `migrations/0001_protocol_kernel.sql` -- Contains: Store interface, in-memory implementation, D1 implementation, Cloudflare KV helpers, SQL tables for current ledgers and stream events. -- Depends on: Protocol record types. -- Used by: Kernel, HTTP app, projections, tests. - -**Projection and Read Model Layer:** -- Purpose: Build scoped, redacted evidence views for review, recovery, and diagnostics. -- Location: `src/protocol/evidence-projections/projections.ts`, `src/protocol/evidence-projections/assembly.ts`, `src/http/routes/evidence-read-route-registry.ts`, `src/http/handlers/evidence-read.ts`, `src/http/handlers/internal-record-read.ts` -- Contains: Contract evidence projection, transaction envelope projection, timeline projection, read-route role/scope metadata, raw record guardrails. -- Depends on: Store reads and protocol record types. -- Used by: Review custody and runtime evidence read endpoints. - -## Authority Boundary - -**Authority lives here:** -- `src/protocol/areas/policy-greenlight/transitions.ts` evaluates policy and records policy decisions while explicitly keeping gateway checks and mutation attempts false. -- `src/protocol/areas/policy-greenlight/policy-record/index.ts` creates `Greenlight` records bound to contract digest, policy pack, gateway, idempotency key, and `maxUses: 1`. -- `src/protocol/areas/gateway-gate/transitions.ts` verifies the exact greenlight, observed request digest, isolation state, protected path posture, delegated authority binding, gateway credential binding, sequence dependencies, idempotency ledger, and gateway policy drift before committing a gateway plan. -- `src/protocol/areas/gateway-gate/artifacts.ts` exposes `verifiedGatewayCheckFromResult` only when the gateway check passes and a mutation attempt/surface operation reference exists. -- `src/adapters/x402-payment/wallet-gateway.ts` signs x402 payloads only after deriving verified gateway evidence from the kernel. -- `src/adapters/package-install/gateway.ts` calls the package-install mutation surface only after verified gateway evidence exists. -- `src/storage/memory/index.ts`, `src/storage/d1/index.ts`, and `migrations/0001_protocol_kernel.sql` enforce replay-sensitive current indexes such as greenlight consumption, idempotency ledger, isolation current state, protected path operation claims, and receipt lookup. - -**Authority does not live here:** -- `src/runtime/ingress/index.ts` records proposed contracts and sets non-authority posture; it does not issue greenlights, gateway checks, or mutation proof. -- `src/http/admission/index.ts` admits callers to routes and evidence reads; admission is custody/read entitlement, not permission to mutate. -- `src/protocol/evidence-projections/*` builds read models; projections never write greenlights or gateway checks. -- `src/cli`, `src/mcp`, `src/sdk`, `src/surfaces`, and `examples/*` expose product surfaces and demos; they must not become hidden policy or gateway authority. -- `src/index.ts` curates public exports and intentionally excludes the kernel class, stores, internal recorder, and reference gateway runners from the root package surface. - -## Passport, Admission, Service Gateway, Principal-Agent Link - -**Current source-owned shapes:** -- Passport-like identity is represented as evidence binding, not authority: `ParticipantIdentityBinding` in `src/protocol/areas/catalog-envelope/schemas.ts` and `OperatingEnvelope.participantIdentityBindings` in `src/protocol/areas/catalog-envelope/schemas.ts`. -- The principal-agent link is already explicit on `OperatingEnvelope` in `src/protocol/areas/catalog-envelope/schemas.ts`, copied onto `ActionContract` in `src/protocol/areas/action-contract/schemas.ts`, and bound through `DelegatedAuthorityRef` in `src/protocol/areas/delegated-authority/schemas.ts`. -- Admission is HTTP route custody and read entitlement in `src/http/admission/index.ts`, using metadata from `src/http/routes/transition-route-registry.ts` and `src/http/routes/evidence-read-route-registry.ts`. -- Service gateway concepts map to `GatewayRegistryEntry` in `src/protocol/areas/catalog-envelope/schemas.ts`, `GatewayCredentialRef` and custody proof packets in `src/protocol/areas/credential-custody/schemas.ts`, and gateway checks in `src/protocol/areas/gateway-gate/*`. - -**Simplification rule:** -- Do not add a separate `Passport` protocol primitive unless it narrows exact gateway enforcement. Treat passport as a projection/readback name over `ParticipantIdentityBinding`, `OperatingEnvelope`, `ActionContract`, and `DelegatedAuthorityRef`. -- Do not make admission a source of protected-action authority. Keep admission as caller custody and route entitlement, then let policy greenlight and gateway check decide consequence. -- Do not introduce a new service-gateway layer beside the existing gateway registry, credential custody, and gateway gate. Rename or project if needed, but keep the mutation boundary in `src/protocol/areas/gateway-gate/*` and adapter gateway files. -- Keep the principal-agent link as canonical source data on envelope, contract, and delegated authority references; avoid duplicating it into a reusable auth token. +- Purpose: Own exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, recovery, review binding, generated-execution evidence boundaries, and canonical transition invariants. +- Location: `src/protocol/` +- Contains: `src/protocol/kernel.ts`, `src/protocol/areas/*`, `src/protocol/foundation/*`, `src/protocol/events/*`, `src/protocol/context/*`, `src/protocol/navigation/*`, `src/protocol/public/*`, `src/protocol/store/*`. +- Depends on: Zod schemas, deterministic canonicalization, `ProtocolStore` port, and protocol-local modules. +- Used by: `src/http/*`, `src/sdk/*`, `src/runtime/*`, `src/mcp/*`, `src/adapters/*`, and tests. + +**Evidence-Only Negotiation Area:** +- Purpose: Record imported A2A/ACP/ANP/AP2/MCP/runtime-handoff negotiation context and local agreement evidence without creating protected-action authority. +- Location: `src/protocol/areas/negotiation/` +- Contains: `NegotiationSessionSchema`, `NegotiationOfferSchema`, `NegotiationDecisionSchema`, `LinkedAgreementSchema`, `AgreementObligationBindingSchema`, and `AgreementStatusTransitionSchema` in `src/protocol/areas/negotiation/schemas.ts`. +- Depends on: `src/protocol/foundation/schema-core.ts` and `zod`. +- Used by: `src/protocol/areas/object-registry/schemas.ts` and protocol tests only. +- Constraint: Do not add `transitions.ts`, package-root exports, SDK/HTTP/MCP/CLI imports, policy-greenlight imports, gateway-gate imports, receipt-export imports, or authority-certificate imports for this phase. + +**Runtime Proposal Evidence:** +- Purpose: Convert observed generated execution into runtime records, graph records, draft tool-call state, intent compilations, action-contract proposals, or refusals. +- Location: `src/runtime/` +- Contains: `src/runtime/ingress/index.ts`, `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/registry.ts`, `src/runtime/package-install/action-proposal.ts`, `src/runtime/codemode-multi-action/*`. +- Depends on: Protocol public/area types and adapter-family proposal builders. +- Used by: HTTP runtime ingress route, SDK `RuntimeClient`, MCP x402 proposal bridge, examples, and tests. + +**HTTP Transport And Admission:** +- Purpose: Bind transition routes to custody roles, validate request bodies, build request-context evidence, apply hosted or token admission, and invoke kernel methods. +- Location: `src/http/` +- Contains: `src/http/app.ts`, `src/http/routes/*`, `src/http/admission/*`, `src/http/handlers/*`, `src/http/errors/*`, `src/http/openapi/*`, `src/http/store/*`. +- Depends on: Protocol public schemas, `HandshakeKernel`, storage resolution, Hono, and admission helpers. +- Used by: `src/worker.ts`, SDK clients, integration tests, and Worker runtime. + +**Storage Port And Implementations:** +- Purpose: Persist canonical protocol records, event streams, current indexes, idempotency state, isolation state, protected-path posture, operation claims, receipt indexes, and greenlight consumption. +- Location: `src/protocol/store/`, `src/storage/` +- Contains: `src/protocol/store/port.ts`, `src/storage/d1/index.ts`, `src/storage/d1/statements.ts`, `src/storage/memory/index.ts`, `src/storage/kv/index.ts`. +- Depends on: Protocol object metadata and event schemas. +- Used by: `ProtocolRecorder`, `HandshakeKernel`, HTTP store resolution, D1/HTTP tests, and invariant tests. + +**Gateway Adapter Proof Lanes:** +- Purpose: Hold reference mutation behavior and upstream profile evidence; mutation-capable adapters run only after verified gateway checks. +- Location: `src/adapters/` +- Contains: `src/adapters/x402-payment/*`, `src/adapters/package-install/*`, `src/adapters/repo-write/*`, `src/adapters/preview-deploy/*`, `src/adapters/auth-md/*`, `src/adapters/protected-path-probes/*`. +- Depends on: Gateway verification helpers and protocol public schemas. +- Used by: `src/experimental.ts`, `src/x402-protected-tool/*`, conformance tests, adapter tests, and demos. + +**Product/Readback Surfaces:** +- Purpose: Expose proposal, setup, profile, readback, readiness, support, and local verification surfaces without creating protocol authority. +- Location: `src/surfaces/`, `src/cli/`, `src/mcp/`, `src/sdk/`, `src/adapter-sdk/`, `src/hosted-admission/`, `src/x402-protected-tool/` +- Contains: Surface boundary manifest, CLI command manifest, MCP catalog/resources, SDK role clients, hosted admission helper exports, adapter authoring definitions, service workflow projection contracts, protected-tool profiles. +- Depends on: Public schemas/inputs, transport helpers, surface manifests, and narrow adapter profile helpers. +- Used by: package exports in `package.json`, package bins in `bin/`, product tests, architecture tests, and examples. ## Data Flow -### Primary Protected-Action Path +### Primary Protected Action Path + +1. Runtime, MCP, SDK, or HTTP submits generated execution/proposal evidence (`src/runtime/ingress/index.ts:176`, `src/mcp/x402-proposal.ts:146`, `src/sdk/surface-clients/runtime-client.ts:20`, `src/http/app.ts:37`). +2. Runtime ingress records runtime execution, generated graph evidence, and finalized tool-call drafts (`src/runtime/ingress/index.ts:190`, `src/runtime/ingress/index.ts:261`, `src/runtime/ingress/index.ts:655`). +3. Intent compilation reduces proposed work to a `CandidateAction` or refusal (`src/protocol/areas/intent-compilation/transitions.ts:43`). +4. Action contract proposal canonicalizes one contractable candidate and asserts catalog/envelope/gateway/credential/delegated-authority bindings (`src/protocol/areas/action-contract/transitions.ts:53`). +5. Policy evaluation computes exact policy input, checks isolation, sequence dependencies, protected-path posture, idempotency, gateway credential refs, and delegated authority refs (`src/protocol/areas/policy-greenlight/transitions.ts:126`). +6. Gateway check verifies the exact greenlight, observed parameters, policy drift, idempotency, isolation, protected-path posture, delegated authority refs, and credential refs before mutation (`src/protocol/areas/gateway-gate/transitions.ts:87`). +7. Adapter performs consequence only after `verifiedGatewayCheckFromResult` returns a verified gate, then records credential resolution, reconciliation, receipt, refusal, or proof gap (`src/adapters/x402-payment/wallet-gateway.ts:177`, `src/adapters/package-install/gateway.ts:95`). +8. Records and stream events commit through `ProtocolRecorder` and `ProtocolStore` (`src/protocol/events/records.ts:77`, `src/protocol/store/port.ts:155`). + +### A2A Negotiation Evidence Path -1. Caller reaches the Worker/Hono app (`src/worker.ts`, `src/http/app.ts`). -2. HTTP route metadata selects custody requirements and the kernel invoker (`src/http/routes/transition-route-registry.ts`, `src/http/routes/transition-invokers.ts`). -3. Admission checks caller role, route family, hosted scope, tenant/org scope, and evidence-read posture (`src/http/admission/index.ts`). -4. Runtime ingress or explicit transition creates intent compilation, contract, catalog envelope, authority reference, credential posture, and related records (`src/runtime/ingress/index.ts`, `src/protocol/kernel.ts`). -5. Policy evaluation records decision and, when allowed, a one-use greenlight bound to the exact contract and gateway (`src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/policy-greenlight/policy-record/index.ts`). -6. Gateway check revalidates current state, exact request digest, idempotency, isolation, delegated authority, credential custody, protected path posture, sequencing, and policy drift (`src/protocol/areas/gateway-gate/transitions.ts`). -7. Adapter performs external mutation only after verified gateway evidence exists (`src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/package-install/gateway.ts`). -8. Receipt, refusal, proof gap, reconciliation, recovery, isolation, or certificate records are appended to the store (`src/protocol/kernel.ts`, `src/protocol/store/port.ts`, `src/storage/*`). +1. External negotiation context is represented as digest-bound imported evidence refs, party proof posture, offers, decisions, linked agreements, obligation bindings, and status transitions (`src/protocol/areas/negotiation/schemas.ts:97`, `src/protocol/areas/negotiation/schemas.ts:113`, `src/protocol/areas/negotiation/schemas.ts:164`). +2. Negotiation object types are admitted to the protocol object registry (`src/protocol/areas/object-registry/schemas.ts:64`, `src/protocol/areas/object-registry/schemas.ts:119`). +3. Negotiation events are represented as event vocabulary for reconstruction (`src/protocol/events/schemas.ts:25`). +4. Architecture tests keep this area out of authority, root package exports, and downstream product/runtime surfaces (`test/architecture/negotiation-no-authority-surface.test.ts:8`). +5. A linked agreement may reference local `candidate_action`, `intent_compilation`, `generated_execution_graph`, or `action_contract` evidence, but it cannot point at greenlights, gateway checks, receipts, certificates, settlement, payment, signers, or reusable authority (`src/protocol/areas/negotiation/schemas.ts:64`, `src/protocol/areas/negotiation/schemas.ts:164`). -### Evidence Read Path +### HTTP Transition Path -1. Caller requests a read route declared in `src/http/routes/evidence-read-route-registry.ts`. -2. Admission validates role, read scope, tenant/org scope, and artifact posture (`src/http/admission/index.ts`). -3. Handler loads only needed protocol records from the store (`src/http/handlers/evidence-read.ts`, `src/http/handlers/internal-record-read.ts`). -4. Projection code redacts and assembles review/readback views (`src/protocol/evidence-projections/projections.ts`, `src/protocol/evidence-projections/assembly.ts`). -5. HTTP response returns evidence projection, not raw authority or mutation permission (`src/http/handlers/evidence-read.ts`). +1. `createApp()` installs transition routes from `transitionRouteDefinitions` (`src/http/app.ts:37`, `src/http/app.ts:54`). +2. `handleTransition()` authorizes caller custody, builds transition request context, parses body against the route schema, resolves hosted scope when configured, and calls the route invoker (`src/http/app.ts:122`). +3. `transitionInvokers` invokes a kernel method or composite runtime-ingress proposal (`src/http/routes/transition-invokers.ts:10`, `src/http/routes/transition-invokers.ts:36`). +4. `kernelFor()` constructs a `HandshakeKernel` over D1 or an explicit fallback store (`src/http/store/resolution.ts:10`). -### Runtime Ingress Proposal Path +### Product/Readback Surface Path -1. Runtime ingress receives tool/action observations and declared runtime posture (`src/runtime/ingress/index.ts`). -2. Registry selects a proposal-only action family (`src/runtime/ingress/registry.ts`, `src/runtime/ingress/families.ts`). -3. Kernel records runtime execution, generated action graph, tool-call draft, intent compilation, and action contract (`src/runtime/ingress/index.ts`, `src/protocol/kernel.ts`). -4. Response declares candidate actions and explicitly marks policy, greenlight, gateway check, mutation, receipt, certificate, and permission as false (`src/runtime/ingress/index.ts`). +1. Surface manifests define which surfaces may write/read which route families and which imports/credential shapes are forbidden (`src/surfaces/boundary-manifest.ts:1`, `src/surfaces/boundary-manifest.ts:202`, `src/surfaces/boundary-manifest.ts:610`). +2. Service workflow contracts expose `Passport`, `ServiceWorkflowAdmission`, `ServiceWorkflowHandle`, `PrincipalAgentLink`, and context refs as projection/readback evidence only (`src/surfaces/service-workflow-admission/index.ts:24`, `src/surfaces/service-workflow-admission/index.ts:58`, `src/surfaces/service-workflow-admission/index.ts:209`). +3. CLI, MCP, SDK, adapter SDK, hosted admission, and x402 protected-tool subpaths must keep non-authority flags explicit and route fresh consequential work back into the protocol authority path (`src/cli/command-manifest.ts`, `src/mcp/x402-proposal.ts`, `src/sdk/surface-clients/*`, `src/adapter-sdk/index.ts`, `src/hosted-admission/index.ts`, `src/x402-protected-tool/index.ts`). **State Management:** -- State is append-only plus current-index ledgers. `migrations/0001_protocol_kernel.sql` defines durable D1 tables for stream events, greenlight consumption, idempotency current state, isolation current state, protected path operation claims, and receipt lookup. `src/storage/memory/index.ts` mirrors those semantics for tests and local runs. +- Durable state is canonical `ProtocolRecord` plus `ContractStreamEvent` evidence, not in-memory service objects (`src/protocol/areas/object-registry/schemas.ts`, `src/protocol/events/schemas.ts`). +- D1 is the durable reference implementation (`src/storage/d1/index.ts:23`); memory is a fixture/oracle (`src/storage/memory/index.ts:29`). +- Current-index state for greenlight issuance, idempotency, isolation, protected path posture, operation claims, and receipt lookup is represented through `ProtocolStore` methods (`src/protocol/store/port.ts:169`, `src/protocol/store/port.ts:177`, `src/protocol/store/port.ts:179`). ## Key Abstractions -**Operating Envelope:** -- Purpose: Bounds attempts, runtime context, participant bindings, catalog references, gateway registry references, and evidence expectations. -- Examples: `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/action-contract/contract-record.ts` -- Pattern: Source data copied into exact contracts; it authorizes attempts, not mutations. - -**Action Contract:** -- Purpose: Exact proposed commitment derived from intent compilation and bound to principal, agent, tenant, organization, gateway, idempotency, protected path, payload, and evidence expectations. -- Examples: `src/protocol/areas/action-contract/schemas.ts`, `src/protocol/areas/action-contract/transitions.ts`, `src/protocol/areas/action-contract/contract-record.ts` -- Pattern: Deterministic contract record before policy and gateway. - -**Policy Decision and Greenlight:** -- Purpose: Machine-checkable decision and one-use authorization candidate for a gateway check. -- Examples: `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/policy-greenlight/policy-record/index.ts` -- Pattern: Policy can allow/refuse/review/halt/quarantine; greenlight is exact and consumed once. - -**Gateway Check:** -- Purpose: Final enforcement proof before mutation. -- Examples: `src/protocol/areas/gateway-gate/transitions.ts`, `src/protocol/areas/gateway-gate/artifacts.ts` -- Pattern: Revalidate exact binding and current posture, then produce verified gateway evidence or refusal/proof gap. - -**Delegated Authority Reference:** -- Purpose: Binds principal, agent, runtime, envelope, gateway, allowed actions, resource bounds, and spend/amount limits without creating mutation authority or secret material. -- Examples: `src/protocol/areas/delegated-authority/schemas.ts`, `src/protocol/areas/delegated-authority/transitions.ts` -- Pattern: Reference and status evidence, checked later by gateway transitions. - -**Credential Custody:** -- Purpose: Records gateway-held credential posture and proof packets while keeping secret material outside protocol records. -- Examples: `src/protocol/areas/credential-custody/schemas.ts`, `src/protocol/areas/credential-custody/transitions.ts` -- Pattern: Evidence of custody and resolution; adapters hold signing/mutation capability. - -**Evidence Projection:** -- Purpose: Read model for review/recovery that omits raw secrets and authority-bearing material. -- Examples: `src/protocol/evidence-projections/projections.ts`, `src/protocol/evidence-projections/assembly.ts` -- Pattern: Redacted projection assembled from stored protocol records. +**`HandshakeKernel`:** +- Purpose: Transition facade over protocol areas. +- Examples: `src/protocol/kernel.ts:100`, `src/protocol/kernel.ts:156`, `src/protocol/kernel.ts:192`, `src/protocol/kernel.ts:196` +- Pattern: Thin method facade; semantic work stays in area modules. + +**`ProtocolStore`:** +- Purpose: Persistence port for records, event streams, current indexes, idempotency, isolation, and gateway-check atomic commits. +- Examples: `src/protocol/store/port.ts:155`, `src/storage/d1/index.ts:23`, `src/storage/memory/index.ts:29` +- Pattern: Port/adapters; protocol transitions depend on the port, not D1/memory directly. + +**`ProtocolRecord` And `ContractStreamEvent`:** +- Purpose: Canonical durable object and append-only reconstruction event. +- Examples: `src/protocol/areas/object-registry/schemas.ts`, `src/protocol/events/schemas.ts` +- Pattern: Discriminated Zod object registry plus event vocabulary. + +**`CandidateAction` -> `ActionContract`:** +- Purpose: Separate compiler output from exact proposed commitment. +- Examples: `src/protocol/areas/intent-compilation/transitions.ts:43`, `src/protocol/areas/action-contract/transitions.ts:53` +- Pattern: Deterministic candidate digest and contract digest binding. + +**`PolicyDecision` / `Greenlight` / `GatewayCheck`:** +- Purpose: Separate exact policy outcome from one-use gateway-bound pre-mutation enforcement. +- Examples: `src/protocol/areas/policy-greenlight/transitions.ts:126`, `src/protocol/areas/gateway-gate/transitions.ts:87` +- Pattern: Policy may issue one-use authority; gateway consumes and verifies before consequence. + +**`AuthorityCertificate`:** +- Purpose: Terminal evidence verification, not permission. +- Examples: `src/protocol/areas/authority-certificate/*`, `src/index.ts:28` +- Pattern: Certificate signs existing terminal evidence and is verified against explicit trust material. + +**`SurfaceBoundary`:** +- Purpose: Source-owned manifest for product/readback surface claims, allowed route families, forbidden imports, and required non-authority flags. +- Examples: `src/surfaces/boundary-manifest.ts:1`, `test/architecture/surface-boundary-posture.test.ts` +- Pattern: Architecture tests enforce boundary posture. + +**`NegotiationSession` / `LinkedAgreement`:** +- Purpose: A2A-style negotiation and agreement evidence records that can support reconstruction without replacing local protected-action clearance. +- Examples: `src/protocol/areas/negotiation/schemas.ts:97`, `src/protocol/areas/negotiation/schemas.ts:151` +- Pattern: Strict evidence-only schema area; no transition module and no root export. ## Entry Points -**Worker HTTP Entry:** +**HTTP Worker:** - Location: `src/worker.ts` -- Triggers: Cloudflare Worker fetch events. -- Responsibilities: Instantiate `createApp()` and delegate HTTP handling. +- Triggers: Cloudflare Worker `fetch` +- Responsibilities: Construct default Hono app and delegate requests. **HTTP App Factory:** - Location: `src/http/app.ts` -- Triggers: Worker, tests, local server runners. -- Responsibilities: Bind store environment, register transition/read routes, run admission, call invokers, format JSON responses. +- Triggers: Worker runtime, tests, embedded server setup. +- Responsibilities: Register transition/evidence routes, enforce admission, parse requests, and invoke kernel transitions. -**Protocol Kernel:** -- Location: `src/protocol/kernel.ts` -- Triggers: HTTP transition invokers, tests, adapter flows. -- Responsibilities: Execute protocol transitions and write protocol records through `ProtocolStore`. - -**Public Package Root:** +**Package Root:** - Location: `src/index.ts` -- Triggers: Package consumers importing `handshake-protocol-kernel`. -- Responsibilities: Export public contract types, role clients, surfaces, and non-internal helpers while excluding kernel/store internals. - -**Experimental Surface:** -- Location: `src/experimental.ts` -- Triggers: Explicit `./experimental` imports. -- Responsibilities: Export reference fixtures and helpers with experimental naming. - -**Adapter Gateways:** -- Location: `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/package-install/gateway.ts` -- Triggers: Adapter-specific protected action execution. -- Responsibilities: Run gateway checks and perform external mutation only after verified gateway evidence. +- Triggers: `import "handshake-protocol-kernel"` +- Responsibilities: Curate stable root exports; keep hosted admission, adapter SDK, MCP, CLI, x402 protected tool, and service workflow helpers on explicit subpaths. + +**CLI:** +- Location: `src/cli/main.ts`, `bin/handshake` +- Triggers: `handshake ...` +- Responsibilities: Local setup/readiness/evidence/conformance/certificate commands; no policy, gateway, signer, receipt export, or mutation authority. + +**MCP Stdio Server:** +- Location: `src/mcp/stdio/server.ts`, `bin/handshake-mcp`, `server.json` +- Triggers: MCP host process. +- Responsibilities: Register proposal tool and read-only evidence resources; no policy, greenlight, gateway check, signer, mutation, receipt export, or certificate minting. + +**SDK Clients:** +- Location: `src/sdk/client.ts`, `src/sdk/surface-clients/*` +- Triggers: Package consumers. +- Responsibilities: Transport transition/evidence requests with role-scoped credentials and typed errors. + +**Runtime Ingress:** +- Location: `src/runtime/ingress/index.ts` +- Triggers: HTTP/SDK runtime ingress route or direct runtime helper call. +- Responsibilities: Convert observed dispatch blocks into proposal evidence and action contracts or refusals. + +**Reference Adapter Gateways:** +- Location: `src/adapters/*/gateway.ts` +- Triggers: Gateway custody process or tests. +- Responsibilities: Verify one-use greenlight through kernel gateway check before calling protected mutation surfaces. ## Architectural Constraints -- **Threading:** TypeScript runs on a single JavaScript event loop in local and Worker-style environments. Concurrency safety is modeled through store-level conflict detection, greenlight consumption, and idempotency ledgers, not threads. -- **Global state:** Runtime ingress action families are registered in module-level maps in `src/runtime/ingress/families.ts` and `src/runtime/ingress/registry.ts`; architecture tests keep them proposal-only. -- **Circular imports:** Architecture tests require protocol areas and the kernel to import area packages through lane-owned public indexes instead of deep sibling internals (`test/architecture/import-posture.test.ts`). -- **Protocol/storage separation:** `src/protocol/areas/*` must not import `src/storage/*`; persistence flows through `src/protocol/store/port.ts`. -- **Transport/protocol separation:** HTTP route metadata, invokers, and response schemas stay in separate files under `src/http/routes`. -- **Projection/authority separation:** Observer and projection files are blocked from importing policy greenlight, gateway gate, delegated authority, credential custody, receipt, isolation, or certificate authority internals. -- **Official signer custody:** The official x402 signer factory remains in `src/adapters/x402-payment/wallet-gateway.ts`; tests block it from SDK, CLI, MCP, root exports, runtime ingress, and generated outputs. +- **Threading:** Node/Bun/Worker event-loop model; no worker-thread orchestration is present in `src/`. +- **Global state:** `src/storage/memory/index.ts` stores fixture state in instance-local maps; `src/mcp/stdio/server.ts` uses reference fixture clients by default; `src/http/app.ts` creates an optional fallback in-memory store only when injected/configured. +- **Circular imports:** Architecture tests in `test/architecture/import-posture.test.ts` guard import posture; use first-level lane manifests such as `src/protocol/LANE.md`, `src/http/LANE.md`, and `src/runtime/LANE.md` when changing imports. +- **Storage atomicity:** Authority-bearing transitions must commit through `ProtocolStore.commitProtocolRecords()` or `ProtocolStore.commitGatewayCheck()` (`src/protocol/store/port.ts:178`, `src/protocol/store/port.ts:179`). +- **Surface/root export curation:** Public subpaths are declared in `package.json`; root export remains curated in `src/index.ts`. +- **Negotiation boundary:** `src/protocol/areas/negotiation/` is evidence-only; do not add policy/gateway/receipt/certificate authority or downstream surface imports. +- **Product surface boundary:** `src/surfaces/service-workflow-admission/index.ts` and `src/hosted-admission/*` are readback/evidence helpers; they must not become policy, gateway, payment, receipt, certificate, or mutation surfaces. ## Anti-Patterns -### Admission As Authority +### Product Surface As Authority -**What happens:** HTTP admission allows a route call and the caller treats that as permission to mutate. -**Why it's wrong:** Admission only proves caller custody/read entitlement; it does not bind an exact action contract, one-use greenlight, gateway check, or mutation attempt. -**Do this instead:** Admit the caller in `src/http/admission/index.ts`, then require policy greenlight and gateway verification through `src/protocol/areas/policy-greenlight/*` and `src/protocol/areas/gateway-gate/*`. +**What happens:** A CLI, MCP, SDK evidence client, service workflow handle, hosted admission record, adapter definition, or x402 protected-tool profile is treated as permission. +**Why it's wrong:** These surfaces expose proposal/readback/setup evidence, not protocol authority. +**Do this instead:** Route consequential work through fresh action-contract, policy, and gateway transitions in `src/protocol/kernel.ts`. -### Projection As Proof +### Negotiation Evidence As Clearance -**What happens:** A review/readback projection is treated as raw evidence or execution proof. -**Why it's wrong:** Projection code intentionally redacts fields such as contract parameters, secret refs, and contract signatures; it is a read model. -**Do this instead:** Use `src/protocol/evidence-projections/*` for review/readback, then trace raw records through scoped store reads and protocol receipts where the caller has authority. +**What happens:** A `LinkedAgreement` or A2A external ref is treated as a greenlight, payment approval, signer access, receipt, or certificate. +**Why it's wrong:** `src/protocol/areas/negotiation/schemas.ts` explicitly marks external refs as imported evidence and blocks authority-shaped obligation refs. +**Do this instead:** Use negotiation records only as evidence refs for a later local protected-action candidate. -### Runtime Ingress As Permission +### Runtime Evidence As Gateway Enforcement -**What happens:** Candidate actions produced by runtime ingress are treated as executable authority. -**Why it's wrong:** Runtime ingress is proposal-only and explicitly reports no policy decision, greenlight, gateway check, mutation attempt, receipt, certificate, or permission. -**Do this instead:** Continue through policy and gateway routes after candidate contract creation (`src/runtime/ingress/index.ts`, `src/protocol/areas/policy-greenlight/*`, `src/protocol/areas/gateway-gate/*`). +**What happens:** Runtime ingress, generated execution graphs, tool-call drafts, or MCP proposal success are treated as enough to mutate. +**Why it's wrong:** Runtime evidence can propose; it cannot evaluate policy, consume greenlights, or own mutation credentials. +**Do this instead:** Use `evaluatePolicy()` and `gatewayCheck()` via `src/protocol/kernel.ts` and only mutate through a gateway adapter after `VerifiedGatewayCheck`. -### New Passport Primitive +### Reusable Greenlight -**What happens:** Passport/admission/service gateway/principal-agent link becomes a parallel protocol object beside existing envelope, contract, delegated authority, credential custody, and gateway registry records. -**Why it's wrong:** It duplicates authority-adjacent state and creates room for reusable ambient permission. -**Do this instead:** Project a passport read model from `ParticipantIdentityBinding`, `OperatingEnvelope`, `ActionContract`, `DelegatedAuthorityRef`, and credential/gateway evidence without adding a new authority-bearing record. +**What happens:** One greenlight is replayed across multiple gateway attempts or divergent parameters. +**Why it's wrong:** This is ambient authority; `ProtocolStore.consumeGreenlight()` and gateway replay refusal exist to prevent it. +**Do this instead:** Create a new exact action contract for new parameters, retries, or follow-up recovery. + +### Hidden Surface Exception + +**What happens:** A product/readback surface imports protocol internals, storage, gateway fixtures, signer code, or raw records to make a demo easier. +**Why it's wrong:** It bypasses the declared surface manifest and makes the UI/API advisory claims look enforceable. +**Do this instead:** Update `src/surfaces/boundary-manifest.ts` first and add architecture tests before exposing any new route family or import root. ## Error Handling -**Strategy:** Protocol transitions return structured decisions, refusals, proof gaps, conflict statuses, and evidence records instead of throwing across authority boundaries. +**Strategy:** Protocol failures become typed `HandshakeProtocolError`, structured HTTP transition error envelopes, durable refusals, replay refusals, proof gaps, or explicit conflict outcomes. **Patterns:** -- Gateway checks return passed/refused/proof-gap outcomes with specific failure posture in `src/protocol/areas/gateway-gate/transitions.ts`. -- Store writes detect greenlight consumption, idempotency conflicts, protected-path conflicts, receipt conflicts, and isolation-current conflicts in `src/storage/memory/index.ts` and `src/storage/d1/index.ts`. -- HTTP handlers catch typed transition outcomes and return JSON with route identity headers in `src/http/app.ts`. -- Missing evidence is recorded as proof gap or diagnostic posture rather than converted into success in `src/protocol/areas/*`. +- Validate all boundary inputs through Zod schemas in files such as `src/protocol/public/inputs.ts`, `src/runtime/ingress/schemas.ts`, and `src/mcp/x402-proposal.ts`. +- Throw `HandshakeProtocolError` for protocol violations and map it to HTTP error envelopes in `src/http/errors/transition-error-envelope.ts`. +- Record refusals and proof gaps as first-class protocol objects rather than smoothing uncertainty into success. +- Return surface-level non-authority outcomes from MCP and CLI for stale metadata, not-ready posture, invalid input, or refused proposals. ## Cross-Cutting Concerns -**Logging:** Runtime and protocol evidence is structured as records in the store, not free-form logs. Console output is limited to examples and scripts such as `examples/*/run.mjs` and `scripts/*`. -**Validation:** Source-owned schema validation lives beside each protocol area in files such as `src/protocol/areas/action-contract/schemas.ts`, `src/protocol/areas/catalog-envelope/schemas.ts`, and `src/protocol/areas/credential-custody/schemas.ts`. -**Authentication:** HTTP admission validates caller role, route family, hosted verifier entitlement, and scope in `src/http/admission/index.ts`; protected-action authority still requires policy and gateway records. -**Receipts:** Receipts, reconciliation, certificates, recovery, and proof gaps are protocol records assembled into projections by `src/protocol/evidence-projections/assembly.ts`. -**Package Boundaries:** `package.json`, `src/index.ts`, `src/experimental.ts`, and `test/architecture/package-surface.test.ts` keep internal authority surfaces out of public root exports. +**Logging:** No shared logging framework is present. Evidence and diagnostics are represented as protocol records, stream events, reason codes, redacted projections, and CLI/MCP structured outputs. + +**Validation:** Zod schemas are the primary boundary validators across `src/protocol/areas/*/schemas.ts`, `src/protocol/public/*`, `src/runtime/ingress/schemas.ts`, `src/mcp/x402-proposal.ts`, and `src/surfaces/service-workflow-admission/index.ts`. + +**Authentication:** HTTP uses role-scoped bearer custody in `src/http/admission/caller-auth.ts`; hosted mode uses provider-neutral verifier adapters and redacted caller evidence in `src/http/admission/*` and `src/hosted-admission/*`. + +**Redaction:** Surface outputs must keep credential/payment material out of records and projections. Guardrails live in `src/surfaces/boundary-manifest.ts`, `src/mcp/resources.ts`, `src/cli/command-manifest.ts`, and adapter custody schemas. + +**Canonicalization:** Authority-bearing digests use canonical digest helpers in `src/protocol/foundation/canonical.ts`; candidate params, contract bindings, policy inputs, gateway checks, and negotiation evidence must remain digest-bound. --- -*Architecture analysis: 2026-05-25* +*Architecture analysis: 2026-05-26* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md index cf90452..3263ac4 100644 --- a/.planning/codebase/CONCERNS.md +++ b/.planning/codebase/CONCERNS.md @@ -1,287 +1,260 @@ # Codebase Concerns -**Analysis Date:** 2026-05-25 - -## Map Scope - -- This document treats `.planning/` as scratch context. Canonical repo truth lives in tracked source and docs such as `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, and `docs/internal/protocol-notes.md`. -- No `TODO`, `FIXME`, `HACK`, or `XXX` markers are detected in tracked source, tests, or canonical docs under `src/`, `test/`, `tests/`, `docs/`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, or `AGENTS.md`. -- No source-owned `Passport`, `PrincipalAgentLink`, or standalone service-gateway kernel object is detected. The source model already carries principal/agent identity evidence, delegated attempt authority, gateway registry binding, credential custody, HTTP admission evidence, and gateway checks. -- Existing service gateway references are fixture or endpoint refs, not a kernel object: `test/support/auth-md-flow.ts`, `test/adapters/auth-md-gateway.test.ts`, and `test/adapters/auth-md-adapter.test.ts`. - -## Protocol / Kernel Simplification Risks - -**Passport/admission/service-gateway/principal-agent object pressure:** -- Issue: Adding a new kernel object named `Passport`, `Admission`, `ServiceGateway`, or `PrincipalAgentLink` duplicates existing protocol responsibilities instead of clarifying authority. -- Files: `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/delegated-authority/schemas.ts`, `src/protocol/areas/delegated-authority/transitions.ts`, `src/http/admission/hosted-caller-identity.ts`, `src/http/admission/request-context.ts`, `src/protocol/areas/object-registry/schemas.ts`. -- Impact: A second object can blur whether authority comes from identity evidence, route admission, delegated authority, gateway custody, or the verified gateway check. That creates ambient permission language around a chain that is meant to stay exact and one-use. -- Fix approach: Reuse the existing primitives. Put principal/agent identity evidence in `ParticipantIdentityBinding` on `OperatingEnvelope`; put scoped attempt authority in `DelegatedAuthorityRef`; put service mutation custody in `GatewayRegistryEntry` and `GatewayCredentialRef`; put transport caller evidence in `TransitionCallerIdentity` and `transition_request_context`; put any "passport" view in a projection or packet under `src/surfaces/` or `src/adapters/`, not a new `src/protocol/areas/` object. - -**Kernel object registry expansion is high-friction by design:** -- Issue: New protocol object types require schema ownership, registry posture, navigation, route roles, storage, export/read posture, evidence projection, claim tests, and migration decisions. -- Files: `src/protocol/areas/object-registry/schemas.ts`, `src/protocol/areas/object-registry/index.ts`, `src/protocol/navigation.ts`, `src/http/routes/transition-route-registry.ts`, `src/http/routes/evidence-read-route-registry.ts`, `src/storage/d1/index.ts`, `migrations/0001_protocol_kernel.sql`. -- Impact: A new object that only renames an existing relation increases protocol surface without increasing enforceable control. The likely debt is inconsistent read posture, incomplete isolation scope refs, missing D1 indexes, root export confusion, and product language overclaim. -- Fix approach: Add a kernel object only when it records a distinct terminal or state-transition event that cannot be represented by the existing protocol areas. Otherwise, add a typed projection, proof packet, or adapter profile. - -**Principal-agent link already has an evidence-only shape:** -- Issue: A standalone principal-agent link object is redundant with the envelope identity-binding and delegated-authority model. -- Files: `src/protocol/areas/catalog-envelope/schemas.ts`, `test/protocol/participant-identity-binding.test.ts`, `src/protocol/areas/delegated-authority/schemas.ts`, `src/protocol/areas/delegated-authority/transitions.ts`. -- Impact: If the link object reads as permission, it violates the boundary that principal/agent identity is evidence and that delegated authority authorizes only attempts, not mutation. -- Fix approach: Keep participant identity bindings evidence-only and canonicalized into the envelope digest. Use `DelegatedAuthorityRef` for scoped principal-agent-runtime-envelope-gateway attempt authority, with `greenlightCreated: false` and `mutationAuthorityCreated: false`. - -**Service gateway is an adapter/gateway role, not a protocol role:** -- Issue: "Service gateway" can be modeled as gateway custody or a protected API adapter, but making it a kernel object creates overlap with gateway registry, credential custody, and gateway check semantics. -- Files: `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/credential-custody/schemas.ts`, `src/adapters/auth-md/gateway.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, `src/http/routes/transition-route-registry.ts`. -- Impact: A service-gateway object can launder operational integration into authority. The authority boundary remains `gatewayCheck`, not service discovery, admission, endpoint registration, or credential provenance. -- Fix approach: Keep service-specific behavior in adapter packages such as `src/adapters/auth-md/` and `src/adapters/x402-payment/`. Promote only generic evidence or terminal protocol state to `src/protocol/areas/`. - -## Product-Language Confusion - -**"Admission" is overloaded across product, HTTP, gateway, and surface packets:** -- Issue: Admission means expansion admission in `docs/internal/decisions.md`, hosted route admission in `src/http/admission/index.ts`, gateway-admission status in receipt export schemas, and auth.md+x402 admission packets in product surfaces. -- Files: `docs/internal/decisions.md`, `src/http/admission/index.ts`, `src/http/admission/hosted-admission-config.ts`, `src/protocol/areas/receipt-export/schemas.ts`, `src/surfaces/proof-packets.ts`, `src/surfaces/product-launch-gate-resolution.ts`. -- Impact: The word can make read admission, readiness, or a launch packet sound like execution authority. That is advisory, not Handshake, unless the chain reaches exact contract, policy, one-use greenlight, gateway check, and receipt/refusal/proof gap. -- Fix approach: Use narrower names in new work: `route admission`, `expansion evidence packet`, `gateway check posture`, or `launch gate packet`. Avoid standalone `Admission` as a kernel noun. - -**auth.md + x402 interlock surfaces are evidence, not composite execution:** -- Issue: The interlock packet verifies structural conditions and proof gaps, but it does not make auth.md credential issuance or x402 payment signing a composite live authority path. -- Files: `src/adapters/auth-md-x402-interlock/packet.ts`, `test/architecture/auth-md-x402-interlock-packet.test.ts`, `src/surfaces/proof-packets.ts`, `src/surfaces/product-launch-gate-resolution.ts`, `docs/internal/decisions.md`. -- Impact: Naming it as admission can imply the service call is already cleared. The packet is a launch/evidence surface; authority remains per protected API call and per x402 exact payment action. -- Fix approach: Keep `readyForCompositeExecution: false` as a hard non-claim until the composite path has exact action contracts, policy decisions, one-use greenlights, verified gateway checks, credential/payment evidence, receipts, refusals, and proof gaps. - -**Certificate/passport language risks permission drift:** -- Issue: `AuthorityCertificate` is terminal evidence, but passport-style naming can suggest reusable entry permission. -- Files: `README.md`, `QUALITY.md`, `docs/internal/decisions.md`, `src/protocol/areas/authority-certificate/schemas.ts`, `src/protocol/areas/authority-certificate/transitions.ts`. -- Impact: A certificate or passport label can be mistaken for identity, permission, settlement, hosted trust, or reusable auth. That is ambient authority wearing a badge if it authorizes later calls. -- Fix approach: Use `certificate` only for terminal evidence and use `proof packet` for reviewable surface state. Do not create reusable passport credentials inside the kernel. +**Analysis Date:** 2026-05-26 ## Tech Debt -**Exact protected-action policy is triggered by parameter keys:** -- Issue: `exactProtectedActionPolicyApplies` identifies exact protected-action policy by checking parameter keys such as `gatewayReadinessRef`, `gatewayReadinessDigest`, `policyVersionRef`, `policyVersionDigest`, and `paymentRequirementsDigest`. -- Files: `src/protocol/areas/policy-greenlight/transitions.ts`, `test/protocol/policy-greenlight.test.ts`, `test/protocol/x402-payment-contract.test.ts`. -- Impact: A new action family can accidentally enter this branch by using similar keys, or miss the branch by expressing equivalent evidence under different keys. That makes expansion brittle and can produce inconsistent refusal/greenlight behavior. -- Fix approach: Bind protected-action policy evaluation to explicit action type or policy-pack capability under `src/protocol/areas/policy-greenlight/`, not incidental parameter names. - -**D1 conflict classification depends on database error text:** -- Issue: D1 conflict handling classifies failures by matching substrings from SQLite/D1 error messages and by intentionally forcing a `NOT NULL` constraint in mismatch cases. -- Files: `src/storage/d1/index.ts`, `src/storage/d1/statements.ts`, `migrations/0001_protocol_kernel.sql`, `test/protocol/protocol-store-atomicity-contract.test.ts`, `test/http/d1-http.test.ts`. -- Impact: D1 or SQLite message drift can turn a structured idempotency or one-use-greenlight refusal into an unclassified storage error. -- Fix approach: Prefer deterministic post-failure readbacks and table-specific invariant checks for conflict classification. Keep the current atomicity tests as the minimum regression net. - -**Surface-boundary posture is enforced by string scans:** -- Issue: The boundary manifest and architecture tests check imports, forbidden terms, and credential shapes through source text patterns. -- Files: `src/surfaces/boundary-manifest.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/claim-boundary.test.ts`. -- Impact: String scans can miss dynamic imports, re-export indirection, alias changes, generated code paths, or semantic authority drift. They are claim guardrails, not a runtime enforcement boundary. -- Fix approach: Continue using the tests for product-language discipline, but keep real authority in HTTP route roles, protocol transitions, gateway checks, and storage invariants. - -**Large projection/profile files concentrate unrelated risk:** -- Issue: Several files mix schema projection, claim language, evidence transformation, and product gate posture in large modules. -- Files: `src/surfaces/proof-packets.ts`, `src/adapters/auth-md/profiles.ts`, `src/cli/x402/index.ts`, `src/mcp/x402-proposal.ts`, `src/protocol/evidence-projections/projections.ts`, `src/protocol/areas/policy-greenlight/transitions.ts`. -- Impact: Small copy or schema changes can silently alter product claims, packet readiness, and protocol evidence shape in the same edit. Review burden is high. -- Fix approach: Split by owned concern when edits touch these files: schemas, builders, product-gate verdicts, and text projections. Do not combine behavior changes with language cleanup. - -**Role clients and root exports are deliberately narrow but easy to blur:** -- Issue: The package exposes curated root exports plus deeper role clients and adapter/runtime subpaths. A convenience export can accidentally imply broader authority or make a proposal-only surface look executable. -- Files: `src/index.ts`, `src/sdk/role-clients/index.ts`, `src/sdk/LANE.md`, `test/architecture/root-exports.test.ts`, `README.md`. -- Impact: Import ergonomics can turn package availability into perceived authority, especially around MCP, runtime ingress, and role clients. -- Fix approach: Keep authority-sensitive helpers behind explicit subpaths and preserve `test/architecture/root-exports.test.ts` as a gate for new exports. +**Authority and proof posture are concentrated in large orchestration files:** +- Issue: Several files carry many authority-boundary responsibilities at once: schema normalization, policy posture, proof projection, readback validation, and reason-code construction. +- Files: `src/mcp/x402-proposal.ts`, `src/runtime/ingress/index.ts`, `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/gateway-gate/transitions.ts`, `src/adapters/x402-payment/protected-tool-profile/index.ts`, `src/surfaces/boundary-manifest.ts`, `src/surfaces/proof-packets/product-completion.ts`, `src/protocol/evidence-projections/projections.ts` +- Impact: Small changes in these modules can accidentally widen authority, weaken refusal semantics, or turn a proof-gap/readback surface into an implied control surface. +- Fix approach: Extract narrow helpers only around already-tested invariants. Keep source-owned tests in `test/protocol/kernel-policy-gateway.test.ts`, `test/runtime/runtime-ingress.test.ts`, `test/adapters/x402-wallet-gateway.test.ts`, and `test/architecture/surface-boundary-posture.test.ts` as the refactor guard. + +**Product completion is encoded as proof constants plus scripts:** +- Issue: Launch and product-completion state is represented through source constants and script-read proof packets rather than a single source-owned terminal state machine. +- Files: `src/surfaces/product-launch-gate-resolution.ts`, `src/surfaces/proof-packets/product-completion.ts`, `scripts/check-product-completion.mjs`, `scripts/check-distribution-provenance.mjs`, `scripts/check-live-x402-paid-retry.mjs`, `scripts/check-host-generated-code-containment.mjs`, `test/architecture/product-launch-gate-resolution.test.ts` +- Impact: Product claims can drift when script inputs, generated proof packets, and source constants disagree. The code has guardrails, but the mechanism is still projection-heavy. +- Fix approach: Treat these outputs as evidence/readback only. Do not add new product authority claims without source constants, proof packet validation, and architecture tests in `test/architecture/product-launch-gate-resolution.test.ts`. + +**Surface boundary enforcement is partly manual and regex-based:** +- Issue: The package/product boundary is encoded in a hand-maintained manifest and architecture tests that scan source text for imports, forbidden language, and exported surfaces. +- Files: `src/surfaces/boundary-manifest.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/claim-boundary.test.ts`, `test/architecture/active-vocabulary.test.ts`, `package.json` +- Impact: Static `from` import scans and vocabulary scans can miss dynamic `import()`, generated export paths, or authority leakage expressed through new terminology. +- Fix approach: Keep the manifest small and explicit. Add an AST-based dependency graph check before allowing new public subpaths, source roots, or generated package artifacts. + +**A2A-style negotiation is evidence-only but has no transition layer:** +- Issue: The negotiation area models external protocol evidence, offers, decisions, linked agreements, obligations, and agreement status transitions as schemas and registered objects only. +- Files: `src/protocol/areas/negotiation/LANE.md`, `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/areas/negotiation/inputs.ts`, `src/protocol/areas/negotiation/index.ts`, `src/protocol/events/schemas.ts`, `src/protocol/areas/object-registry/index.ts`, `test/protocol/negotiation-schemas.test.ts`, `test/architecture/negotiation-no-authority-surface.test.ts` +- Impact: The current lane is correctly non-authority, but it does not enforce lifecycle ordering, referential integrity, or readback consistency between a negotiation decision and later protected action evidence. +- Fix approach: Keep `src/protocol/areas/negotiation/` free of policy, gateway, receipt, and authority-certificate imports. Add transition/readback code only if it records evidence and preserves `evidencePosture: "imported_evidence_only"` for A2A references. + +**Runtime ingress caps generated execution blocks at local schema limits:** +- Issue: Runtime ingress accepts at most 32 observed dispatches per block and uses bounded evidence lists, but generated-code programs can branch, loop, retry, and dynamically construct calls beyond a single bounded block. +- Files: `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/index.ts`, `src/runtime/codemode-multi-action/generated-program-runner.ts`, `src/runtime/codemode-multi-action/generated-graph-evidence.ts`, `test/runtime/runtime-ingress.test.ts` +- Impact: Over-limit or truncated execution graphs become proof-gap/refusal evidence. They are not complete host containment proof or full generated-program authority analysis. +- Fix approach: Preserve `truncationStatus`, `unobservedRegionRefs`, and refusal reason codes whenever accepting larger host transcripts or multi-block generated execution evidence. ## Known Bugs -**No reproducible source bug detected in the concern scan:** -- Symptoms: No concrete tracked-source bug is identified by `TODO`/`FIXME` markers or by the targeted passport/admission/service-gateway/principal-agent search. -- Files: `src/`, `test/`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`. -- Trigger: Not applicable. -- Workaround: Treat documented proof gaps and cut lines as product boundaries, not hidden bugs. +**Current distribution launch gate is blocked:** +- Symptoms: Source-owned launch state records current local metadata as `handshake-protocol-kernel@0.2.8`, while public npm latest evidence is `0.2.7`, missing current exports, and MCP Registry lookup/search is not accepted or discoverable. +- Files: `src/surfaces/product-launch-gate-resolution.ts`, `src/surfaces/proof-packets/product-completion.ts`, `scripts/check-distribution-provenance.mjs`, `test/architecture/product-launch-gate-resolution.test.ts`, `README.md`, `docs/internal/decisions.md`, `package.json`, `server.json` +- Trigger: Any product claim that treats public npm or MCP Registry as current 0.2.8 distribution proof. +- Workaround: Claim only historical 0.2.7 distribution evidence. Keep 0.2.8 publication and MCP Registry discoverability as proof gaps until official readback matches `package.json` and `server.json`. -**Live/provider x402 execution is intentionally refused:** -- Symptoms: Non-reference provider environments are rejected before x402 signing. -- Files: `src/adapters/x402-payment/wallet-gateway.ts`, `test/adapters/x402-wallet-gateway.test.ts`, `docs/internal/decisions.md`, `README.md`. -- Trigger: Use of a provider environment posture other than `local_reference_sandbox`. -- Workaround: Keep live/provider x402 claims out of docs and demos until provider custody, facilitator behavior, gateway installation, and settlement evidence are proven. +**Live external x402 proof is blocked by missing funded signer and signed retry evidence:** +- Symptoms: The live provider gate remains `resolved_blocked` with `funded_customer_gateway_signer_missing` and `live_signed_retry_not_exercised`. +- Files: `src/surfaces/product-launch-gate-resolution.ts`, `src/surfaces/proof-packets/product-completion.ts`, `scripts/check-live-x402-paid-retry.mjs`, `test/architecture/product-launch-gate-resolution.test.ts`, `src/adapters/x402-payment/wallet-gateway.ts` +- Trigger: Any claim that the package has completed live external x402 paid execution or customer gateway custody. +- Workaround: Use local/reference x402 proof only. Treat external sandbox/live readiness as custody/readiness evidence until a customer-held funded signer and terminal signed retry proof exist. + +**Codex host activation can be misread as host containment:** +- Symptoms: Codex activation records one default raw sibling probe as `detected` and can still yield host-specific activation readiness, while product completion requires raw sibling refusal in a live host containment transcript before the containment gate can pass. +- Files: `src/adapters/x402-payment/protected-tool-profile/codex-activation.ts`, `src/adapters/protected-path-probes/host-fixture.ts`, `src/surfaces/proof-packets/product-completion.ts`, `scripts/check-host-generated-code-containment.mjs`, `test/adapters/x402-protected-tool-codex-activation.test.ts`, `docs/internal/decisions.md` +- Trigger: A consumer treats `host_specific_ready` activation evidence as proof that raw shell, browser, direct MCP, network, package-manager, signer, or sibling SDK paths are blocked. +- Workaround: Keep activation and containment separate. Host containment requires the structured transcript path consumed by `scripts/check-host-generated-code-containment.mjs`. ## Security Considerations -**Hosted admission verifier is a seam, not a production auth system:** -- Risk: A weak `HostedCallerVerifier` can return a validly shaped `TransitionCallerIdentity` for the wrong caller, tenant, org, project, role, or scope. -- Files: `src/http/admission/index.ts`, `src/http/admission/hosted-caller-identity.ts`, `src/http/admission/hosted-admission-config.ts`, `src/http/LANE.md`, `test/http/http.test.ts`. -- Current mitigation: Hosted admission validates identity shape, freshness, roles, hosted read scopes, route scope, and request context evidence. The hosted config explicitly reports no hosted mutation authority, no payment management, no settlement authority, and no provider custody. -- Recommendations: Treat provider verification, org auth, service credential issuance, and hosted operation as deployment-specific security work outside the kernel. Keep hosted operation in proof-gap language until a concrete verifier implementation and threat model exist. - -**Static bearer role tokens are reference transport credentials:** -- Risk: `CallerAuthTokens` can be mistaken for production organization authentication. -- Files: `src/http/admission/caller-auth.ts`, `src/sdk/client.ts`, `src/sdk/surface-clients/transport.ts`, `src/sdk/LANE.md`, `README.md`. -- Current mitigation: Tokens are role-scoped and constant-time compared; hosted caller identity is modeled separately. -- Recommendations: Use static tokens only for local/reference deployments. Production paths need a hosted verifier with tenant/org/project/role/scope evidence. - -**Credential redaction is heuristic in adapter profiles:** -- Risk: auth.md credential material detection relies on structured schemas plus regex/base64 heuristics that can miss provider-specific secret formats. -- Files: `src/adapters/auth-md/profiles.ts`, `src/adapters/auth-md/gateway.ts`, `src/protocol/areas/credential-custody/schemas.ts`, `docs/internal/protocol-notes.md`. -- Current mitigation: Evidence schemas reject raw credential material and keep `GatewayCredentialRef` opaque. Gateway adapters record credential resolution after verified gateway checks. -- Recommendations: Add provider-specific credential fixtures, fuzzing, and negative tests before any live credential custody claim. - -**Runtime ingress is caller-observed evidence, not host containment:** -- Risk: Raw or sibling tool paths can bypass runtime ingress, especially browser-side tools, shell commands, package managers, or direct network calls outside a wrapper. -- Files: `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/index.ts`, `src/runtime/LANE.md`, `docs/internal/protocol-notes.md`. -- Current mitigation: Runtime ingress records wrapped/raw-sibling/ambiguous posture and emits proposals only. It does not create policy, greenlights, gateway checks, or receipts. -- Recommendations: Do not claim broad runtime interception or sandbox containment. For each runtime integration, document raw bypass posture and prove the protected mutation must pass through the gateway. - -**MCP surfaces are proposal/evidence only:** -- Risk: Registry availability or MCP tool exposure can be misread as executable protection. -- Files: `src/mcp/server.ts`, `src/mcp/x402-proposal.ts`, `server.json`, `README.md`, `test/architecture/root-exports.test.ts`. -- Current mitigation: README and claim-boundary tests state MCP has no policy decisions, greenlights, gateway checks, signers, mutations, receipt export, hosted operation, or broad protection. -- Recommendations: Keep MCP Registry discoverability as a proof gap until acceptance and lookup are verified, and keep MCP authority claims out of package surfaces. +**Hosted raw record reads depend on a configured audit sink in promoted modes:** +- Risk: Raw record read admission requires roles, scopes, purpose, expiry, and raw-read posture, but durable audit persistence is delegated through `hostedRawReadAuditSink`. +- Files: `src/http/handlers/internal-record-read.ts`, `src/http/handlers/raw-read-audit.ts`, `src/http/admission/hosted-admission-config.ts`, `src/http/app-options.ts`, `test/http/http.test.ts` +- Current mitigation: Preview/production hosted raw reads fail closed with `hosted_raw_read_audit_sink_required` when raw reads are gated or allowed and no sink is configured. +- Recommendations: Add a source-owned durable audit sink implementation or D1 audit table before scaling hosted raw reads beyond controlled deployments. + +**Project and workspace raw-read hiding relies on optional payload fields:** +- Risk: Hosted record scope checks always compare tenant/org metadata, but project and workspace checks only apply when `projectId` and `workspaceId` exist on the record payload. +- Files: `src/http/handlers/hosted-record-scope.ts`, `src/http/handlers/internal-record-read.ts`, `src/protocol/store/port.ts`, `test/http/http.test.ts` +- Current mitigation: Cross-tenant and cross-organization reads are hidden as not found, and project/workspace reads are hidden when payload fields are present. +- Recommendations: Promote project/workspace scope into `StoredProtocolRecord` metadata or a dedicated index before relying on hosted raw read isolation for multi-project tenants. + +**Self-hosted transition custody uses static bearer tokens:** +- Risk: Self-hosted callers are admitted by per-role bearer tokens and constant-time comparison. Token rotation, issuance provenance, and revocation are outside the protocol kernel. +- Files: `src/http/admission/caller-auth.ts`, `src/http/admission/index.ts`, `test/support/d1-http-harness.ts`, `README.md` +- Current mitigation: Hosted mode has a verifier-adapter path, and self-hosted mode is explicit about custody being local configuration. +- Recommendations: Do not treat self-hosted bearer token possession as principal identity. Use hosted verifier evidence or an external gateway-controlled admission layer for promoted deployments. + +**Signing and payment material remain narrow but high blast radius:** +- Risk: Wallet payment payload/signature creation and authority-certificate signing handle sensitive signing material. These paths must not leak raw keys, payment payloads, or signatures into package roots, logs, or readback surfaces. +- Files: `src/adapters/x402-payment/wallet-gateway.ts`, `src/protocol/areas/authority-certificate/inputs.ts`, `src/protocol/areas/authority-certificate/signing.ts`, `test/adapters/x402-wallet-gateway.test.ts`, `test/protocol/authority-certificate.test.ts` +- Current mitigation: Payment payload/signature creation occurs after a verified gateway check, and certificate signing is terminal evidence rather than permission. +- Recommendations: Keep these modules out of broad exports. Add redaction tests whenever a new readback, proof packet, CLI command, or MCP resource touches these paths. + +**Negotiation records are audit-readable transition evidence:** +- Risk: Negotiation objects, including A2A imported evidence refs and agreement obligation bindings, are registered as `transition_evidence` with `audit_read`. Misusing those records as authorization would turn evidence into permission. +- Files: `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/areas/object-registry/index.ts`, `test/protocol/negotiation-object-registry.test.ts`, `test/protocol/negotiation-schemas.test.ts`, `test/architecture/negotiation-no-authority-surface.test.ts` +- Current mitigation: Schemas reject authority-shaped obligation refs and external protocol evidence postures such as authorization, identity proof, execution proof, settlement, payment, receipt, or certificate. +- Recommendations: Any A2A importer or readback surface must preserve imported-evidence-only language and must never populate greenlight, gateway-check, receipt, signer, or payment fields from negotiation records. ## Performance Bottlenecks -**In-memory store uses scans and is not a scaling store:** -- Problem: The local store keeps protocol records in memory and resolves many queries by iterating maps or arrays. -- Files: `src/storage/memory/index.ts`, `test/protocol/protocol-store-atomicity-contract.test.ts`. -- Cause: It is designed as local/test/reference storage, not tenant-scale persistence. -- Improvement path: Keep production-facing performance claims on D1 or a real durable store, not `createInMemoryProtocolStore`. - -**Evidence projection and proof packet construction parse large JSON records:** -- Problem: Projection paths fetch protocol records and reconstruct evidence views in process. -- Files: `src/protocol/evidence-projections/projections.ts`, `src/surfaces/proof-packets.ts`, `src/storage/d1/index.ts`. -- Cause: Projection code favors reconstructability and schema validation over precomputed read models. -- Improvement path: Add explicit read models or indexed projection tables only after profiling real tenant workloads. Do not make projection caches authority-bearing. - -**Runtime ingress has bounded dispatch but no broader throughput model:** -- Problem: Dispatch proposal input is capped and validated, but runtime ingestion is not modeled as high-volume event streaming. -- Files: `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/index.ts`. -- Cause: The runtime path is a proposal compiler for known dispatch families, not a host-wide telemetry pipeline. -- Improvement path: Keep the cap as a safety control. Add backpressure and event-stream storage only when a concrete runtime integration requires it. +**D1 record listing is unpaginated for common read paths:** +- Problem: D1 store methods list records by type or action contract without cursor pagination and JSON-parse every returned row. +- Files: `src/storage/d1/index.ts`, `src/protocol/store/port.ts`, `migrations/0001_protocol_kernel.sql`, `test/protocol/protocol-store-atomicity-contract.test.ts` +- Cause: The protocol store API is optimized for reconstructable proof tests and small evidence sets. +- Improvement path: Add cursor/limit arguments to list methods before high-volume hosted readback, tenant export, or audit search. + +**Memory store scans are fixture-grade:** +- Problem: The in-memory store uses maps, arrays, structured cloning, and local scans for indexes that D1 stores in tables. +- Files: `src/storage/memory/index.ts`, `src/protocol/store/port.ts`, `test/protocol/model-based-invariants.test.ts`, `test/protocol/protocol-store-atomicity-contract.test.ts` +- Cause: The memory store is a deterministic test/reference implementation, not a production index. +- Improvement path: Keep production hosted paths on D1-compatible storage. Do not use `createInMemoryProtocolStore` as a scalability signal. + +**Repository quality gates are broad and script-heavy:** +- Problem: The main gate builds, typechecks, lints, formats, tests, packs, and checks diffs; product-proof scripts then require built `dist` artifacts and optional external readbacks. +- Files: `package.json`, `scripts/check-product-completion.mjs`, `scripts/check-distribution-provenance.mjs`, `scripts/check-package-surface.mjs`, `scripts/build-package-bundles.mjs` +- Cause: Product truth is intentionally source-owned and evidence-heavy, so local verification pays full repo cost. +- Improvement path: Keep `npm run check:repo` as the closeout bar, but add focused preflight scripts for mapper/planner tasks that do not need package build or live distribution proof. + +**Large tests slow targeted review:** +- Problem: Several tests exceed 800 lines and bundle many cases into single files. +- Files: `test/architecture/proof-packets.test.ts`, `test/http/http.test.ts`, `test/http/d1-http.test.ts`, `test/runtime/runtime-ingress.test.ts`, `test/adapters/x402-wallet-gateway.test.ts`, `test/protocol/kernel-policy-gateway.test.ts`, `test/integration/x402-d1-http.test.ts` +- Cause: Invariant coverage is centralized around broad protocol stories. +- Improvement path: Split new cases by invariant boundary, not by feature label. Keep high-level regression tests, but add smaller files for new authority, hosted, negotiation, or x402 payment concerns. ## Fragile Areas -**Gateway check consumption and idempotency are correctness-critical:** -- Files: `src/protocol/areas/gateway-gate/transitions.ts`, `src/protocol/areas/gateway-gate/gateway-policy.ts`, `src/storage/d1/index.ts`, `migrations/0001_protocol_kernel.sql`, `test/protocol/protocol-store-atomicity-contract.test.ts`. -- Why fragile: The one-use greenlight invariant depends on exact digest checks, gateway-policy drift checks, idempotency ledger entries, and durable consumption records staying aligned. -- Safe modification: Change gateway consumption, idempotency, or D1 statements only with atomicity tests and replay/refusal tests. Do not loosen digest comparisons to improve ergonomics. -- Test coverage: Strong local and D1 tests exist, but conflict classification remains tied to D1 error behavior. - -**Policy evaluation mixes generic and family-specific checks:** -- Files: `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/action-contract/schemas.ts`, `src/protocol/areas/delegated-authority/transitions.ts`. -- Why fragile: Policy checks cover isolation, protected path, sequence deps, gateway credential refs, delegated authority refs, x402-like exact payment parameters, and action-specific matching in one transition area. -- Safe modification: Add explicit evaluators per protected action family while keeping all evaluators under the policy-greenlight transition boundary. -- Test coverage: x402 and delegated-authority tests cover current behavior, but a new action family needs negative tests for accidental policy-branch entry. - -**auth.md adapter profiles contain secret-redaction and provenance logic together:** -- Files: `src/adapters/auth-md/profiles.ts`, `src/adapters/auth-md/gateway.ts`, `test/adapters/auth-md-adapter.test.ts`, `test/adapters/auth-md-gateway.test.ts`. -- Why fragile: Credential provenance, identity assertions, lifecycle evidence, gateway intake, and secret-redaction checks share one profile module. -- Safe modification: Keep raw credential rejection tests green for every profile edit. Split helper modules before adding provider-specific credential formats. -- Test coverage: Good reference tests exist; provider-specific fuzzing and live provider fixtures are gaps. - -**Surface packets can harden or distort product truth:** -- Files: `src/surfaces/proof-packets.ts`, `src/surfaces/product-launch-gate-resolution.ts`, `test/architecture/claim-boundary.test.ts`. -- Why fragile: These files turn protocol evidence into product-facing claims. A field rename can imply a stronger boundary than the kernel enforces. -- Safe modification: Update product packets with claim-boundary tests and canonical docs in the same review. -- Test coverage: Claim-boundary tests are broad, but they remain text and schema checks rather than formal product-proof validation. +**D1 conflict classification depends on provider error text:** +- Files: `src/storage/d1/index.ts`, `test/protocol/protocol-store-atomicity-contract.test.ts`, `test/integration/x402-d1-http.test.ts` +- Why fragile: Atomicity and idempotency paths classify some conflicts from D1 error messages and constraint behavior. Provider wording or driver behavior can change. +- Safe modification: Add tests against the exact D1 adapter behavior before changing schema constraints, unique indexes, or conflict handling. +- Test coverage: `test/protocol/protocol-store-atomicity-contract.test.ts` covers the store contract, but remote/provider drift still needs integration proof. + +**Boundary checks can miss non-static import paths:** +- Files: `src/surfaces/boundary-manifest.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/root-exports.test.ts`, `test/architecture/package-surface.test.ts` +- Why fragile: Current architecture tests primarily inspect static source text and package export metadata. +- Safe modification: When adding a subpath export, generated bundle, or runtime adapter, update `src/surfaces/boundary-manifest.ts`, `package.json`, and package-surface tests in the same change. +- Test coverage: Static tests are strong for known roots and forbidden fragments, but dynamic imports and generated artifacts need additional build-output checks. + +**A2A negotiation records can be overread by downstream consumers:** +- Files: `src/protocol/areas/negotiation/LANE.md`, `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/events/schemas.ts`, `test/protocol/negotiation-events.test.ts`, `test/architecture/negotiation-no-authority-surface.test.ts` +- Why fragile: Terms such as offer, decision, agreement, obligation, and status transition look authority-shaped to product consumers even though the lane is evidence-only. +- Safe modification: Keep event names `*_recorded`, keep object registry export posture as `transition_evidence`, and reject authority-shaped fields at schema boundaries. +- Test coverage: Tests cover non-authority surface posture and schema rejection. They do not prove imported A2A object refs correspond to retrievable source evidence. + +**Readiness names can be stronger than the authority they represent:** +- Files: `src/adapters/x402-payment/protected-tool-readiness/index.ts`, `src/adapters/x402-payment/protected-tool-facade/index.ts`, `src/x402-protected-tool/index.ts`, `test/adapters/x402-hosted-custody-readiness.test.ts`, `test/runtime/x402-protected-tool-facade.test.ts` +- Why fragile: `external_custody_ready`, `host_specific_ready`, and package-readiness outputs are easy to confuse with execution authority. +- Safe modification: Preserve authority-boundary fields and non-claims whenever exposing readiness objects through CLI, MCP, docs, or package subpaths. +- Test coverage: Existing tests assert readiness is pre-contract evidence, but external consumers can still overclaim if examples or docs drop the boundary language. + +**Proof scripts depend on built package artifacts:** +- Files: `scripts/check-product-completion.mjs`, `scripts/check-package-surface.mjs`, `scripts/check-published-entrypoints.mjs`, `scripts/build-package-bundles.mjs`, `package.json` +- Why fragile: Scripts that inspect `dist/` can report stale package shape if source changes without a fresh build. +- Safe modification: Run `npm run build` or the full `npm run check:repo` before treating package-surface or product-completion output as current. +- Test coverage: Package-surface scripts and architecture tests guard the expected shape, but stale local `dist/` state is still an operator hazard. ## Scaling Limits -**Per-call spend is modeled; aggregate spend is not enforced:** -- Current capacity: `DelegatedAuthorityRef` supports per-action atomic limits such as `maxAtomicAmountPerAction`, and policy inputs include per-call amount checks. -- Limit: The kernel does not enforce aggregate budget depletion, rolling spend windows, or multi-call balance reservation. -- Scaling path: Add budget ledger semantics only as a new explicit protocol area or transition, with one-use reservation/consumption/refund evidence. Do not overload `DelegatedAuthorityRef` into aggregate spend. - -**One official x402 buyer-side exact action is the live proof lane:** -- Current capacity: The official wedge is one buyer-side `x402_payment.exact` per-call protected action. -- Limit: Broad x402 compatibility, seller/facilitator finality, provider custody, settlement proof, and cross-merchant payment management are proof gaps. -- Scaling path: Expand by adding action-specific contracts and gateway checks, not by broadening the meaning of the existing x402 contract. - -**Hosted operation is read/admission evidence, not provider enforcement:** -- Current capacity: Hosted admission config and caller identity model route and scope transition/read access. -- Limit: The kernel does not prove production hosted mutation authority, customer gateway installation, provider-side enforcement, or org-wide identity governance. -- Scaling path: Add deployment-specific verifier and gateway-install evidence before claiming hosted operation. - -**Protocol object count is already broad:** -- Current capacity: The object registry includes catalog, envelope, delegated authority, credential custody, runtime evidence, intent compilation, action contract, policy, review, gateway gate, mutation, receipt, recovery, certificate, and stream-event objects. -- Limit: Adding synonyms rather than distinct state transitions increases cognitive load and migration cost. -- Scaling path: Prefer projections and packets for new views; promote to protocol object only for new enforceable state. +**Per-call x402 spend is bounded; aggregate spend is not enforced:** +- Current capacity: The first wedge enforces one exact `x402_payment.exact` per-call protected action with amount, selected payment requirement, gateway credential, delegated authority, and one-use greenlight bindings. +- Limit: There is no source-owned aggregate spend window, budget ledger, merchant risk policy, or multi-call allowance policy in the kernel. +- Scaling path: Add aggregate spend as a separate protected action or policy ledger. Do not reuse one greenlight across calls. +- Files: `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/gateway-gate/gateway-policy.ts`, `src/adapters/x402-payment/action-proposal.ts`, `test/protocol/kernel-policy-gateway.test.ts` + +**Hosted operation is read/admission posture, not hosted mutation authority:** +- Current capacity: Hosted readiness reports admission and redacted/raw evidence read posture, D1/KV presence, verifier strategy, and unsupported capabilities. +- Limit: Hosted mode does not create provider custody, settlement authority, payment management, or hosted mutation authority. +- Scaling path: Introduce explicit hosted mutation contracts and gateway-held custody proof before adding hosted execution claims. +- Files: `src/http/handlers/hosted-readiness.ts`, `src/http/admission/hosted-admission-config.ts`, `src/hosted-admission/hosted-verifier-adapter.ts`, `test/http/http.test.ts`, `README.md` + +**Generated execution evidence is bounded by observed dispatch capture:** +- Current capacity: Runtime ingress handles bounded dispatch blocks, candidate/refusal classification, generated graph evidence, and reason codes. +- Limit: Unobserved code regions, dynamic tool construction, raw sibling routes, and over-limit blocks remain proof gaps or refusals, not complete generated-program containment. +- Scaling path: Add host-native dispatch interception and transcript ingestion before claiming broad codemode protection. +- Files: `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/index.ts`, `src/runtime/codemode-multi-action/generated-program-runner.ts`, `src/runtime/codemode-multi-action/generated-graph-evidence.ts`, `test/runtime/runtime-ingress.test.ts` + +**Negotiation evidence has no durable cross-object lifecycle index:** +- Current capacity: Negotiation objects are registered and events can record sessions, offers, decisions, linked agreements, obligations, and status transitions. +- Limit: The kernel does not enforce status transition ordering, obligation satisfaction, A2A object availability, or agreement-to-action trace closure. +- Scaling path: Add evidence-only transitions and indexes before building A2A importers, readbacks, or reconciliation tools. +- Files: `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/events/schemas.ts`, `src/protocol/areas/object-registry/index.ts`, `migrations/0001_protocol_kernel.sql`, `test/protocol/negotiation-events.test.ts` ## Dependencies at Risk -**MCP alpha packages:** -- Risk: `@modelcontextprotocol/client` and `@modelcontextprotocol/server` are alpha-version dependencies. -- Impact: API or protocol drift can break MCP proposal/evidence tooling. -- Migration plan: Keep MCP under proposal/evidence-only subpaths and preserve smoke tests around `src/mcp/` before broadening docs or exports. - -**x402 SDK packages:** -- Risk: `@x402/core`, `@x402/evm`, and `@x402/fetch` are external protocol SDK dependencies. -- Impact: Exact payment schema, signature generation, selected payment requirement handling, or provider behavior can drift from local assumptions. -- Migration plan: Keep x402 signing behind `src/adapters/x402-payment/wallet-gateway.ts` and conformance tests. Treat live provider behavior as unproven until tested against real providers. - -**Cloudflare D1/Wrangler behavior:** -- Risk: D1 SQL constraints, conflict messages, and Worker runtime behavior are external to the TypeScript kernel. -- Impact: Storage atomicity can fail noisily or classify errors incorrectly if runtime messages change. -- Migration plan: Prefer durable invariant readbacks over message parsing, and keep D1 tests in `test/http/d1-http.test.ts` and `test/integration/x402-d1-http.test.ts`. - -**Bun/TypeScript pre-release stack:** -- Risk: The repo targets Bun and TypeScript 6-era tooling. -- Impact: Build, typecheck, and module-resolution behavior can drift under dependency upgrades. -- Migration plan: Keep `bun.lock`, `tsconfig.json`, `package.json`, and repo gates aligned; run `npm run check:repo` for release-sensitive edits. +**MCP packages are alpha:** +- Risk: `@modelcontextprotocol/client` and `@modelcontextprotocol/server` are pinned to `^2.0.0-alpha.2`. +- Impact: SDK surface drift can break MCP proposal/evidence server behavior, package smoke tests, or external discovery scripts. +- Migration plan: Keep MCP usage behind `src/mcp/` and package smoke tests in `scripts/check-package-surface.mjs`; do not let MCP behavior become authority. +- Files: `package.json`, `src/mcp/x402-proposal.ts`, `src/mcp/server.ts`, `scripts/check-package-surface.mjs` + +**x402 SDK behavior is authority-adjacent:** +- Risk: `@x402/core` and `@x402/fetch` at `2.12.0` define payment payload/signature construction behavior for the buyer-side exact action. +- Impact: SDK drift can change payment material shape, header expectations, or official payment-required parsing. +- Migration plan: Keep SDK calls inside wallet/readiness adapter modules and rerun `test/adapters/x402-wallet-gateway.test.ts`, `test/adapters/x402-payment-action-proposal.test.ts`, and `test/integration/x402-d1-http.test.ts` for upgrades. +- Files: `package.json`, `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/x402-payment/action-proposal.ts`, `src/adapters/x402-payment/protected-tool-readiness/index.ts` + +**Cloudflare D1/KV behavior is part of reconstruction reliability:** +- Risk: Hosted storage uses D1 for structured evidence and KV as a non-authoritative cache. +- Impact: D1 constraint semantics, error messages, or KV expiration behavior can affect atomicity, isolation cache freshness, and readback reliability. +- Migration plan: Treat `src/storage/d1/index.ts` as the production storage contract and keep KV limited to cache posture. +- Files: `package.json`, `src/storage/d1/index.ts`, `src/storage/kv/index.ts`, `migrations/0001_protocol_kernel.sql`, `test/http/d1-http.test.ts` + +**Bun test and Node runtime surfaces both matter:** +- Risk: Tests run under Bun while package scripts, bins, and consumer smoke paths run as Node ESM bundles. +- Impact: A path can pass Bun tests and still fail after bundling or under installed-package Node execution. +- Migration plan: Keep package-surface and installed-artifact checks in the closeout gate when changing exports, bins, MCP server entrypoints, or build output. +- Files: `package.json`, `scripts/build-package-bundles.mjs`, `scripts/check-package-surface.mjs`, `scripts/check-published-entrypoints.mjs`, `test/product/hosted-package-consumer.test.ts` ## Missing Critical Features -**Provider-grade auth.md credential custody:** -- Problem: auth.md credential provenance and redacted gateway intake exist as reference evidence, not provider-grade secret lifecycle proof. -- Blocks: Live protected API custody claims and broad service-gateway claims. -- Files: `src/adapters/auth-md/profiles.ts`, `src/adapters/auth-md/gateway.ts`, `docs/internal/protocol-notes.md`, `docs/internal/decisions.md`. +**Current 0.2.8 public publication and MCP Registry discoverability:** +- Problem: Source metadata targets `handshake-protocol-kernel@0.2.8`, but source-owned launch state keeps current publication and MCP Registry acceptance as blockers. +- Blocks: Current-surface distribution claim, MCP discovery claim, and product-completion closeout. +- Files: `package.json`, `server.json`, `src/surfaces/product-launch-gate-resolution.ts`, `scripts/check-distribution-provenance.mjs`, `README.md`, `docs/internal/decisions.md` -**Composite auth.md + x402 execution:** -- Problem: The interlock packet is a non-authority readiness/evidence surface; composite paid credentialed API calls are not a finished official execution lane. -- Blocks: Claims that auth.md identity/credential issuance plus x402 payment are cleared as one composite service gateway event. -- Files: `src/adapters/auth-md-x402-interlock/packet.ts`, `src/surfaces/product-launch-gate-resolution.ts`, `test/architecture/auth-md-x402-interlock-packet.test.ts`. +**Customer-held live x402 execution proof:** +- Problem: The repo has local/reference and readiness proof paths, but lacks funded customer gateway signer proof and live signed retry evidence. +- Blocks: Live external provider x402 proof and customer gateway custody claim. +- Files: `src/surfaces/product-launch-gate-resolution.ts`, `scripts/check-live-x402-paid-retry.mjs`, `src/adapters/x402-payment/wallet-gateway.ts`, `test/adapters/x402-hosted-custody-readiness.test.ts` -**Hosted operation proof:** -- Problem: Hosted route admission and readiness exist, but production hosted mutation authority and provider/customer gateway installation are proof gaps. -- Blocks: SaaS-style hosted trust claims. -- Files: `src/http/admission/hosted-admission-config.ts`, `src/http/admission/index.ts`, `docs/internal/decisions.md`, `README.md`. +**Source-owned hosted raw-read audit storage:** +- Problem: Hosted raw-read auditing is represented by an application-provided sink, not a protocol-owned durable table in the migration. +- Blocks: Strong hosted raw-read reconstruction guarantees without deployment-specific audit wiring. +- Files: `src/http/handlers/raw-read-audit.ts`, `src/http/handlers/internal-record-read.ts`, `src/http/app-options.ts`, `migrations/0001_protocol_kernel.sql` -**Aggregate budget management:** -- Problem: Per-call spend controls exist, but no aggregate spend ledger or reservation lifecycle exists. -- Blocks: Customer budget products and multi-call payment limits. -- Files: `src/protocol/areas/delegated-authority/schemas.ts`, `src/protocol/areas/delegated-authority/transitions.ts`, `src/protocol/areas/policy-greenlight/transitions.ts`. +**A2A negotiation importer/readback lane:** +- Problem: Negotiation schemas support A2A-style imported evidence refs, but there is no importer, retriever, status transition API, or readback projection that proves the external evidence exists and stays non-authority. +- Blocks: Safe A2A negotiation evidence use in downstream protected-action context. +- Files: `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/areas/negotiation/LANE.md`, `test/protocol/negotiation-schemas.test.ts`, `test/architecture/negotiation-no-authority-surface.test.ts` -**Broad runtime interception:** -- Problem: Runtime ingress supports selected dispatch families and bypass posture evidence; it does not intercept all generated code, browser-side tools, shells, package managers, or network clients. -- Blocks: Claims of host-wide agent containment. -- Files: `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/index.ts`, `src/runtime/LANE.md`. +**Host-native generated-code containment:** +- Problem: Current containment proof is transcript/readback based and explicitly refuses host-wide containment claims. +- Blocks: Claims that Handshake controls arbitrary raw shell, browser, direct MCP, network, package-manager, signer, or sibling SDK routes in a host. +- Files: `scripts/check-host-generated-code-containment.mjs`, `scripts/build-host-generated-code-containment-transcript.mjs`, `src/surfaces/proof-packets/product-completion.ts`, `docs/internal/decisions.md` ## Test Coverage Gaps -**New passport/admission/service-gateway language:** -- What's not tested: No test enforces that `Passport`, standalone `Admission`, `ServiceGateway`, or `PrincipalAgentLink` remains out of the kernel as an authority-bearing object. -- Files: `test/architecture/claim-boundary.test.ts`, `test/architecture/root-exports.test.ts`, `test/protocol/participant-identity-binding.test.ts`, `src/protocol/areas/object-registry/schemas.ts`. -- Risk: A future object or export can introduce permission semantics outside exact contract and gateway check. -- Priority: High. - -**Provider-specific credential redaction and custody:** -- What's not tested: Broad provider credential formats, malformed auth.md credentials, and fuzzed encoded secret shapes. -- Files: `src/adapters/auth-md/profiles.ts`, `test/adapters/auth-md-adapter.test.ts`, `test/adapters/auth-md-gateway.test.ts`. -- Risk: Secret material can enter evidence or receipts if new formats bypass heuristics. -- Priority: High. - -**Live x402 provider/facilitator behavior:** -- What's not tested: Real provider payment requirements, facilitator responses, settlement/finality evidence, and provider custody outside local reference sandbox. -- Files: `src/adapters/x402-payment/wallet-gateway.ts`, `test/adapters/x402-wallet-gateway.test.ts`, `test/integration/x402-d1-http.test.ts`. -- Risk: Local exact-payment proof can be mistaken for live payment finality. -- Priority: High. - -**Semantic boundary enforcement for surfaces:** -- What's not tested: AST-level import restrictions, dynamic imports, generated code, and semantic authority claims in surfaces. -- Files: `src/surfaces/boundary-manifest.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/claim-boundary.test.ts`. -- Risk: A surface can import or imply authority through a path that string scans miss. -- Priority: Medium. - -**Policy evaluator expansion:** -- What's not tested: Negative cases for new protected-action families that share parameter names with x402-like exact protected actions. -- Files: `src/protocol/areas/policy-greenlight/transitions.ts`, `test/protocol/policy-greenlight.test.ts`. -- Risk: Expansion paths can receive wrong policy behavior without obvious type errors. -- Priority: Medium. +**Negotiation lifecycle and A2A object availability:** +- What's not tested: Status transition ordering, linked agreement lifecycle closure, obligation satisfaction, duplicate/refused transition behavior, and retrievable external A2A object refs. +- Files: `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/events/schemas.ts`, `test/protocol/negotiation-schemas.test.ts`, `test/protocol/negotiation-events.test.ts` +- Risk: Downstream readbacks can present a coherent-looking negotiation chain whose external evidence is missing, stale, or not linked to later protected action evidence. +- Priority: High + +**Dynamic import and generated bundle boundary leakage:** +- What's not tested: AST-level dynamic imports, generated bundle dependency graphs, and package artifact imports beyond explicit package-surface scripts. +- Files: `src/surfaces/boundary-manifest.ts`, `test/architecture/surface-boundary-posture.test.ts`, `scripts/build-package-bundles.mjs`, `scripts/check-package-surface.mjs` +- Risk: A public surface can acquire hidden authority-adjacent imports without being caught by string-based source scans. +- Priority: High + +**Remote D1/provider drift under contention:** +- What's not tested: Live remote D1 constraint wording, provider-specific retry behavior under high contention, and migration drift outside the local harness. +- Files: `src/storage/d1/index.ts`, `migrations/0001_protocol_kernel.sql`, `test/http/d1-http.test.ts`, `test/integration/x402-d1-http.test.ts` +- Risk: One-use greenlight consumption, idempotency, and receipt indexing can degrade if provider conflict behavior differs from local test assumptions. +- Priority: Medium + +**Hosted raw-read audit persistence implementations:** +- What's not tested: A production-grade durable audit sink implementation, audit retention/export policy, and raw-read audit search/readback. +- Files: `src/http/handlers/raw-read-audit.ts`, `src/http/handlers/internal-record-read.ts`, `src/http/app-options.ts`, `test/http/http.test.ts` +- Risk: Hosted deployments can satisfy fail-closed sink wiring while still producing audit records that are hard to reconstruct or export. +- Priority: Medium + +**Live host containment evidence:** +- What's not tested: A real host adapter transcript proving dispatch interception, raw sibling refusal, dynamic-tool refusal, and truncated-graph refusal for the named host. +- Files: `scripts/check-host-generated-code-containment.mjs`, `scripts/build-host-generated-code-containment-transcript.mjs`, `src/surfaces/proof-packets/product-completion.ts`, `test/adapters/x402-protected-tool-codex-activation.test.ts` +- Risk: Local activation/readiness evidence can be mistaken for containment without live host transcript proof. +- Priority: High --- -*Concerns audit: 2026-05-25* +*Concerns audit: 2026-05-26* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md index 4e6138e..b558d86 100644 --- a/.planning/codebase/CONVENTIONS.md +++ b/.planning/codebase/CONVENTIONS.md @@ -1,177 +1,127 @@ # Coding Conventions -**Analysis Date:** 2026-05-25 +**Analysis Date:** 2026-05-26 ## Naming Patterns **Files:** -- Use kebab-case files named by owned protocol concepts: `src/protocol/areas/action-contract/transitions.ts`, `src/protocol/areas/gateway-gate/artifacts.ts`, `src/runtime/package-install/action-proposal.ts`. -- Use `index.ts` as the public face for multi-file folders. `test/architecture/naming-posture.test.ts` enforces this for source folders with more than three TypeScript files. -- Keep protocol primitives under `src/protocol/areas//`. Do not add root-level compatibility shims such as `src/protocol/policy.ts`; `test/architecture/import-posture.test.ts` asserts removed shim paths stay absent. -- Do not create bucket directories named `utils`, `helpers`, `common`, `misc`, `stuff`, `manager`, or `service` under `src/**`; `test/architecture/naming-posture.test.ts` fails on those path segments. -- Every first-level source lane needs a `LANE.md` or `README.md` with ownership fields. Existing lanes include `src/protocol/LANE.md`, `src/runtime/LANE.md`, `src/mcp/LANE.md`, `src/sdk/LANE.md`, `src/cli/LANE.md`, `src/surfaces/LANE.md`, and `src/conformance/LANE.md`. -- Tests live in domain folders under `test/`: `test/protocol/`, `test/runtime/`, `test/adapters/`, `test/http/`, `test/architecture/`, `test/mcp/`, `test/cli/`, `test/product/`, `test/conformance/`, `test/integration/`, `test/sdk/`, and `test/adapter-sdk/`. Do not add loose root `test/*.test.ts` files. +- Use lowercase kebab-case for owned source concepts: `src/runtime/package-install/action-proposal.ts`, `src/protocol/areas/action-contract/contract-record.ts`, `src/http/routes/transition-route-registry.ts`. +- Keep protocol primitives under `src/protocol/areas//`: `src/protocol/areas/action-contract`, `src/protocol/areas/policy-greenlight`, `src/protocol/areas/negotiation`. +- Use `index.ts` as the public face for multi-file modules: `src/protocol/areas/action-contract/index.ts`, `src/sdk/surface-clients/index.ts`, `src/http/routes/index.ts`. +- Use lane manifests for first-level source ownership: `src/protocol/LANE.md`, `src/http/LANE.md`, `src/install/LANE.md`, `src/x402-protected-tool/LANE.md`. +- Do not add bucket directories named `utils`, `helpers`, `common`, `misc`, `stuff`, `manager`, or `service` under `src/**`; `test/architecture/naming-posture.test.ts` enforces this. +- Keep tests under a domain directory with `.test.ts` suffix: `test/protocol/kernel-policy-gateway.test.ts`, `test/http/http.test.ts`, `test/adapters/x402-wallet-gateway.test.ts`. Root `test/*.test.ts` files are banned by `test/architecture/naming-posture.test.ts`. **Functions:** -- Use camelCase for functions and methods: `proposeActionContract()` in `src/protocol/areas/action-contract/transitions.ts`, `evaluatePolicy()` in `src/protocol/areas/policy-greenlight/transitions.ts`, `gatewayCheck()` in `src/protocol/areas/gateway-gate/transitions.ts`. -- Protocol write functions should make the write explicit with verbs such as `record*`, `persist*`, `commit*`, `consume*`, `mark*`, or `activate*`. Examples include `recordCredentialResolutionEvidence()` in `src/protocol/kernel.ts` and `commitGatewayCheckPlan()` in `src/protocol/areas/gateway-gate/transitions.ts`. -- Read and derivation functions should use `get*`, `list*`, `derive*`, `build*`, `format*`, `resolve*`, or `project*`. Examples include `deriveGatewayConstraintEvaluation()` in `src/protocol/areas/gateway-gate/transitions.ts`, `buildPolicyInput()` in `src/protocol/areas/policy-greenlight/transitions.ts`, and `projectProtectedActionMetadata()` in `src/protocol/areas/protected-action-representation/projections.ts`. -- Avoid vague protocol mutation verbs such as `handle*`, `process*`, `do*`, and `run*` inside `src/protocol/**`. Runtime and adapter runner entrypoints may use `run*`, such as `runX402WalletGateway()` in `src/adapters/x402-payment/wallet-gateway.ts`. -- Avoid overclaiming function names such as `ensureSafe*`, `guarantee*`, `proveExecution*`, `trustedAgent*`, and `secureApproval*`; `test/architecture/naming-posture.test.ts` enforces this in source. +- Use camelCase exported functions with explicit protocol verbs: `proposeActionContract` in `src/protocol/areas/action-contract/transitions.ts`, `evaluatePolicy` in `src/protocol/areas/policy-greenlight/transitions.ts`, `proposeRuntimeIngressActionContracts` in `src/runtime/ingress/index.ts`. +- Use durable write verbs when a function records state: `recordCredentialResolutionEvidence` in `src/protocol/kernel.ts`, `commitProtocolRecords` in `src/storage/memory/index.ts`, `consumeGreenlight` in `src/storage/memory/index.ts`. +- Use read and derivation verbs for pure projection or lookup work: `getCurrentIdempotencyLedgerEntry` in `src/storage/memory/index.ts`, `derivePolicyConstraintEvaluation` and `buildPolicyInput` in `src/protocol/areas/policy-greenlight/transitions.ts`. +- Avoid vague protocol mutation names in protocol modules. `test/architecture/naming-posture.test.ts` rejects `handle*`, `process*`, `do*`, and `run*` patterns under `src/protocol`. +- Public runners may use `run*` only where runner semantics are explicit, such as `runCliCommand` in `src/cli/main.ts`, `runX402WalletGateway` in `src/adapters/x402-payment/wallet-gateway.ts`, and example `run.ts` files under `examples/**`. +- Avoid overclaiming names such as `ensureSafe*`, `guarantee*`, `proveExecution*`, `trustedAgent*`, and `secureApproval*`; `test/architecture/naming-posture.test.ts` enforces this in `src/**`. **Variables:** -- Use camelCase for local variables and object members. Use precise suffixes for authority-bearing refs and digests: `actionContractId`, `greenlightId`, `candidateDigest`, `gatewayRegistryDigest`, `policyInputDigest`. -- Use uppercase constants for version and fixed-registry values: `PROTOCOL_VERSION` in `src/protocol/foundation/schema-core.ts`, `CANONICALIZER_VERSION` in `src/protocol/foundation/canonical.ts`, and `MAX_STREAM_COMMIT_RETRIES` in `src/protocol/areas/gateway-gate/transitions.ts`. -- Use explicit non-authority booleans on projection and surface outputs: `authorityCreated`, `greenlightCreated`, `gatewayCheckPerformed`, `mutationAttempted`, `rawInternalRecordIncluded`, `credentialMaterialIncluded`, `receiptExportCreated`, and `authorityCertificateMinted`. +- Use camelCase for local values and object fields: `policyInputDigest`, `gatewayCredentialBindingEvaluation`, and `protectedPathPosture` in `src/protocol/areas/policy-greenlight/transitions.ts`. +- Use UPPER_SNAKE_CASE for stable exported constants where they are global protocol headers or versions: `PROTOCOL_VERSION` in `src/protocol/foundation/schema-core.ts`, `CANONICALIZER_VERSION` in `src/protocol/foundation/canonical.ts`. +- Use explicit non-authority flags on product, runtime, CLI, and MCP projections: `authorityCreated`, `greenlightCreated`, `gatewayCheckPerformed`, `mutationAttempted`, `credentialMaterialIncluded`, `authorityCertificateMinted`. +- Use `as const` and `satisfies` to lock literal surfaces without widening: `TEST_CALLER_AUTH_TOKENS` in `test/http/http.test.ts`, `expectedIdByType` in `test/protocol/negotiation-object-registry.test.ts`. +- Use fixture names that state authority posture: `createGreenlitContract`, `recordSafeBypassProbes`, and `makePackageInstallCandidate` in `test/support/fixtures.ts`. **Types:** -- Use PascalCase for TypeScript types and classes: `HandshakeKernel` in `src/protocol/kernel.ts`, `ActionContract` in `src/protocol/areas/action-contract/schemas.ts`, `GatewayCheckResult` in `src/protocol/areas/gateway-gate/artifacts.ts`. -- Pair Zod schemas with inferred types using the `FooSchema` / `type Foo = z.infer` pattern. Examples: `ActionContractSchema` and `ActionContract` in `src/protocol/areas/action-contract/schemas.ts`; `GatewayCheckAttemptSchema` and `GatewayCheckAttempt` in `src/protocol/areas/gateway-gate/schemas.ts`. -- Public transition inputs use named input schemas: `ProposeActionContractInputSchema`, `EvaluatePolicyInputSchema`, `GatewayCheckInputSchema`, `CreateRuntimeExecutionInputSchema`. -- Literal registries use readonly arrays with `as const`, then derive union types from them. Examples: `surfaceIds`, `surfaceRouteFamilies`, and `surfaceAuthorityPostures` in `src/surfaces/boundary-manifest.ts`. +- Use PascalCase type names and schema names ending in `Schema`: `ActionContractSchema` and `ActionContract` in `src/protocol/areas/action-contract/schemas.ts`, `NegotiationSessionSchema` and `NegotiationSession` in `src/protocol/areas/negotiation/schemas.ts`. +- Derive runtime-validated types from Zod schemas with `z.infer` for stored records and `z.input` for caller input shapes: `RuntimeIngressProposalInput` in `src/runtime/ingress/index.ts`, `TransitionErrorEnvelope` in `src/http/errors/transition-error-envelope.ts`. +- Model transition results as discriminated unions or explicit outcome records: `RuntimeIngressActionProposal` in `src/runtime/ingress/index.ts`, `PolicyEvaluationResponse` in `src/protocol/areas/policy-greenlight/transitions.ts`. +- Keep protocol object names exact where they represent primitives: `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheck`, `Receipt`, `Refusal`, `ProofGap`, and `IsolationState` are named in `QUALITY.md`. ## Code Style **Formatting:** -- Use Prettier from `.prettierrc.json`: `printWidth: 120`, semicolons enabled, double quotes, trailing commas. -- Use `.editorconfig`: UTF-8, LF endings, two-space indentation, final newline, trimmed trailing whitespace except Markdown. -- TypeScript is strict. `tsconfig.json` enables `strict`, `noUncheckedIndexedAccess`, and `exactOptionalPropertyTypes`. Treat optional values and array indexing as explicit proof obligations. +- Use Prettier from `.prettierrc.json`: `printWidth: 120`, semicolons enabled, double quotes, trailing commas enabled. +- Use `.editorconfig`: UTF-8, LF endings, two-space indentation, final newline, and trimmed trailing whitespace for code. +- Keep Markdown trailing whitespace behavior from `.editorconfig`; `.md` files do not trim trailing whitespace. +- Format the full tree with `npm run format` and check it with `npm run format:check` from `package.json`. +- TypeScript is strict. `tsconfig.json` enables `strict`, `noUncheckedIndexedAccess`, and `exactOptionalPropertyTypes`; treat optional values and indexed reads as proof obligations. **Linting:** -- ESLint config is `eslint.config.js` with `typescript-eslint` recommended rules. -- Use type-only imports where possible; `@typescript-eslint/consistent-type-imports` is an error and uses separate type imports. -- Unused variables are errors unless prefixed with `_`. -- `console` is an error except `console.warn` and `console.error`; use structured protocol records, receipts, refusals, proof gaps, or CLI JSON instead of incidental logs. - -**Quality gates:** -- Full closeout gate: `npm run check:repo`. -- Focused claim gate: `npm run quality:claims`. -- Focused architecture gate: `npm run quality:architecture`. -- Focused storage/kernel gate: `npm run quality:storage`. -- Package gate: `npm run pack:check`. -- Base local checks: `npm run check:types`, `npm run lint`, `npm run format:check`, `npm run test`, and `git diff --check`. +- Use ESLint 10 with `typescript-eslint` recommended config from `eslint.config.js`. +- Lint only `src/**/*.ts` and `test/**/*.ts` with `npm run lint`; `dist/**`, `coverage/**`, `node_modules/**`, and `docs/internal/archive/**` are ignored in `eslint.config.js`. +- Enforce separate type imports through `@typescript-eslint/consistent-type-imports` in `eslint.config.js`. +- Treat unused values as errors unless they are intentionally prefixed with `_`; this is configured in `eslint.config.js`. +- Do not use `console` in source or tests except `console.warn` and `console.error`; this is enforced by `eslint.config.js`. ## Import Organization **Order:** -1. External packages and Node builtins: `zod`, `bun:test`, `node:fs`, `node:path`, `@x402/*`. -2. Source value imports from the nearest owning module or public index. -3. Source type imports using `import type`. -4. Test support imports from `test/support/*`. +1. Import external packages and Node built-ins first: `zod`, `hono`, `bun:test`, `node:fs`, `node:path`. +2. Import source value modules by relative path from the current lane: `src/http/app.ts` imports protocol, storage, route, and handler modules by relative paths. +3. Import source types with `import type`; ESLint requires separate type imports. Examples: `src/protocol/kernel.ts`, `src/runtime/ingress/index.ts`. +4. Import local sibling files last: protocol area transition files import `./schemas`, `./inputs`, `./guards`, or `./types` after cross-area dependencies. +5. In tests, import `bun:test` first, then source under `../../src`, then support helpers under `../support`. Examples: `test/protocol/kernel-policy-gateway.test.ts`, `test/runtime/runtime-ingress.test.ts`. **Path Aliases:** -- No TypeScript path aliases are configured in `tsconfig.json`. Use relative imports. -- Protocol modules should import other protocol areas through public area indexes where possible, such as `../policy-greenlight` rather than internal transition files. `test/architecture/import-posture.test.ts` enforces public-index imports between protocol areas. - -**Layer constraints:** -- `src/protocol/**` must not import `src/http/**`, `src/storage/**`, `src/runtime/**`, `src/sdk/**`, or adapter fixtures. Use the `ProtocolStore` port in `src/protocol/store/port.ts`. -- `src/http/**` owns transport, route metadata, handlers, errors, admission, and store resolution; it must not define protocol meaning. `test/architecture/import-posture.test.ts` keeps route registry metadata separate from invokers and response schemas. -- `src/runtime/**` is proposal-only. `test/architecture/import-posture.test.ts` checks `src/runtime/ingress/registry.ts` for `authorityPosture: "proposal_only"`, `compileInputAuthority: "candidate_only"`, and `rawBypassPosture: "bypass_evidence_only"`. -- `src/mcp/**` is proposal/evidence only. `test/architecture/mcp-surface-posture.test.ts` forbids imports of `protocol/kernel`, policy/gateway internals, adapters, storage, experimental surfaces, and `sdk/client`. -- Official x402 signer and paid-client imports are allowed only in `src/adapters/x402-payment/wallet-gateway.ts`; `test/architecture/import-posture.test.ts` forbids `@x402/core/client`, `@x402/fetch`, `@x402/axios`, and `@x402/evm*` elsewhere in `src/**`. +- No TypeScript path aliases are configured in `tsconfig.json`; use relative imports inside `src` and `test`. +- Package self-imports are used only where package subpath behavior is under test, such as `handshake-protocol-kernel/sdk/role-clients` in `test/sdk/role-clients.test.ts`. +- Public package surfaces are curated through `src/index.ts`, `src/adapter-sdk/index.ts`, `src/conformance/index.ts`, `src/runtime/index.ts`, `src/mcp/index.ts`, `src/x402-protected-tool/index.ts`, and `src/hosted-admission/index.ts`. +- Import posture is test-enforced by `test/architecture/import-posture.test.ts`: protocol cannot import storage adapters, HTTP/SDK cannot import protocol area internals, storage cannot import primitive behavior modules, and area-to-area imports stay on public `index.ts` faces. +- Official x402 signer and paid-client imports stay inside `src/adapters/x402-payment/wallet-gateway.ts`; `test/architecture/import-posture.test.ts` forbids `@x402/core/client`, `@x402/fetch`, `@x402/axios`, and `@x402/evm*` elsewhere in `src/**`. ## Error Handling **Patterns:** -- Validate public transition inputs with Zod at the boundary. Examples: `ProposeActionContractInputSchema.parse()` in `src/protocol/areas/action-contract/transitions.ts`, `EvaluatePolicyInputSchema.parse()` in `src/protocol/areas/policy-greenlight/transitions.ts`, and `GatewayCheckInputSchema.parse()` in `src/protocol/areas/gateway-gate/transitions.ts`. -- Throw `HandshakeProtocolError` from `src/protocol/foundation/errors.ts` with stable `code`, message, HTTP-like `status`, and optional metadata for retryability, commit state, proof refs, and refusal refs. -- Use `HandshakeAmbiguousCommitError` for ambiguous transition commits; it sets retryability to `ambiguous` and commit state to `unknown`. -- HTTP error responses go through `transitionErrorResult()` and `TransitionErrorResponseSchema` in `src/http/errors/transition-error-envelope.ts`. Do not return ad hoc error JSON from handlers. -- Record refusals and proof gaps instead of smoothing missing evidence. `test/protocol/kernel-policy-gateway.test.ts`, `test/protocol/evidence-projections.test.ts`, and `test/adapters/x402-wallet-gateway.test.ts` assert refusal/proof-gap outcomes at the authority boundary. -- Test helpers may throw plain `Error` for impossible fixture states, such as `requireCandidateDigest()` in `test/support/fixtures.ts`. Production protocol code should prefer typed `HandshakeProtocolError`. +- Parse external or boundary input with Zod before transition logic runs. Examples: `EvaluatePolicyInputSchema.parse` in `src/protocol/areas/policy-greenlight/transitions.ts`, `RuntimeIngressDispatchBlockSchema.parse` in `src/runtime/ingress/index.ts`, `TransitionErrorResponseSchema.parse` in `src/http/errors/transition-error-envelope.ts`. +- Use `HandshakeProtocolError` for protocol and HTTP transition failures that need a stable code, status, retryability, commit state, proof ref, or refusal ref. Definition: `src/protocol/foundation/errors.ts`. +- Use guard functions returning `TransitionGuardResult` for invariant checks that should become structured transition errors. Examples: `guardPolicyEvaluation` in `src/protocol/areas/policy-greenlight/guards.ts`, `guardCatalogRegistration` in `src/protocol/areas/catalog-envelope`. +- Return structured refusals, proof gaps, and non-authority outcomes instead of generic success/failure booleans. Examples: `PolicyEvaluationResponse` in `src/protocol/areas/policy-greenlight/transitions.ts`, `RuntimeIngressResponsePosture` in `src/runtime/ingress/index.ts`. +- Convert protocol errors to HTTP error envelopes at the transport edge. `src/http/app.ts` uses `transitionErrorResult`; `src/sdk/surface-clients/transport.ts` converts failed responses into `HandshakeClientError`. +- Use generic `Error` for impossible internal/test fixture assertions and external adapter fixture failures only when no protocol envelope is being emitted. Examples: fixture assertions in `test/support/fixtures.ts` and `test/protocol/model-based-invariants.test.ts`. +- Preserve ambiguous commit as an explicit error state. `HandshakeAmbiguousCommitError` in `src/protocol/foundation/errors.ts` carries `retryability: "ambiguous"` and `commitState: "unknown"`. ## Logging -**Framework:** console is restricted by `eslint.config.js`. +**Framework:** console **Patterns:** +- Do not add ordinary `console.log` calls to `src` or `test`; `eslint.config.js` rejects console usage except `warn` and `error`. - Do not use logs as protocol evidence. Durable evidence lives in protocol records, stream events, receipts, refusals, proof gaps, and redacted projections. -- CLI and surface outputs must carry explicit non-authority flags. `test/architecture/cli-command-posture.test.ts` requires every CLI JSON output to include fields such as `authorityCreated`, `greenlightCreated`, `gatewayCheckPerformed`, and `mutationAttempted`. -- Surface helpers should return schema-validated objects. `surfaceOutcomeBase()` in `src/surfaces/outcome.ts` always sets authority-related fields to `false` or `null`. +- CLI and demo output should flow through explicit output/rendering modules or process stdout behavior rather than incidental logging. Relevant files: `src/cli/main.ts`, `src/cli/command-manifest.ts`, `examples/service-workflow-admission/run.ts`. +- Tests assert serialized output and generated artifacts directly instead of depending on console logs. Examples: `test/cli/cli-evidence.test.ts`, `test/product/external-adapter-sdk-demo.test.ts`, `test/product/service-workflow-admission.test.ts`. ## Comments **When to Comment:** -- Prefer schemas, precise names, `LANE.md` files, and tests over explanatory comments. -- Add comments only when a complex transition or evidence boundary is not obvious from function names and types. -- Use lane manifests for durable ownership notes. Each first-level `src/*/LANE.md` states authority owner, proof claim, use cases, constraints, allowed imports, forbidden imports, guarding tests, and scope boundary. +- Keep comments sparse and tied to boundary or type-level intent. Use names, schemas, lane manifests, and tests as the primary documentation mechanism. +- Use comments for intentional compile-time negative tests with `@ts-expect-error`, as in `test/sdk/role-clients.test.ts`. +- Avoid TODO/FIXME/HACK/XXX comments in active source and tests; no matches were detected under `src` or `test`. **JSDoc/TSDoc:** -- Not broadly used. Do not introduce large docblocks as a substitute for typed schemas or tests. -- Public behavior should be encoded in `src/protocol/public/*`, package exports in `src/index.ts`, package subpaths in `package.json`, and executable tests under `test/**`. +- Not a primary convention. Public meaning is expressed through Zod schemas, exported TypeScript types, lane manifests such as `src/protocol/LANE.md`, and architecture tests such as `test/architecture/root-exports.test.ts`. ## Function Design -**Size:** Transition functions may orchestrate several steps, but keep phase helpers small and named by their role. The dominant pattern is parse -> load context -> derive constraints -> build plan -> commit plan -> return typed response. +**Size:** Prefer orchestration functions that delegate into named context/build/commit helpers for transitions. Examples: `evaluatePolicy` in `src/protocol/areas/policy-greenlight/transitions.ts`, `proposeRuntimeIngressActionContracts` in `src/runtime/ingress/index.ts`. -**Parameters:** Public and protocol transition functions should take one object input type, not positional argument clusters. Examples include `EvaluatePolicyInput`, `GatewayCheckInput`, `CreateRuntimeExecutionInput`, and `ProposeActionContractInput`. +**Parameters:** Use object parameters for public transition inputs and complex helper calls. Examples: `CompileIntentInput` in `src/protocol/public/inputs.ts`, `EvaluatePolicyInput` in `src/protocol/areas/policy-greenlight/inputs.ts`, `RuntimeIngressDispatchBlock` in `src/runtime/ingress/index.ts`. -**Return Values:** Return schema-shaped records or explicit outcome objects. Authority-bearing responses must distinguish policy decisions, one-use greenlights, gateway checks, mutation attempts, refusals, receipts, and proof gaps. +**Return Values:** Return typed records or discriminated results with explicit authority flags. Examples: `PolicyEvaluationResponse` in `src/protocol/areas/policy-greenlight/transitions.ts`, `RuntimeIngressResult` in `src/runtime/ingress/index.ts`, CLI output in `src/cli/main.ts`. -**Transition pattern:** -```typescript -export async function evaluatePolicy( - store: ProtocolStore, - recorder: ProtocolRecorder, - inputValue: EvaluatePolicyInput, -): Promise { - const input = EvaluatePolicyInputSchema.parse(inputValue); - const context = await getPolicyEvaluationContext(recorder, input); - assertTransition(guardPolicyEvaluation(context.contract, context.envelope)); - const constraints = await derivePolicyConstraintEvaluation(store, context); - // build, commit, then return explicit authority/non-authority posture -} -``` +**Async:** Use `async` for store-backed transitions, digest calculation, gateway checks, HTTP handling, and process proofs. Examples: `digestCanonical` in `src/protocol/foundation/canonical.ts`, `createRuntimeIngressEvidence` in `src/runtime/ingress/index.ts`, `createGeneratedGraphEvidenceFixture` in `test/support/http-protocol-fixtures.ts`. -Use this shape when adding new kernel transitions under `src/protocol/areas/*`. +**Validation:** Validate before building authority-bearing objects. Examples: `derivePolicyConstraintEvaluation` in `src/protocol/areas/policy-greenlight/transitions.ts` collects isolation, sequence, posture, idempotency, credential, and delegated-authority state before policy decision construction; `runX402WalletGateway` tests in `test/adapters/x402-wallet-gateway.test.ts` assert signing happens only after a verified gateway check. ## Module Design -**Exports:** -- Keep package root exports curated in `src/index.ts`. `test/architecture/root-exports.test.ts` asserts the exact root export list and keeps internals such as `HandshakeKernel`, `ProtocolRecorder`, `InMemoryProtocolStore`, and `D1ProtocolStore` off the root surface. -- Public subpaths are declared in `package.json`: `.`, `./conformance`, `./adapter-sdk`, `./runtime`, `./sdk/role-clients`, `./cli`, `./mcp`, `./x402-protected-tool`, and `./experimental`. -- Adapter authoring helpers belong on `src/adapter-sdk/index.ts`; runtime ingress belongs on `src/runtime/index.ts`; conformance checks belong on `src/conformance/index.ts`. - -**Barrel Files:** -- Use local `index.ts` files as intentional public faces, not dumping grounds. -- `src/protocol/public/schemas.ts` and `src/protocol/public/inputs.ts` are aggregators only; `test/architecture/import-posture.test.ts` fails if they contain lines other than `export * from ...`. -- Area `types.ts` files are local-only faces. `test/architecture/import-posture.test.ts` restricts them to allowed schema/input exports. - -## Authority-Language Rules - -Use the exact product/protocol vocabulary from `QUALITY.md`, `STRUCTURE.md`, `AGENTS.md`, `docs/internal/decisions.md`, and `docs/internal/protocol-notes.md`. - -- Say `protected actions for automated decision making`, not engineering-agent-only category language. -- Say `cleared protected-action event` for one terminal event with reconstructable evidence. -- Say `protocol kernel` for source-owned state machine and schemas. -- Say `product surface` for CLI, MCP, SDK, docs, demo, or readback surfaces that expose proposal/evidence/readback without creating authority. -- Say `AuthorityCertificate` is terminal evidence, not permission, identity, settlement, hosted trust, or reusable auth. -- Say public npm availability and MCP Registry discoverability are distribution facts, not authority. -- Say missing provider custody, hosted operation, settlement/finality, aggregate spend, host-wide containment, and broad x402 compatibility are proof gaps, outside claims, or cut lines until source and gates change. - -The claim-boundary gate is executable in `test/architecture/claim-boundary.test.ts`; update that test when simplifying canonical language so the simplification keeps the invariant rather than weakening it. - -## Projection Vs Authority - -Projection code must expose readback without becoming authority. +**Exports:** Export stable package surfaces deliberately. `src/index.ts` exposes HTTP app creation, public schemas/inputs, selected evidence/navigation helpers, and SDK client types; `test/architecture/root-exports.test.ts` enforces the exact root export list. -- Projection helpers use `project*` names and return non-authority fields. Examples: `projectProtectedActionMetadata()` and `projectProtectedActionChallengeFromRefusal()` in `src/protocol/areas/protected-action-representation/projections.ts`. -- Surface outputs in `src/surfaces/outcome.ts` set `authorityCreated`, `greenlightCreated`, `gatewayCheckPerformed`, `mutationAttempted`, `credentialMaterialIncluded`, `rawInternalRecordIncluded`, `receiptExportCreated`, and `authorityCertificateMinted` to `false`. -- `src/surfaces/boundary-manifest.ts` declares `authorityPosture`, `allowedRouteFamilies`, `forbiddenRouteFamilies`, forbidden credential shapes, forbidden output fields, and claim-boundary labels for each product surface. -- `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/cli-command-posture.test.ts`, and `test/architecture/mcp-surface-posture.test.ts` enforce that SDK, CLI, MCP, and x402 protected-tool surfaces do not import or expose authority internals. +**Barrel Files:** Use `index.ts` barrels as ownership faces, not uncontrolled dumping grounds. Examples: `src/protocol/areas/action-contract/index.ts`, `src/protocol/areas/negotiation/index.ts`, `src/http/routes/index.ts`. -Do not simplify kernel language by merging projection, evidence, policy, gateway, and mutation terms. Use shorter words only when the state boundary remains explicit. +**Area Modules:** Keep protocol primitive code under `src/protocol/areas/*` with local `schemas.ts`, `inputs.ts`, `types.ts`, `transitions.ts`, `guards.ts`, and `index.ts` faces where applicable. Examples: `src/protocol/areas/gateway-gate`, `src/protocol/areas/policy-greenlight`, `src/protocol/areas/receipt-export`. -## Simplification Rules +**Schema Modules:** Define Zod schemas beside their owned primitive and export derived TypeScript types from the same file. Examples: `src/protocol/areas/action-contract/schemas.ts`, `src/protocol/areas/gateway-gate/schemas.ts`, `src/protocol/areas/negotiation/schemas.ts`. -When simplifying confusing kernel language: +**Schema-Only Evidence Areas:** For evidence-only areas that must not create authority, follow the negotiation pattern from commit `4946237`: `src/protocol/areas/negotiation/index.ts` exports only `./schemas` and `./inputs`; `src/protocol/areas/negotiation` has no `transitions.ts`; `src/index.ts` does not export negotiation; downstream product/runtime surfaces do not import negotiation. `test/architecture/negotiation-no-authority-surface.test.ts` enforces the guard. -- Preserve the chain: exact contract -> policy decision -> one-use greenlight or refusal -> gateway check -> receipt/refusal/proof gap. -- Prefer shorter nouns already accepted in `QUALITY.md`: `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheck`, `Receipt`, `Refusal`, `ProofGap`, and `IsolationState`. -- Do not rename a projection to imply enforcement. A `project*` function cannot evaluate policy, create a greenlight, perform a gateway check, mutate, or mint terminal evidence. -- Do not remove non-claim fields from public outputs; they are part of the boundary contract. -- Update canonical docs and their tests together: `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`, `test/architecture/claim-boundary.test.ts`, `test/architecture/active-vocabulary.test.ts`, and `test/architecture/naming-posture.test.ts`. +**Boundary Tests:** Treat architecture and naming tests as part of module design. `test/architecture/import-posture.test.ts`, `test/architecture/naming-posture.test.ts`, `test/architecture/package-surface.test.ts`, `test/architecture/root-exports.test.ts`, and `test/architecture/negotiation-no-authority-surface.test.ts` define what future modules may import, name, export, and claim. --- -*Convention analysis: 2026-05-25* +*Convention analysis: 2026-05-26* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md index 6ff8698..2efda7f 100644 --- a/.planning/codebase/INTEGRATIONS.md +++ b/.planning/codebase/INTEGRATIONS.md @@ -1,246 +1,165 @@ # External Integrations -**Analysis Date:** 2026-05-25 +**Analysis Date:** 2026-05-26 -## Integration Boundary Summary +## Source Stamp -Handshake currently integrates with external rails as evidence, proposal, transport, storage, and distribution surfaces. Those surfaces do not become authority by existing. - -**Current enforcement boundary:** -- `src/protocol/areas/action-contract/` binds one exact proposed protected action. -- `src/protocol/areas/policy-greenlight/` evaluates one exact contract and may issue one-use `Greenlight` evidence. -- `src/protocol/areas/gateway-gate/` verifies exact greenlight binding before mutation. -- Mutation-capable adapter fixtures under `src/adapters/` run only after `VerifiedGatewayCheck`. -- Receipts, refusals, replay refusals, proof gaps, and terminal certificates are terminal evidence, not permission. - -**Simplification mapping:** -- "Passport" is not an integration in the current codebase. External identity is carried as evidence-only `participantIdentityBindings` on `OperatingEnvelopeSchema` and `ActionContractSchema` in `src/protocol/areas/catalog-envelope/schemas.ts` and `src/protocol/areas/action-contract/schemas.ts`. -- "Admission" is HTTP transition/read custody in `src/http/admission/`. It gates who can write or read protocol records, not who may mutate a protected surface. -- "Service gateway" is the combination of `GatewayRegistryEntry`, `GatewayCredentialRef`, gateway custody proof, role-scoped `GatewayClient`, and the `gatewayCheck` transition. Source files: `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/credential-custody/schemas.ts`, `src/sdk/surface-clients/gateway-client.ts`, and `src/protocol/areas/gateway-gate/`. -- "Principal-agent link" is protocol evidence on `OperatingEnvelope`, `DelegatedAuthorityRef`, runtime/candidate records, and exact `ActionContract`. It is not reusable auth and does not skip policy or gateway checks. +- Current source stamp: `git rev-parse --short HEAD` returned `4946237`. +- Current checkout is dirty: `git status --short` reports source, test, docs, package, and `.planning/` changes. This map reflects the current working tree. +- Source-owned integration truth is in `package.json`, `README.md`, `server.json`, `wrangler.toml`, `.github/workflows/check.yml`, `src/**`, `test/**`, `scripts/**`, and `docs/internal/**`. +- `.planning/**` remains scratch per `.planning/STATE.md`; use tracked source/docs/tests over older `.planning/codebase/*.md` when facts disagree. ## APIs & External Services -**Cloudflare Worker Runtime:** -- Cloudflare Workers - Hosts the Hono protocol app. - - SDK/Client: `wrangler` ^4.92.0 and `@cloudflare/workers-types` ^4.20260517.1 in `package.json`. - - Implementation: `src/worker.ts`, `src/http/app.ts`, and `src/http/app-options.ts`. - - Auth: Local bearer role tokens in `src/http/admission/caller-auth.ts`; hosted caller verifier interface in `src/http/admission/hosted-caller-identity.ts`. - - Config: `wrangler.toml` declares Worker name `handshake-protocol-kernel`, D1 binding `DB`, and KV binding `CACHE`. - -**x402 Payment Protocol:** -- x402 exact buyer-side payment rail - First official protected-action wedge is one buyer-side `x402_payment.exact` per-call path. - - SDK/Client: `@x402/core` 2.12.0, `@x402/evm` 2.12.0, and dev/test `@x402/fetch` 2.12.0 in `package.json`. - - Implementation: `src/adapters/x402-payment/upstream-evidence.ts`, `src/adapters/x402-payment/install-proposal.ts`, `src/adapters/x402-payment/action-proposal.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/x402-payment/protected-tool-readiness/`, `src/adapters/x402-payment/protected-tool-facade/`, and `src/x402-protected-tool/index.ts`. - - Auth: No raw x402 secret env var is read by source. Signing is injected through `ClientEvmSigner` into the gateway-held signing surface in `src/adapters/x402-payment/wallet-gateway.ts`. - - Authority boundary: `PaymentPayload` and `PAYMENT-SIGNATURE` creation occur only inside the gateway signing surface after `verifiedGatewayCheckFromResult()` returns a `VerifiedGatewayCheck`. - - Current non-claims: no facilitator operation, seller middleware, settlement finality, broad x402 compatibility, provider custody, live hosted payment management, or aggregate spend-window enforcement. - -**MCP Local Stdio:** -- Model Context Protocol - Local proposal/evidence server for model-facing x402 protected action candidates. - - SDK/Client: `@modelcontextprotocol/server` and `@modelcontextprotocol/client` 2.0.0-alpha.2 in `package.json`. - - Server: `src/mcp/stdio/server.ts` and `src/mcp/stdio/entry.ts`. - - Registry metadata: `server.json`. - - Tool: `handshake.actions.x402_payment.propose` in `src/mcp/catalog.ts`. - - Resources: `handshake://metadata/*`, `handshake://challenges/*`, `handshake://evidence/*`, `handshake://health/*`, and `handshake://certificates/*` in `src/mcp/resources.ts`. - - Auth: MCP is not an enforcement auth boundary. It bridges to runtime proposal and redacted evidence only. - -**npm And MCP Registry Distribution:** -- npm package registry - Distribution target for `handshake-protocol-kernel@0.2.7`. - - Package metadata: `package.json`. - - Package allowlist: `package.json#files`. - - Package checks: `scripts/check-package-surface.mjs`, `scripts/check-published-entrypoints.mjs`, `scripts/check-clean-installed-activation.mjs`, and `scripts/check-release-proof.mjs`. - - Auth: npm publish credentials are external to the repo. `.npmrc` was not read. - - Boundary: Publication is distribution evidence only. It does not create protocol authority. -- MCP Registry - Discoverability metadata for the local stdio MCP package. - - Config: `server.json` uses schema `https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json`. - - Package: npm/stdio entry points to `handshake-protocol-kernel` version `0.2.7`. - - Boundary: Registry acceptance and lookup are distribution facts only. - -**auth.md / OAuth Metadata Profiles:** -- auth.md profile lane - Models credential discovery, registration provenance, lifecycle evidence, protected API-call contracts, and auth.md/x402 interlock packets. - - SDK/Client: No external provider SDK detected. - - Implementation: `src/adapters/auth-md/profiles.ts`, `src/adapters/auth-md/action-proposal.ts`, `src/adapters/auth-md/gateway.ts`, `src/adapters/auth-md/revocation.ts`, `src/adapters/auth-md/bypass-probes.ts`, and `src/adapters/auth-md-x402-interlock/packet.ts`. - - Auth: Issued credential material is represented only as gateway custody evidence and `GatewayCredentialRef` inputs; raw credential material is rejected/redacted by auth.md schemas. - - Boundary: auth.md metadata and credential issuance are provenance. They are not protected-action authority, an OAuth server, an identity provider, a service gateway, or a WorkOS-style managed auth product. - -**Agent Host Profiles:** -- Host activation artifacts - Bind x402 protected-tool readiness to host-specific tool/profile descriptors. - - Codex local: `src/adapters/x402-payment/protected-tool-profile/codex-activation.ts`. - - Claude Code managed MCP: `src/adapters/x402-payment/protected-tool-profile/claude-code-activation.ts`. - - Hermes tool packet: `src/adapters/x402-payment/protected-tool-profile/hermes-activation.ts`. - - OpenClaw tool packet: `src/adapters/x402-payment/protected-tool-profile/openclaw-activation.ts`. - - Generic MCP stdio: `src/adapters/x402-payment/protected-tool-profile/generic-mcp-activation.ts`. - - Public subpath: `src/x402-protected-tool/index.ts`. - - Boundary: Host profiles can prepare activation/readiness artifacts and raw sibling posture evidence. They do not mutate host config by default, certify native hosts, contain host-wide bypass, invoke signers, or perform gateway checks. - -**HTTP Client Surfaces:** -- Handshake HTTP SDK - Typed client for protocol transition and evidence routes. - - Low-level client: `src/sdk/client.ts`. - - Role-scoped clients: `src/sdk/surface-clients/`. - - Auth: Bearer role credentials are supplied through `HandshakeClientOptions` in `src/sdk/client.ts` or one role credential in `src/sdk/surface-clients/transport.ts`. - - Boundary: SDK clients send requests and parse responses. They do not infer authority from evidence reads or command success. - -**CI Service:** -- GitHub Actions - Runs the repository quality gate. - - Config: `.github/workflows/check.yml`. - - Auth: Not detected in source. - - Commands: `bun install --frozen-lockfile`, then `npm run check:repo`. +**x402 protected payment evidence:** +- x402 official SDK - Used for the narrow buyer-side `x402_payment.exact` per-call proof path, `PAYMENT-REQUIRED` evidence decoding, exact EVM payment payload creation, and `PAYMENT-SIGNATURE` evidence after a verified gateway check. + - SDK/Client: `@x402/core` and `@x402/evm` in `src/adapters/x402-payment/upstream-evidence.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, and `src/adapters/x402-payment/sandbox-http.ts`; `@x402/fetch` appears in `test/conformance/x402-upstream-exact-fixtures.test.ts`. + - Auth: gateway-held signer object (`ClientEvmSigner`) and gateway credential refs are injected through `src/adapters/x402-payment/wallet-gateway.ts`; no source code reads an x402 private key environment variable as a required runtime config. + - Boundary: local/reference sandbox support lives in `src/adapters/x402-payment/sandbox-http.ts`; `README.md` and `docs/internal/decisions.md` cut broad x402 compatibility, facilitator operation, seller middleware, settlement finality, provider custody, and aggregate spend management from the current claim. + +**Model Context Protocol:** +- Local MCP stdio proposal/evidence server - Exposes one protected proposal tool plus read-only metadata, contract, health, and receipt timeline resources. + - SDK/Client: `@modelcontextprotocol/server` in `src/mcp/stdio/server.ts`; `@modelcontextprotocol/client` in `src/mcp/stdio/process-proof.ts` and `scripts/check-published-entrypoints.mjs`. + - Auth: `server.json` declares npm/stdio transport and does not carry bearer tokens; MCP proposal does not evaluate policy, create greenlights, perform gateway checks, mutate, or export receipts. + - Tool surface: `handshake.actions.x402_payment.propose` is declared in `src/mcp/catalog.ts`, validated by `src/mcp/x402-proposal.ts`, implemented by `src/mcp/stdio/server.ts`, and packaged by `server.json`. + +**Cloudflare platform:** +- Cloudflare Workers - HTTP deployment target for the Hono app. + - SDK/Client: Worker entry `src/worker.ts`, Hono app `src/http/app.ts`, binding types from `@cloudflare/workers-types`, config in `wrangler.toml`. + - Auth: role bearer tokens are read from Worker bindings in `src/http/admission/caller-auth.ts`. +- Cloudflare D1 - Durable protocol record and reconstruction storage. + - Client: `D1ProtocolStore` in `src/storage/d1/index.ts`. + - Schema: `migrations/0001_protocol_kernel.sql`. + - Binding: `DB` in `wrangler.toml` and `src/http/app-options.ts`. +- Cloudflare KV - Optional non-authoritative isolation cache. + - Client: `KvIsolationCache` in `src/storage/kv/index.ts`. + - Binding: `CACHE` in `wrangler.toml` and `src/http/app-options.ts`. + +**Hosted identity providers:** +- Provider-neutral hosted caller evidence - Supports provider-shaped identity evidence without bundling provider-specific SDKs. + - SDK/Client: no Clerk, OAuth/OIDC, Cloudflare Access, or custom JWT SDK dependency is declared in `package.json`; adapters implement `HostedVerifierAdapter` in `src/hosted-admission/hosted-verifier-adapter.ts`. + - Auth: raw provider sessions, service credentials, claims, and membership proof must be consumed by server-side adapters and converted into redacted `TransitionCallerIdentity` evidence in `src/hosted-admission/hosted-caller-identity.ts`. + - Provider kinds: `clerk`, `oauth_oidc`, `cloudflare_access`, `custom_jwt`, `service_credential`, `test_fixture`, and `other` are schema values in `src/hosted-admission/hosted-caller-identity.ts`. + - Configuration: deployment mode, verifier strategy, secret names, public var names, read entitlements, raw-read posture, retention posture, export posture, D1, and KV are validated by `src/hosted-admission/hosted-admission-config.ts`. + +**auth.md protected API call profile:** +- OAuth protected-resource/authorization-server metadata profile - Used as an adjacent protected API call evidence path, not as current broad auth provider integration. + - SDK/Client: no external `auth.md` SDK dependency is declared in `package.json`; profile code is in `src/adapters/auth-md/profiles.ts`, proposal code in `src/adapters/auth-md/action-proposal.ts`, gateway execution boundary in `src/adapters/auth-md/gateway.ts`, and interlock packet code in `src/adapters/auth-md-x402-interlock/packet.ts`. + - Auth: gateway credential refs/digests are modeled in parameters; raw Authorization header material is refused or redacted by `src/adapters/auth-md/action-proposal.ts`, `src/adapters/auth-md/profiles.ts`, and `src/adapters/auth-md/gateway.ts`. + +**npm, MCP Registry, and release readback:** +- npm registry - Used for package identity, publication posture, public readback, dist-signature/provenance evidence, and clean installed-artifact smoke checks. + - SDK/Client: npm CLI and package install calls in `scripts/check-package-surface.mjs`, `scripts/project-release-repository.js`, `scripts/check-release-admin.js`, and `scripts/check-clean-installed-activation.mjs`; public registry HTTP readback in `scripts/check-npm-maintainer-posture.mjs` and `scripts/check-distribution-provenance.mjs`. + - Auth: package publish credentials are not read by source scripts; remote readback uses public npm registry APIs such as `https://registry.npmjs.org/handshake-protocol-kernel/latest` in `scripts/check-distribution-provenance.mjs`. +- MCP Registry - Used only for distribution discoverability readback. + - SDK/Client: HTTP fetch/curl readback in `scripts/check-distribution-provenance.mjs`; package metadata in `server.json`. + - Auth: no MCP Registry credential is read by source code; `README.md` states MCP Registry discoverability remains a proof gap until registry acceptance and lookup are verified. +- GitHub Actions and git remotes - Used for CI and release-admin artifact posture. + - SDK/Client: CI workflow in `.github/workflows/check.yml`; release/artifact gates in `scripts/check-release-admin.js`, `scripts/check-release-proof.mjs`, `scripts/project-release-repository.js`, and `scripts/build-publish-handoff-packet.mjs`. + - Auth: GitHub Actions tokens and trusted-publish credentials are external to this checkout; source scripts inspect workflow shape, pinned actions, remote refs, package artifacts, and evidence packets, not secret values. + +**Engineering protected-action adapter surfaces:** +- Package install, repo write, and preview deploy adapters - Source-owned reference adapter surfaces for conformance and expansion proof, not provider-specific production integrations. + - SDK/Client: package-install gateway in `src/adapters/package-install/gateway.ts`, repo-write gateway in `src/adapters/repo-write/gateway.ts`, preview-deploy gateway in `src/adapters/preview-deploy/gateway.ts`, runtime proposals under `src/runtime/**`, and conformance exports in `src/conformance/index.ts`. + - Auth: each mutation adapter requires `verifiedGatewayCheckFromResult` before invoking the injected downstream surface; downstream provider clients are supplied by host/test harnesses rather than bundled in this package. ## Data Storage **Databases:** -- Cloudflare D1 - Durable reconstruction source for the reference implementation. +- Cloudflare D1 / SQLite-compatible protocol store - Connection: Worker binding `DB` in `wrangler.toml` and `src/http/app-options.ts`. - Client: `D1ProtocolStore` in `src/storage/d1/index.ts`. - - Schema: `migrations/0001_protocol_kernel.sql`. - - Stores: `protocol_records`, `protocol_record_action_contract_refs`, `stream_events`, `greenlight_consumptions`, `greenlight_issuances`, `idempotency_ledger_current`, `recovery_terminal_claims`, `protected_path_posture_current`, `isolation_state_current`, `protected_surface_operation_claim_current`, and `receipt_by_mutation_attempt`. -- In-memory store - Test/demo fixture and invariant oracle. + - Schema: `migrations/0001_protocol_kernel.sql` creates `protocol_records`, `protocol_record_action_contract_refs`, `greenlight_consumptions`, `greenlight_issuances`, `idempotency_ledger_current`, `recovery_terminal_claims`, `protected_path_posture_current`, `isolation_state_current`, `protected_surface_operation_claim_current`, `receipt_by_mutation_attempt`, `stream_events`, and indexes. +- In-memory protocol store + - Connection: explicit injection only, not production durable storage. - Client: `InMemoryProtocolStore` in `src/storage/memory/index.ts`. - - Usage: Injected through `AppOptions.store` or `allowEphemeralStore` in `src/http/app.ts`. + - Use: tests, examples, and explicit `allowEphemeralStore` paths in `src/http/app.ts`. **File Storage:** -- Local CLI project state: `.handshake/project.json` generated/read by `src/cli/local-project/index.ts`. -- External local CLI refs: `XDG_STATE_HOME` or `~/.local/state/handshake` paths used by `src/cli/local-project/index.ts`. -- Demo outputs: `examples/self-hosted-activation/output/`, `examples/x402-protected-spend/output/`, `examples/external-adapter-sdk/output/`, `examples/x402-protected-tool-profiles/output/`, and `examples/mcp-reference-transcript/output/`. -- Package output: `dist/` generated by `npm run build`. +- Local filesystem only for CLI state, demos, package projection, and release evidence. + - CLI project state: `.handshake/project.json` is read/written by `src/cli/local-project/index.ts` and declared by `src/cli/command-manifest.ts`. + - Demo outputs: `examples/self-hosted-activation/output/`, `examples/x402-protected-spend/output/`, `examples/service-workflow-admission/output/`, `examples/external-adapter-sdk/output/`, `examples/mcp-reference-transcript/output/`, and `examples/x402-protected-tool-profiles/output/`. + - Package/artifact projection: temporary filesystem work in `scripts/project-release-repository.js`, `scripts/check-release-admin.js`, `scripts/check-clean-installed-activation.mjs`, `scripts/build-product-closeout-bundle.mjs`, and `scripts/build-publish-handoff-packet.mjs`. **Caching:** -- Cloudflare KV - Non-authoritative isolation cache posture only. - - Connection: Worker binding `CACHE` in `wrangler.toml` and `src/http/app-options.ts`. +- Cloudflare KV optional cache + - Connection: Worker binding `CACHE` in `wrangler.toml`. - Client: `KvIsolationCache` in `src/storage/kv/index.ts`. - - Boundary: KV must not become protocol authority or durable reconstruction truth. + - Authority: non-authoritative cache only; D1 remains the durable reconstruction store per `migrations/0001_protocol_kernel.sql` and `src/http/handlers/hosted-readiness.ts`. +- Not detected: Redis, Memcached, browser storage, external object storage, or external queue service. ## Authentication & Identity **Auth Provider:** -- Custom local bearer-token admission. - - Implementation: `src/http/admission/caller-auth.ts`. - - Roles: `control_plane`, `runtime_evidence`, `gateway_custody`, and `review_custody`. - - Env vars: `HANDSHAKE_CONTROL_PLANE_TOKEN`, `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN`, `HANDSHAKE_GATEWAY_CUSTODY_TOKEN`, and `HANDSHAKE_REVIEW_CUSTODY_TOKEN`. -- Pluggable hosted caller verifier. - - Interface: `HostedCallerVerifier` in `src/http/admission/hosted-caller-identity.ts`. - - Config schema: `src/http/admission/hosted-admission-config.ts`. - - Supported strategy labels: `local_test_verifier`, `cloudflare_access_jwt`, `pinned_jwks`, and `custom_server_verifier`. - - Provider implementation: Not detected. These are local schema/interface hooks, not a managed identity integration. - -**Principal-Agent Link:** -- `OperatingEnvelopeSchema` in `src/protocol/areas/catalog-envelope/schemas.ts` binds `principalId`, `agentId`, optional evidence-only `participantIdentityBindings`, allowed action classes, allowed gateways, allowed resources, policy pack, issued time, expiry, and revocation time. -- `ParticipantIdentityBindingSchema` can carry external identity provider refs, subject refs/digests, claims digests, and verification evidence refs. Its `authorityPosture` is fixed to `evidence_only`. -- `ActionContractSchema` in `src/protocol/areas/action-contract/schemas.ts` copies `principalId`, `agentId`, participant identity bindings, gateway registry binding, credential custody posture, gateway authority holder, delegated authority refs, and exact params digest into the proposed commitment. -- `DelegatedAuthorityRefSchema` in `src/protocol/areas/delegated-authority/schemas.ts` records bounded attempt authority for spend, mutation, or API calls. It includes `mutationAuthorityCreated: false` and `greenlightCreated: false`. - -**Credential Custody:** -- `GatewayCredentialRefSchema` in `src/protocol/areas/credential-custody/schemas.ts` records opaque provider-neutral credential refs and explicitly sets `secretMaterialIncluded: false`. -- `GatewayCustodyProofPacketSchema` records redacted custody/posture evidence and explicitly sets `authorityCreated: false`. -- `CredentialResolutionEvidenceSchema` records post-gate gateway credential use evidence and explicitly sets `credentialMaterialIncluded: false`. - -## Protocol Rails - -**x402 protected spend:** -- Install proposal: `src/adapters/x402-payment/install-proposal.ts` compiles `x402_payment.exact` setup records, gateway registry entries, operating envelopes, credential refs, delegated spend refs, spend bounds, and bypass probe plans. -- Runtime proposal: `src/adapters/x402-payment/action-proposal.ts` builds x402 payment attempts, validates per-call bounds, binds payment requirement digests, and proposes contracts through runtime/protocol APIs. -- Gateway signing: `src/adapters/x402-payment/wallet-gateway.ts` runs `gatewayCheck`, records credential resolution evidence, signs through an injected gateway signing surface, reconciles downstream payment status, and returns proof gaps when downstream finality is unknown. -- Protected tool facade: `src/adapters/x402-payment/protected-tool-facade/index.ts` prepares proposal-only runtime dispatch blocks after readiness and metadata preflight; it emits no authority. -- Host profile readiness: `src/adapters/x402-payment/protected-tool-readiness/index.ts` and `src/adapters/x402-payment/protected-tool-profile/index.ts` bind pre-contract readiness, custody proof, raw sibling posture, and host profile descriptors. - -**auth.md protected API call:** -- Discovery/profile evidence: `src/adapters/auth-md/profiles.ts`. -- Runtime proposal: `src/adapters/auth-md/action-proposal.ts`. -- Gateway execution fixture: `src/adapters/auth-md/gateway.ts`. -- Lifecycle/revocation evidence: `src/adapters/auth-md/revocation.ts`. -- Composite admission/proof packet with x402: `src/adapters/auth-md-x402-interlock/packet.ts`. -- Boundary: auth.md stays provenance and gateway-custody evidence until a protected API call clears through exact contract, policy, one-use greenlight, gateway check, and post-gate credential resolution. - -**Package install / repo write / preview deploy proof contexts:** -- Package install reference adapter: `src/adapters/package-install/`. -- Repo write reference gateway: `src/adapters/repo-write/gateway.ts`. -- Preview deploy reference gateway: `src/adapters/preview-deploy/gateway.ts`. -- Runtime helpers: `src/runtime/package-install/action-proposal.ts`, `src/runtime/repo-write/action-proposal.ts`, and `src/runtime/preview-deploy/action-proposal.ts`. -- Boundary: These are proof contexts and adapter fixtures unless a source admission packet names generated execution shape, protected path, gateway authority holder, credential holder, candidate/refusal boundary, bypass posture, evidence path, proof-gap model, recovery/isolation path, non-claims, and gates. +- Local HTTP bearer-token custody + - Implementation: `src/http/admission/caller-auth.ts` maps transition roles to `HANDSHAKE_CONTROL_PLANE_TOKEN`, `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN`, `HANDSHAKE_GATEWAY_CUSTODY_TOKEN`, and `HANDSHAKE_REVIEW_CUSTODY_TOKEN`. + - Use: `src/http/admission/index.ts` gates transition routes and evidence reads before invoking protocol transitions. +- Hosted caller verifier adapter + - Implementation: `createHostedCallerVerifierFromAdapter` in `src/hosted-admission/hosted-verifier-adapter.ts` accepts server-side provider adapters and emits redacted hosted identity evidence through `src/hosted-admission/hosted-caller-identity.ts`. + - Providers: `clerk`, `oauth_oidc`, `cloudflare_access`, `custom_jwt`, `service_credential`, `test_fixture`, and `other` are schema-supported provider kinds; no provider SDK is bundled in `package.json`. +- Authority certificate verifier + - Implementation: local pinned trust material is projected and verified by `src/http/handlers/verifier.ts` and `src/protocol/areas/authority-certificate/**`. + - Boundary: `/v0.2/verifier/metadata` in `src/http/handlers/verifier.ts` reports `remoteTrustFetchAllowed: false`; JWKS/key-set routes project local trust material from `AppOptions.authorityCertificateTrustMaterial`. ## Monitoring & Observability **Error Tracking:** -- None detected. No Sentry, Datadog, OpenTelemetry, Honeycomb, or similar dependency appears in `package.json`. +- None detected. `package.json` does not declare Sentry, OpenTelemetry, Datadog, Honeycomb, or similar observability packages. **Logs:** -- No external log service detected. -- HTTP failures return structured transition error envelopes from `src/http/errors/transition-error-envelope.ts`. -- Protocol observability is durable evidence: records, stream events, receipts, refusals, proof gaps, redacted projections, terminal certificates, and support bundles. -- ESLint allows only `console.warn` and `console.error` in `eslint.config.js`. +- HTTP errors return structured protocol envelopes through `src/http/errors/transition-error-envelope.ts` and the `app.onError` handler in `src/http/app.ts`. +- CLI and release scripts write process output/errors through Node/Bun process APIs in files such as `src/cli/main.ts`, `scripts/check-release-admin.js`, and `scripts/check-package-surface.mjs`. +- ESLint permits only `console.warn` and `console.error` in `eslint.config.js`; no centralized logger framework is configured. +- Evidence, refusal, proof-gap, receipt, idempotency, isolation, and audit records are protocol records in `src/protocol/store/port.ts`, `src/storage/d1/index.ts`, and `src/storage/memory/index.ts`, not a generic tracing backend. ## CI/CD & Deployment **Hosting:** -- Cloudflare Workers target via `wrangler.toml` and `src/worker.ts`. -- D1 binding `DB` is required for durable HTTP protocol endpoints unless an explicit injected test store is supplied. -- Hosted operation is not proven by this repo alone. `src/http/admission/hosted-admission-config.ts` models hosted readiness/admission posture, not provider custody or hosted mutation authority. +- npm package distribution for `handshake-protocol-kernel@0.2.8` is declared in `package.json` and `server.json`; `README.md` states public npm `0.2.7` is historical provenance only until current `0.2.8` publication/readback passes. +- Local MCP stdio package surface is declared in `server.json`, implemented by `src/mcp/stdio/server.ts`, and exposed by `bin/handshake-mcp`. +- Cloudflare Worker HTTP app is configured by `wrangler.toml` and `src/worker.ts`; no production deploy workflow beyond CI was detected in `.github/workflows/check.yml`. **CI Pipeline:** -- GitHub Actions in `.github/workflows/check.yml`. -- CI uses pinned `actions/checkout` and `oven-sh/setup-bun`, installs Bun `1.3.9`, runs `bun install --frozen-lockfile`, then `npm run check:repo`. - -**Package Gate:** -- `npm run pack:check` in `package.json` runs `npm run build`, `scripts/check-package-surface.mjs`, `scripts/check-published-entrypoints.mjs`, `scripts/check-clean-installed-activation.mjs`, and `scripts/check-release-proof.mjs`. -- Package checks verify package allowlist, exports, bins, local CLI schema output, MCP stdio process behavior, role-client subpath, x402 protected-tool subpath, and installed-artifact smoke. +- GitHub Actions workflow `.github/workflows/check.yml` + - Trigger: `push` and `pull_request`. + - Permissions: `contents: read`. + - Toolchain: pinned `actions/checkout`, pinned `oven-sh/setup-bun`, Bun 1.3.9. + - Gate: `bun install --frozen-lockfile` followed by `npm run check:repo`. +- Release/package gates are local/scripted: + - `package.json#scripts.pack:check` runs package surface, published entrypoint, clean installed activation, release proof, host-generated-code containment, live x402 paid retry posture, auth.md+x402 admission packet posture, product completion, and npm maintainer posture checks. + - `scripts/check-release-admin.js` runs clean-source, clean-clone, lockfile install, full repo gate, artifact projection, artifact boundary, smoke imports, smoke CLI, and optional remote readback. ## Environment Configuration **Required env vars:** -- Local bearer admission: - - `HANDSHAKE_CONTROL_PLANE_TOKEN` - - `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN` - - `HANDSHAKE_GATEWAY_CUSTODY_TOKEN` - - `HANDSHAKE_REVIEW_CUSTODY_TOKEN` -- Cloudflare bindings: - - `DB` - - `CACHE` -- Optional local state: - - `XDG_STATE_HOME` +- `HANDSHAKE_CONTROL_PLANE_TOKEN` - Local HTTP control-plane transition bearer token in `src/http/admission/caller-auth.ts`. +- `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN` - Local HTTP runtime-evidence transition bearer token in `src/http/admission/caller-auth.ts`. +- `HANDSHAKE_GATEWAY_CUSTODY_TOKEN` - Local HTTP gateway-custody transition bearer token in `src/http/admission/caller-auth.ts`. +- `HANDSHAKE_REVIEW_CUSTODY_TOKEN` - Local HTTP review-custody/evidence-read bearer token in `src/http/admission/caller-auth.ts`. +- `DB` - Cloudflare D1 Worker binding in `wrangler.toml` and `src/http/app-options.ts`. +- `CACHE` - Optional Cloudflare KV Worker binding in `wrangler.toml` and `src/http/app-options.ts`. +- Hosted mode secrets/public vars - Names are supplied by `HostedAdmissionConfig.secretNames` and `HostedAdmissionConfig.publicVarNames` in `src/hosted-admission/hosted-admission-config.ts`; source does not hardcode production provider secret names. **Secrets location:** -- Secrets are not stored in the repo. -- `.gitignore` excludes `.dev.vars`, `.env`, `.env.local`, `.env.*.local`, `*.pem`, and `*.key`. -- Cloudflare secrets should live in platform bindings. -- npm/MCP Registry credentials are external to this checkout. -- x402 signer material must be held behind the gateway signing surface, not in runtime, MCP, CLI, docs, examples, or protocol records. +- Cloudflare Worker bindings/secrets or explicit `AppOptions` injection are the source-supported locations for HTTP tokens, hosted verifier config, trust material, D1, and KV in `src/http/app-options.ts`. +- Local CLI state avoids token values according to `src/cli/command-manifest.ts` and writes external local posture refs through `src/cli/x402/local-state.ts`. +- No root `.env*` file was detected. `.gitignore` excludes `.dev.vars`, `.env`, `.env.local`, and `.env.*.local`; if present, list only and never quote contents. ## Webhooks & Callbacks **Incoming:** -- No webhook endpoints detected. -- Protocol transition routes are registered in `src/http/routes/transition-route-registry.ts`. -- Redacted evidence read routes are registered in `src/http/routes/evidence-read-route-registry.ts`. -- Additional HTTP endpoints in `src/http/app.ts`: `/health`, `/openapi.json`, `/v0.2/hosted/readiness`, `/v0.2/verifier/metadata`, `/v0.2/verifier/key-set`, `/v0.2/verifier/jwks.json`, `/v0.2/verifier/status/:subjectKind/:subjectRef`, `/v0.2/verifier/authority-certificates/verify`, and `/v0.2/records/:objectType/:objectId`. -- MCP incoming requests are stdio tool/resource calls handled by `src/mcp/stdio/server.ts`. +- No provider webhook route was detected in `src/http/app.ts`, `src/http/routes/transition-route-registry.ts`, or `src/http/routes/evidence-read-route-registry.ts`. +- HTTP transition and evidence-read routes are registered from `src/http/routes/transition-route-registry.ts` and `src/http/routes/evidence-read-route-registry.ts`. +- Additional readback/verifier routes live in `src/http/app.ts`: `/health`, `/openapi.json`, `/v0.2/hosted/readiness`, `/v0.2/verifier/metadata`, `/v0.2/verifier/key-set`, `/v0.2/verifier/jwks.json`, `/v0.2/verifier/status/:subjectKind/:subjectRef`, `/v0.2/verifier/authority-certificates/verify`, and `/v0.2/records/:objectType/:objectId`. +- Hosted verifier schemas include `provider_webhook_verified` as an evidence posture in `src/hosted-admission/hosted-verifier-adapter.ts`, but source does not implement an incoming provider webhook endpoint. **Outgoing:** -- SDK clients call a configured Handshake base URL through `fetch` in `src/sdk/client.ts` and `src/sdk/surface-clients/transport.ts`. -- Reference adapters call injected surfaces rather than hard-coded provider APIs: - - `src/adapters/x402-payment/wallet-gateway.ts` calls an injected `X402WalletSigningSurface`. - - `src/adapters/auth-md/gateway.ts` calls an injected `AuthMdProtectedApiCallSurface`. - - `src/adapters/package-install/gateway.ts`, `src/adapters/repo-write/gateway.ts`, and `src/adapters/preview-deploy/gateway.ts` use caller-supplied mutation surfaces. -- No production webhook/callback delivery integration detected. - -## Distribution Surfaces - -**npm package:** -- Public package shape is `handshake-protocol-kernel` with executable bins and subpath exports in `package.json`. -- `scripts/check-package-surface.mjs` keeps private source, tests, planning scratch, scripts, examples, migrations, and internal docs out of the package artifact. - -**MCP Registry:** -- `server.json` advertises one npm/stdio package entry for the MCP server. -- MCP Registry discoverability is separate from npm publication and does not create authority. - -**Examples:** -- `examples/self-hosted-activation/run.ts` emits local self-hosted activation evidence. -- `examples/x402-protected-spend/run.ts` emits local/reference protected-spend evidence. -- `examples/external-adapter-sdk/run.ts` emits definition-only adapter SDK readback. -- `examples/x402-protected-tool-profiles/run.ts` emits protected tool host profile artifacts. -- `examples/mcp-reference-transcript/run.ts` emits local MCP transcript evidence. -- Example outputs are product/readback samples, not production storage or authority. +- Role-scoped SDK clients use `fetch` against configured Handshake base URLs in `src/sdk/surface-clients/transport.ts`; the lower-level `HandshakeClient` uses `fetch` in `src/sdk/client.ts`. +- x402 gateway signing calls an injected `X402WalletSigningSurface` only after `VerifiedGatewayCheck` in `src/adapters/x402-payment/wallet-gateway.ts`; local downstream fixture behavior is in `src/adapters/x402-payment/sandbox-http.ts`. +- auth.md protected API calls execute through an injected `AuthMdProtectedApiCallSurface` only after `VerifiedGatewayCheck` in `src/adapters/auth-md/gateway.ts`; no concrete outbound provider client is bundled. +- Package install, preview deploy, and repo write adapters call injected downstream surfaces only after `VerifiedGatewayCheck` in `src/adapters/package-install/gateway.ts`, `src/adapters/preview-deploy/gateway.ts`, and `src/adapters/repo-write/gateway.ts`. +- Release/readback scripts call public npm registry APIs, MCP Registry APIs, curl fallback, npm CLI, and optional remote git readback in `scripts/check-npm-maintainer-posture.mjs`, `scripts/check-distribution-provenance.mjs`, and `scripts/check-release-admin.js`. --- -*Integration audit: 2026-05-25* +*Integration audit: 2026-05-26* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md index 08cb152..9b00588 100644 --- a/.planning/codebase/STACK.md +++ b/.planning/codebase/STACK.md @@ -1,170 +1,114 @@ # Technology Stack -**Analysis Date:** 2026-05-25 - -## Protocol Kernel Shape - -**Current package:** -- `handshake-protocol-kernel@0.2.7` in `package.json`. -- MCP package name is `io.github.CreasyBear/handshake-protocol-kernel` in `package.json` and `server.json`. -- Runtime requirement is Node.js `>=20` in `package.json`; the current local shell reports `node --version` as `v25.2.1`. - -**Kernel boundary:** -- The source-owned protocol kernel lives under `src/protocol/`. Its transition facade is `src/protocol/kernel.ts`. -- The kernel records exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, recovery, review binding, generated-execution evidence, delegated-authority evidence, gateway-credential evidence, and terminal `AuthorityCertificate` evidence. -- Product surfaces live outside protocol meaning: `src/cli/`, `src/mcp/`, `src/sdk/`, `src/runtime/`, `src/adapters/`, `src/x402-protected-tool/`, and `examples/`. These surfaces may expose proposal, readiness, redacted readback, demos, or host activation artifacts, but they must not create authority unless they call the protocol and gateway path. - -**Authority sequence:** -- Runtime or generated execution evidence is recorded by `src/protocol/areas/runtime-evidence/`, `src/protocol/areas/generated-execution-graph/`, and `src/protocol/areas/tool-call-draft/`. -- Intent compilation and exact contract proposal live in `src/protocol/areas/intent-compilation/` and `src/protocol/areas/action-contract/`. -- Policy and one-use greenlights live in `src/protocol/areas/policy-greenlight/`. -- Gateway enforcement lives in `src/protocol/areas/gateway-gate/`; mutation-capable reference adapters use `verifiedGatewayCheckFromResult()` from `src/protocol/areas/gateway-gate/`. -- Reconstruction lives in `src/protocol/events/`, `src/protocol/evidence-projections/`, `src/protocol/areas/receipt-export/`, `src/protocol/areas/proof-gap/`, and `src/protocol/areas/authority-certificate/`. - -**Passport / admission / service gateway / principal-agent link:** -- There is no standalone `Passport` primitive in tracked source. Do not add one unless it reduces ambiguity more than the current typed records. -- HTTP caller admission is transport custody in `src/http/admission/`; it authenticates transition callers and read entitlements, not protected-action authority. -- The protected-action principal-agent link is `principalId`, `agentId`, and evidence-only `participantIdentityBindings` on `OperatingEnvelopeSchema` in `src/protocol/areas/catalog-envelope/schemas.ts`, then copied into `ActionContractSchema` in `src/protocol/areas/action-contract/schemas.ts`. -- Attempt authority is represented by `DelegatedAuthorityRefSchema` in `src/protocol/areas/delegated-authority/schemas.ts`; it records principal/agent/runtime/envelope/gateway scoped bounds and can be revoked or expired into isolation, but it is not a greenlight. -- Service gateway authority is represented by `GatewayRegistryEntrySchema` in `src/protocol/areas/catalog-envelope/schemas.ts`, `GatewayCredentialRefSchema` and `GatewayCustodyProofPacketSchema` in `src/protocol/areas/credential-custody/schemas.ts`, and the final `gatewayCheck()` transition in `src/protocol/kernel.ts`. +**Analysis Date:** 2026-05-26 + +## Source Stamp + +- Current source stamp: `git rev-parse --short HEAD` returned `4946237`. +- Current checkout is dirty: `git status --short` reports source, test, docs, package, and `.planning/` changes. This map reflects the current working tree, not only the committed tree. +- Source truth for stack claims is `package.json`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `server.json`, `wrangler.toml`, `.github/workflows/check.yml`, `src/**`, `test/**`, `scripts/**`, and `docs/internal/**`. +- `.planning/**` is scratch coordination per `.planning/STATE.md`; do not treat older `.planning/codebase/*.md` as canonical when source files disagree. ## Languages **Primary:** -- TypeScript 6.0.3 - All source, tests, examples, protocol schemas, HTTP routes, SDK clients, CLI, MCP server, adapters, and storage implementations under `src/`, `test/`, and `examples/`. +- TypeScript 6.0.3 - Strict ESM source, tests, examples, and declaration output. Core source lives under `src/**/*.ts`, tests under `test/**/*.test.ts`, demos under `examples/**/run.ts`, and declaration emit is configured by `tsconfig.build.json`. **Secondary:** -- JavaScript ESM - Build and package verification scripts under `scripts/`, including `scripts/build-package-bundles.mjs`, `scripts/check-package-surface.mjs`, `scripts/check-published-entrypoints.mjs`, and `scripts/check-release-proof.mjs`. -- SQL - Cloudflare D1 schema in `migrations/0001_protocol_kernel.sql`. -- Markdown - Canonical repo docs in `README.md`, `AGENTS.md`, `QUALITY.md`, `STRUCTURE.md`, and `docs/internal/*.md`; example docs under `examples/*/README.md`. -- TOML/JSON/YAML - Worker config in `wrangler.toml`, package metadata in `package.json`, MCP Registry metadata in `server.json`, TypeScript config in `tsconfig.json`, formatting/lint config in `.prettierrc.json` and `eslint.config.js`, and CI in `.github/workflows/check.yml`. +- JavaScript - Node-side release, package, build, and posture scripts live in `scripts/*.mjs` and `scripts/*.js`; executable package stubs live in `bin/handshake` and `bin/handshake-mcp`. +- SQL - Cloudflare D1/SQLite-compatible durable storage schema lives in `migrations/0001_protocol_kernel.sql`. +- Markdown - Repo-facing source docs live in `README.md`, `QUALITY.md`, `STRUCTURE.md`, `AGENTS.md`, and `docs/internal/*.md`. +- JSON/TOML/YAML - Package and runtime metadata live in `package.json`, `server.json`, `tsconfig.json`, `tsconfig.build.json`, `.prettierrc.json`, `wrangler.toml`, and `.github/workflows/check.yml`. ## Runtime **Environment:** -- Node.js `>=20` - Required by `package.json#engines`; Node ESM bundles are executed by `bin/handshake` and `bin/handshake-mcp`. -- Bun `1.3.9` - Declared in `package.json#packageManager`, present in `bun.lock`, used by `.github/workflows/check.yml`, used for tests and bundling. -- Cloudflare Workers - Worker entrypoint is `src/worker.ts`; `wrangler.toml` points `main` to that file. +- Node.js `>=20` - Declared in `package.json#engines`; package binaries `bin/handshake` and `bin/handshake-mcp` are Node executable stubs importing built ESM entrypoints from `dist/bin/*.mjs`. +- Bun 1.3.9 - Declared in `package.json#packageManager`, present in `bun.lock`, used by `package.json#scripts.test`, `scripts/build-package-bundles.mjs`, and CI in `.github/workflows/check.yml`. +- Cloudflare Workers - HTTP runtime target configured by `wrangler.toml`; Worker entrypoint is `src/worker.ts`; bindings are typed in `src/http/app-options.ts`. +- ES modules - `package.json` sets `"type": "module"` and package exports point to `dist/**/*.mjs`. **Package Manager:** -- Bun `1.3.9` - Primary install/test package manager. -- npm `11.7.0` observed locally - Used by `package.json#scripts` and package checks such as `npm pack --dry-run --json`. -- Lockfile: `bun.lock` present. +- Bun 1.3.9 - Source package manager and lockfile owner. CI runs `bun install --frozen-lockfile` in `.github/workflows/check.yml`. +- npm CLI - Used as script runner in `package.json#scripts` and by package/release scripts such as `scripts/check-release-admin.js`, `scripts/check-package-surface.mjs`, and `scripts/check-npm-maintainer-posture.mjs`. +- Lockfile: present as `bun.lock`. +- Not detected at root: `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lockb`. ## Frameworks **Core:** -- `hono` ^4.12.19 - HTTP/Worker app and route dispatch in `src/http/app.ts`. -- Cloudflare Workers + Wrangler ^4.92.0 - Deployment/runtime target configured by `wrangler.toml`; Worker/D1/KV types supplied by `@cloudflare/workers-types`. -- `zod` ^4.4.3 - Runtime validation and schema backbone across `src/protocol/**`, `src/http/**`, `src/runtime/**`, `src/adapters/**`, `src/cli/**`, `src/mcp/**`, and `src/x402-protected-tool/**`. -- MCP TypeScript SDK 2.0.0-alpha.2 - Local stdio MCP server/client proof in `src/mcp/stdio/server.ts`, `src/mcp/stdio/process-proof.ts`, and `scripts/check-published-entrypoints.mjs`. -- x402 SDK 2.12.0 - Official buyer-side exact payment evidence/signing path in `src/adapters/x402-payment/upstream-evidence.ts`, `src/adapters/x402-payment/action-proposal.ts`, and `src/adapters/x402-payment/wallet-gateway.ts`. +- Hono `^4.12.19` - HTTP router/app framework in `src/http/app.ts`, exported through `src/index.ts`, and served by `src/worker.ts`. +- Zod `^4.4.3` - Runtime schema layer across protocol, HTTP, adapters, CLI, MCP, SDK, hosted admission, and product-surface code. Representative paths: `src/protocol/foundation/schema-core.ts`, `src/protocol/public/schemas.ts`, `src/http/routes/transition-response-schemas.ts`, `src/mcp/x402-proposal.ts`, and `src/hosted-admission/hosted-admission-config.ts`. +- Cloudflare Workers APIs - D1 and KV binding types come from `@cloudflare/workers-types`; source uses them in `src/http/app-options.ts`, `src/http/store/resolution.ts`, `src/storage/d1/index.ts`, and `src/storage/kv/index.ts`. +- x402 SDK `2.12.0` - Official buyer-side exact payment evidence and signing helpers use `@x402/core` and `@x402/evm` in `src/adapters/x402-payment/upstream-evidence.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, and `src/adapters/x402-payment/sandbox-http.ts`. +- Model Context Protocol SDK `^2.0.0-alpha.2` - Local stdio proposal/evidence server uses `@modelcontextprotocol/server` in `src/mcp/stdio/server.ts`; process and published-entrypoint checks use `@modelcontextprotocol/client` in `src/mcp/stdio/process-proof.ts` and `scripts/check-published-entrypoints.mjs`. **Testing:** -- Bun test - Test runner via `package.json#scripts.test`. -- TypeScript compiler - Type gate via `npm run check:types` and `npm run typecheck`. -- Architecture and claim tests - Focused repo-boundary tests under `test/architecture/`. +- Bun test - `package.json#scripts.test` runs `bun test`; test files under `test/**` import `describe`, `it`, and `expect` from `bun:test`. +- Bun SQLite - D1 HTTP harness tests use `bun:sqlite` in `test/support/d1-http-harness.ts`. +- Architecture/product/integration gates - `package.json` defines `quality:architecture`, `quality:claims`, and `quality:storage`, backed by `test/architecture/**`, `test/product/**`, `test/integration/**`, `test/protocol/**`, and `test/storage/**`. **Build/Dev:** -- TypeScript declarations - `npm run build:types` runs `tsc -p tsconfig.build.json`. -- Bun bundler - `scripts/build-package-bundles.mjs` bundles package entrypoints and bins into `dist/`. -- ESLint 10.4.0 + `typescript-eslint` 8.59.4 - Linting configured by `eslint.config.js`. -- Prettier 3.8.3 - Formatting configured by `.prettierrc.json`. -- Wrangler - `npm run dev` runs `wrangler dev`. +- TypeScript compiler `^6.0.3` - `npm run build:types` runs `tsc -p tsconfig.build.json`; `npm run check:types` runs `tsc --noEmit --pretty false`. +- Bun bundler - `scripts/build-package-bundles.mjs` runs `bun build --target=node --format=esm` for package subpaths and CLI/MCP binaries. +- Wrangler `^4.92.0` - `package.json#scripts.dev` runs `wrangler dev`; `wrangler.toml` points to `src/worker.ts` and declares D1/KV bindings. +- ESLint `^10.4.0` plus `typescript-eslint ^8.59.4` - Configured by `eslint.config.js` for `src/**/*.ts` and `test/**/*.ts`. +- Prettier `^3.8.3` - Configured by `.prettierrc.json`; `package.json#scripts.format:check` checks the repo. +- GitHub Actions - `.github/workflows/check.yml` runs Bun install and `npm run check:repo` on `push` and `pull_request`. ## Key Dependencies **Critical:** -- `zod` ^4.4.3 - Defines strict protocol, adapter, MCP, CLI, hosted admission, and evidence schemas. -- `hono` ^4.12.19 - Owns HTTP routing for `/health`, `/openapi.json`, transition routes, evidence routes, hosted readiness, verifier routes, and internal record reads in `src/http/app.ts`. -- `@x402/core` 2.12.0 - Validates `PaymentRequired` and `PaymentPayload` evidence in `src/adapters/x402-payment/upstream-evidence.ts` and `src/adapters/x402-payment/wallet-gateway.ts`. -- `@x402/evm` 2.12.0 - Provides `ExactEvmScheme` and `ClientEvmSigner` for gateway-held exact EVM signing in `src/adapters/x402-payment/wallet-gateway.ts`. -- `@modelcontextprotocol/server` 2.0.0-alpha.2 - Builds `handshake-mcp` local stdio server in `src/mcp/stdio/server.ts`. -- `@modelcontextprotocol/client` 2.0.0-alpha.2 - Verifies the local MCP process in `src/mcp/stdio/process-proof.ts` and `scripts/check-published-entrypoints.mjs`. +- `zod` `^4.4.3` - Defines source-owned protocol, adapter, HTTP, MCP, CLI, SDK, and hosted admission schemas in `src/protocol/**`, `src/adapters/**`, `src/http/**`, `src/mcp/**`, `src/cli/**`, `src/sdk/**`, and `src/hosted-admission/**`. +- `hono` `^4.12.19` - Owns HTTP routing, middleware, errors, request parsing, and response handling in `src/http/app.ts` and `src/http/handlers/**`. +- `@x402/core` `2.12.0` - Validates x402 `PaymentRequired` / `PaymentPayload` shapes and creates official x402 clients in `src/adapters/x402-payment/upstream-evidence.ts` and `src/adapters/x402-payment/wallet-gateway.ts`. +- `@x402/evm` `2.12.0` - Provides `ExactEvmScheme` and `ClientEvmSigner` for gateway-held exact payment signing in `src/adapters/x402-payment/wallet-gateway.ts`. +- `@modelcontextprotocol/server` `^2.0.0-alpha.2` - Implements local MCP stdio resources and the `handshake.actions.x402_payment.propose` tool in `src/mcp/stdio/server.ts`. +- `@modelcontextprotocol/client` `^2.0.0-alpha.2` - Used for MCP stdio process proof and package entrypoint smoke checks in `src/mcp/stdio/process-proof.ts` and `scripts/check-published-entrypoints.mjs`. **Infrastructure:** -- `@cloudflare/workers-types` ^4.20260517.1 - Worker, D1, and KV TypeScript bindings used by `src/http/app-options.ts`, `src/storage/d1/index.ts`, and `src/storage/kv/index.ts`. -- `wrangler` ^4.92.0 - Cloudflare Worker local development and deployment CLI. -- `typescript` ^6.0.3 - Strict source checking with `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes` in `tsconfig.json`. -- `eslint` ^10.4.0 and `typescript-eslint` ^8.59.4 - Type import, unused variable, and console discipline in `eslint.config.js`. -- `prettier` ^3.8.3 - Formatting for source, docs, and generated example outputs. -- `@x402/fetch` 2.12.0 - Dev/test fixture dependency used by `test/conformance/x402-upstream-exact-fixtures.test.ts`. -- `@types/bun` ^1.3.14 - Bun type support for tests, scripts, and examples. -- `@cfworker/json-schema` ^4.1.1 - Listed in `package.json`; no active source import detected under `src/`, `test/`, `scripts/`, or `examples/`. +- `@cloudflare/workers-types` `^4.20260517.1` - Provides Cloudflare Worker, D1, and KV types used by `src/http/app-options.ts`, `src/storage/d1/index.ts`, and `src/storage/kv/index.ts`. +- `@types/bun` `^1.3.14` - Supports Bun globals/APIs used by tests and examples such as `examples/service-workflow-admission/run.ts`, `examples/x402-protected-spend/run.ts`, and `test/support/d1-http-harness.ts`. +- `@x402/fetch` `2.12.0` - Dev dependency used for upstream x402 fixture parity in `test/conformance/x402-upstream-exact-fixtures.test.ts`. +- `@cfworker/json-schema` `^4.1.1` - Declared in `package.json`; no direct import was detected under `src/`, `test/`, `examples/`, or `scripts/` during this remap. +- `typescript`, `eslint`, `typescript-eslint`, `prettier`, and `wrangler` - Source quality, type checking, formatting, package bundling, and Cloudflare Worker tooling in `package.json`, `tsconfig.json`, `eslint.config.js`, `.prettierrc.json`, and `wrangler.toml`. ## Configuration **Environment:** -- Worker D1 binding `DB` and KV binding `CACHE` are declared in `wrangler.toml`. -- Local bearer transition admission reads `HANDSHAKE_CONTROL_PLANE_TOKEN`, `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN`, `HANDSHAKE_GATEWAY_CUSTODY_TOKEN`, and `HANDSHAKE_REVIEW_CUSTODY_TOKEN` in `src/http/admission/caller-auth.ts`. -- Hosted admission is configured through `AppOptions.authMode`, `AppOptions.hostedAdmissionConfig`, and `AppOptions.hostedCallerVerifier` in `src/http/app-options.ts`; provider strategy values are schema-only in `src/http/admission/hosted-admission-config.ts`. -- CLI local project state uses `.handshake/project.json` and external local state refs managed by `src/cli/local-project/index.ts`. -- `.env`, `.env.local`, `.env.*.local`, `.dev.vars`, `*.pem`, and `*.key` are ignored by `.gitignore`. No `.env*` file contents were read. +- HTTP role custody uses explicit bearer token bindings named `HANDSHAKE_CONTROL_PLANE_TOKEN`, `HANDSHAKE_RUNTIME_EVIDENCE_TOKEN`, `HANDSHAKE_GATEWAY_CUSTODY_TOKEN`, and `HANDSHAKE_REVIEW_CUSTODY_TOKEN` in `src/http/admission/caller-auth.ts`. +- Cloudflare durable protocol storage uses D1 binding `DB`, declared in `wrangler.toml` and consumed by `src/http/store/resolution.ts` and `src/storage/d1/index.ts`. +- Cloudflare optional cache uses KV binding `CACHE`, declared in `wrangler.toml` and consumed by `src/storage/kv/index.ts` and `src/http/handlers/hosted-readiness.ts`. +- Hosted admission configuration is injected via `AppOptions.hostedAdmissionConfig` in `src/http/app-options.ts` and validated by `src/hosted-admission/hosted-admission-config.ts`; production provider secret names are declared by config, not hardcoded. +- Hosted identity adapters implement `HostedVerifierAdapter` in `src/hosted-admission/hosted-verifier-adapter.ts`; no Clerk, OAuth/OIDC, or Cloudflare Access SDK dependency is bundled in `package.json`. +- CLI local state uses `.handshake/project.json` and falls back to `XDG_STATE_HOME` or `~/.local/state/handshake` in `src/cli/local-project/index.ts`. +- No root `.env*` file was detected. `.gitignore` excludes `.dev.vars`, `.env`, `.env.local`, and `.env.*.local`; if present, these files must be listed only and never read. **Build:** -- `tsconfig.json` targets `ES2022`, uses `module: ESNext`, `moduleResolution: Bundler`, `lib: ["ES2022", "WebWorker"]`, strict checking, Worker/Bun types, and `outDir: dist`. -- `tsconfig.build.json` emits declarations only from `src/` into `dist/`. -- `scripts/build-package-bundles.mjs` bundles package entrypoints: `src/index.ts`, `src/conformance/index.ts`, `src/adapter-sdk/index.ts`, `src/surfaces/index.ts`, `src/runtime/index.ts`, `src/sdk/surface-clients/index.ts`, `src/cli/index.ts`, `src/mcp/index.ts`, `src/x402-protected-tool/index.ts`, `src/experimental.ts`, `src/cli/main.ts`, and `src/mcp/stdio/entry.ts`. -- `eslint.config.js` ignores `dist/**`, `coverage/**`, `node_modules/**`, and `docs/internal/archive/**`; it enforces consistent type imports, unused-var cleanup, and no `console` except `warn` and `error`. -- `.prettierrc.json` sets `printWidth: 120`, semicolons, double quotes, and trailing commas. - -## Package Surface - -**npm package:** -- Package name/version: `handshake-protocol-kernel` `0.2.7` in `package.json`. -- License: Apache-2.0 in `package.json`, with package files `LICENSE` and `NOTICE`. -- Published allowlist is `bin`, `dist`, `server.json`, `README.md`, `CHANGELOG.md`, `LICENSE`, and `NOTICE` in `package.json#files`. -- `scripts/check-package-surface.mjs` rejects packaged `.planning/`, `.agents/`, `skills-lock.json`, `src/`, `test/`, `scripts/`, `examples/`, `migrations/`, `docs/internal/`, old docs trees, root canon files such as `AGENTS.md`, `QUALITY.md`, `STRUCTURE.md`, and `bun.lock`. - -**Exports:** -- `.` -> root protocol/HTTP/SDK curated API from `src/index.ts`. -- `./conformance` -> reference conformance checks from `src/conformance/index.ts`. -- `./adapter-sdk` -> definition-only adapter pack surface from `src/adapter-sdk/index.ts`. -- `./runtime` -> proposal-only runtime ingress surface from `src/runtime/index.ts`. -- `./sdk/role-clients` -> role-scoped clients from `src/sdk/surface-clients/index.ts`. -- `./cli` -> CLI helper surface from `src/cli/index.ts`. -- `./mcp` -> MCP catalog/resource/proposal surface from `src/mcp/index.ts`. -- `./x402-protected-tool` -> normal-agent-tool facade, readiness, host profile, and activation artifacts from `src/x402-protected-tool/index.ts`. -- `./experimental` -> explicit reference adapter exports from `src/experimental.ts`. - -**Bins:** -- `handshake` -> `bin/handshake` -> `dist/bin/handshake.mjs`; local operator/evidence CLI. -- `handshake-mcp` -> `bin/handshake-mcp` -> `dist/bin/handshake-mcp.mjs`; local stdio MCP proposal/evidence server. -- `handshake-protocol-kernel` -> `bin/handshake-mcp`; package-name execution alias for MCP hosts. - -## Protocol Product Surfaces - -**CLI:** -- Command manifest lives in `src/cli/command-manifest.ts`. -- Active commands include `schema`, `init`, `doctor`, `evidence aps-report`, `evidence contract-view`, `evidence receipt-timeline`, `cert verify`, `support bundle`, `install x402-payment`, `probes x402-payment`, `register x402-gateway-readiness`, `install health`, and `conformance x402-payment`. -- CLI output is evidence/readiness only. It does not evaluate policy, issue greenlights, perform gateway checks, use signers, mutate protected surfaces, export receipts as authority, or mint terminal certificates. - -**MCP:** -- MCP catalog lives in `src/mcp/catalog.ts`. -- The only proposal tool is `handshake.actions.x402_payment.propose`. -- Read-only resources use `handshake://metadata/*`, `handshake://challenges/*`, `handshake://evidence/*`, `handshake://health/*`, and `handshake://certificates/*` in `src/mcp/resources.ts`. -- MCP proposal handling in `src/mcp/x402-proposal.ts` can create runtime evidence, tool-call drafts, intent compilations, and proposed action contracts through a runtime client. It does not evaluate policy, greenlight, gateway-check, mutate, export receipts, mint certificates, or carry credential material. - -**SDK:** -- Low-level `HandshakeClient` lives in `src/sdk/client.ts`. -- Role-scoped activation clients live under `src/sdk/surface-clients/`: `InstallClient`, `RuntimeClient`, `ControlPlaneClient`, `PolicyClient`, `GatewayClient`, and `EvidenceClient`. -- Use role-scoped clients for activation code because each class carries one custody role. Avoid teaching new activation paths with the multi-role `HandshakeClient` token map unless the test specifically needs route parity. +- Package identity, subpath exports, binaries, files allowlist, scripts, dependency versions, and MCP package identity live in `package.json`. +- Source/test TypeScript options live in `tsconfig.json`; declaration-only build options live in `tsconfig.build.json`. +- Bundle entrypoint mapping lives in `scripts/build-package-bundles.mjs`. +- Cloudflare Worker development/deployment config lives in `wrangler.toml`; Worker entry delegates to the Hono app in `src/worker.ts`. +- MCP Registry/package metadata lives in `server.json`. +- CI config lives in `.github/workflows/check.yml`. ## Platform Requirements **Development:** -- Install dependencies with `bun install --frozen-lockfile`; `.github/workflows/check.yml` uses that command. -- Main repo gate is `npm run check:repo`, which runs `npm run check:types`, `npm run lint`, `npm run format:check`, `npm run test`, `npm run pack:check`, and `git diff --check`. -- Focused gates are `npm run quality:architecture`, `npm run quality:claims`, and `npm run quality:storage`. -- Demo generation commands are `npm run demo:self-hosted`, `npm run demo:aps`, `npm run demo:adapter-sdk`, `npm run demo:x402-tool-profiles`, and `npm run demo:mcp-transcript`. +- Install dependencies with Bun using `bun.lock`; CI uses `bun install --frozen-lockfile` in `.github/workflows/check.yml`. +- Run all tests with `npm run test` or `bun test` from `package.json`. +- Run the full repo gate with `npm run check:repo` from `package.json`; it builds, typechecks, lints, format-checks, runs tests, verifies package surface, checks release/package posture, and runs `git diff --check`. +- Run the HTTP Worker locally with `npm run dev` (`wrangler dev`) when exercising `src/worker.ts` and `src/http/app.ts`. +- Use `npm run demo:x402-tool-profiles`, `npm run demo:aps`, `npm run demo:self-hosted`, `npm run demo:adapter-sdk`, and `npm run demo:service-workflow-admission` from `package.json` for source-owned demo outputs under `examples/**/output/`. **Production:** -- HTTP service target is Cloudflare Workers through `src/worker.ts` and `wrangler.toml`. -- Durable reconstruction store is Cloudflare D1 through `src/storage/d1/index.ts` and `migrations/0001_protocol_kernel.sql`. -- KV is cache posture only through `src/storage/kv/index.ts`; it is not durable protocol truth. -- Public package consumers use Node ESM bundles under `dist/` and executable wrappers under `bin/`. -- Public npm availability, MCP Registry metadata, host profiles, and install health do not create authority. The gateway check remains the final enforcement point before consequence. +- Package version in the current dirty checkout is `handshake-protocol-kernel@0.2.8` in `package.json` and `server.json`. +- `README.md` states public npm `0.2.7` is historical provenance only; current local `0.2.8` still needs publish/readback proof before claiming current-surface npm publication. +- Published package files are limited by `package.json#files` to `bin`, `dist`, `server.json`, `README.md`, `CHANGELOG.md`, `LICENSE`, and `NOTICE`; `scripts/check-package-surface.mjs` and `scripts/check-published-entrypoints.mjs` enforce this boundary. +- Local MCP distribution is stdio-based through `bin/handshake-mcp`, `dist/bin/handshake-mcp.mjs`, `src/mcp/stdio/server.ts`, and `server.json`; MCP is proposal/evidence only. +- HTTP deployment target is Cloudflare Workers with D1 as durable protocol record storage and KV as non-authoritative cache, configured by `wrangler.toml`, `src/http/store/resolution.ts`, `src/storage/d1/index.ts`, and `src/storage/kv/index.ts`. +- Release administration is script-gated and non-authoritative: `scripts/check-release-admin.js`, `scripts/check-release-proof.mjs`, `scripts/check-npm-maintainer-posture.mjs`, and `scripts/check-distribution-provenance.mjs` verify package/artifact/readback posture without creating policy decisions, greenlights, gateway checks, or protected mutations. --- -*Stack analysis: 2026-05-25* +*Stack analysis: 2026-05-26* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md index eefade3..875ffd6 100644 --- a/.planning/codebase/STRUCTURE.md +++ b/.planning/codebase/STRUCTURE.md @@ -1,293 +1,358 @@ # Codebase Structure -**Analysis Date:** 2026-05-25 +**Analysis Date:** 2026-05-26 ## Directory Layout ```text Handshake v0.0.2/ -├── src/ # Source-owned protocol, transport, adapters, clients, and surfaces -├── test/ # Unit, product, architecture, smoke, and integration tests -├── examples/ # Runnable demos and generated-output fixtures -├── scripts/ # Quality, packaging, docs, and architecture guard scripts -├── migrations/ # Cloudflare D1 schema for protocol kernel state -├── bin/ # Package CLI entry shims -├── docs/internal/ # Canonical product, protocol, and decision notes -├── .github/workflows/ # CI gates -├── .planning/codebase/ # GSD scratch codebase maps -├── package.json # Package scripts, exports, dependencies, and files surface -├── tsconfig.json # TypeScript project settings -├── wrangler.toml # Cloudflare Worker/D1 configuration -├── README.md # Current repo orientation and commands -├── QUALITY.md # TypeScript and naming quality rules -└── STRUCTURE.md # Tracked source, docs, and test ownership rules +|-- src/ # TypeScript source for protocol kernel, surfaces, adapters, SDK, CLI, MCP, storage +| |-- protocol/ # Authority state machine, primitives, canonicalization, events, store port +| | |-- areas/ # Primitive-owned area modules +| | | `-- negotiation/ # A2A-style imported negotiation evidence only +| | |-- foundation/ # Canonicalization, ids, errors, base schemas, reason codes +| | |-- events/ # Event schema, digest chains, record commits +| | |-- context/ # Transition request context records +| | |-- navigation/ # Source-owned transition metadata +| | |-- public/ # Public schema/input aggregators +| | `-- store/ # Store port and indexing helpers +| |-- http/ # Hono/Worker transport, admission, routes, handlers, errors, OpenAPI, store resolution +| |-- runtime/ # Generated-execution evidence and proposal helpers +| |-- adapters/ # Reference adapter profiles, gateway fixtures, protected-path probes +| |-- adapter-sdk/ # Definition-only public adapter authoring subpath +| |-- install/ # Install proposal and protected-action adapter-pack contracts +| |-- sdk/ # Low-level HTTP client and role-scoped clients +| |-- cli/ # Local operator/evidence command surface +| |-- mcp/ # MCP proposal/evidence catalog, resources, x402 proposal bridge, stdio server +| |-- surfaces/ # Surface boundary manifests, service workflow projections, proof packets +| |-- storage/ # D1, memory, and KV/noop store implementations +| |-- conformance/ # Public conformance checks +| |-- hosted-admission/ # Public hosted caller identity/admission subpath +| |-- x402-protected-tool/ # Public protected-tool acceptance/facade/readiness/profile subpath +| |-- index.ts # Curated package root export surface +| |-- experimental.ts # Explicit experimental fixture exports +| `-- worker.ts # Cloudflare Worker entrypoint +|-- test/ # Bun tests by architecture, protocol, runtime, HTTP, MCP, SDK, CLI, adapters, product +|-- examples/ # Runnable demos/readback examples and generated output folders +|-- scripts/ # Build, package-surface, release, proof, and quality helper scripts +|-- migrations/ # D1 schema for protocol kernel storage +|-- bin/ # Thin package executable wrappers +|-- docs/internal/ # Compact canonical decisions, protocol notes, architecture docs, runbooks +|-- dist/ # Generated package build output +|-- .planning/codebase/ # Scratch codebase intelligence docs +|-- package.json # Package metadata, exports, scripts, dependencies +|-- tsconfig.json # TypeScript project config +|-- tsconfig.build.json # Declaration emit config +|-- eslint.config.js # ESLint config +|-- wrangler.toml # Cloudflare Worker/D1 binding config +|-- server.json # MCP Registry metadata for stdio server +|-- README.md # Current repo orientation and package usage +|-- QUALITY.md # TypeScript quality and naming rules +|-- STRUCTURE.md # Canonical source ownership map +`-- AGENTS.md # Doctrine, invariants, and repo truth boundaries ``` ## Directory Purposes -**`src/`:** -- Purpose: Source-owned implementation of the protocol kernel and product surfaces. -- Contains: Protocol areas, HTTP transport, storage adapters, runtime ingress, adapters, SDK role clients, CLI, MCP, surfaces, installation helpers, conformance exports, x402 protected-tool helper. -- Key files: `src/index.ts`, `src/worker.ts`, `src/protocol/kernel.ts`, `src/http/app.ts` - **`src/protocol/`:** -- Purpose: Protocol authority kernel, state-machine areas, store port, navigation, utilities, and evidence projections. -- Contains: `src/protocol/areas/*`, `src/protocol/store/port.ts`, `src/protocol/evidence-projections/*`, `src/protocol/navigation.ts`, `src/protocol/utils/*` -- Key files: `src/protocol/kernel.ts`, `src/protocol/LANE.md` +- Purpose: Source-owned authority semantics for exact contracts, policy decisions, one-use greenlights, gateway checks, receipts, refusals, proof gaps, isolation, recovery, review binding, generated-execution evidence, and transition invariants. +- Contains: `src/protocol/kernel.ts`, `src/protocol/areas/*`, `src/protocol/foundation/*`, `src/protocol/events/*`, `src/protocol/context/*`, `src/protocol/navigation/*`, `src/protocol/public/*`, `src/protocol/store/*`. +- Key files: `src/protocol/kernel.ts`, `src/protocol/areas/index.ts`, `src/protocol/public/schemas.ts`, `src/protocol/public/inputs.ts`, `src/protocol/store/port.ts`, `src/protocol/events/records.ts`. **`src/protocol/areas/`:** -- Purpose: Source-owned protocol primitives grouped by area. -- Contains: Action contract, catalog envelope, credential custody, delegated authority, gateway gate, policy greenlight, receipts, recovery, isolation, terminal certificate, and related transition modules. -- Key files: `src/protocol/areas/action-contract/schemas.ts`, `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/gateway-gate/transitions.ts` +- Purpose: Primitive-owned protocol modules split by authority or evidence area. +- Contains: One folder per primitive, commonly `index.ts`, `types.ts`, `schemas.ts`, `inputs.ts`, `transitions.ts`, plus `guards.ts` or support files where needed. +- Key files: `src/protocol/areas/intent-compilation/transitions.ts`, `src/protocol/areas/action-contract/transitions.ts`, `src/protocol/areas/policy-greenlight/transitions.ts`, `src/protocol/areas/gateway-gate/transitions.ts`, `src/protocol/areas/operation-lifecycle/transitions.ts`. + +**`src/protocol/areas/negotiation/`:** +- Purpose: A2A-style negotiation evidence imported into the protocol object/event model without protected-action authority. +- Contains: `src/protocol/areas/negotiation/LANE.md`, `src/protocol/areas/negotiation/index.ts`, `src/protocol/areas/negotiation/inputs.ts`, `src/protocol/areas/negotiation/schemas.ts`, `src/protocol/areas/negotiation/types.ts`. +- Key files: `src/protocol/areas/negotiation/schemas.ts`, `test/architecture/negotiation-no-authority-surface.test.ts`, `test/protocol/negotiation-schemas.test.ts`, `test/protocol/negotiation-object-registry.test.ts`, `test/protocol/negotiation-events.test.ts`. +- Rule: Keep this area evidence-only; do not add `transitions.ts`, package-root exports, downstream surface imports, policy imports, gateway imports, receipt-export imports, or authority-certificate imports. + +**`src/protocol/foundation/`:** +- Purpose: Shared deterministic protocol helpers and failure types. +- Contains: Canonicalization, content digests, ids, errors, reason codes, transition guards, and schema core helpers. +- Key files: `src/protocol/foundation/canonical.ts`, `src/protocol/foundation/content-digests.ts`, `src/protocol/foundation/errors.ts`, `src/protocol/foundation/ids.ts`, `src/protocol/foundation/reason-codes.ts`, `src/protocol/foundation/schema-core.ts`. + +**`src/protocol/events/`:** +- Purpose: Event-chain construction, event schemas, and stored record commit helpers. +- Contains: `src/protocol/events/chains.ts`, `src/protocol/events/records.ts`, `src/protocol/events/schemas.ts`, `src/protocol/events/index.ts`. +- Key files: `src/protocol/events/records.ts`, `src/protocol/events/chains.ts`, `src/protocol/events/schemas.ts`. + +**`src/protocol/public/`:** +- Purpose: Public schema/input aggregators for root exports and transport-facing imports. +- Contains: Aggregator-only `src/protocol/public/schemas.ts`, `src/protocol/public/inputs.ts`, `src/protocol/public/transitions.ts`, `src/protocol/public/index.ts`. +- Key files: `src/protocol/public/schemas.ts`, `src/protocol/public/inputs.ts`. +- Rule: Add public exports here only for intentional protocol/public surfaces. Do not add negotiation exports here while A2A negotiation remains evidence-only. + +**`src/protocol/store/`:** +- Purpose: Storage port, action-contract indexing helper, and store exports. +- Contains: `src/protocol/store/port.ts`, `src/protocol/store/action-contract-index.ts`, `src/protocol/store/index.ts`. +- Key files: `src/protocol/store/port.ts`. **`src/http/`:** -- Purpose: HTTP entry, route metadata, admission, handlers, OpenAPI helpers, and HTTP-facing navigation. -- Contains: `src/http/admission`, `src/http/routes`, `src/http/handlers`, `src/http/errors`, `src/http/openapi`, `src/http/store` -- Key files: `src/http/app.ts`, `src/http/admission/index.ts`, `src/http/routes/transition-route-registry.ts`, `src/http/routes/evidence-read-route-registry.ts` - -**`src/storage/`:** -- Purpose: Concrete protocol store implementations and Cloudflare storage integration. -- Contains: D1 store, in-memory store, KV helpers, and storage lane docs. -- Key files: `src/storage/d1/index.ts`, `src/storage/memory/index.ts`, `src/storage/store.ts` +- Purpose: Hono/Worker transport for protocol transitions, evidence reads, hosted admission/readiness, verifier endpoints, errors, OpenAPI, and store resolution. +- Contains: `src/http/app.ts`, `src/http/app-options.ts`, `src/http/admission/*`, `src/http/routes/*`, `src/http/handlers/*`, `src/http/errors/*`, `src/http/openapi/*`, `src/http/navigation/*`, `src/http/store/*`. +- Key files: `src/http/app.ts`, `src/http/routes/transition-route-registry.ts`, `src/http/routes/transition-invokers.ts`, `src/http/routes/evidence-read-route-registry.ts`, `src/http/admission/index.ts`. **`src/runtime/`:** -- Purpose: Proposal-only runtime ingress for generated execution observations. -- Contains: Ingress handler, family registry, runtime family definitions, posture checks. -- Key files: `src/runtime/ingress/index.ts`, `src/runtime/ingress/registry.ts`, `src/runtime/ingress/families.ts` +- Purpose: Generated-execution observations, candidate extraction inputs, wrapper-produced graph evidence, refusals, uncertainty markers, and proposal helpers. +- Contains: `src/runtime/ingress/*`, `src/runtime/package-install/*`, `src/runtime/repo-write/*`, `src/runtime/preview-deploy/*`, `src/runtime/x402-payment/*`, `src/runtime/auth-md`-adjacent dispatch support through adapter family builders, and `src/runtime/codemode-multi-action/*`. +- Key files: `src/runtime/ingress/index.ts`, `src/runtime/ingress/schemas.ts`, `src/runtime/ingress/registry.ts`, `src/runtime/ingress/families.ts`, `src/runtime/package-install/action-proposal.ts`, `src/runtime/codemode-multi-action/generated-program-runner.ts`. **`src/adapters/`:** -- Purpose: Adapter implementations that connect verified gateway checks to real mutation surfaces. -- Contains: x402 payment adapter and package-install adapter. -- Key files: `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/package-install/gateway.ts` +- Purpose: Reference adapter profiles, upstream evidence intake, protected-path probes, gateway fixtures, and post-gate mutation discipline. +- Contains: `src/adapters/x402-payment/*`, `src/adapters/package-install/*`, `src/adapters/repo-write/*`, `src/adapters/preview-deploy/*`, `src/adapters/auth-md/*`, `src/adapters/auth-md-x402-interlock/*`, `src/adapters/protected-path-probes/*`. +- Key files: `src/adapters/x402-payment/action-proposal.ts`, `src/adapters/x402-payment/wallet-gateway.ts`, `src/adapters/x402-payment/protected-tool-facade/index.ts`, `src/adapters/x402-payment/protected-tool-readiness/index.ts`, `src/adapters/package-install/gateway.ts`, `src/adapters/auth-md/gateway.ts`. + +**`src/adapter-sdk/`:** +- Purpose: Public definition-only adapter authoring surface. +- Contains: `src/adapter-sdk/index.ts`, `src/adapter-sdk/LANE.md`. +- Key files: `src/adapter-sdk/index.ts`. + +**`src/install/`:** +- Purpose: Install proposal contracts and protected-action adapter-pack definition contracts used by adapter SDK and x402 install proposal compilation. +- Contains: `src/install/install-proposal/*`, `src/install/protected-action-adapter-pack/*`, `src/install/index.ts`, `src/install/LANE.md`. +- Key files: `src/install/install-proposal/index.ts`, `src/install/protected-action-adapter-pack/index.ts`. **`src/sdk/`:** -- Purpose: Role-scoped clients and SDK entry points for product consumers. -- Contains: Role clients and SDK lane docs. -- Key files: `src/sdk/role-clients.ts`, `src/sdk/LANE.md` +- Purpose: Low-level and role-scoped HTTP clients over public transition and diagnostic evidence routes. +- Contains: `src/sdk/client.ts`, `src/sdk/surface-clients/*`, `src/sdk/transport-url.ts`, `src/sdk/activation/*`, `src/sdk/LANE.md`. +- Key files: `src/sdk/client.ts`, `src/sdk/surface-clients/runtime-client.ts`, `src/sdk/surface-clients/policy-client.ts`, `src/sdk/surface-clients/gateway-client.ts`, `src/sdk/surface-clients/evidence-client.ts`, `src/sdk/surface-clients/transport.ts`. **`src/cli/`:** -- Purpose: CLI command contracts and command dispatch surfaces. -- Contains: Command manifest, CLI entry implementation, readback commands. -- Key files: `src/cli/command-manifest.ts`, `src/cli/index.ts`, `src/cli/LANE.md` +- Purpose: Local command manifest, JSON output envelope, evidence rendering, local project setup/readiness, x402 install/probe/readiness commands, support bundles, and certificate verification. +- Contains: `src/cli/main.ts`, `src/cli/index.ts`, `src/cli/command-manifest.ts`, `src/cli/output.ts`, `src/cli/x402/*`, `src/cli/local-project/*`, `src/cli/demo/*`. +- Key files: `src/cli/main.ts`, `src/cli/command-manifest.ts`, `src/cli/x402/index.ts`, `src/cli/projection-evidence.ts`. **`src/mcp/`:** -- Purpose: MCP server surface for product integration. -- Contains: Server descriptors, route/tool wiring, MCP package surface. -- Key files: `src/mcp/server.ts`, `src/mcp/server.json`, `src/mcp/LANE.md` +- Purpose: MCP proposal/evidence catalog, strict x402 proposal schema, read-only resource mapping, reference transcript builder, and local stdio process harness. +- Contains: `src/mcp/catalog.ts`, `src/mcp/output.ts`, `src/mcp/resources.ts`, `src/mcp/x402-proposal.ts`, `src/mcp/stdio/*`, `src/mcp/reference-transcript.ts`, `src/mcp/reference-transcript-fixtures.ts`. +- Key files: `src/mcp/x402-proposal.ts`, `src/mcp/resources.ts`, `src/mcp/stdio/server.ts`. **`src/surfaces/`:** -- Purpose: Non-authority review/readback surface models. -- Contains: Review renderer models and surface posture helpers. -- Key files: `src/surfaces/LANE.md` +- Purpose: Shared non-authority product/readback boundary manifests, service workflow projection contracts, launch/activation/release proof records, and proof-packet projectors. +- Contains: `src/surfaces/boundary-manifest.ts`, `src/surfaces/service-workflow-admission/*`, `src/surfaces/service-workflow-lifecycle-projections/*`, `src/surfaces/proof-packets/*`, `src/surfaces/release-proof.ts`, `src/surfaces/product-launch-gate-resolution.ts`, `src/surfaces/x402-protected-tool-acceptance.ts`. +- Key files: `src/surfaces/boundary-manifest.ts`, `src/surfaces/service-workflow-admission/index.ts`, `src/surfaces/proof-packets/index.ts`. -**`src/install/`:** -- Purpose: Installation, registry, and package setup helpers. -- Contains: Install-related package and server metadata helpers. -- Key files: `src/install/LANE.md` - -**`src/adapter-sdk/`:** -- Purpose: Public adapter SDK definitions that support third-party adapter packs without giving them protocol authority. -- Contains: Definition-only adapter pack contracts and helpers. -- Key files: `src/adapter-sdk/index.ts`, `src/adapter-sdk/LANE.md` +**`src/storage/`:** +- Purpose: Protocol store mechanics and implementations. +- Contains: `src/storage/d1/*`, `src/storage/memory/*`, `src/storage/kv/*`, `src/storage/store.ts`, `src/storage/LANE.md`. +- Key files: `src/storage/d1/index.ts`, `src/storage/d1/statements.ts`, `src/storage/memory/index.ts`, `src/storage/kv/index.ts`. **`src/conformance/`:** -- Purpose: Conformance package surface for protocol/adapters compatibility checks. -- Contains: Conformance exports and fixtures. -- Key files: `src/conformance/index.ts`, `src/conformance/LANE.md` +- Purpose: Public conformance checks for protected mutation adapters and x402 upstream fixture posture. +- Contains: `src/conformance/index.ts`, `src/conformance/x402-payment/*`, `src/conformance/LANE.md`. +- Key files: `src/conformance/index.ts`, `src/conformance/x402-payment/*`. + +**`src/hosted-admission/`:** +- Purpose: Public package subpath for provider-neutral hosted identity evidence, hosted caller verification, hosted admission config, and hosted verifier adapter helpers. +- Contains: `src/hosted-admission/index.ts`, `src/hosted-admission/hosted-admission-config.ts`, `src/hosted-admission/hosted-caller-identity.ts`, `src/hosted-admission/hosted-verifier-adapter.ts`, `src/hosted-admission/roles.ts`, `src/hosted-admission/LANE.md`. +- Key files: `src/hosted-admission/index.ts`, `src/hosted-admission/hosted-verifier-adapter.ts`. **`src/x402-protected-tool/`:** -- Purpose: Narrow package surface for x402 protected-tool helpers. -- Contains: Tool helper exports and lane documentation. -- Key files: `src/x402-protected-tool/index.ts`, `src/x402-protected-tool/LANE.md` +- Purpose: Public package subpath for the first x402 protected-tool facade/profile/readiness distribution surface. +- Contains: `src/x402-protected-tool/index.ts`, `src/x402-protected-tool/LANE.md`. +- Key files: `src/x402-protected-tool/index.ts`, `src/adapters/x402-payment/protected-tool-facade/index.ts`, `src/adapters/x402-payment/protected-tool-readiness/index.ts`, `src/adapters/x402-payment/protected-tool-profile/index.ts`. **`test/`:** -- Purpose: Verification suite for protocol invariants, architecture boundaries, product claims, examples, and integrations. -- Contains: `test/architecture`, `test/product`, `test/smoke`, `test/integration`, plus focused protocol and package tests. -- Key files: `test/architecture/import-posture.test.ts`, `test/architecture/package-surface.test.ts`, `test/architecture/surface-boundary-posture.test.ts` - -**`examples/`:** -- Purpose: Runnable demonstrations with checked source and ignored generated output. -- Contains: Example READMEs, `run.mjs` scripts, TypeScript helpers, and `output/.gitignore` files. -- Key files: `examples/x402-full-chain/run.mjs`, `examples/external-adapter-sdk/run.mjs`, `examples/x402-protected-tool/README.md` - -**`scripts/`:** -- Purpose: Repository quality, architecture, claims, package, docs, and example-output gates. -- Contains: Node scripts invoked from `package.json`. -- Key files: `scripts/check-architecture-docs.mjs`, `scripts/check-claims.mjs`, `scripts/check-package-surface.mjs`, `scripts/check-example-outputs.mjs` - -**`docs/internal/`:** -- Purpose: Tracked canonical product and architecture decisions. -- Contains: Decision log, protocol notes, protocol definition, protocol kernel architecture, and focused internal docs. -- Key files: `docs/internal/decisions.md`, `docs/internal/protocol-notes.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md` - -**`.planning/codebase/`:** -- Purpose: GSD scratch codebase maps for planner/executor agents. -- Contains: Generated architecture, structure, stack, testing, convention, concern, and integration maps. -- Key files: `.planning/codebase/ARCHITECTURE.md`, `.planning/codebase/STRUCTURE.md` +- Purpose: Bun test suite by architecture, protocol, runtime, HTTP, MCP, SDK, CLI, adapters, product, storage, integration, conformance, and support fixtures. +- Contains: `test/architecture/*`, `test/protocol/*`, `test/runtime/*`, `test/http/*`, `test/mcp/*`, `test/sdk/*`, `test/cli/*`, `test/adapters/*`, `test/product/*`, `test/integration/*`, `test/conformance/*`, `test/support/*`. +- Key files: `test/architecture/import-posture.test.ts`, `test/architecture/root-exports.test.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/negotiation-no-authority-surface.test.ts`, `test/protocol/negotiation-schemas.test.ts`. ## Key File Locations **Entry Points:** -- `src/worker.ts`: Cloudflare Worker fetch entry that delegates to the HTTP app. -- `src/http/app.ts`: Hono app factory and transport entry for transition/read routes. -- `src/index.ts`: Curated public root package exports. -- `src/experimental.ts`: Explicit experimental exports and reference fixtures. -- `bin/handshake.js`: Package CLI entry shim. +- `src/index.ts`: Package root export curation. +- `src/worker.ts`: Cloudflare Worker fetch entrypoint. +- `src/http/app.ts`: Hono app factory and route registration. +- `src/cli/main.ts`: CLI command dispatch. +- `src/mcp/stdio/entry.ts`: MCP stdio process entrypoint. +- `bin/handshake`: CLI executable wrapper. +- `bin/handshake-mcp`: MCP executable wrapper. **Configuration:** -- `package.json`: Scripts, package exports, package files, dependency list. -- `tsconfig.json`: TypeScript compiler settings. -- `vitest.config.ts`: Test runner configuration. -- `wrangler.toml`: Cloudflare Worker and D1 binding configuration. -- `.github/workflows/check.yml`: CI quality gate. +- `package.json`: Package exports, bins, scripts, dependency versions, and release/package-surface contract. +- `tsconfig.json`: TypeScript project config. +- `tsconfig.build.json`: Declaration/build config. +- `eslint.config.js`: ESLint config. +- `.prettierrc.json`: Prettier config. +- `wrangler.toml`: Worker and D1 binding config. +- `server.json`: MCP Registry metadata. +- `.github/workflows/check.yml`: CI gate. **Core Logic:** - `src/protocol/kernel.ts`: Protocol transition facade. -- `src/protocol/store/port.ts`: Store interface between protocol and persistence. -- `src/protocol/areas/action-contract/*`: Exact action contract records and transitions. -- `src/protocol/areas/policy-greenlight/*`: Policy decision and one-use greenlight records. -- `src/protocol/areas/gateway-gate/*`: Gateway enforcement transition and verified gateway artifacts. -- `src/protocol/areas/delegated-authority/*`: Principal-agent-runtime delegated authority references and status. -- `src/protocol/areas/credential-custody/*`: Gateway credential references and custody proof packets. -- `src/runtime/ingress/*`: Proposal-only runtime observation compiler. -- `src/adapters/x402-payment/wallet-gateway.ts`: Official x402 buyer-side signing gateway after verification. -- `src/adapters/package-install/gateway.ts`: Package-install gateway execution after verification. - -**Read Models and Projections:** -- `src/protocol/evidence-projections/projections.ts`: Redacted contract/timeline/readback projection helpers. -- `src/protocol/evidence-projections/assembly.ts`: Transaction envelope assembly from protocol records. -- `src/http/routes/evidence-read-route-registry.ts`: Evidence read route contracts, scopes, and role requirements. -- `src/http/handlers/evidence-read.ts`: Evidence projection HTTP handler. -- `src/http/handlers/internal-record-read.ts`: Raw/internal record read guardrails. - -**Admission and Routing:** -- `src/http/admission/index.ts`: Transition, evidence-read, hosted verifier, and raw/readiness admission checks. -- `src/http/routes/transition-route-registry.ts`: Transition route metadata and custody roles. -- `src/http/routes/transition-invokers.ts`: Route ID to kernel method mapping. - -**Persistence:** -- `src/storage/memory/index.ts`: In-memory store with conflict/idempotency semantics. -- `src/storage/d1/index.ts`: D1-backed store implementation. -- `src/storage/store.ts`: Store construction from environment. -- `migrations/0001_protocol_kernel.sql`: Durable D1 schema. +- `src/protocol/areas/object-registry/schemas.ts`: Protocol object discriminated union and object-type registry. +- `src/protocol/events/records.ts`: Canonical record and event commit helper. +- `src/protocol/store/port.ts`: Atomic persistence contract. +- `src/runtime/ingress/index.ts`: Composite runtime evidence to action-contract proposal path. +- `src/protocol/areas/negotiation/schemas.ts`: A2A-style negotiation evidence-only schemas. + +**Protocol Authority Areas:** +- `src/protocol/areas/intent-compilation/transitions.ts`: Vague intent/generated evidence to candidate action or refusal. +- `src/protocol/areas/action-contract/transitions.ts`: Candidate to exact action contract. +- `src/protocol/areas/policy-greenlight/transitions.ts`: Policy decision, review/refusal/proof-gap, one-use greenlight, idempotency reservation. +- `src/protocol/areas/gateway-gate/transitions.ts`: Pre-mutation greenlight verification, mutation attempt, receipt/refusal/proof-gap. +- `src/protocol/areas/operation-lifecycle/transitions.ts`: Downstream protected-surface reconciliation. +- `src/protocol/areas/isolation-breaker/index.ts`: Isolation state and breaker decisions. +- `src/protocol/areas/authority-certificate/index.ts`: Terminal certificate signing and verification helpers. + +**Product/Readback Surfaces:** +- `src/surfaces/boundary-manifest.ts`: Surface boundary contract. +- `src/surfaces/service-workflow-admission/index.ts`: Admission/handle/principal-agent-link/context-ref projection contracts. +- `src/hosted-admission/index.ts`: Hosted identity evidence helper public subpath. +- `src/sdk/surface-clients/*`: Role-scoped transition clients. +- `src/mcp/x402-proposal.ts`: MCP proposal bridge. +- `src/cli/command-manifest.ts`: CLI command surface metadata. +- `src/adapter-sdk/index.ts`: Definition-only adapter SDK subpath. +- `src/x402-protected-tool/index.ts`: Protected-tool public subpath. + +**Storage:** +- `src/storage/d1/index.ts`: D1 `ProtocolStore` implementation. +- `src/storage/d1/statements.ts`: D1 SQL statement builders. +- `src/storage/memory/index.ts`: Memory `ProtocolStore` implementation. +- `src/storage/kv/index.ts`: KV/noop isolation cache plumbing. +- `migrations/0001_protocol_kernel.sql`: D1 schema. **Testing:** -- `test/architecture/import-posture.test.ts`: Lane, import, authority, projection, storage, and signer boundary checks. -- `test/architecture/root-exports.test.ts`: Public root export restrictions. -- `test/architecture/package-surface.test.ts`: Packed package file and export restrictions. -- `test/architecture/surface-boundary-posture.test.ts`: Surface authority posture checks. -- `test/product/*`: Product behavior and example-output expectations. +- `test/architecture/import-posture.test.ts`: Lane import constraints. +- `test/architecture/package-surface.test.ts`: Package export/subpath shape. +- `test/architecture/root-exports.test.ts`: Root export curation. +- `test/architecture/surface-boundary-posture.test.ts`: Surface manifest enforcement. +- `test/architecture/negotiation-no-authority-surface.test.ts`: Negotiation evidence-only boundary. +- `test/protocol/kernel-policy-gateway.test.ts`: Kernel policy/gateway path. +- `test/runtime/runtime-ingress.test.ts`: Runtime ingress proposal behavior. +- `test/http/http.test.ts`: HTTP route behavior. +- `test/mcp/mcp-x402-proposal.test.ts`: MCP x402 proposal behavior. ## Naming Conventions **Files:** -- Protocol areas use lowercase kebab-case directories with explicit implementation files: `src/protocol/areas/gateway-gate/transitions.ts`, `src/protocol/areas/action-contract/schemas.ts`. -- Each first-level source lane has a `LANE.md` file: `src/protocol/LANE.md`, `src/http/LANE.md`, `src/runtime/LANE.md`. -- Tests use `*.test.ts` and live under a semantic test directory: `test/architecture/import-posture.test.ts`, `test/product/x402-demo-output.test.ts`. -- Example runners use `run.mjs`: `examples/external-adapter-sdk/run.mjs`, `examples/x402-full-chain/run.mjs`. -- Scripts use descriptive kebab-case `.mjs` names: `scripts/check-package-surface.mjs`. +- Protocol area files use stable role names: `schemas.ts`, `inputs.ts`, `types.ts`, `transitions.ts`, `guards.ts`, `index.ts` under `src/protocol/areas//`. +- Runtime proposal helpers use `action-proposal.ts`, as in `src/runtime/package-install/action-proposal.ts` and adapter-family helpers such as `src/adapters/x402-payment/action-proposal.ts`. +- Lane ownership files are named `LANE.md` at first-level source lanes and selected subareas, such as `src/protocol/LANE.md` and `src/protocol/areas/negotiation/LANE.md`. +- Tests use `.test.ts` and live under category directories such as `test/protocol/`, `test/runtime/`, `test/architecture/`, and `test/adapters/`. **Directories:** -- Protocol source directories are domain names, not stage labels: `src/protocol/areas/policy-greenlight`, `src/protocol/areas/gateway-gate`. -- Transport directories are responsibility names: `src/http/admission`, `src/http/routes`, `src/http/handlers`. -- Adapter directories name protected-action families: `src/adapters/x402-payment`, `src/adapters/package-install`. -- Test directories name verification class: `test/architecture`, `test/product`, `test/smoke`, `test/integration`. - -**Symbols:** -- Public experimental exports must be named with `experimental*` or `Experimental*` from `src/experimental.ts`. -- Authority-bearing symbols should keep exact domain names such as `ActionContract`, `PolicyDecision`, `Greenlight`, `GatewayCheckAttempt`, `VerifiedGatewayCheck`, `DelegatedAuthorityRef`, and `GatewayCredentialRef`. -- Do not introduce broad names such as `Passport`, `Session`, `Approval`, or `Auth` as authority records unless they map to an existing exact protocol primitive. +- First-level `src/` directories are ownership lanes, not generic technical buckets. +- Protocol primitives live under `src/protocol/areas//`. +- Product/readback contracts live under explicit surfaces such as `src/surfaces/service-workflow-admission/`, `src/mcp/`, `src/cli/`, `src/sdk/surface-clients/`, and `src/x402-protected-tool/`. +- Storage implementations live under `src/storage//`. ## Where to Add New Code -**New Protocol Primitive:** +**New Protocol Authority Primitive:** - Primary code: `src/protocol/areas//` -- Required files: `schemas.ts`, `inputs.ts` when needed, `transitions.ts`, `index.ts`, and focused helper modules. -- Kernel wiring: `src/protocol/kernel.ts` -- Store impact: `src/protocol/store/port.ts`, `src/storage/memory/index.ts`, `src/storage/d1/index.ts`, `migrations/0001_protocol_kernel.sql` if durable state changes. -- Tests: focused protocol tests plus `test/architecture/import-posture.test.ts` updates when import posture changes. - -**New Gateway-Enforced Action Family:** -- Primary code: existing or new protocol records under `src/protocol/areas/*`; gateway logic under `src/adapters//gateway.ts`. -- Runtime proposal support: `src/runtime/ingress/families.ts`, `src/runtime/ingress/registry.ts`, `src/runtime/ingress/index.ts` if the family can be detected from runtime observations. -- HTTP route support: `src/http/routes/transition-route-registry.ts`, `src/http/routes/transition-invokers.ts` if a new transition is needed. -- Tests: adapter tests, protocol gateway tests, product demo tests, and architecture boundary tests. - -**New Projection or Read Model:** -- Primary code: `src/protocol/evidence-projections/` -- HTTP route: `src/http/routes/evidence-read-route-registry.ts` -- Handler: `src/http/handlers/evidence-read.ts` or `src/http/handlers/internal-record-read.ts` -- Tests: projection tests and `test/architecture/import-posture.test.ts` to keep read models out of authority imports. - -**Passport/Admission/Service Gateway Simplification:** -- Passport readback should be added as a projection over `ParticipantIdentityBinding`, `OperatingEnvelope`, `ActionContract`, `DelegatedAuthorityRef`, `GatewayRegistryEntry`, and `GatewayCredentialRef`. -- Admission changes belong in `src/http/admission/index.ts` and route metadata under `src/http/routes/*`; they must not create greenlights or mutation authority. -- Service gateway language should map to `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/credential-custody/*`, `src/protocol/areas/gateway-gate/*`, and adapter gateway files before adding new protocol state. -- Principal-agent link changes belong in `src/protocol/areas/catalog-envelope/schemas.ts`, `src/protocol/areas/action-contract/schemas.ts`, and `src/protocol/areas/delegated-authority/schemas.ts`. +- Required local files: `src/protocol/areas//schemas.ts`, `src/protocol/areas//inputs.ts`, `src/protocol/areas//types.ts`, `src/protocol/areas//index.ts` +- Add transitions only when the primitive creates protocol state authority: `src/protocol/areas//transitions.ts` +- Add to: `src/protocol/areas/index.ts`, `src/protocol/public/schemas.ts`, `src/protocol/public/inputs.ts`, `src/protocol/areas/object-registry/schemas.ts`, `src/protocol/events/schemas.ts`, `src/protocol/navigation/index.ts`, `src/protocol/kernel.ts` +- Tests: `test/protocol/.test.ts`, relevant `test/architecture/import-posture.test.ts`, `test/architecture/root-exports.test.ts` + +**New Evidence-Only Protocol Area:** +- Primary code: `src/protocol/areas//` +- Follow the A2A negotiation pattern in `src/protocol/areas/negotiation/`. +- Add schemas and input aliases: `src/protocol/areas//schemas.ts`, `src/protocol/areas//inputs.ts`, `src/protocol/areas//index.ts` +- Add object/event vocabulary only when records must be durable: `src/protocol/areas/object-registry/schemas.ts`, `src/protocol/events/schemas.ts` +- Do not add: `transitions.ts`, package-root exports, downstream surface imports, policy/gateway/receipt/certificate imports. +- Tests: `test/protocol/-schemas.test.ts`, `test/protocol/-object-registry.test.ts`, `test/architecture/-no-authority-surface.test.ts` + +**New Runtime Dispatch Family:** +- Registry: `src/runtime/ingress/registry.ts` +- Input schema: `src/runtime/ingress/schemas.ts` +- Family mapping: `src/runtime/ingress/families.ts` +- Proposal builder: `src/runtime//action-proposal.ts` or `src/adapters//action-proposal.ts` +- Tests: `test/runtime/runtime-ingress.test.ts`, `test/runtime/-runtime.test.ts`, protocol candidate/graph tests as needed. + +**New Gateway Adapter:** +- Implementation: `src/adapters//gateway.ts` +- Proposal/evidence helpers: `src/adapters//action-proposal.ts` or `src/runtime//action-proposal.ts` +- Bypass/probe support: `src/adapters//bypass-probes.ts` or `src/adapters/protected-path-probes/*` +- Public experimental export only when explicitly intended: `src/experimental.ts` +- Tests: `test/adapters/-gateway.test.ts`, `test/conformance/protected-mutation-adapter-conformance.test.ts`, integration tests under `test/integration/` when storage/HTTP is involved. + +**New HTTP Transition Route:** +- Route metadata: `src/http/routes/transition-route-registry.ts` +- Invoker: `src/http/routes/transition-invokers.ts` +- Response schema: `src/http/routes/transition-response-schemas.ts` +- Scope resolver if needed: `src/http/routes/transition-scope-resolvers.ts` +- Navigation projection: `src/http/navigation/index.ts` +- Kernel method: `src/protocol/kernel.ts` +- Tests: `test/http/http.test.ts`, `test/http/d1-http.test.ts`, architecture route/nav tests as needed. + +**New Product/Readback Surface:** +- Boundary first: `src/surfaces/boundary-manifest.ts` +- Implementation lane: choose explicit lane such as `src/cli/`, `src/mcp/`, `src/sdk/surface-clients/`, `src/hosted-admission/`, `src/surfaces//`, or `src/x402-protected-tool/` +- Package export only when intended: `package.json`, `src/index.ts` only if root export is allowed. +- Tests: `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/package-surface.test.ts`, `test/architecture/root-exports.test.ts`, plus surface-specific tests. + +**New Service Workflow Projection:** +- Primary code: `src/surfaces/service-workflow-admission/index.ts` or a sibling under `src/surfaces/` +- Preserve: projection/readback only, `freshActionContractRequired: true`, no gateway/policy/payment/receipt authority. +- Tests: `test/architecture/workflow-admission-boundary.test.ts`, `test/product/service-workflow-admission.test.ts` + +**New SDK Role Client:** +- Implementation: `src/sdk/surface-clients/-client.ts` +- Transport: `src/sdk/surface-clients/transport.ts` +- Export: `src/sdk/surface-clients/index.ts` +- Boundary update: `src/surfaces/boundary-manifest.ts` +- Tests: `test/sdk/role-clients.test.ts`, `test/architecture/surface-boundary-posture.test.ts`, `test/architecture/package-surface.test.ts` **New CLI Command:** -- Primary code: `src/cli/` -- Command contract: `src/cli/command-manifest.ts` -- Tests: CLI/product tests plus architecture checks if command claims authority. - -**New MCP Tool:** -- Primary code: `src/mcp/` -- Public package/server metadata: `src/mcp/server.json`, `package.json` exports if needed. -- Tests: MCP/package-surface tests and claim-boundary tests. - -**New SDK Client Capability:** -- Primary code: `src/sdk/role-clients.ts` -- Package export: `package.json` subpath export if public. -- Tests: SDK tests plus `test/architecture/root-exports.test.ts` and `test/architecture/package-surface.test.ts` when exports change. - -**New Example:** -- Primary code: `examples//` -- Output posture: generated outputs under `examples//output/` with only `.gitignore` tracked unless product tests require fixtures. -- Tests: `test/product/*` and `scripts/check-example-outputs.mjs` updates when generated output contracts matter. - -**Utilities:** -- Protocol-only utilities: `src/protocol/utils/` -- HTTP-only utilities: `src/http/` -- Script-only utilities: `scripts/` -- Do not place shared authority logic in examples, CLI, MCP, SDK, or surfaces. +- Metadata first: `src/cli/command-manifest.ts` +- Dispatcher: `src/cli/main.ts` +- Output envelope: `src/cli/output.ts` +- Command implementation: `src/cli/.ts` or `src/cli//index.ts` +- Tests: `test/architecture/cli-command-posture.test.ts`, `test/cli/.test.ts` + +**New MCP Tool Or Resource:** +- Catalog: `src/mcp/catalog.ts` +- Tool implementation: `src/mcp/.ts` +- Resource mapping: `src/mcp/resources.ts` +- Stdio registration: `src/mcp/stdio/server.ts` +- Tests: `test/mcp/mcp-schema-contract.test.ts`, `test/mcp/mcp-resource-redaction.test.ts`, `test/mcp/.test.ts`, `test/architecture/mcp-surface-posture.test.ts` + +**New Storage Behavior:** +- Port first: `src/protocol/store/port.ts` +- Memory implementation: `src/storage/memory/index.ts` +- D1 implementation: `src/storage/d1/index.ts`, `src/storage/d1/statements.ts`, `migrations/0001_protocol_kernel.sql` +- Tests: `test/protocol/protocol-store-atomicity-contract.test.ts`, `test/http/d1-http.test.ts`, `test/protocol/fault-injecting-protocol-store.test.ts` ## Special Directories **`dist/`:** -- Purpose: Build output published by package scripts. -- Generated: Yes -- Committed: No +- Purpose: Generated package build output. +- Generated: Yes. +- Committed: Present in this checkout; do not treat as source authority when mapping behavior. **`examples/*/output/`:** -- Purpose: Generated demo packets such as JSON/Markdown readbacks. -- Generated: Yes -- Committed: Only `.gitignore` files are tracked unless a test deliberately adds a stable fixture. +- Purpose: Generated demo/readback outputs. +- Generated: Yes. +- Committed: Output folders include `.gitignore`; generated outputs are runtime artifacts. **`.planning/`:** -- Purpose: GSD scratch plans and codebase maps. -- Generated: Yes -- Committed: Some codebase maps may be tracked, but they are not canonical product truth. +- Purpose: GSD scratch planning, macro plans, codebase maps, archived planning artifacts. +- Generated: Yes. +- Committed: Present, but not canonical product/protocol truth. +- Rule: Only `.planning/codebase/ARCHITECTURE.md` and `.planning/codebase/STRUCTURE.md` are in scope for this mapper run. **`docs/internal/`:** -- Purpose: Durable product, protocol, and architecture canon. -- Generated: No -- Committed: Yes +- Purpose: Compact canonical internal docs, decisions, protocol architecture, release runbook, and service workflow story. +- Generated: No. +- Committed: Yes. +- Rule: Do not promote `.planning/` language into these docs without explicit source-backed doc work. **`migrations/`:** -- Purpose: Durable D1 schema for protocol storage. -- Generated: No -- Committed: Yes - -**`.github/workflows/`:** -- Purpose: Repository CI quality gates. -- Generated: No -- Committed: Yes +- Purpose: D1 schema for reference durable protocol storage. +- Generated: No. +- Committed: Yes. -**`.gstack/`, `.strategy/`, `.cursor/`:** -- Purpose: Local agent/tooling metadata if present. -- Generated: Yes -- Committed: No current tracked files detected. +**`bin/`:** +- Purpose: Thin package executable wrappers for bundled CLI and MCP entrypoints. +- Generated: No. +- Committed: Yes. --- -*Structure analysis: 2026-05-25* +*Structure analysis: 2026-05-26* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md index 8e742f8..01a14f3 100644 --- a/.planning/codebase/TESTING.md +++ b/.planning/codebase/TESTING.md @@ -1,118 +1,119 @@ # Testing Patterns -**Analysis Date:** 2026-05-25 +**Analysis Date:** 2026-05-26 ## Test Framework **Runner:** -- Bun test through `bun test`. -- Package manager/runtime declared in `package.json`: `bun@1.3.9`, Node engine `>=20`. -- Config: no separate `bunfig.toml` or Vitest/Jest config detected. Test behavior is driven by `package.json`, TypeScript settings in `tsconfig.json`, and source/test imports. +- Bun test runner via `bun test`. +- Runtime/package manager version is pinned as `bun@1.3.9` in `package.json`; CI installs Bun 1.3.9 in `.github/workflows/check.yml`. +- No `bunfig.toml`, `vitest.config.*`, or `jest.config.*` file is present. **Assertion Library:** -- `bun:test` provides `describe`, `it`, and `expect`. -- Common matchers include `toBe`, `toEqual`, `toMatchObject`, `toContain`, `toHaveLength`, `toThrow`, `rejects.toThrow`, and Bun-specific matchers such as `toBeFunction()` and `toBeString()`. +- Use `bun:test` for `describe`, `it`, and `expect`. Examples: `test/protocol/canonical.test.ts`, `test/http/http.test.ts`, `test/architecture/import-posture.test.ts`. +- Use Bun-specific matchers where useful: `toBeString`, `toBeFunction`, `rejects.toThrow`, `toMatchObject`, `arrayContaining`, and `it.each` appear in tests such as `test/protocol/kernel-policy-gateway.test.ts`, `test/sdk/role-clients.test.ts`, and `test/protocol/negotiation-schemas.test.ts`. **Run Commands:** ```bash -npm run test # Run all Bun tests -npm run test -- test/path.test.ts # Run one focused test file -npm run quality:claims # Claim-boundary language gate -npm run quality:architecture # Naming, imports, exports, surface posture, conformance gate -npm run quality:storage # Storage/kernel invariant slice -npm run check:repo # Full repo gate +npm run test # Run all Bun tests through package script +bun test # Run all tests directly +npm run quality:architecture # Run architecture/import/export/naming/conformance gate slice +npm run quality:claims # Run public-claim and vocabulary boundary tests +npm run quality:storage # Run storage, transition, model, and receipt invariant slices +npm run check:repo # Full build, typecheck, lint, format, tests, package checks, and git diff whitespace check ``` ## Test File Organization **Location:** -- Tests are separate from source under `test/**`. -- Test support code lives under `test/support/**`. -- Root `test/*.test.ts` files are forbidden by `test/architecture/naming-posture.test.ts`. +- Tests live under `test//*.test.ts`; 113 `.test.ts` files are present under `test`. +- Shared test-only helpers live under `test/support`: `test/support/fixtures.ts`, `test/support/fault-injecting-protocol-store.ts`, `test/support/d1-http-harness.ts`, `test/support/transition-budget-recorder.ts`. +- No root `test/*.test.ts` files are allowed. `test/architecture/naming-posture.test.ts` enforces this. **Naming:** -- Test files use `*.test.ts`. -- Test names describe the boundary or failure mode, not just the implementation path. Examples: `test/architecture/claim-boundary.test.ts`, `test/protocol/kernel-policy-gateway.test.ts`, `test/runtime/runtime-ingress.test.ts`, `test/adapters/x402-wallet-gateway.test.ts`. +- Use `.test.ts` names inside the relevant domain: `test/protocol/kernel-policy-gateway.test.ts`, `test/runtime/codemode-multi-action-runtime.test.ts`, `test/product/external-adapter-sdk-demo.test.ts`. +- Use architecture gate names for repo shape and claims: `test/architecture/import-posture.test.ts`, `test/architecture/root-exports.test.ts`, `test/architecture/package-surface.test.ts`, `test/architecture/claim-boundary.test.ts`. +- Use schema/registry/event names for protocol evidence slices: `test/protocol/negotiation-schemas.test.ts`, `test/protocol/negotiation-object-registry.test.ts`, `test/protocol/negotiation-events.test.ts`. **Structure:** ```text test/ - architecture/ # claim, naming, import, export, package, surface, CLI, MCP gates - protocol/ # kernel state machine, canonicalization, policy, gateway, evidence, isolation - runtime/ # generated-execution proposal helpers and runtime ingress - adapters/ # reference gateway fixtures and adapter profiles - http/ # Hono/D1 route and store behavior - integration/ # D1/HTTP end-to-end protected action paths - mcp/ # proposal/evidence schema and resource contracts - cli/ # operator/evidence/local readiness command posture - product/ # demo/readback and acceptance packet contracts - conformance/ # adapter conformance checks - sdk/ # role-scoped clients - adapter-sdk/ # definition-only adapter authoring surface - support/ # fixtures, fakes, local harnesses, invariant helpers + architecture/ # Static repo, import, naming, package, claim, CI, and authority-surface posture gates + protocol/ # Protocol state machine, schemas, canonicalization, policy, gateway, receipt, recovery invariants + http/ # Hono app, route/admission, hosted identity, D1-backed HTTP behavior + runtime/ # Generated execution proposal wrappers and runtime ingress + adapters/ # Reference gateway/adaptor behavior, x402/auth-md/package/repo/preview slices + conformance/ # Adapter conformance and upstream x402 shape checks + integration/ # Cross-lane flows over protocol, adapters, and D1/HTTP harnesses + product/ # Demo/readback outputs and package consumer proofs + sdk/ # Role-scoped SDK client behavior + cli/ # CLI projections and local readback commands + mcp/ # MCP schema/resource/proposal/stdio behavior + adapter-sdk/ # Adapter authoring SDK contract tests + storage/ # Storage cache behavior + support/ # Fixtures, fake stores, local D1 harness, flow builders ``` -There are 98 `*.test.ts` files under `test/**`. - ## Test Structure **Suite Organization:** ```typescript import { describe, expect, it } from "bun:test"; -import { makeKernelFixture, registerFixtureObjects } from "../support/fixtures"; - -describe("runtime ingress adapter", () => { - it("observes supported dispatch and proposes a contract without policy or gateway authority", async () => { - const fixture = makeKernelFixture(); - await registerFixtureObjects(fixture); - - const result = await proposeRuntimeIngressActionContracts(/* ... */); +import { NegotiationSessionSchema } from "../../src/protocol/areas/negotiation"; - expect(result.responsePosture).toMatchObject({ - authorityCreated: false, - greenlightCreated: false, - gatewayCheckPerformed: false, - mutationAttempted: false, +describe("negotiation evidence schemas", () => { + it("parses a strict NegotiationSession with explicit party proof posture and imported external evidence", () => { + expect(NegotiationSessionSchema.parse(validSession())).toMatchObject({ + negotiationSessionId: "negotiation_session_demo", + externalProtocolEvidenceRefs: [{ evidencePosture: "imported_evidence_only" }], }); - expect(await recordCount(fixture.store, "greenlight")).toBe(0); }); }); ``` +Source pattern: `test/protocol/negotiation-schemas.test.ts`. **Patterns:** -- Build a fixture, register source-owned catalog/envelope/gateway objects, exercise one transition, then assert both returned posture and durable record counts. -- Use `makeKernelFixture()`, `registerFixtureObjects()`, `createGreenlitContract()`, `recordSafeBypassProbes()`, and `proposalInputForCompilation()` from `test/support/fixtures.ts` for kernel tests. -- Use local harnesses for integration boundaries: `createD1HttpHarness()` in `test/support/d1-http-harness.ts`, `createPackageManifestSurface()` in `test/support/package-install-flow.ts`, and `createRepoWriteSurface()` in `test/support/repo-write-flow.ts`. -- Assert negative space directly: no policy decision, no greenlight, no gateway check, no mutation attempt, no signer use, no raw credential material, no receipt export, no hosted/broad claims. +- Use `describe` blocks around the invariant surface, not only the implementation class. Examples: `"Handshake kernel invariants: policy and gateway"` in `test/protocol/kernel-policy-gateway.test.ts`, `"protocol module import posture"` in `test/architecture/import-posture.test.ts`. +- Use test names that state the protected invariant or forbidden behavior: `test/runtime/codemode-multi-action-runtime.test.ts` checks that generated programs emit ordered contracts without policy or gateway authority. +- Assert both positive state and absence of authority side effects. Examples: `test/runtime/runtime-ingress.test.ts` checks zero policy decisions, greenlights, gateway checks, and mutation attempts after runtime proposal. +- Use exact record counts for protocol side effects when authority boundaries matter. Examples: `test/protocol/kernel-policy-gateway.test.ts`, `test/runtime/runtime-ingress.test.ts`. +- Use `try/finally` when harnesses need cleanup. Example: `test/protocol/protocol-store-atomicity-contract.test.ts` disposes memory/D1 harnesses. +- Use table tests with `it.each` for forbidden vocabularies, unsupported surfaces, and object-kind matrices. Examples: `test/protocol/negotiation-schemas.test.ts`, `test/conformance/x402-payment-conformance.test.ts`, `test/protocol/kernel-cross-scope-matrix.test.ts`. ## Mocking -**Framework:** No dedicated mocking library is used. +**Framework:** Hand-written fakes and harnesses; no Jest/Vitest/Bun mock API usage was detected in `src` or `test`. **Patterns:** ```typescript -const store = new FaultInjectingProtocolStore(new InMemoryProtocolStore()); -store.hideListRecordsByTypeOnce("greenlight"); +class MockKvNamespace { + readonly putCalls: Array<{ key: string; value: string; options?: KVNamespacePutOptions }> = []; + readonly deleteCalls: string[] = []; -const duplicate = await fixture.kernel.evaluatePolicy({ - actionContractId: fixture.contract.actionContractId, - envelopeId: fixture.envelope.envelopeId, -}); + async put(key: string, value: string, options?: KVNamespacePutOptions): Promise { + this.putCalls.push(options ? { key, value, options } : { key, value }); + } -expect(duplicate.decision.decisionReasonCode).toBe("idempotency_duplicate_authority"); + async delete(key: string): Promise { + this.deleteCalls.push(key); + } +} ``` +Source pattern: `test/storage/kv-isolation-cache.test.ts`. **What to Mock:** -- Use fakes at system boundaries, not inside the protocol state machine. -- Storage faults are modeled by `FaultInjectingProtocolStore` in `test/support/fault-injecting-protocol-store.ts`. -- D1 is modeled by a local Bun SQLite-backed `LocalD1Database` inside `test/support/d1-http-harness.ts`. -- Filesystem mutation surfaces are modeled by test surfaces such as `FilePackageManifestSurface` in `test/support/package-manifest-surface.ts` and repo-write helpers in `test/support/repo-write-surface.ts`. -- x402 signer behavior is modeled with tracked signing surfaces in `test/adapters/x402-wallet-gateway.test.ts`, while official signer imports stay constrained to `src/adapters/x402-payment/wallet-gateway.ts`. +- Mock transport with explicit fake `fetch` implementations that capture path, method, headers, and body. Example: `captureFetch` in `test/sdk/role-clients.test.ts`. +- Mock persistence faults with protocol-store wrappers rather than global monkeypatching. Example: `FaultInjectingProtocolStore` in `test/support/fault-injecting-protocol-store.ts`. +- Mock D1 locally with Bun SQLite while preserving D1-shaped methods. Example: `LocalD1Database` and `LocalD1PreparedStatement` in `test/support/d1-http-harness.ts`. +- Mock host file surfaces with fixture classes. Examples: `test/support/package-manifest-surface.ts`, `test/support/repo-write-surface.ts`. +- Mock KV bindings with narrow local classes that record calls. Example: `MockKvNamespace` in `test/storage/kv-isolation-cache.test.ts`. **What NOT to Mock:** -- Do not mock `HandshakeKernel` transitions when asserting protocol authority behavior. Use the real kernel with `InMemoryProtocolStore`, `D1ProtocolStore`, or `FaultInjectingProtocolStore`. -- Do not mock away gateway checks in adapter tests. Conformance tests in `test/conformance/protected-mutation-adapter-conformance.test.ts` must prove adapters do not mutate without `VerifiedGatewayCheck`. -- Do not mock public surface manifests or package exports. Architecture tests import actual `src/**`, `package.json`, and `server.json`. +- Do not mock the protocol state machine when testing policy/gateway behavior. Use `HandshakeKernel` with `InMemoryProtocolStore`, `D1ProtocolStore`, or a fault-injecting wrapper as in `test/protocol/kernel-policy-gateway.test.ts`. +- Do not mock architecture rules. Static tests read real files with `node:fs` in `test/architecture/import-posture.test.ts`, `test/architecture/naming-posture.test.ts`, and `test/architecture/negotiation-no-authority-surface.test.ts`. +- Do not mock product demos when their generated output is the contract. `test/product/external-adapter-sdk-demo.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`, and `test/product/service-workflow-admission.test.ts` run scripts with `Bun.spawn` and inspect generated artifacts. +- Do not mock MCP stdio when checking process proof. `test/mcp/mcp-stdio-process.test.ts` uses `runMcpStdioProcessProof` against the local stdio server. +- Do not mock gateway checks away in adapter mutation tests. `test/adapters/x402-wallet-gateway.test.ts` asserts signer invocation only after a verified gateway check. ## Fixtures and Factories @@ -123,58 +124,91 @@ export function makeKernelFixture() { const kernel = new HandshakeKernel(store); const createdAt = nowIso(); - const tool: ToolCapability = { /* wrapped consequential tool */ }; - const actionType: ActionType = { /* package.install action type */ }; - const gateway: GatewayRegistryEntry = { /* customer gateway adapter */ }; - const envelope: OperatingEnvelope = { /* allowed action/resource bounds */ }; + const tool = { toolCapabilityId: "tool_package_install", readWriteClassification: "consequential" }; + const actionType = { actionTypeId: "atype_package_install", actionClass: "package.install" }; + const gateway = { gatewayRegistryEntryId: "gateway_registry_package", gatewayId: "gateway_package_manager" }; + const envelope = { envelopeId: "env_demo", allowedActionClasses: ["package.install"] }; return { store, kernel, tool, actionType, gateway, envelope }; } ``` +Condensed source pattern: `test/support/fixtures.ts`. **Location:** -- `test/support/fixtures.ts`: kernel fixtures, catalog registration, safe bypass probes, greenlit contracts. -- `test/support/kernel-invariant-helpers.ts`: kernel posture and out-of-band drift helpers. -- `test/support/d1-http-harness.ts`: Hono/D1 harness with role tokens and local SQLite D1 implementation. -- `test/support/fault-injecting-protocol-store.ts`: fault injection for commit conflicts, ambiguous commits, stale reads, hidden records, and posture drift. -- `test/support/package-install-flow.ts`, `test/support/repo-write-flow.ts`, `test/support/preview-deploy-flow.ts`, `test/support/auth-md-flow.ts`: adapter-specific flow builders. -- `test/support/codemode-multi-action-flow.ts`: generated-program/multi-action support. +- Core protocol fixtures: `test/support/fixtures.ts`. +- Gateway/posture invariant helpers: `test/support/kernel-invariant-helpers.ts`. +- Store fault injection: `test/support/fault-injecting-protocol-store.ts`. +- Transition performance budgets: `test/support/transition-budget-recorder.ts`. +- HTTP/D1 harness: `test/support/d1-http-harness.ts`. +- HTTP protocol fixtures: `test/support/http-protocol-fixtures.ts`. +- Runtime flow fixtures: `test/support/package-install-flow.ts`, `test/support/repo-write-flow.ts`, `test/support/preview-deploy-flow.ts`, `test/support/codemode-multi-action-flow.ts`, `test/support/auth-md-flow.ts`. +- Negotiation fixtures are local to their test files for now: `test/protocol/negotiation-schemas.test.ts`, `test/protocol/negotiation-object-registry.test.ts`, `test/protocol/negotiation-events.test.ts`. ## Coverage -**Requirements:** Not enforced by a configured coverage threshold or package script. +**Requirements:** No line or branch coverage threshold is configured. No coverage script appears in `package.json`, and no coverage config file was detected. **View Coverage:** ```bash -bun test --coverage # Available Bun coverage command, not wired into package scripts +bun test --coverage # Available Bun capability, not a repo-defined gate ``` -Coverage discipline is behavioral rather than percentage-based. New protocol work should add invariant tests for authority creation, refusal, replay, proof gap, projection redaction, isolation, and gateway-side enforcement. +**Gate Coverage:** Invariant coverage is enforced by focused scripts in `package.json`: `quality:architecture`, `quality:claims`, and `quality:storage`. The full closeout gate is `npm run check:repo`. ## Test Types **Unit Tests:** -- Protocol and schema behavior: `test/protocol/canonical.test.ts`, `test/protocol/refusal-format.test.ts`, `test/protocol/reason-code-registry.test.ts`, `test/protocol/object-registry.test.ts`. -- Surface shape and package boundaries: `test/architecture/root-exports.test.ts`, `test/architecture/package-surface.test.ts`, `test/architecture/mcp-surface-posture.test.ts`. +- Protocol primitive and pure helper tests live under `test/protocol`: `test/protocol/canonical.test.ts`, `test/protocol/reason-code-registry.test.ts`, `test/protocol/refusal-format.test.ts`. +- Protocol schema tests validate Zod contract shape and negative authority-shaped fields: `test/protocol/negotiation-schemas.test.ts`, `test/protocol/object-registry.test.ts`, `test/protocol/representation-contract.test.ts`. +- Surface client tests live under `test/sdk`: `test/sdk/role-clients.test.ts`. +- Adapter unit tests live under `test/adapters`: `test/adapters/package-install-gateway.test.ts`, `test/adapters/x402-wallet-gateway.test.ts`. **Integration Tests:** -- HTTP and D1-backed protocol paths: `test/http/d1-http.test.ts`, `test/integration/x402-d1-http.test.ts`, `test/integration/repo-write-d1-http.test.ts`. -- End-to-end adapter workflows: `test/integration/package-install-end-to-end.test.ts`, `test/integration/auth-md-protected-call.test.ts`, `test/integration/auth-md-receipt-reconstruction.test.ts`. +- D1/HTTP-backed flows live under `test/http` and `test/integration`: `test/http/d1-http.test.ts`, `test/integration/x402-d1-http.test.ts`, `test/integration/package-install-end-to-end.test.ts`. +- Store parity and atomicity are tested across memory and D1 via `test/protocol/protocol-store-atomicity-contract.test.ts`. +- Runtime-generated multi-action behavior is tested through kernel + fixtures in `test/runtime/codemode-multi-action-runtime.test.ts`. **E2E Tests:** -- No browser E2E framework is used. -- Product/demo contract tests act as source-owned acceptance checks: `test/product/self-hosted-activation.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`, `test/product/external-adapter-sdk-demo.test.ts`, `test/product/x402-protected-tool-acceptance.test.ts`. +- Product/demo smoke tests execute scripts or package-facing flows: `test/product/external-adapter-sdk-demo.test.ts`, `test/product/x402-protected-spend-demo-report.test.ts`, `test/product/hosted-package-consumer.test.ts`, `test/product/service-workflow-admission.test.ts`. +- MCP process proof uses the local stdio server path in `test/mcp/mcp-stdio-process.test.ts`. +- CLI readback and local project behavior live under `test/cli`: `test/cli/cli-evidence.test.ts`, `test/cli/cli-local-project.test.ts`, `test/cli/cli-x402-install-probes.test.ts`. + +**Architecture Tests:** +- Repo shape and naming posture are first-class tests: `test/architecture/naming-posture.test.ts`. +- Import and lane boundaries are tested in `test/architecture/import-posture.test.ts`. +- Package exports and packable files are tested in `test/architecture/package-surface.test.ts` and `test/architecture/root-exports.test.ts`. +- Public claim language is tested in `test/architecture/claim-boundary.test.ts` and `test/architecture/active-vocabulary.test.ts`. +- Negotiation remains schema-only and non-authority through `test/architecture/negotiation-no-authority-surface.test.ts`. + +**Conformance Tests:** +- Adapter no-mutation and gateway posture conformance live in `test/conformance/protected-mutation-adapter-conformance.test.ts`. +- x402 upstream exact fixture and first-wedge conformance live in `test/conformance/x402-upstream-exact-fixtures.test.ts` and `test/conformance/x402-payment-conformance.test.ts`. + +**Negotiation Evidence Tests:** +- Commit `4946237` added schema-only negotiation evidence coverage. `test/protocol/negotiation-schemas.test.ts` validates strict evidence schemas for sessions, offers, decisions, linked agreements, obligation bindings, status transitions, and imported external protocol refs. +- `test/protocol/negotiation-object-registry.test.ts` verifies negotiation object types are registered as `transition_evidence` with `audit_read` posture and payload-owned object IDs. +- `test/protocol/negotiation-events.test.ts` accepts only recorded-only negotiation stream events and rejects authority-shaped names such as `negotiation_authorized`, `agreement_executed`, and `agreement_certified`. +- `test/architecture/negotiation-no-authority-surface.test.ts` blocks negotiation imports into protected-action control areas, rejects `src/protocol/areas/negotiation/transitions.ts`, keeps negotiation out of `src/index.ts`, and prevents CLI/MCP/HTTP/SDK/adapters/storage/runtime surfaces from importing it. + +Focused command for this slice: +```bash +npm run test -- test/protocol/negotiation-schemas.test.ts test/protocol/negotiation-object-registry.test.ts test/protocol/negotiation-events.test.ts test/architecture/negotiation-no-authority-surface.test.ts +``` ## Common Patterns **Async Testing:** ```typescript -await expect( - proposeRuntimeIngressActionContracts(fixture.kernel, {}, input), -).rejects.toThrow("Runtime ingress package-install dispatch requires packageInstall config."); -``` +const fixture = await createGreenlitContract(); +const duplicate = await fixture.kernel.evaluatePolicy({ + actionContractId: fixture.contract.actionContractId, + envelopeId: fixture.envelope.envelopeId, +}); -Use async tests for kernel transitions, HTTP/D1 paths, filesystem surfaces, MCP process proof, CLI commands, and adapter gateways. +expect(duplicate.decision.decision).toBe("refuse"); +expect(duplicate.greenlight).toBeNull(); +``` +Source pattern: `test/protocol/kernel-policy-gateway.test.ts`. **Error Testing:** ```typescript @@ -182,81 +216,63 @@ await expect( fixture.kernel.putCatalogObject({ objectType: "greenlight", payload: fixture.greenlight }), ).rejects.toThrow("Direct writes are not allowed"); ``` +Source pattern: `test/protocol/kernel-policy-gateway.test.ts`. -Prefer stable reason codes and posture fields over brittle message-only assertions. Message assertions are acceptable for explicit boundary text already covered by reason-code tests. - -**Refusal and proof-gap testing:** +**Compile-Time Negative Testing:** ```typescript -expect(result.outcome).toBe("gateway_check_refused"); -expect(result.gatewayCheck.gateAttempt.gateDecisionReasonCode).toBe("params_mismatch"); -expect(result.gatewayCheck.mutationAttempt).toBeNull(); -expect(surface.signatureCount()).toBe(0); +const invalidGatewayRoleMap: GatewayClientOptions = { + roleCredential: "gateway-token", + // @ts-expect-error gateway client must not accept role maps. + transitionTokens: {}, +}; +void invalidGatewayRoleMap; ``` +Source pattern: `test/sdk/role-clients.test.ts`. -Use this shape when a generated action, observed parameter drift, stale posture, missing evidence, or replay must fail before signer use or mutation. - -## Claim-Boundary Gates - -`npm run quality:claims` runs: - -```bash -npm run test -- test/architecture/active-vocabulary.test.ts test/architecture/claim-boundary.test.ts +**Redaction Testing:** +```typescript +expect(JSON.stringify(output)).not.toContain("PaymentPayload"); +expect(JSON.stringify(output)).not.toContain("PAYMENT-SIGNATURE"); +expect(JSON.stringify(output)).not.toContain("privateKey"); ``` +Source patterns: `test/cli/cli-evidence.test.ts`, `test/mcp/mcp-stdio-process.test.ts`, `test/protocol/credential-custody.test.ts`. -Use this gate when simplifying product or kernel language in `AGENTS.md`, `README.md`, `QUALITY.md`, `STRUCTURE.md`, `docs/internal/decisions.md`, `docs/internal/protocol-definition.md`, `docs/internal/protocol-kernel-architecture.md`, `docs/internal/protocol-layman.md`, `docs/internal/protocol-notes.md`, or `examples/x402-protected-spend/README.md`. - -The gate enforces: -- `cleared protected-action event`, `protocol kernel`, and `product surface` vocabulary. -- Category language: `protected actions for automated decision making`. -- Certificate boundary: terminal evidence, not permission. -- Distribution boundary: public npm and MCP Registry discoverability do not create authority. -- Production proof ledger and expansion admission language in `docs/internal/decisions.md`. -- Non-claims for hosted operation, provider custody, settlement/finality, broad x402 compatibility, aggregate spend, host-wide containment, and marketplace/certification. - -## Architecture and Naming Gates - -`npm run quality:architecture` runs: +**Static Source Tests:** +```typescript +const violations = walk("src") + .map((file) => normalize(file)) + .filter((file) => file.endsWith(".ts")) + .filter((file) => file.split("/").some((segment) => bannedSourcePathSegments.has(segment))); -```bash -npm run test -- test/architecture/import-posture.test.ts test/architecture/naming-posture.test.ts test/architecture/package-surface.test.ts test/architecture/root-exports.test.ts test/architecture/surface-boundary-posture.test.ts test/architecture/cli-command-posture.test.ts test/architecture/mcp-surface-posture.test.ts test/conformance/protected-mutation-adapter-conformance.test.ts +expect(violations).toEqual([]); ``` +Source pattern: `test/architecture/naming-posture.test.ts`. -Use this gate for source moves, package export changes, CLI/MCP/SDK surface changes, adapter conformance changes, and naming simplification. - -The gate enforces: -- No workspace junk or scratch canon in active repo surfaces. -- No bucket source path names. -- No internal planning-stage labels in repo-facing surfaces. -- No vague protocol mutation names or overclaiming function names. -- Public source lanes have `LANE.md` ownership manifests. -- Protocol, HTTP, runtime, storage, SDK, MCP, adapters, and surfaces keep their import boundaries. -- Surface outputs carry non-authority posture and forbid credential/raw record/payment material leakage. -- Package files exclude `src`, `test`, `examples`, scripts, `.planning`, `.agents`, and internal docs. -- Adapter conformance proves no mutation can occur without `VerifiedGatewayCheck`. - -## Projection-Vs-Authority Tests - -Use these tests when changing readback, projection, CLI, MCP, SDK role clients, or support bundles: - -- `test/architecture/surface-boundary-posture.test.ts`: each surface has `authorityPosture`, route families, forbidden credentials, forbidden outputs, non-authority flags, and claim-boundary labels. -- `test/architecture/cli-command-posture.test.ts`: CLI commands stay evidence/local-readiness/conformance oriented and reject mutation-shaped command names. -- `test/architecture/mcp-surface-posture.test.ts`: MCP stays proposal/evidence only and cannot name executable authority or credential material. -- `test/protocol/evidence-projections.test.ts`: projections expose redacted evidence without creating authority. -- `test/protocol/representation-contract.test.ts`: Metadata, Challenge, Request, and EvidenceProjection shapes stay non-authority. -- `test/sdk/role-clients.test.ts`: role-scoped clients do not acquire all-role authority. - -## Protocol Simplification Gate - -When simplifying confusing kernel language, test the simplification against three slices: - -```bash -npm run quality:claims -npm run quality:architecture -npm run test -- test/protocol/kernel-compilation-contract.test.ts test/protocol/kernel-policy-gateway.test.ts test/protocol/evidence-projections.test.ts test/runtime/runtime-ingress.test.ts +**Authority-Surface Negative Tests:** +```typescript +expect(existsSync(join(negotiationRoot, "transitions.ts"))).toBe(false); +expect(readFileSync("src/index.ts", "utf8")).not.toContain("Negotiation"); +expect(violations).toEqual([]); ``` +Source pattern: `test/architecture/negotiation-no-authority-surface.test.ts`. -This is the minimum focused slice for language changes that touch proposal, evidence, action contracts, policy, gateway checks, and readback. Add adapter-specific tests such as `test/adapters/x402-wallet-gateway.test.ts` or `test/integration/x402-d1-http.test.ts` when the wording change affects x402 signer custody, per-call spend, PaymentPayload evidence, replay refusal, or downstream proof gaps. +**Store Parity Tests:** +```typescript +for (const factory of storeFactories) { + describe(`ProtocolStore atomicity contract (${factory.name})`, () => { + it("does not partially commit protocol records when greenlight issuance conflicts", async () => { + const { store, dispose } = await factory.create(); + try { + // assertions against the real ProtocolStore contract + } finally { + await dispose(); + } + }); + }); +} +``` +Source pattern: `test/protocol/protocol-store-atomicity-contract.test.ts`. --- -*Testing analysis: 2026-05-25* +*Testing analysis: 2026-05-26* From 8d77722970aad5ac844f25bae3b635d4f314c0e2 Mon Sep 17 00:00:00 2001 From: Joel Chan Date: Tue, 26 May 2026 11:26:55 +0800 Subject: [PATCH 019/144] feat(protocol): add a2a negotiation room --- .../IMPLEMENTATION-EVAL-REVIEW.md | 109 ++++ examples/a2a-negotiated-x402-room/README.md | 11 + examples/a2a-negotiated-x402-room/generate.ts | 65 ++ examples/a2a-negotiated-x402-room/latest.json | 95 +++ examples/a2a-negotiated-x402-room/latest.md | 12 + src/adapters/x402-payment/action-proposal.ts | 4 +- .../areas/action-attempt-lifecycle/matrix.ts | 62 ++ .../areas/action-attempt-lifecycle/schemas.ts | 3 + .../areas/gateway-gate/transitions.ts | 3 +- .../areas/idempotency-ledger/entries.ts | 8 +- src/protocol/areas/negotiation/index.ts | 2 + src/protocol/areas/negotiation/policy.ts | 318 +++++++++ src/protocol/areas/negotiation/schemas.ts | 13 + src/protocol/areas/negotiation/transitions.ts | 604 ++++++++++++++++++ .../areas/operation-lifecycle/transitions.ts | 9 +- .../policy-greenlight/policy-record/index.ts | 4 +- .../areas/policy-greenlight/transitions.ts | 180 +++++- src/protocol/foundation/reason-codes.ts | 44 ++ src/protocol/kernel.ts | 40 ++ src/protocol/navigation/index.ts | 79 +++ src/surfaces/a2a-negotiation-support/index.ts | 245 +++++++ .../negotiation-no-authority-surface.test.ts | 15 +- test/product/a2a-negotiated-x402-room.test.ts | 143 +++++ test/protocol/authority-certificate.test.ts | 41 ++ .../negotiation-object-registry.test.ts | 13 + test/protocol/negotiation-policy.test.ts | 218 +++++++ test/protocol/negotiation-schemas.test.ts | 13 + test/protocol/negotiation-transitions.test.ts | 177 +++++ test/protocol/protocol-navigation.test.ts | 16 +- test/protocol/transition-matrix.test.ts | 22 +- test/support/negotiation-fixtures.ts | 234 +++++++ test/support/x402-negotiation-fixture.ts | 358 +++++++++++ 32 files changed, 3122 insertions(+), 38 deletions(-) create mode 100644 .planning/macro-plan/a2a-negotiation/IMPLEMENTATION-EVAL-REVIEW.md create mode 100644 examples/a2a-negotiated-x402-room/README.md create mode 100644 examples/a2a-negotiated-x402-room/generate.ts create mode 100644 examples/a2a-negotiated-x402-room/latest.json create mode 100644 examples/a2a-negotiated-x402-room/latest.md create mode 100644 src/protocol/areas/negotiation/policy.ts create mode 100644 src/protocol/areas/negotiation/transitions.ts create mode 100644 src/surfaces/a2a-negotiation-support/index.ts create mode 100644 test/product/a2a-negotiated-x402-room.test.ts create mode 100644 test/protocol/negotiation-policy.test.ts create mode 100644 test/protocol/negotiation-transitions.test.ts create mode 100644 test/support/negotiation-fixtures.ts create mode 100644 test/support/x402-negotiation-fixture.ts diff --git a/.planning/macro-plan/a2a-negotiation/IMPLEMENTATION-EVAL-REVIEW.md b/.planning/macro-plan/a2a-negotiation/IMPLEMENTATION-EVAL-REVIEW.md new file mode 100644 index 0000000..b5c025a --- /dev/null +++ b/.planning/macro-plan/a2a-negotiation/IMPLEMENTATION-EVAL-REVIEW.md @@ -0,0 +1,109 @@ +# A2A Negotiation Implementation Eval Review + +Status: `PRODUCTION_READY_FOR_BOUNDED_LOCAL_REFERENCE_ROOM` +Score: `96/100` +Date: `2026-05-26` + +## Invariant At Stake + +Agent-to-agent agreement is evidence and policy input. It is not authority. + +The implementation is acceptable only if accepted negotiation evidence cannot +mint a policy decision, greenlight, gateway check, mutation attempt, receipt, or +certificate, and every consequential x402 payment remains bound to one exact +ActionContract plus one-use gateway enforcement. + +## Evaluation Verdict + +The bounded room is implemented end to end: + +```text +NegotiationSession +-> NegotiationOffer +-> NegotiationDecision +-> LinkedAgreement +-> AgreementObligationBinding +-> ActionContract +-> PolicyDecision / Greenlight or Refusal / ProofGap +-> GatewayCheck +-> x402 signer invocation only after verified gate +-> Receipt / ProofGap / ReplayRefusal +-> Support packet readback +``` + +## Coverage Matrix + +| Dimension | Result | Evidence | +| --- | --- | --- | +| Schema strictness | Covered | `test/protocol/negotiation-schemas.test.ts` | +| Object registry posture | Covered | `test/protocol/negotiation-object-registry.test.ts` | +| Recorded-only events | Covered | `test/protocol/negotiation-events.test.ts` | +| Negotiation transitions | Covered | `test/protocol/negotiation-transitions.test.ts` | +| Agreement creates no authority | Covered | `test/protocol/negotiation-transitions.test.ts`, `test/product/a2a-negotiated-x402-room.test.ts` | +| Obligation-to-contract exact binding | Covered | `src/protocol/areas/negotiation/transitions.ts`, `test/protocol/negotiation-policy.test.ts` | +| Policy refusal and proof-gap gates | Covered | `src/protocol/areas/negotiation/policy.ts`, `test/protocol/negotiation-policy.test.ts` | +| Scope drift rejection | Covered | `src/protocol/areas/negotiation/transitions.ts`, `src/protocol/areas/negotiation/policy.ts`, `test/protocol/negotiation-transitions.test.ts` | +| Session and offer expiry | Covered | `src/protocol/areas/negotiation/transitions.ts`, `src/protocol/areas/negotiation/policy.ts`, `test/protocol/negotiation-transitions.test.ts`, `test/protocol/negotiation-policy.test.ts` | +| Single-use obligation authority | Covered | Agreement-backed greenlights use an obligation-scoped idempotency ledger key; `test/protocol/negotiation-transitions.test.ts`, `test/protocol/negotiation-policy.test.ts` | +| Gateway remains final enforcement | Covered | `test/product/a2a-negotiated-x402-room.test.ts` | +| x402 signer material appears only post-gate | Covered | `test/product/a2a-negotiated-x402-room.test.ts` | +| Replay refusal | Covered | `test/product/a2a-negotiated-x402-room.test.ts` | +| Readback/support packet redaction | Covered | `src/surfaces/a2a-negotiation-support/index.ts`, `test/product/a2a-negotiated-x402-room.test.ts` | +| Generated fixture output | Covered | `examples/a2a-negotiated-x402-room/latest.json`, `examples/a2a-negotiated-x402-room/latest.md` | +| External A2A trust / legal contract / settlement | Explicit non-goal | Macro plan forbids these claims; source keeps refs imported evidence only | + +## Gates Run + +- `bun test test/protocol/negotiation-schemas.test.ts test/protocol/negotiation-object-registry.test.ts test/protocol/negotiation-events.test.ts test/architecture/negotiation-no-authority-surface.test.ts test/protocol/negotiation-transitions.test.ts test/protocol/negotiation-policy.test.ts test/product/a2a-negotiated-x402-room.test.ts` +- `bun examples/a2a-negotiated-x402-room/generate.ts` +- `npm run check:types` +- `npm run lint` +- `npm run quality:claims` +- `npm run quality:architecture` +- `npm run test` +- `npm run format:check` +- `npm run check:repo` after sidecar-review blocker fixes: 804 tests, 0 failures + +## Sidecar Review Findings Closed + +- Cross-scope negotiation evidence is refused before binding or policy. +- Expired negotiation sessions and offers are refused at transition time and + policy time. +- One linked agreement obligation cannot be rebound to multiple action + contracts, and agreement-backed greenlights reserve an obligation-scoped + idempotency ledger key. +- `x402_payment.exact` policy now applies by action class, not by optional + parameter presence. +- The support packet reports lifecycle assembly status instead of silently + collapsing errors into null lifecycle state. +- The A2A room now tests selected payment requirement drift and ships both JSON + and Markdown fixture output. + +## Residual Risks + +- The room is local/reference. It does not prove cross-org trust, identity + verification, marketplace operation, escrow, legal contract formation, + settlement finality, reputation, provider custody, or hosted production + custody. +- Negotiation transitions are kernel-only. No CLI, HTTP, MCP, SDK, or root + package surface is admitted for negotiation yet. +- The support packet is a readback projection over existing records. It is not a + review renderer and does not create authority. +- The single-use obligation ledger is proven through the existing policy + idempotency reservation path, not a new marketplace/settlement ledger. + +## Verdict + +Keep. + +This is a valid Tier 3 heat-up slice because it binds A2A negotiation evidence +into the existing protected-action spine without weakening the authority model. +The product claim must stay narrow: + +```text +Handshake records, binds, clears, refuses, and reconstructs one local/reference +agent-negotiated protected-action obligation. +``` + +The next mechanism is an admitted transport surface for recording negotiation +evidence, still without exposing greenlight or gateway authority. diff --git a/examples/a2a-negotiated-x402-room/README.md b/examples/a2a-negotiated-x402-room/README.md new file mode 100644 index 0000000..05c8767 --- /dev/null +++ b/examples/a2a-negotiated-x402-room/README.md @@ -0,0 +1,11 @@ +# A2A Negotiated x402 Room Fixture + +This fixture exercises one buyer/seller negotiation over a single buyer-side `x402_payment.exact` protected action. + +The accepted agreement and obligation binding are evidence only. The policy greenlight is created only after the exact `ActionContract` is bound to the active agreement obligation, and the payment signer is invoked only after a passed gateway check. + +Generate the readback fixture: + +```sh +bun examples/a2a-negotiated-x402-room/generate.ts +``` diff --git a/examples/a2a-negotiated-x402-room/generate.ts b/examples/a2a-negotiated-x402-room/generate.ts new file mode 100644 index 0000000..44cfd29 --- /dev/null +++ b/examples/a2a-negotiated-x402-room/generate.ts @@ -0,0 +1,65 @@ +import { mkdir } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { runNegotiatedX402Room } from "../../test/support/x402-negotiation-fixture"; + +const outputPath = join(import.meta.dir, "latest.json"); +const markdownOutputPath = join(import.meta.dir, "latest.md"); + +const room = await runNegotiatedX402Room(); +const output = { + generatedAt: new Date().toISOString(), + fixtureKind: "a2a_negotiated_x402_room", + contract: { + actionContractId: room.contract.actionContractId, + actionContractDigest: room.contract.actionContractDigest, + paramsDigest: room.contract.paramsDigest, + actionClass: room.contract.actionClass, + resourceRef: room.contract.resourceRef, + clearingEvidenceRefs: room.contract.clearingEvidenceRefs, + }, + authorityBoundary: { + acceptedAgreementCreatedPolicyDecision: false, + acceptedAgreementCreatedGreenlight: false, + acceptedAgreementPerformedGatewayCheck: false, + acceptedAgreementAttemptedMutation: false, + signerInvokedBeforeGatewayCheck: false, + gatewayCheckRemainsFinalEnforcementPoint: true, + }, + policy: { + decision: room.policy.decision.decision, + decisionReasonCode: room.policy.decision.decisionReasonCode, + greenlightId: room.greenlight.greenlightId, + greenlightMaxUses: room.greenlight.maxUses, + }, + gateway: { + firstOutcome: room.gatewayResult.outcome, + firstGateDecision: room.gatewayResult.gatewayCheck.gateAttempt.gateDecision, + firstMutationAttempted: room.gatewayResult.gatewayCheck.mutationAttempt !== null, + replayOutcome: room.replay.outcome, + replayReasonCode: room.replay.gatewayCheck.gateAttempt.gateDecisionReasonCode, + signerInvocationCount: room.surface.signatureCount(), + }, + supportPacket: room.supportPacket, +}; + +await mkdir(dirname(outputPath), { recursive: true }); +await Bun.write(outputPath, JSON.stringify(output, null, 2) + "\n"); +await Bun.write( + markdownOutputPath, + [ + "# A2A Negotiated x402 Room", + "", + "This fixture is local/reference evidence only. It does not claim marketplace operation, legal contract formation, escrow, settlement finality, reputation, cross-org trust, provider custody, or reusable authority.", + "", + `- Action contract: ${room.contract.actionContractId}`, + `- Agreement created authority: ${output.authorityBoundary.acceptedAgreementCreatedGreenlight}`, + `- Policy decision: ${room.policy.decision.decision}`, + `- Greenlight max uses: ${room.greenlight.maxUses}`, + `- First gateway decision: ${room.gatewayResult.gatewayCheck.gateAttempt.gateDecision}`, + `- Replay refusal reason: ${room.replay.gatewayCheck.gateAttempt.gateDecisionReasonCode}`, + `- Signer invocation count: ${room.surface.signatureCount()}`, + `- Downstream finality: ${room.supportPacket.lifecycle.downstreamFinalityStatus ?? "unknown"}`, + "", + ].join("\n"), +); +console.log(outputPath); diff --git a/examples/a2a-negotiated-x402-room/latest.json b/examples/a2a-negotiated-x402-room/latest.json new file mode 100644 index 0000000..ca30398 --- /dev/null +++ b/examples/a2a-negotiated-x402-room/latest.json @@ -0,0 +1,95 @@ +{ + "generatedAt": "2026-05-26T02:56:20.995Z", + "fixtureKind": "a2a_negotiated_x402_room", + "contract": { + "actionContractId": "act_d8f1fe92-3b71-4170-9703-022f7e797977", + "actionContractDigest": "sha256:ae040b6921766928b09607cba72570010f769d0377213969c741f376d75b3ede", + "paramsDigest": "sha256:ad9a5dc544d359aeb171db4dc75a7ea98326765858574a755c050ebead3b8413", + "actionClass": "x402_payment.exact", + "resourceRef": "x402:base-sepolia:0xpayee:https://api.example.com/mcp/premium-context", + "clearingEvidenceRefs": { + "obligationRef": "obligation:x402-exact-call", + "counterpartyRef": "agent:seller" + } + }, + "authorityBoundary": { + "acceptedAgreementCreatedPolicyDecision": false, + "acceptedAgreementCreatedGreenlight": false, + "acceptedAgreementPerformedGatewayCheck": false, + "acceptedAgreementAttemptedMutation": false, + "signerInvokedBeforeGatewayCheck": false, + "gatewayCheckRemainsFinalEnforcementPoint": true + }, + "policy": { + "decision": "greenlight", + "decisionReasonCode": "policy_passed", + "greenlightId": "grn_3b9cd60f-dade-4db7-8f23-6e788d63b5bc", + "greenlightMaxUses": 1 + }, + "gateway": { + "firstOutcome": "payment_signature_proof_gap", + "firstGateDecision": "passed", + "firstMutationAttempted": true, + "replayOutcome": "gateway_check_refused", + "replayReasonCode": "already_consumed", + "signerInvocationCount": 1 + }, + "supportPacket": { + "packetKind": "a2a_negotiation_support_packet", + "actionContractId": "act_d8f1fe92-3b71-4170-9703-022f7e797977", + "actionContractDigest": "sha256:ae040b6921766928b09607cba72570010f769d0377213969c741f376d75b3ede", + "paramsDigest": "sha256:ad9a5dc544d359aeb171db4dc75a7ea98326765858574a755c050ebead3b8413", + "actionClass": "x402_payment.exact", + "resourceRef": "x402:base-sepolia:0xpayee:https://api.example.com/mcp/premium-context", + "agreement": { + "linkedAgreementId": "linked_agreement_demo", + "agreementDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "agreementStatus": "active", + "obligationRef": "obligation:x402-exact-call", + "counterpartyRef": "agent:seller", + "evidencePosture": "local_evidence_only" + }, + "obligationBinding": { + "agreementObligationBindingId": "agreement_obligation_binding_demo", + "obligationRef": "obligation:x402-exact-call", + "actionContractDigest": "sha256:ae040b6921766928b09607cba72570010f769d0377213969c741f376d75b3ede", + "paramsDigest": "sha256:ad9a5dc544d359aeb171db4dc75a7ea98326765858574a755c050ebead3b8413", + "counterpartyRef": "agent:seller" + }, + "negotiation": { + "negotiationSessionId": "negotiation_session_demo", + "acceptedOfferVersionId": "offer_version_1", + "acceptedNegotiationDecisionId": "negotiation_decision_accept_v1", + "acceptedOfferContentDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "partyRefs": ["agent:buyer", "agent:seller"] + }, + "lifecycle": { + "assemblyStatus": "assembled", + "assemblyReasonCode": null, + "assemblyReason": null, + "policyDecisionId": "pol_152fd0d9-6ff3-47d3-a5af-f8da67f41379", + "policyDecision": "greenlight", + "greenlightId": "grn_3b9cd60f-dade-4db7-8f23-6e788d63b5bc", + "gatewayCheckAttemptId": "gat_eca052e0-9c7d-4ccb-b37c-8ddfd24e722e", + "mutationAttemptId": "mut_714fa094-c531-4eda-b879-29bbcd3725a5", + "receiptId": "rcp_a3b0ac29-cd51-4000-b8fc-b789daf90a18", + "downstreamFinalityStatus": "unknown", + "proofGapIds": ["gap_59093024-7f9b-43d7-9c68-c048cd97e96f"], + "refusalIds": ["ref_248010ff71fba79e7fbe92d9fd51863a509c116efd99a8c7"] + }, + "authorityBoundary": { + "agreementAcceptanceCreatedAuthority": false, + "obligationBindingCreatedAuthority": false, + "policyMayCreateOneUseGreenlight": true, + "gatewayCheckRemainsFinalEnforcementPoint": true, + "downstreamSuccessClaimedByAgreement": false + }, + "redaction": { + "rawTranscriptIncluded": false, + "rawOfferTermsIncluded": false, + "paymentPayloadIncluded": false, + "paymentSignatureIncluded": false, + "credentialMaterialIncluded": false + } + } +} diff --git a/examples/a2a-negotiated-x402-room/latest.md b/examples/a2a-negotiated-x402-room/latest.md new file mode 100644 index 0000000..7f8a2fa --- /dev/null +++ b/examples/a2a-negotiated-x402-room/latest.md @@ -0,0 +1,12 @@ +# A2A Negotiated x402 Room + +This fixture is local/reference evidence only. It does not claim marketplace operation, legal contract formation, escrow, settlement finality, reputation, cross-org trust, provider custody, or reusable authority. + +- Action contract: act_d8f1fe92-3b71-4170-9703-022f7e797977 +- Agreement created authority: false +- Policy decision: greenlight +- Greenlight max uses: 1 +- First gateway decision: passed +- Replay refusal reason: already_consumed +- Signer invocation count: 1 +- Downstream finality: unknown diff --git a/src/adapters/x402-payment/action-proposal.ts b/src/adapters/x402-payment/action-proposal.ts index a2bf6f1..c3596cf 100644 --- a/src/adapters/x402-payment/action-proposal.ts +++ b/src/adapters/x402-payment/action-proposal.ts @@ -4,7 +4,7 @@ import { DelegatedAuthorityBindingSchema } from "../../protocol/areas/delegated- import { GatewayCredentialBindingSchema } from "../../protocol/areas/credential-custody"; import type { CompileIntentInput, IntentCompilationRecord } from "../../protocol/areas/intent-compilation"; import { digestCanonical } from "../../protocol/foundation/canonical"; -import { DigestSchema } from "../../protocol/foundation/schema-core"; +import { ClearingEvidenceRefsSchema, DigestSchema } from "../../protocol/foundation/schema-core"; import { x402PaymentResourceRef } from "./install-proposal"; import type { X402PaymentRequiredEvidence } from "./upstream-evidence"; @@ -56,6 +56,7 @@ export const X402PaymentAttemptSchema = z.strictObject({ extensionKeys: z.array(z.string().min(1)).default([]), sequenceNumber: z.number().int().nonnegative().default(1), requiredPriorActionContractIds: z.array(z.string().min(1)).default([]), + clearingEvidenceRefs: ClearingEvidenceRefsSchema.default({}), }); export type X402PaymentAttempt = z.input; @@ -381,6 +382,7 @@ async function buildX402PaymentCompileIntentInputUnchecked( ...runtimeConfig.gatewayCredentialBinding.evidenceExpectationRefs, ...runtimeConfig.delegatedAuthorityBinding.evidenceExpectationRefs, ]), + clearingEvidenceRefs: attempt.clearingEvidenceRefs, bounds: { endpointDomain, payee: attempt.payee, diff --git a/src/protocol/areas/action-attempt-lifecycle/matrix.ts b/src/protocol/areas/action-attempt-lifecycle/matrix.ts index 04f09db..ca49aac 100644 --- a/src/protocol/areas/action-attempt-lifecycle/matrix.ts +++ b/src/protocol/areas/action-attempt-lifecycle/matrix.ts @@ -37,6 +37,20 @@ const catalogRecorded = { terminalOutcome: "evidence_only", } as const; +const negotiationRecorded = { + phase: "negotiation", + state: "negotiation_recorded", + authorityEffect: "evidence_only", + terminalOutcome: "open", +} as const; + +const negotiationConflict = { + phase: "negotiation", + state: "negotiation_conflict", + authorityEffect: "none", + terminalOutcome: "proof_gap", +} as const; + export const actionAttemptHostileTraceMatrix: Record = { unknown_consequential_tool: entry( { @@ -357,6 +371,54 @@ export const actionAttemptLifecycleMatrix: Partial