Repository navigation
M6: Revision Provenance (diff, rollback, audit export) + FROST go/no-go - #413
Merged
Merged
Conversation
Document Sign-Off v1 (ROADMAP M6). History already had chained platform attestations (#375); this adds the other three pieces, all off-chain. Diff: diffVersions compares any two versions of a document. The metadata diff always works, including hash-only versions whose bytes never left the signer's machine; the line diff runs when both versions carry their bytes inline as UTF-8 text, and says why when it cannot. Bounded at 4M LCS cells after trimming the common prefix and suffix. Rollback: restoreVersion re-publishes an earlier version's exact content as version N+1. Append-only — nothing in between is deleted, the restore is logged (version.restored, with its source) and attested, and approvals never come back: the restored version starts a fresh round at zero. Restoring the current head is refused. Wallet members only. Audit export: mesh-multisig.document-signoff.audit.v1 — every version with its lineage and its standalone proof.v1, the whole event log, and the attestation chain with its keys. verifyAuditPackage re-runs every check offline and cross-checks the two records (each version attested once at its own hash, each restore carrying the hash it names, Approved only with the approvals to back it). A new format rather than more fields on proof.v1. uploadVersion, publishDraft and restoreVersion now share one appendVersion helper instead of three copies of the supersede logic; event metadata is unchanged. exportProof builds through the same buildProofPackage as the audit export, and now carries partyId/partyRole for contract-party reviews, which the verifier binds against. Also: ROADMAP M5/M6 PR mapping rows, Revision Provenance vault note, public roadmap data (Sign-Off MVP and v1 history marked done). Tests: documentDiff, documentAudit (tamper cases), and a real-DB/real-CIP-8 documentProvenance suite; full unit run 1620 passing; tsc clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DwjSXosdJg8rATTa7pQEn
…220) Closes the ROADMAP M6 research item. Verdict: no-go on replacing native scripts with FROST; conditional go on an opt-in FROST signer as one leaf inside a native script; no-go on post-quantum multi-sig until the ledger can verify a PQ signature. FROST(Ed25519, SHA-512) works on Cardano with no ledger change: RFC 9591's Ed25519 ciphersuite emits plain RFC 8032 signatures, so a t-of-n aggregate is one ordinary 101-byte vkey witness under one key hash. The research PoC (scripts/research/frost-ed25519, trusted dealer, not for production) reproduces the RFC 9591 Appendix E.1 vector byte for byte and verifies 2-of-3 and 3-of-5 aggregates with noble and with the CSL fork Mesh ships, as an enterprise address and as a sig leaf in an atLeast script. It also recovers a signer's share from a reused nonce, which is the operational hazard. The saving is 206 / 371 bytes per tx (0.009 / 0.016 ADA at 44 lovelace/byte); the cost is the on-chain signer set and threshold this app's DRep and CIP-1854 features read, plus CIP-30 and hardware-wallet support. "Lemour" is Lemur (ePrint 2026/1161), a lattice aggregate multi-signature with no public implementation; no Plutus builtin verifies any PQ signature. ROADMAP M6 proof-of-completion rows for Quirin's tasks; Andre's three M6 rows marked merged (#399, released in #393). FROST and PQC vault notes and the public roadmap research item updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DwjSXosdJg8rATTa7pQEn
Audit verifier - Proof-level errors (format, hash shape, requiredSigners < 1) are reported, not dropped; proof wallet and attestation wallet are cross-checked. - Lineage is re-derived from the event log and must match what the package states, so a restore cannot be relabelled as an upload. Events now carry their versionId. - A version whose log shows review.started must carry its proof, and the proof's threshold must match the one the round started with — the threshold is in no signed payload, so this is the only check on it. - An emptied event log is an error; requireAttestation turns a stripped chain into an error. AUDIT_INSTRUCTIONS now say plainly what is signed and what is a database record. Public verifyAudit - auditPackageProblem: structural, bounded shape check (versions, reviews, chain, events capped) so malformed input is a 400, not a TypeError 500, and nobody can buy unbounded CIP-8 work. Verification wrapped likewise. - No Math.min spread over the chain; a deployment with no attestation key falls back to the package's keys (flagged) instead of failing every chain. restoreVersion - Refused when the head already has the source's content (not only when it is the same row), so a restore cannot silently end a round over the same bytes. - Optional expectedHeadVersionId: a stale view of the head is a CONFLICT. The UI sends it, hides Restore for same-content versions, and warns when restoring would end an in-review round with signatures. - A unique-constraint race (P2002) is a CONFLICT, not a 500. exportAudit reads versions, events and attestations in one RepeatableRead transaction and no longer loads inline bytes. Diff - Split on \n only: a line-ending change is visible, and a trailing-newline-only change explains itself instead of an empty diff. - UTF-8 decoded with fatal + ignoreBOM, so BOM files diff. - toHunks is linear; LCS table is Uint16 (8MB at the cap); removals before additions, as in unified diff. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DwjSXosdJg8rATTa7pQEn
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
QSchlegel
marked this pull request as ready for review
October 16, 2026 19:52
This was referenced Oct 17, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Completes Quirin's MRP Month 6 (September 2026) items in ROADMAP.md: Document Sign-Off v1 — Revision Provenance, and the FROST research go/no-go (#220). Builds on PRD-001 (Document Sign-Off).
Revision Provenance (Document Sign-Off v1)
History was already covered by the chained platform attestations (#375). This PR adds the other three pieces, all off-chain.
diffVersions,src/lib/documents/diff.ts): compares any two versions of a document.restoreVersion): re-publishes an earlier version's exact content as version N+1.version.restoredand attested.expectedHeadVersionIdis stale.exportAudit/ publicverifyAudit): new formatmesh-multisig.document-signoff.audit.v1.proof.v1, the full event log, and the attestation chain with its keys.verifyAuditPackagere-runs every check offline and cross-checks the signed material against the database records.proof.v1, because theproof.v1field names are a contract that existing verifiers parse.Refactor:
uploadVersion,publishDraftandrestoreVersionnow share oneappendVersionhelper. Event metadata is unchanged.exportProofbuilds through the sharedbuildProofPackageand now carriespartyId/partyRolefor contract-party reviews. For threshold proofs the output is byte-identical.FROST / PQ research (#220)
The findings are in
docs/research/frost-go-no-go.md.scripts/research/frost-ed25519/(research only, trusted dealer):Roadmap
Testing
documentDiff,documentAudit(tamper cases, malformed input, bounds) andfrostResearchPoc. The full unit run has 1632 tests passing.documentProvenanceruns against real Postgres with real CIP-8 signatures and a real attestation key. It covers diff, rollback (including that the approval stays on v1), audit export and offline verification. Thedocument*andcontractPartiessuites pass: 13 tests.tsc --noEmitis clean. Prettier has been applied.Known limits / follow-ups
verifyAuditPackagecross-checks them against the signatures and the chain, andAUDIT_INSTRUCTIONSsays so plainly.startReviewandsubmitSignerActiondo not yet writepartyId. A proof where one person signs in two roles would still trip the verifier's duplicate-signer check, which is keyed on address. This PR doesn't change that.🤖 Generated with Claude Code
https://claude.ai/code/session_016DwjSXosdJg8rATTa7pQEn
Generated by Claude Code