Public: anyone can read this; the crew can change it.

forge.db and ssh/host_ed25519 leave the tree, and the tree refuses runtime state #671

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

The host private key is no longer tracked. The forge now refuses to boot with its state inside its own checkout, and the gate fails if a private key or a SQLite database is committed.

shipped production is serving it deploy 4183511

opened this

The host private key is no longer tracked. The forge now refuses to boot with its state inside its own checkout, and the gate fails if a private key or a SQLite database is committed.

  • Tree: ssh/host_ed25519 and ssh/host_ed25519.pub are deleted. forge.db had already been removed in #580. .gitignore now lists /forge.db*, /ssh/ and /*.sock.
  • Boot refusal (src/kernel/data_home.ts, called from src/main.ts before createApp): git finds the root of the checkout the forge runs from. If FORGE_DATA is that root, or a path inside it that git check-ignore does not cover, the forge prints one line saying why and exits 1. A path that doesn't exist yet is checked with a trailing slash, so data/ in .gitignore covers a data directory that hasn't been created. A forge running from outside any git checkout (an image, or a checkout-index deploy) is left alone. The default data/ still works, and so do production and preview, whose data directories are elsewhere.
  • Gate rule (scripts/tree.ts, run by test/tree.test.ts): it fails on any tracked file that starts with the SQLite header or contains a -----BEGIN … PRIVATE KEY----- block, unless that file is listed in FIXTURES. That list is empty for now. The forge's check directory has no .git, so there the rule walks the directory instead of running git ls-files, skipping node_modules. The source and test files build the key header in pieces so they don't trip the rule themselves.
  • Tests: test/data-home.test.ts covers the checkout itself, a path that resolves to it, an unignored path inside it, ignored paths that exist and that don't, a path outside it, and no checkout at all. It also boots src/main.ts with FORGE_DATA set to the checkout and expects exit 1 with one line on stderr. That boot test is skipped where there is no .git, because main.ts would really boot there. test/tree.test.ts checks the real tree and unit-tests the detector and the allow-list. Both files are added to GATE.

I chose not to rewrite history: the key still exists in past commits. No live forge uses it, so removing it from the tree is enough.

To try it: FORGE_DATA=. bun run src/main.ts prints the refusal and exits. git show HEAD~1:ssh/host_ed25519 > ssh/k && git add -f ssh/k && bun test test/tree.test.ts fails.

bun x tsc --noEmit and the full gate (bun scripts/test-shards.ts --timeout 60000 --gate) pass: 914 tests, 0 failures. I had to run them outside my sandbox, which refuses the Unix sockets the tests listen on.

🤖 Generated with Claude Code

Closes #622

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs