Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -173,11 +173,55 @@ address of its database on another, as a file, and reaches it by a name the mesh
|
||||
stated absence looks like a boundary, and somebody wiring this up should not spend an afternoon
|
||||
looking for a password that was never going to be there.
|
||||
|
||||
**What remains is the secret itself**, and it is the larger half: it must exist, be stored, reach
|
||||
one node and not the others, and rotate with every holder informed — which is
|
||||
[the invariant set](0001-mesh-brokers-nodes-host-agents-think.md) that was found violated three
|
||||
ways at once, and the reason it is not something to add in passing. What is built is the shape it
|
||||
will arrive in.
|
||||
### And the secret, which is delivered without ever being held
|
||||
|
||||
*Written 2026-08-30, after looking at how the existing mesh does it. The design here is a reaction
|
||||
to a measurement, not a preference.*
|
||||
|
||||
**The obvious arrangement is a credentials column, encrypted at rest.** It exists, and its own
|
||||
tooling records what it bought:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| the tool for finding a secret matches **by value**, not by name | because one password is in the provisions table, the environment table, each node's environment file in plain text, and **inside every connection string composed from it** — copies its documentation calls *"often the only copies actually in use"* |
|
||||
| a query against the encrypted column **returns zero rows and proves nothing** | so auditing moved to the decrypted copies on the machines |
|
||||
|
||||
**Two faults, and encryption at rest addresses neither.** The control plane can read what it
|
||||
stores, so a copy of its database is a copy of every credential in the mesh. And one secret has
|
||||
many homes with nothing tracking them — **composition is what mints the untracked ones**, because
|
||||
building a connection string centrally creates a new secret-bearing value no rotation path knows
|
||||
about.
|
||||
|
||||
**So the value is sealed to the node that will use it before it is stored.** With a key that node
|
||||
generated and whose private half the mesh has never seen — a third key beside the identity and the
|
||||
overlay, for the same reason those are two rather than one. What is stored is unusable by whoever
|
||||
holds it, the mesh included, and the broker relays a blob it cannot read. This is what makes
|
||||
[ADR 0004](0004-a-node-and-how-it-joins.md)'s *compromise of a node is compromise of that node*
|
||||
true of secrets rather than true of identity and quietly false of everything that matters.
|
||||
|
||||
**And nothing is composed centrally.** A connection string is assembled on the machine that needs
|
||||
one, if at all. The mesh delivers parts.
|
||||
|
||||
**What it costs, stated because it is real:** the mesh cannot audit by value. That is the right
|
||||
trade rather than an oversight — a query over an encrypted column could not either, so the audit
|
||||
was never real. What *is* answerable is which node holds what, which is the question rotation
|
||||
actually asks.
|
||||
|
||||
**A consequence that shapes the mechanism.** The mesh discarded the plaintext, so it cannot
|
||||
compose a file containing it. The credential is therefore **its own file**, holding the value and
|
||||
nothing else, beside the readable one. That is better than the alternative it was forced into:
|
||||
the readable half stays readable in the declaration, and the secret half changes only when the
|
||||
secret does, so a service reloading on it reloads for a real reason.
|
||||
|
||||
**Rotation is generating a new one**, because reading the old one back is not possible. Both ends
|
||||
are re-sealed and reach their machines in the same push — which removes the window where half the
|
||||
mesh holds a dead credential, the failure
|
||||
[recorded in ADR 0001](0001-mesh-brokers-nodes-host-agents-think.md) as consumers on three nodes
|
||||
holding one for two days.
|
||||
|
||||
**What remains is a provisioner** — something that creates the database user the credential is
|
||||
for. The mesh now generates the secret, tells the provider to create it and the consumer to use
|
||||
it; nothing yet acts on the telling.
|
||||
|
||||
**One check that only became possible now.** Two machines wired together across no private network
|
||||
is a mesh that reports itself configured and does not work, and the failure surfaces as a
|
||||
|
||||
Reference in New Issue
Block a user