Skip to content

v1.97.0 - Delivery Trust

Choose a tag to compare

@itechmeat itechmeat released this 02 Nov 07:38
07125f6

Open Second Brain v1.97.0 - Delivery Trust

Open Second Brain v1.97.0 is the delivery-trust release. Until now, the surfaces that hand stored vault text to a remote agent did not state whose words they were delivering, a delivery could not be re-checked against the vault after the fact, and nothing let the operator sign the store state its surfaces stamp. Now every MCP read that returns stored-record text - the search family, the report-shaped reads, the context tools and the osb:// resources - fences agent-origin or unproven text at remote reach inside the same wrapper the intake path uses and fails closed whenever provenance cannot be derived, while local reads and the stored bytes stay untouched; context receipts gain a verify face that re-hashes what a session was delivered against the live vault; the opencode lane closes most of its distance to the Claude Code lane with fail-soft tool gating and once-per-turn prompt-time injection; and o2b brain attest measures the log heads and the state-surface stamps into an Ed25519-signed record under an operator-managed key, so store verification answers from evidence instead of a live answer.

Delivery Trust

What ships

  • Tier-keyed quote fencing on remote read deliveries. Stored text that reaches a caller below local reach arrives wrapped in the explicit <untrusted_source origin="..."> fence the intake path already uses - same tag, same body neutralization, no second delimiter vocabulary - with the origin attribute naming the page's derived provenance: an untrusted_source marker, a content_class: prompt-derived class, or an origin_channel of mcp-tool or import reads agent-authored, while origin_channel: cli with no other marker is the one operator-authored answer that ships plain. The derivation fails closed - a page with no stamps, the unset channel literal, or one that cannot be read resolves fenced, never trusted - because absence of a stamp is a statement about knowledge, not authorship. The fence lives inside the delivered field on the search family, the report-shaped reads, brain_context and brain_pinned_context, and the osb:// preference, topic, active, lessons, digest and backlinks resources, so no output schema grows a marker field. Read-time only: local reach stays byte-identical to the pre-wave bytes and the stored bytes the fence reads do not change, and the fail-soft delivery-provenance-unknown doctor check counts the delivered pages whose provenance nothing proves, naming up to five paths.
  • Context-receipt verify: what a session was delivered, re-checked against the vault. o2b brain context-receipts verify <receipt-id> and a new verify operation on the brain_context_receipts MCP tool re-hash each item's recorded delivered-text digest against the live vault, re-applying the delivery-time transforms including the recorded per-item character budget, so an item delivered trimmed does not false-CHANGED. Each item answers match / changed / unavailable with its reason (no_path, no_hash, file_missing, unreadable), and match is a claim about delivered bytes, never liveness - a retired note verifies against its retired body. Nothing persists; the read is the product. The fail-soft receipt-content-drift doctor check rides the same kernel over the twenty most recent context receipts within thirty days and reports per-verdict counts with the command naming the newest drifted receipt.
  • opencode lane parity: fail-soft tool gating and once-per-turn prompt injection. The native opencode plugin relays the opt-in pretool-orient and pretool-host-backup shims through the host's tool.execute.before event with synthetic PreToolUse payloads, so the vault hook-state stamps and the audit trail behave exactly as they do on the Claude Code lane; only an explicit structured permissionDecision: "deny" blocks the tool call, while a flag that is off (which also means zero spawns), a missing binary, a spawn failure, a timeout or malformed shim output passes the call untouched. On the prompt event the plugin relays the four opt-in injection shims - recall, navigation, counterparty brief, reground - into a single-slot per-turn queue that the existing context delivery points drain on the first model request of the turn, exactly once per turn, so the injection ledger dedupes as it does on the Claude Code lane. All six flags are default-OFF, and a hook-parity census pins the surface: every hooks/hooks.json row is either carried by the plugin or a declared divergence with a written reason, with the thirteen opencode-specific rows named in install/opencode.md.
  • Ed25519 attestations: the operator signs the store. o2b brain attest keygen | sign | list | verify turns store verification into evidence instead of a live answer. keygen creates the operator keypair under .open-second-brain/keys/attestation/ (private half 0600 and never synced, never auto-generated; the passphrase arrives as an env var name or on stdin, never argv), sign measures the vault identity, one chain head per Brain log shard, a file-name inventory of every ledger directory the doctor sweeps and the search index's embedding-ABI stamp into one signed JSON record, and verify re-measures the store against the newest attestation, answering per-shard intact / appended / diverged / missing. Post-signing ledger growth is the normal case and reads as such, and nothing here repairs a store. The MCP face is a read-only brain_attestations tool that answers identically at every reach because it carries no note content, while keygen and sign have no tool surface anywhere, and the fail-soft attestation-stale-or-diverged doctor check folds the facts that age badly into one warning naming the next command.
  • A mutation by a non-CLI lane re-stamps an inherited origin_channel: cli. Update and append operations coming from any lane other than the CLI - an MCP tool call, an import replay, an unclaimed process - rewrite an inherited cli stamp to the writing lane's own channel, so text an agent wrote through MCP stops shipping as plain operator-authored prose from its first edit forward; a CLI-lane mutation keeps the stamp, and a page whose stamp already names a non-CLI lane is left alone. This is the release's one write-side change to stored bytes.
  • Docs. docs/cli-reference.md gains the o2b brain attest rows, the verify form on the context-receipts row and a delivery-trust section naming the fenced surfaces; docs/mcp.md documents the brain_attestations tool, the verify operation on brain_context_receipts and the fence contract on resource bodies delivered at remote reach; install/opencode.md documents tool gating, prompt-time injection, the live-verification steps and the declared-divergences table.

Process wins

  • The wave was built on verified premises: the four capability cards were checked against the live source before anything was designed, five line-drift corrections were recorded against the cards, and the signed-store card ships under the noun attestation so it does not collide with the four meanings checkpoint already carries in this tree.
  • Review ran in nine rounds - seven open-review rounds over the branch plus a two-round retry on the merge delta - fixing 118 findings in conventional commits with regression tests where behavior changed and declining 34 with recorded reasons; CodeRabbit's two rounds added eight findings, all fixed with failing-first regression tests and answered on their threads, and the last rounds returned only test-only lows.
  • Quality record: the CI validate gate on the release head reports 21,461 tests / 0 fail (24 skipped) with typecheck clean and lint at 0 errors, manifest version sync, plugin mirrors, the OpenClaw bundle and the broken-link ratchet green, and the windows shards 1-10, CodeQL, the three analyze lanes and both plugin scans green on the same commit.

Notes

  • The attestation signature covers exactly the measured surfaces and never raw note bytes: an out-of-band edit to a note's body that moves no log head, no ledger file name and no index stamp is not something an attestation can see - per-note content drift is the context-receipt verify's question - and attest verify re-measures against the newest attestation only.
  • Along the way the shared frontmatter read cache began judging containment before any read, so a vault-relative path that resolves outside the vault fails closed to the unreadable verdict instead of opening a file beside the vault, and Windows separators fold to their POSIX spelling so both spellings of one page share one cache entry.
  • CodeRabbit skipped the final head - informational, and expected: the diff spans 111 files, above its 100-file limit. Cycle follow-ups are recorded: the brain_artifact_get replay reach binding, the MCP trusted-stamp doctrine, stale counts in docs/architecture.md, and live-verification of the opencode gate against a released build.
  • The version bump to 1.97.0 shipped inside the PR (#285), per the project rule in CLAUDE.md.
  • Release image: the canonical terminal style, here as an interaction diagram (animated GIF in this body; static PNG, 2x PNG and the SVG source attached as assets).