Skip to content

feat(pilot): capture existing Product access without repaying - #220

Merged
knzeng-e merged 3 commits into
devfrom
feat/pilot-access-readback
Sep 28, 2026
Merged

knzeng-e merged 3 commits into
devfrom
feat/pilot-access-readback

Conversation

@knzeng-e

@knzeng-e knzeng-e commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Outcome

An operator can open an already-paid Classic track in a candidate-bound Product capture and export fresh entitlement/key evidence without paying again. The browser panel and CLI now require the key release to follow a read-back for the matching account, chain, runtime and content hash.

Issue and context

Refs #158. Scope: W13 pilot release; handoff: W13 evidence.

PR #219 made native payment recovery durable. W13's next live step is to reuse an existing entitlement, but normal playback of an existing purchase did not produce a payment read-back event. Operators could obtain a key without being able to export the corresponding fresh access read. Starting another payment to fill that gap would be unnecessary.

Starting dev: 9c25093d7508e643258fd3a66b576a8cea312707, with all Dev Quality Gates passing. The historical feat/pilot-release branch belongs to another worktree, so this slice uses feat/pilot-access-readback.

Architecture and key concepts

useCatalog calls a small read-only collector on explicit Classic selection in Product mode. The collector accepts only the hasPaid and canAccess read port, never a payment writer. It runs only inside an explicitly bound capture matching the current SHA/app version, then checks that the account, selection and capture are still current before publishing.

The existing bounded session evidence journal gains an allowlisted access-readback event. This is current entitlement evidence, not a transaction receipt: it contains no transaction hash, amount, signature or key. Payment events remain separate. The CLI computes its own gates from event facts instead of trusting the browser summary.

How it works

  1. Bind the exact deployed CID in the existing operator panel.
  2. Open a Classic track with the connected Product account that already paid for it.
  3. Capture hasPaid and canAccess, then follow the normal protected-key request.
  4. Export the existing smoke JSON. A matching read/key pair can pass access/key gates, while approval, native value and transaction-readback gates remain blocked unless actual write evidence exists.

Design decisions and tradeoffs

  • Reuse the existing selection, capture and export boundaries; no new listener workflow or payment action.
  • Keep schema v2 with an additive event and gate. Existing complete payment fixtures still pass; old validators cannot certify the new read-only path.
  • Do not synthesize a payment event from a saved receipt, current catalog price or existing access. Those facts cannot establish a new transfer.
  • An active operator capture makes two extra parallel reads before requesting the key. Ordinary playback without a bound current-build capture makes none.

Security, failure, and operations

Runtime/API access checks remain authoritative. Evidence never grants access. RPC errors produce unknown results; stale account, track or candidate results are discarded. Cross-runtime, cross-chain and pre-read key events cannot complete the access/key journey, and a latest key denial/error remains visible.

Capture remains bounded, session-local and explicitly activated. The allowlist excludes secrets, but diagnostic exports contain account/release identifiers: keep them private and separate from aggregate pilot evidence, and reset the capture after use. The runbooks document this boundary.

No contract, deployment, secret, hosted configuration or payment-rail change. CASH remains non-executable; no PVM migration. Rollback is the ordinary application-code rollback, with no storage migration.

Review guide

Suggested order

  1. web/src/features/productHost/productAccessReadback.ts and its tests: opt-in capture, read-only authority, stale-result rejection.
  2. web/src/hooks/useCatalog.ts: explicit selection trigger before key delivery.
  3. productCdmHostSmokeEvidence.ts and its tests: allowlisted event, truthful separate gates, matching key identity.
  4. web/scripts/product-devnet-journey-harness.mjs and its tests: independent CLI verification and blocked write gates.
  5. Product/general deployment runbooks and W13 handoff: repeatable capture and remaining release gates.

Verify carefully

  • Existing access cannot make approval or transfer gates pass.
  • Account/selection/capture changes cannot append stale entitlement evidence.
  • A key from another runtime, chain or earlier read cannot satisfy this journey.
  • Diagnostic evidence stays outside aggregate participant data.

Validation

Tested implementation: 8ac508037413776681ca5c477a5a214d474428d6 (the focused unit/CLI/browser checks ran on the identical source before commit).

Evidence What it proves
Focused Vitest: Product collector/evidence, payments, Product CDM adapter 88 passing tests, including journal recovery, no automatic second payment, and CASH guardrails
Node tests: Product journey, pilot readiness, CASH settlement 43 passing tests; entitlement cannot certify payment and CASH remains blocked
Playwright e2e/classic-unlock.spec.ts 13 passing desktop/mobile tests: unlock, funding error, pending dismissal, tab-close recovery and cancellation
npx tsc -b, npm run lint, changed-file Prettier check Passed; lint retains 3 pre-existing hook dependency warnings in untouched files
npm run build Passed; existing Rollup annotation, mixed-import and chunk-size warnings
VITE_DOTIFY_RUNTIME_ADAPTER=product-cdm VITE_DOTIFY_DEBUG_PANEL=true npm run build:product-devnet:frozen Passed from clean implementation commit, using tracked bootstrap; no deployment
Backlog offline check and git diff --check Passed
smoke:pilot-release on implementation SHA 79 pass, 0 fail, 2 blocked, 8 not run; missing live evidence stays visible

Known limitations and follow-ups

This is W13 capture tooling, not W13 acceptance. No physical Product host/device session, payment, publication, rollback rehearsal or consented pilot was performed. After review, an authorized candidate publication and real existing-entitlement/key/room capture are still required. Signing/value forwarding needs separately authorized evidence; another payment is not required merely to validate existing access. Issue #158 stays open.

Metadata checklist

  • Backlog issue linked with correct close/reference semantics
  • Local backlog document linked
  • Added to Project 5 (Dotify sprints)
  • Project Priority, Track, Phase, Type, and Backlog doc mirror the issue
  • Workflow status matches draft/review state (In Progress)
  • Assignee set
  • Applicable labels set
  • Applicable milestone set, or confirmed none exists
  • Reviewers requested when ownership is known (none other than author identified)
  • Draft/ready state is intentional

@knzeng-e knzeng-e added documentation Improvements or additions to documentation P0 product testing dotify-backlog Tracked by docs/backlog/backlog.json and Project 5 labels Sep 27, 2026
@knzeng-e knzeng-e self-assigned this Sep 27, 2026
@netlify

netlify Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for muzinga canceled.

Name Link
🔨 Latest commit 1cf29ab
🔍 Latest deploy log https://app.netlify.com/projects/muzinga/deploys/6aba33bf5be7a40009f365fa

@knzeng-e
knzeng-e marked this pull request as ready for review September 28, 2026 09:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T09:16:48.300975Z 0e0ad67 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e0ad673eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/claude-code-review.yml
@knzeng-e
knzeng-e merged commit c22e08e into dev Sep 28, 2026
16 checks passed
@knzeng-e
knzeng-e deleted the feat/pilot-access-readback branch September 28, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation dotify-backlog Tracked by docs/backlog/backlog.json and Project 5 P0 product testing

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant