From e1ba9b39be221cb436f85fb712442ecbc9069e72 Mon Sep 17 00:00:00 2001 From: notplants-bot Date: Thu, 20 Aug 2026 22:08:17 +0000 Subject: [PATCH] secrets: project-scoped secrets go in /secrets// Operator convention, 2026-08-20. If a secret belongs to one project it lives in that project's directory rather than in files/ with the project name baked into the filename: /secrets/lichen/test-pds.env, not /secrets/files/lichen-test-pds.env. files/ is reserved for things genuinely shared across projects. A flat directory forces every name to carry its own scope, which nobody does consistently, and then 'what does this project hold' and 'what do I revoke if it is compromised' both need a grep. A directory answers both by listing. The convention already existed in practice (b1, notplants-orchestrator, emily-sandbox) and was simply never written down. The symlink rule is unchanged: a consumer insisting on a fixed path gets a symlink into /secrets//, so the file still exists exactly once. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01V3LdmEL7CvCYTNpoBq1kce --- secrets.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/secrets.py b/secrets.py index 513376a..b1d6f0f 100755 --- a/secrets.py +++ b/secrets.py @@ -7,12 +7,29 @@ in .env files, a private key at mode 0644. Anything in a repo is one `git add -A a push. So: ONE encrypted file, OUTSIDE every git tree, and a helper every project uses. /secrets/store.yaml sops+age ciphertext (0600) — values our code reads - /secrets/files/ real files (0600) SYMLINKED from the fixed path a third - party insists on: ~/.ssh keys, a systemd EnvironmentFile, - nix authKeyFile, a TLS keypair + /secrets// PROJECT-SCOPED secrets (0600): everything belonging to one + project lives together, e.g. /secrets/lichen/, + /secrets/b1/, /secrets/notplants-orchestrator/ + /secrets/files/ CROSS-PROJECT files (0600) SYMLINKED from the fixed path a + third party insists on: ~/.ssh keys, a systemd + EnvironmentFile, nix authKeyFile, a TLS keypair ~/.config/sops/age/keys.txt the age private key, 0600 -One home per secret: a value is in the store OR a file in /secrets/files, never both. +PROJECT SECRETS GO IN /secrets// (operator, 2026-08-20). If a secret belongs to one +project, it goes in that project's directory — not in files/, and not with the project name +baked into the filename. `/secrets/lichen/test-pds.env`, not `/secrets/files/lichen-test-pds.env`. +Reserve files/ for things genuinely shared across projects. + +WHY: a flat directory forces every name to carry its own scope, which nobody does consistently, +and then nobody can answer "what does this project hold?" or "what do I revoke if this project is +compromised?" without grepping. A directory answers both by listing. Put a README.md in the +project directory saying what each file is, what consumes it, and what breaks if it is lost — +the next person to read it will be doing so under time pressure. + +The symlink rule is unchanged and applies the same way: a consumer that insists on a fixed path +gets a SYMLINK into /secrets//, so the file still exists exactly once. + +One home per secret: a value is in the store OR a file under /secrets, never both. /secrets is outside every git tree — not a repo, no remote — and outside /srv, which agents grep and walk constantly.