Skip to content

chore: remove stray govd ledgers + gitignore ruff cache - #2

Merged
rhCat merged 1 commit into
mainfrom
chore/repo-cleanup
Jun 12, 2026
Merged

chore: remove stray govd ledgers + gitignore ruff cache#2
rhCat merged 1 commit into
mainfrom
chore/repo-cleanup

Conversation

@rhCat

@rhCat rhCat commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Follow-up cleanup to #1.

govd ledgers belong under record_root (~/cyberware_govd, or the /data/govd volume) — never in the repo. The fix on the usage side is to mount a dedicated dir / named volume, not $(pwd).

🤖 Generated with Claude Code

…d mount) + gitignore .ruff_cache

Two run-id/ledger.json dirs landed in the repo root because a container mounted the repo as record_root;
git add -A swept them into the prior commit. Remove them and ignore the ruff cache. govd ledgers belong
under record_root (~/cyberware_govd or the /data/govd volume), never in the repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rhCat
rhCat merged commit 2ae9d84 into main Jun 12, 2026
1 check passed
rhCat added a commit that referenced this pull request Jul 22, 2026
…r-run, PG-safe read

Four-lens adversarial review (crypto / value-free-boundary / web-surface /
enforcement-path) found four real defects; this fixes all of them.

- [crypto Medium] values_sha was an UNSALTED hash of low-entropy plaintext,
  living in the value-free chain/index — the same DB as the ciphertext — so a
  backup/replica/over-granted role could brute-force the values without touching
  the envelope (contradicting the module's own at-rest claim). Now SALTED:
  sha256(salt ‖ plaintext) with a fresh salt sealed INSIDE the AEAD blob; an
  authorized decryptor recovers salt+plaintext and re-verifies. Full-width keyid
  too (no rewrap truncation-collision/evict).
- [enforcement #2/#3] record_values ran BEFORE execute_step with a first-wins
  upsert, so a refused/retried step orphaned a value row and a retry with
  corrected values desynced the chain sha from the stored blob. Now records ONLY
  on a terminal step_result (ok/error), at-most-once, so the stored blob and the
  chain-bound sha always agree; a refusal records nothing.
- [enforcement #1] decrypt_values read the drain worker's shared (unguarded
  psycopg) connection — a monitor read racing a drain write could drop a tier-1
  chain-index row. Now reads through a FRESH backend connection (reconciler
  discipline).
- [key siting] the node key defaulted into the replicated record root
  (backup+key = broken at-rest); govd now warns loudly and the doc requires
  value_ledger.node_key_file off the backup path.

Residuals documented (accepted): name-based secret filter, plaintext view behind
the shared monitor token, values queue pressure. Tests updated for the salted
commitment + a retry-desync regression. infra/ ruff clean; store selftest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rhCat added a commit that referenced this pull request Jul 22, 2026
…+ monitor detail (M0) (#230)

* feat(store): tier-2 value ledger — encrypted-at-rest per-step inputs + monitor detail (M0)

Makes each governed tool-use inspectable and reproducible WITHOUT weakening the
value-free wire/monitor (docs/pg-provenance-ledger.md, M0).

- infra/store/valuecrypt.py: envelope encryption (X25519+HKDF+AES-GCM, no new dep).
  Fresh per-blob DEK wrapped to a recipient set (node standalone; +mothership at
  fleet join via rewrap without re-encrypting). values_sha commits the PLAINTEXT.
- backend: run_values table (sqlite live; PG inert-parallel, raw BYTEA + JSONB) +
  record_values/get_values on both adapters; store_selftest interface-conformance
  covers them.
- mirror: new value-free `values` queue op (single drain writer; backend only,
  never the chain) + values_sha added to _SAFE_EVENT_KEYS.
- govd Store: node recipient key at boot (0600, default-on, inert if disabled);
  record_values encrypts + enqueues at the ONE WS point plaintext exists, binds
  values_sha into the tier-1 chain step event; decrypt_values for the operator view.
  New operator-gated endpoint GET /monitor/values/<run_id> (node-local decrypt).
- monitors: local dashboard run tab + fleetdash run page each gain a "tool-use
  detail" reveal that decrypts step inputs on request (textContent-only, no
  inline-onclick sink); fleetdash _EVENT_KEYS + proxy allowlist gain values_sha /
  monitor/values.
- tests: test_value_ledger.py (9) + 3 integrated delegated cases. Full suite green.

Secrets never recorded (declared-subset, secret-filtered, *_FILE pointers stay
node-local). Off-node at rest = ciphertext only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(store): adversarial-review fixes — salted commitment, record-after-run, PG-safe read

Four-lens adversarial review (crypto / value-free-boundary / web-surface /
enforcement-path) found four real defects; this fixes all of them.

- [crypto Medium] values_sha was an UNSALTED hash of low-entropy plaintext,
  living in the value-free chain/index — the same DB as the ciphertext — so a
  backup/replica/over-granted role could brute-force the values without touching
  the envelope (contradicting the module's own at-rest claim). Now SALTED:
  sha256(salt ‖ plaintext) with a fresh salt sealed INSIDE the AEAD blob; an
  authorized decryptor recovers salt+plaintext and re-verifies. Full-width keyid
  too (no rewrap truncation-collision/evict).
- [enforcement #2/#3] record_values ran BEFORE execute_step with a first-wins
  upsert, so a refused/retried step orphaned a value row and a retry with
  corrected values desynced the chain sha from the stored blob. Now records ONLY
  on a terminal step_result (ok/error), at-most-once, so the stored blob and the
  chain-bound sha always agree; a refusal records nothing.
- [enforcement #1] decrypt_values read the drain worker's shared (unguarded
  psycopg) connection — a monitor read racing a drain write could drop a tier-1
  chain-index row. Now reads through a FRESH backend connection (reconciler
  discipline).
- [key siting] the node key defaulted into the replicated record root
  (backup+key = broken at-rest); govd now warns loudly and the doc requires
  value_ledger.node_key_file off the backup path.

Residuals documented (accepted): name-based secret filter, plaintext view behind
the shared monitor token, values queue pressure. Tests updated for the salted
commitment + a retry-desync regression. infra/ ruff clean; store selftest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(store): end-to-end HTTP proof of GET /monitor/values — the fleet-monitor plaintext path

The fleet monitor reviews plaintext via the LIVE PROXY: fleetdash → /proxy/<node>/
monitor/values/<run_id> → the node decrypts with its own recipient key → plaintext
back. This adds the first over-HTTP test of that node endpoint (unit tests covered
the Store; this covers the wire):
  (1) 403 without the monitor token (fail-closed gate),
  (2) 200 with the decrypted per-step values when authed,
  (3) the value-free /monitor/run for the SAME run carries only values_sha — no
      plaintext leaks into the value-free view.

Confirms decryption stays node-side (no central key, no central ciphertext) — the
live-proxy oversight model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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