Skip to content

Clarify unsigned provenance and preserve authenticated credential identity - #273

Merged
brianorwhatever merged 9 commits into
mainfrom
fix/237-signed-action-records
Oct 4, 2026
Merged

brianorwhatever merged 9 commits into
mainfrom
fix/237-signed-action-records

Conversation

@brianorwhatever

@brianorwhatever brianorwhatever commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Historical action JSON was presented as cryptographic proof even when unsigned. Label recognized placeholders as unsigned and unknown proof material as unverified, remove unsupported ownership claims from provenance panels and header/public badges, and preserve the existing CEL/WebVH verification and vcProof storage/wire shapes. The authenticated actor now retains its session/API-key row identity separately from the authorizing account; it does not expose credential secrets.

This is a bounded foundation for #237, not completion. New action writers still produce placeholders. Signing custody (service attestation versus author-held/asynchronous signing), issuer trust/rotation and failure policy need a product decision before the shared single/batch/recurring signed-record path and independent verifier can be implemented. No signing key or live configuration was changed. See docs/action-records.md.

Prerequisite #271 has merged into main. This PR now contains only its own feature changes relative to main.

Validation: latest commit ab52182 passes CI: 645 unit tests, the complete browser suite, web/Android/unsigned iOS builds, Lighthouse and automated review. Independent delegated follow-up review found no actionable issues and passed 24 focused tests. Combined integration with #272 passed 27 focused tests, frontend/backend TypeScript and focused lint. The remaining header/public badge ownership claims are fixed: DID presence is explicitly unverified metadata, malformed public documents are handled safely, and separate anchor/CEL verification remains intact. Automated review confirms the badge feedback is closed. GitHub reports no merge conflict. This is technically ready for its partial foundation scope; signed writers, custody/rotation policy and live/native validation remain outside the deliverable.

Note

Clarify unsigned provenance labels and preserve credential identity in actors

  • authenticate now returns a credential field on ResolvedActor that distinguishes the authenticated session or API-key row from the account, and requireSession returns the matched access-session row ID. Account, DID, scope, and revocation handling are unchanged. See actor.ts and session.ts.
  • Adds legacyActionEvidence classifier: only the recognized VC-shaped JSON placeholder counts as unsigned; other evidence is unverified. Provenance UI now labels each record with this classification and no longer claims cryptographic proof of ownership or authorship. See legacyActionEvidence.ts and ProvenanceInfo.tsx.
  • Memoizes Convex query configurations in OfflineAccessMonitor batch components, keyed by token and resources, instead of rebuilding them on every render. See OfflineAccessMonitor.tsx.
  • Adds test coverage for actor credential separation, API-key revocation, legacy evidence classification, offline subscription lifecycle, and provenance presentation; updates share/sharing e2e tests to the new "Publish publicly" / "Share list" wording and OG image path.
  • Behavioral Change: provenance panels now say "historical ownership record" instead of "Verifiable Credential" and append "unsigned"/"unverified" to each row; the VcProofRow icon changed from a checkmark to a document icon. The ResolvedActor shape gains a credential field.

Macroscope summarized 4a41722.

@railway-app

railway-app Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the boop-pr-273 environment in Friends

Service Status Web Updated
boop ✅ Success (View Logs) Web Oct 4, 2026 at 11:48 pm UTC

@railway-app
railway-app Bot temporarily deployed to Friends / boop-pr-273 October 4, 2026 22:23 Destroyed
@brianorwhatever
brianorwhatever marked this pull request as ready for review October 4, 2026 22:25
@railway-app
railway-app Bot temporarily deployed to Friends / boop-pr-273 October 4, 2026 22:27 Destroyed

@pullfrog pullfrog 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.

ℹ️ No blocking issues. There's one scope gap to look at and one test-runner nit inline.

Reviewed changes

I reviewed the full diff at 4a41722. That covers the provenance relabelling, the credential identity added to ResolvedActor, and the prerequisite #271 commits bundled here.

  • Credential identity on the actor: requireSession now also returns accessSessionId, and authenticate adds credential: { kind, id } (an access-session row or an API-key row) without exposing token or key hashes. None of the requireSession callers declare return validators, so the extra field is safe on the wire.
  • Legacy evidence classification: legacyActionEvidence marks a proof as unsigned only when it is absent or matches the exact JSON VC placeholder shape. That shape is what convex/items.ts, convex/lists.ts and the remintUserDidDb rewrites produce. Anything else is unverified, so a real proof is never downgraded.
  • ProvenanceInfo copy: VC rows are relabelled as "… record (unsigned|unverified)", and the list and item footers no longer claim cryptographic proof.
  • Docs and tests: docs/action-records.md records the pending custody decisions. The new tests fail without the source changes and pass under bun test.
  • Bundled #271: OfflineAccessMonitor now memoizes its useQueries requests, and the e2e copy and fixture handlers are updated. The PR body says #271 should merge first.

