07 — The publish output
Summary
The first version of this file was a rule policing where an output directory may live — the maintainer removed the question instead: sgit publish takes no target, writes .sg_vault/publish/ and nothing else on disk, and deployment is a separate act. Then r9 removed the last copy too: the output is the plaintext surface only — loader, cover, manifest, key file, optional API docs — and never contains ciphertext. The manifest enumerates the store (ids, sizes, sha256), so publishing is O(KB) regardless of vault size (measured: 5 files, ~5 KB, for a 22-object store), and re-publishing never churns a gigabyte store. The served root is composed at deployment — co-located (the one-repo pattern: serve the repo, zero copies) or assembled by a keyless copy of bare/ into place — and sgit vault serve composes virtually by routing. Invariant I1 becomes true by construction: what is served is the store. The two index.html files stay apart: the loader is generated plaintext, always sgit's template; the vault's own index.html is encrypted content — the decrypted page wins at expanded deployment. r10 then removes the folder's * self-ignore: in the canonical one-repo flow the folder must reach GitHub — it is what the Pages workflow deploys — and post-r9 it is a few KB of plaintext with nothing sensitive, so plain git add -A includes it. The gitignore that matters is the three-line repo-side set guarding key material.
Key concepts
- Remove the question rather than police it — no target argument means no containment rule, no refusal messages, no escape hatch — and the amplification loop is impossible by construction, not by rule
- The surface, not the store — publish emits O(KB) of plaintext; the ciphertext is never duplicated on disk or in git — composition happens at deployment, by keyless copy or by serving the repo itself
- The gitignore that matters guards keys — the canonical repo-side set is three lines: local/ (live secrets), backups/ (zips can carry the vault key itself as VAULT-KEY), .sg_vault_new/ (a second store, with its own secrets, during a move)
- The two index.html files — the loader (generated, plaintext, byte-identical everywhere) versus the vault's own page (ordinary encrypted content) — conflating them was the earlier framing's one real error
Key ideas
- .sg_vault/publish/ contains no vault content at all, which is why it is safe to commit to a public repository even for a private vault.
- Tabletop 11 executed the keyed-backup hazard: one keyed backup plus git add -A stages the vault key under a local/-only ignore — the canonical set excludes it.
- The secondary vault.html loader copy was dropped: it guarded a partial-expansion mode that does not exist.
- manifest.json records which file ended up at the served root and its hash, so the choice is auditable from the artefact rather than from console history.