]> quire.kejadlen.dev Git - quire.git/commitdiff
Add docs/config.md for the Fennel config schemas
authorAlpha Chen <alpha@kejadlen.dev>
Mon, 27 Apr 2026 02:53:07 +0000 (19:53 -0700)
committerAlpha Chen <alpha@kejadlen.dev>
Mon, 27 Apr 2026 03:11:24 +0000 (20:11 -0700)
Assisted-by: Claude Opus 4.7 via Claude Code
README.md
docs/config.md [new file with mode: 0644]

index ada3cb965f9d42785285de689a4d003f255fdc2f..324ea777c4ecf3c8eb1b2741091a92effb5da42a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -38,10 +38,10 @@ Quire's data lives under one volume:
 /var/quire/
   repos/           bare git repos; per-repo config lives in-tree at .quire/config.fnl
   runs/            CI run metadata, artifacts, and logs; retention-policied
-  config.fnl       global config (GitHub PAT, SMTP creds, etc.)
+  config.fnl       global config; see docs/config.md for the schema
 ```
 
-Host-side config (sshd_config block, Caddyfile, docker-compose file) lives on the host, version-controlled separately. See `PLAN.md` for the reference layout.
+Host-side config (sshd_config block, Caddyfile, docker-compose file) lives on the host, version-controlled separately. See `PLAN.md` for the reference layout, `docs/config.md` for the global and per-repo Fennel schemas.
 
 ## Status
 
diff --git a/docs/config.md b/docs/config.md
new file mode 100644 (file)
index 0000000..cadae50
--- /dev/null
@@ -0,0 +1,71 @@
+# Config files
+
+Quire reads two Fennel config files. Both are pure data — a single
+top-level table — loaded via the embedding described in
+[`fennel.md`](fennel.md).
+
+## Global config
+
+Lives at `/var/quire/config.fnl` on the bind-mounted volume.
+Operator-created. Re-read on every call (no caching today).
+
+| Key              | Type           | Required | Purpose                                                  |
+|------------------|----------------|----------|----------------------------------------------------------|
+| `:github :token` | `SecretString` | yes      | GitHub PAT used for `http.extraHeader` on mirror pushes. |
+| `:sentry :dsn`   | `SecretString` | no       | Sentry DSN for error reporting. Omit to disable.         |
+
+Minimal:
+
+```fennel
+{:github {:token "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}
+```
+
+With Sentry, and the token sourced from a Docker secret:
+
+```fennel
+{:github {:token {:file "/run/secrets/github_token"}}
+ :sentry {:dsn "https://key@o0.ingest.sentry.io/0"}}
+```
+
+A missing file is a typed error (`Error::ConfigNotFound`). A malformed
+file surfaces as a Fennel parse or eval error with source labels.
+
+## Per-repo config
+
+Lives at `.quire/config.fnl` *checked into the repo* — quire reads it
+from `HEAD` of the bare repo via `git show HEAD:.quire/config.fnl`
+whenever a hook needs it. Repos without the file (or without a given
+key) get defaults; this is a no-op for the post-receive hook, not an
+error.
+
+| Key            | Type     | Required | Purpose                                                                       |
+|----------------|----------|----------|-------------------------------------------------------------------------------|
+| `:mirror :url` | `String` | no       | HTTPS URL of the mirror remote. URLs with embedded `user:pass@` are rejected. |
+
+Example:
+
+```fennel
+{:mirror {:url "https://github.com/owner/repo.git"}}
+```
+
+## SecretString values
+
+Any field typed as `SecretString` accepts two shapes:
+
+- A plain string: `"hunter2"`.
+- A file reference: `{:file "/run/secrets/github_token"}`.
+
+File references are resolved on first call to `.reveal()` and cached
+for the lifetime of the parsed value. A single trailing newline is
+stripped (Docker secrets convention); additional trailing newlines are
+preserved.
+
+The `Debug` impl redacts the value, so a config struct slipping into a
+`tracing::debug!` call won't leak the secret. Calling `.reveal()` and
+logging the result bypasses this — don't.
+
+## See also
+
+- [`fennel.md`](fennel.md) — how Fennel files are loaded into Rust structs.
+- `src/quire.rs` — `GlobalConfig`, `RepoConfig`, `MirrorConfig` definitions.
+- `src/secret.rs` — `SecretString` implementation and tests.