ℹ️ Header verification badges still claim cryptographic ownership proof

The PR removes the "cryptographic proof of ownership" wording from ProvenanceInfo. Two more prominent surfaces still make that claim, and neither checks any evidence:

  • The list and note header badge (src/components/VerificationBadge.tsx) shows "✓ Verifiable Credential — This data has cryptographic proof of ownership via a Decentralized Identifier". It appears whenever list.assetDid exists.
  • The public list badge (src/components/publish/VerificationBadge.tsx) always says "Verified" and "The DID document cryptographically proves the list's authenticity and ownership".

A user who opens the provenance panel now reads "historical attribution records may be unsigned", while the header above it still says "✓ Verifiable Credential". If this PR is meant to remove every unsupported ownership claim, these two badges are still open. If they are being left for a follow-up, docs/action-records.md should say so.

Technical details
# Remaining unsupported ownership/verification claims

## Affected sites
- src/components/VerificationBadge.tsx:165-186 — `vcState` is "verified" whenever `hasVC` is true. Callers pass `hasVC={!!list.assetDid}` (src/pages/ListView.tsx:722, src/pages/NoteView.tsx:153). The tooltip claims "cryptographic proof of ownership".
- src/components/VerificationBadge.tsx:234 — the badge label is "VC".
- src/components/publish/VerificationBadge.tsx:51, :102-104 — "Verified" is always shown, and the copy says the DID document "cryptographically proves the list's authenticity and ownership".

## Required outcome
- Header and public badges make no claim of verification or ownership proof unless verification actually ran, and their wording matches the new `ProvenanceInfo` copy.

## Open questions for the human
- Should this be fixed in this PR, or tracked as a follow-up under #237?

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread scripts/provenance-presentation.test.mjs Outdated
@railway-app
railway-app Bot temporarily deployed to Friends / boop-pr-273 October 4, 2026 22:29 Destroyed

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

Since my last review at 4a41722, the only net change is a fix to the test runner setup.

  • Provenance test DOM setup: scripts/provenance-presentation.test.mjs now registers happy-dom behind a guard, then imports React, Testing Library and the router dynamically. Both tests now pass under node --test and under bun test. I re-ran both to confirm.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@railway-app
railway-app Bot temporarily deployed to Friends / boop-pr-273 October 4, 2026 23:46 Destroyed
@brianorwhatever

Copy link
Copy Markdown
Contributor Author

Addressed the remaining header/public badge feedback from review #273 (review) in ab52182. DID presence now displays as unverified metadata with a neutral icon; it cannot set a verified credential state. Public document display makes no authenticity/ownership claim and handles absent/malformed documents. Actual anchor status remains separate. Added rendered header/item/public regressions, including anchor preservation. Focused tests pass; independent follow-up review and latest CI are running. Signing custody remains an explicit separate blocker for full #237.

@pullfrog pullfrog 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.

✅ No new issues found. The header and public badge gap from my first review is closed.

Reviewed changes

Since my last review at db8cfc1, one commit (ab52182) relabels the remaining verification badges and adds tests for them.

  • Removed hasVC from the header and item badges: VerificationBadge, ListVerificationBadge and ItemVerificationBadge now base the identifier badge on did alone. A recorded DID shows "DID (unverified)" with a neutral info icon. A missing DID shows "No DID" in headers and nothing in compact items. Both callers (ListView.tsx, NoteView.tsx) are updated, and tsc -b --force is clean.
  • Fixed the anchor label: the none state now reads "Not anchored". Before this, it was mislabelled "Anchored". Confirmed and pending anchors keep their own tooltips.
  • Rewrote the public list badge copy: "Verified" is now "DID (unverified)" and the shield-check icon is gone. The explanation no longer says the DID document proves authenticity or ownership. parsedDocument now accepts only a non-array object, so null, primitive and array documents can no longer reach the verificationMethod lookup.
  • Added scripts/verification-badges.test.mjs: it covers header, compact and public badges across empty, invalid and declared-key inputs, all three anchor states, and the absence of the old checkmark path. All 22 tests pass under both node --test and bun test.
  • Extended docs/action-records.md: a new section sets out the identifier-badge evidence boundary.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@brianorwhatever
brianorwhatever merged commit 6b456db into main Oct 4, 2026
10 checks passed

This branch was successfully deployed

No deployments
Friends / boop-pr-273 — ab521824 Deployed Oct 4, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant