mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-05 08:10:39 +00:00
Relocate the Mintlify tree to docs/public and consolidate internal docs under docs/internal. Update build scripts, tests, CI filters, README references, and local docs skills to follow the new layout.
3.4 KiB
3.4 KiB
Server Secrets Strategy
This document defines how Fabro handles server-level secrets.
Core Rules
ServerSecretsis the canonical server-secret reader.- It reads from
process envand<storage>/server.env. - Resolution is snapshot-based: env and file are read once at construction, then treated as immutable for the life of the process.
process envwins overserver.envon conflicts.fabro server startnever generates secrets. Missing required secrets are a startup error.std::env::set_varandstd::env::remove_varare banned workspace-wide. Tests are not exempt. Enforced by clippy viadisallowed_methodsinclippy.toml; intentional exceptions must be annotated with a scoped#[expect(clippy::disallowed_methods, reason = "...")]at the call site.
Active Server Secrets
These values belong to the server runtime and are read via state.server_secret(...):
| Secret | Used by |
|---|---|
SESSION_SECRET |
Cookie encryption and JWT signing derivation |
FABRO_DEV_TOKEN |
Dev-token user auth when server.auth.methods includes dev-token |
GITHUB_APP_PRIVATE_KEY |
GitHub App credentials |
GITHUB_APP_WEBHOOK_SECRET |
GitHub webhook verification |
GITHUB_APP_CLIENT_SECRET |
GitHub OAuth login |
FABRO_JWT_PRIVATE_KEY and FABRO_JWT_PUBLIC_KEY are removed. SESSION_SECRET is the single auth root.
Startup
- Foreground and daemon startup use the same validation path.
- Required-at-startup secrets are:
SESSION_SECRETFABRO_DEV_TOKENwhen dev-token auth is enabledGITHUB_APP_CLIENT_SECRETwhen GitHub auth is enabled
- Other server secrets remain lazy/feature-specific rather than universal boot blockers.
Provisioning
Server secrets come from one of two sources:
- Platform env for 12-factor deployments
server.envwritten by install flows
There is no compatibility layer for removed secrets and no startup-time secret generation.
Subprocess Boundaries
- Worker and render-graph subprocesses start from
env_clear()and re-add only explicit allowlisted variables. - Authority-bearing values are re-injected intentionally. For worker subprocesses this is
FABRO_WORKER_TOKEN, not user auth state such asFABRO_DEV_TOKENorauth.json. - The worker reads
FABRO_WORKER_TOKENfrom its env at startup (inmain()before Tokio initializes) and immediately callsstd::env::remove_varto scrub it. The token then flows through function arguments torunner::execute. Every descendant process (hooks, sandbox commands, devcontainer setup, MCP stdio, etc.) therefore inherits a worker env that no longer contains the bearer, so an unscrubbed spawn site cannot leak it. - The daemon child inherits the parent env unchanged except for output-format hygiene (
FABRO_JSONremoval).
Tests
- In-process tests must inject server secrets with construction-time stubs (
EnvSource,StubEnv) or by writingserver.env. - Subprocess tests must set child env with
Command::env. - Tests must not mutate the process-wide environment.
Rotation
- Secret rotation requires restart.
- Live rotation is intentionally unsupported.
Adding A New Server Secret
- Provision it through platform env or install-written
server.env. - Read it through
state.server_secret(...). - Decide explicitly whether startup should fail when it is absent.
- If a worker or render subprocess needs it, re-inject it explicitly rather than broadening inheritance casually.