ADR 0098: a fact a provider makes at first start is fetched from it; issue 076 resolved; design 08 amended; 074 down to one bed
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
---
|
||||
topic: the tiers
|
||||
status: accepted
|
||||
date: 2026-09-21
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0085-a-secret-is-a-provision.md
|
||||
---
|
||||
|
||||
# 98. A fact a provider makes at first start is fetched from it, not carried in its manifest
|
||||
|
||||
## Context
|
||||
|
||||
The catalogue's certificate authority declared its root certificate, its root key and that key's
|
||||
password as its own secrets, and told the container to initialise from them. The mesh mints an
|
||||
own secret as random bytes, and random bytes are not a certificate: as written the authority
|
||||
could not start, and no bed had raised it
|
||||
([issue 076](../04-ISSUES/076-a-served-fact-made-at-first-start-cannot-be-served/00-report.md)).
|
||||
The authority can make its own root at first start. What it could not do then was tell the mesh
|
||||
what that root is: a consumer was given `${bound:acme-ca:root}` from the provider's `serves`,
|
||||
which is written in the manifest before anything runs.
|
||||
|
||||
## Considered Options
|
||||
|
||||
1. **A secret the module makes**, with the mesh taking custody once the file exists. Rejected
|
||||
for now: a node would have to send a value up to the mesh, which no channel does today, and
|
||||
a root key is the one thing the mesh has no reason to hold.
|
||||
2. **A served fact the provider contributes at run time.** Rejected for now: the same new
|
||||
channel, for a fact that is not secret at all.
|
||||
3. **The consumer fetches it from the provider**, over the mesh network, through a gate before
|
||||
the thing that needs it starts. Adopted.
|
||||
|
||||
## Decision
|
||||
|
||||
A provider's `serves` names where a fact made at first start can be fetched — the authority
|
||||
serves its root at a path beside its ACME directory — and a consumer fetches it in a `run-once`
|
||||
step declared before the resource that needs it, from the provider's bound address. The mesh
|
||||
network is where the fetch happens, which is what makes fetching without a prior trust
|
||||
acceptable: it is the network the mesh itself authenticates. The mesh mints only what it can
|
||||
make: the authority's password. The root key stays where it was made.
|
||||
|
||||
## Consequences
|
||||
|
||||
The catalogue's authority starts, and the proxy that requires it trusts what it fetched. What
|
||||
got harder: a consumer of such a fact carries one more resource, the gate that fetches it, and
|
||||
a fact that changes after first start is refetched only when the declaration changes.
|
||||
|
||||
## How it is checked
|
||||
|
||||
The route-forwarding bed installs the authority, the proxy and a consumer from the catalogue and
|
||||
asserts a routed name is served through the proxy; the proxy cannot start without the root its
|
||||
gate fetched. The catalogue-wide manifest test parses both manifests.
|
||||
|
||||
## References
|
||||
|
||||
- [issue 076](../04-ISSUES/076-a-served-fact-made-at-first-start-cannot-be-served/00-report.md)
|
||||
- [ADR 0053](0053-a-step-that-runs-on-a-schedule.md), [ADR 0085](0085-a-secret-is-a-provision.md)
|
||||
- [`03-DESIGN/01-to-be/08-connectivity.md`](../03-DESIGN/01-to-be/08-connectivity.md)
|
||||
@@ -115,6 +115,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0092** — [An operator delivers a pair credential, and the mesh never replaces it](0092-an-operator-delivers-a-pair-credential.md)
|
||||
- **0094** — [A module may hold several secrets from one provider, each a pair of its own](0094-a-module-may-hold-several-secrets-from-one-provider.md)
|
||||
- **0095** — [The control plane is the way to ask a module](0095-the-control-plane-is-the-way-to-ask-a-module.md)
|
||||
- **0098** — [A fact a provider makes at first start is fetched from it, not carried in its manifest](0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md)
|
||||
|
||||
### What runs on them, and how it gets there
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ code:
|
||||
- mesh-controller internal/identity/authority.go
|
||||
- mesh-host internal/identity/serving.go
|
||||
- mesh-host internal/apply (the service that reflects a rule set)
|
||||
updated: 2026-09-09
|
||||
updated: 2026-09-21
|
||||
decisions:
|
||||
- 02-DECISIONS/0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md
|
||||
- 02-DECISIONS/0005-the-node-host.md
|
||||
- 02-DECISIONS/0004-a-node-and-how-it-joins.md
|
||||
- 02-DECISIONS/0007-connectivity.md
|
||||
@@ -557,6 +558,15 @@ fingerprint in its token ([ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-j
|
||||
so nothing needs the CA before membership. It certifies internal names afterwards, and that is
|
||||
all it does.
|
||||
|
||||
**The internal authority makes its own root at first start, and a consumer fetches it**
|
||||
([ADR 0098](../../02-DECISIONS/0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md)).
|
||||
The mesh mints the authority's password and nothing else of its: a root certificate and its key
|
||||
are things only the authority can make, and a served fact written in a manifest cannot carry what
|
||||
does not exist until the authority has run. So the authority serves its root at a path beside its
|
||||
ACME directory, and the proxy that requires it fetches that root over the mesh network in a
|
||||
run-once step before it starts. *How it is checked:* the route-forwarding bed installs the
|
||||
authority, the proxy and a consumer from the catalogue and asserts the routed name is served.
|
||||
|
||||
### What was built
|
||||
|
||||
*2026-08-31.*
|
||||
|
||||
@@ -30,3 +30,6 @@ route-forwarding, which needs the certificate authority beside the proxy, and th
|
||||
|
||||
*Route-forwarding's conversion is blocked:* the catalogue's authority cannot be raised as written
|
||||
([issue 076](../076-a-served-fact-made-at-first-start-cannot-be-served/00-report.md)).
|
||||
|
||||
*Later the same day.* Route-forwarding converted, with the authority beside the proxy
|
||||
(ADR 0098). One bed remains declared: the large mesh test, with its three fixtures.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
status: located
|
||||
status: resolved
|
||||
opened: 2026-09-21
|
||||
located-in: [mesh-catalog modules/step-ca, mesh-controller internal/catalogue (serves)]
|
||||
fixed-by:
|
||||
amended-design:
|
||||
located-in: [mesh-catalog modules/step-ca, mesh-catalog modules/route-proxy]
|
||||
fixed-by: ADR 0098; mesh-catalog multiple-fixes (the authority makes its own root and serves it; the proxy fetches it through a gate); proven by the route-forwarding bed
|
||||
amended-design: 03-DESIGN/01-to-be/08-connectivity.md
|
||||
---
|
||||
|
||||
# A served fact made at first start cannot be served, so the catalogue's authority cannot start
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Diagnosis — 2026-09-21
|
||||
|
||||
1. The certificate bed already raised the same authority image with no root supplied, and it made
|
||||
its own root and issued within a second. The manifest's three minted "secrets" were not needed
|
||||
by the authority; they were needed by the consumer, which was handed the root as a served fact.
|
||||
2. Of the three ways to get a fact made at first start to a consumer, two need a channel from a
|
||||
node up to the mesh that does not exist. The third needs nothing new: the provider serves the
|
||||
fact at a path, and the consumer fetches it over the mesh network in a gate before it starts.
|
||||
|
||||
**Located in:** the two manifests. Decided in
|
||||
[ADR 0098](../../02-DECISIONS/0098-a-fact-a-provider-makes-at-first-start-is-fetched-from-it.md).
|
||||
Reference in New Issue
Block a user