papa-hq reads 01 research -> 03 decision -> 02 design. The order is a scar, not a choice: 02-DESIGN existed from its initial commit, and when adr/ was finally promoted on 2026-07-13 it took the next free number rather than its place in the sequence. By then design was too settled to renumber. hal-hq was three commits old, so it is not. adr/ becomes 02-DECISIONS and 02-DESIGN becomes 03-DESIGN, and following the folder numbers now walks the process in the order it happens: research produces a decision, the decision authorises a design. 00-GENESIS becomes 00-META, matching papa's rename from the same restructure. Every path reference rewritten across documents, frontmatter, playbooks and skills. All links resolve; all 58 frontmatter blocks parse and their path fields still point at files that exist.
87 lines
3.8 KiB
Markdown
87 lines
3.8 KiB
Markdown
---
|
|
layer: as-is
|
|
status: implemented
|
|
code: [hal]
|
|
updated: 2026-08-23
|
|
decisions:
|
|
- 02-DECISIONS/0004-managed-files-are-generated-never-edited.md
|
|
- 02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md
|
|
---
|
|
|
|
# Configuration and secrets
|
|
|
|
Every value a module reads at runtime comes from a file on a node's disk. Every one of those
|
|
files is **generated**.
|
|
|
|
## The rule
|
|
|
|
A managed file is derived from the mesh database. A synchroniser rewrites it when the values
|
|
behind it change. The write path is the mesh operation that owns the value; the file is an
|
|
output ([ADR 0004](../../02-DECISIONS/0004-managed-files-are-generated-never-edited.md)).
|
|
|
|
An edit to a managed file survives until the next synchronisation and is then overwritten
|
|
silently, taking whatever it was fixing with it — bringing back the bug the edit had removed,
|
|
with a delay, and with no error to connect the two events.
|
|
|
|
There is a way to ask whether a given file is managed. That question has to be asked, because
|
|
the answer is not visible from the file.
|
|
|
|
## What is managed
|
|
|
|
Generated environment files for each module, service definitions in each module's runtime
|
|
directory, managed configuration files a module declares, and node-level settings. The list is
|
|
not a category — it is whatever a synchroniser claims, which is why the question is asked of
|
|
the tooling rather than answered from a rule.
|
|
|
|
## How a value is decided
|
|
|
|
Values resolve by precedence, highest first:
|
|
|
|
1. **A database override** — set deliberately, or written by a provisioner.
|
|
2. **The value already in the generated file** — preserved for anything without an override.
|
|
3. **A generated value** — a random secret, a template composed from other variables, or a
|
|
value pulled from the node's own record.
|
|
4. **The manifest default.**
|
|
|
|
Two consequences follow, and both are subtle enough to have caused confusion.
|
|
|
|
The second rule is what keeps a generated password **stable** across regenerations. It is not
|
|
an oversight; without it every regeneration would issue a new secret and break whatever holds
|
|
the old one.
|
|
|
|
The same rule means that **changing a manifest's default does not change anything already
|
|
using it**. The existing file's value wins. The new default reaches only installations that
|
|
never had one.
|
|
|
|
Removing a declaration is worse than changing it: the old override row and the file it produced
|
|
are both left behind. Configuration is additive in practice, whatever the manifest says.
|
|
|
|
## Secrets
|
|
|
|
Generated secrets are produced by the mesh, never authored. Provisioned credentials arrive as
|
|
database overrides written by the provisioner and are marked as such, so they can be
|
|
distinguished from a deliberate override and cleaned up when the grant is removed
|
|
([ADR 0005](../../02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md)).
|
|
|
|
Nothing in the repository contains a credential. The repository has no per-node content at all,
|
|
which is what makes that guarantee structural rather than a matter of care.
|
|
|
|
Two known weaknesses, both recorded rather than resolved:
|
|
|
|
**Generated environment files were world-readable.** The mode passed at write time only applies
|
|
when the file is created, so regeneration left the previous mode in place. The class of bug is
|
|
worth remembering beyond the instance: a permission set at creation is not a permission
|
|
maintained.
|
|
|
|
**Rotation is not a mesh operation.** Secrets can be generated and granted; there is no
|
|
mechanism that rotates one and informs everything holding it. Where a rotation has been done,
|
|
it has been done by hand, and doing it wrong has taken services down.
|
|
|
|
## Node-level and mesh-level values
|
|
|
|
A node-level value applies to everything on one node. A mesh-level value applies everywhere and
|
|
is read by every node — the broker's location is the canonical example, and a wrong one is how
|
|
a mesh fails to form.
|
|
|
|
Neither is a file that anyone edits. Both are database records that produce files.
|