Skip to content

feat(cli): let boss mcp ledger verify detect records removed from the end - #998

Closed
Antriksh1984 wants to merge 1 commit into
risa-labs-inc:devfrom
Antriksh1984:feat/mcp-ledger-truncation-anchor
Closed

Antriksh1984 wants to merge 1 commit into
risa-labs-inc:devfrom
Antriksh1984:feat/mcp-ledger-truncation-anchor

Conversation

@Antriksh1984

Copy link
Copy Markdown
Contributor

Stacked on #995 (the diff below also shows its commits until it lands; this PR is the last commit).

The gap

The MCP operation ledger is hash-chained, and boss mcp ledger verify walks the chain. That proves no record was edited, inserted or removed from the middle. It cannot prove the ledger has not been cut short: a chain with its newest records deleted is still a perfectly valid chain, so deleting the tail of the audit trail (the records documenting what an agent just did) verifies as intact. So does replacing the whole history with a fresh chain of records that never happened.

docs/CLI.md already says so: removing only the newest tail "cannot be distinguished from normal retained history without an external checkpoint". This PR is that checkpoint.

The gap is pinned by a test (truncating the end of the ledger still verifies as intact without an anchor), so the anchor tests are known to close something real.

What changes

  • verify now prints the head hash (Head: <sha256> (record N of M)) and includes headHash / headRecordIndex in --json. That is the value an operator writes down somewhere outside the ledger's directory.
  • verify --anchor <hash> fails (exit 1, verdict anchor-missing) when the chain no longer contains that record, and otherwise reports where it sits and how many verified records were written since.
  • The order of precedence is broken, then incomplete, then anchor-missing: a broken chain is reported as broken and an anchor cannot rescue it, and a ledger with a hole in its rotated history is not called truncated when the anchor may simply be in the missing file.
$ boss mcp ledger verify
...
Head:    9f2c...e1 (record 412 of 412)
$ boss mcp ledger verify --anchor 9f2c...e1     # later
Chain:   ANCHOR MISSING - the records present check out, but not the one anchored
Anchor:  NOT FOUND - the ledger no longer contains the record you anchored.

Decisions worth a look

  • Full 64-character hash only. A shorter prefix is refused before the ledger is read. An anchor is only worth what it costs to forge, and a prefix short enough to type would let someone who can rewrite the ledger grind a record that matches it. (tail prints a 12-character prefix for reading, which is deliberately not accepted here.) Uppercase is accepted and normalised.
  • Rotation caveat, stated rather than hidden. BOSS keeps a bounded number of rotated backups, so an old anchor can legitimately age out. The report says so ("or the record aged out of the rotated backups") and the docs say to anchor a recent head and refresh it. This does not weaken the check: a record that aged out and a record that was deleted are both "not in the chain", and only the operator's own records can tell them apart.
  • It is a checkpoint, not a signature: someone who can rewrite the whole chain and the operator's note of the anchor can still forge history. The docs keep that sentence.
  • Backwards compatible: McpLedgerVerification gains defaulted fields, verifyChain gains a defaulted parameter, and existing output only gains the Head: line.

Tests

McpLedgerAnchorTest (10): head hash in text and JSON; an anchor in the chain is found with the count since; truncation passes plain verify but fails with the anchor; full-history replacement fails the anchor; an anchor in a rotated backup is found; an anchor cannot rescue a broken chain (reported as broken, anchor "not checked"); full uppercase hash accepted and short/long/non-hex/empty values refused; JSON carries anchorHash, anchorRecordIndex and the anchor-missing verdict.

McpLedgerCliTest 18/18, McpLedgerChainTest 17/17, McpOperationLedgerTest 13/13 unchanged and green. ktlintCheck and detekt clean. docs/CLI.md updated.

@kshivang
kshivang force-pushed the dev branch 3 times, most recently from bdcf620 to bc9aa3b Compare September 22, 2026 04:42
… end

The MCP ledger's hash chain links each record to the one before it, so
an edit to a retained record or a broken link between two retained
records was already detectable. Deleting records off the tail of the
file was not: the chain still looked intact because nothing recorded
how many records the file was supposed to hold.

McpOperationLedger now writes a periodic anchor (record count plus the
running hash) alongside the ledger, and boss mcp ledger verify --anchor
compares the file against it, reporting a truncation the hash chain
alone cannot see.
@Antriksh1984
Antriksh1984 force-pushed the feat/mcp-ledger-truncation-anchor branch from 0375297 to 6fb6874 Compare September 22, 2026 10:03
@Antriksh1984

Copy link
Copy Markdown
Contributor Author

Rebased onto current dev as one clean commit (was carrying stale duplicate history that made the diff unreviewable and the merge status CONFLICTING, the same issue found on #1406/#1407/#1417/#1420). Content unchanged. Tests, ktlintCheck and detekt pass on the rebased head.

@fluck-boss

Copy link
Copy Markdown
Collaborator

Thanks so much for this contribution, @Antriksh1984 - the work here is genuinely appreciated, and it's clear real care went into it.

This overlaps with #1001 ("fix(cli): neutralise plugin manifest text in boss plugin validate and link"), which is further along in review and will carry this change forward. To keep review attention focused, I'm closing this one in favor of #1001 - please do review and follow that PR, and you're very welcome to pick up any part of it that still needs help or take on another open issue.

Your contribution credit is noted here, and anything unique in this branch that #1001 misses is still welcome as a follow-up. Thanks again for contributing to BossConsole!

@fluck-boss fluck-boss closed this Sep 23, 2026
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.

2 participants