Issue 008 — a provider runtime has no seal key the mesh can deliver

Found building the module-runtime vertical slice: a provider's provisioner
requires a seal key it has no way to receive, and the consumer no way to obtain
the matching one. The runtime cannot come up as delivered.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
2026-09-04 22:23:24 +02:00
parent 64913ed0d3
commit d1aa4254c9
@@ -0,0 +1,67 @@
---
status: open
opened: 2026-09-04
located-in: []
fixed-by:
amended-design:
---
# A provider module's runtime needs a seal key the mesh cannot deliver
## What was observed
Building the vertical slice for the module runtime (the module runs its own code as its
own process under its own account), a **provider** module — one that stands up a per-consumer
resource and hands back a credential — was assigned to a node and run as a broker-bound
runtime. The runtime hosts the module's provisioner, and the provisioner's reconcile harness
opens with:
- it requires a **seal key**, read from the environment, and fails immediately without one;
- every credential it produces for a consumer is **sealed to that key** before it is written.
Nothing in the control plane delivers such a key to a module's runtime. The mesh delivers a
module its **broker account** (a sealed, machine-bound credential) and its **own-secrets**,
and it seals those deliveries with a key of its own — but there is no provision for handing a
provider the key it must seal *its own* outputs with, nor for a consumer to receive the
matching key to unseal them.
The consequence has two faces, both bad:
- **A provider runtime cannot start.** The harness treats the missing key as a hard,
up-front failure — correctly, because a provider that silently sealed to nothing would be
worse. So a provider module, assigned and pushed, comes up dead until a key is supplied
out of band.
- **Supplying one out of band is not a fix.** A key set by hand on the provider is a key the
consumer has no principled way to obtain. The seal is symmetric; the two ends must share
it, and there is nothing that makes them share it.
The slice proved the mechanism only by setting a lab-local key in the manifest by hand — an
admission, not a solution. The test that does so says as much in its header.
## Why it matters beyond this instance
The module-runtime design (the ADR that says a module runs its own code under its own
account) is the model every provider now follows — a cache, an object store, a database,
each stands up per-consumer resources and returns sealed credentials. The delivery the mesh
already does for a broker account is exactly the shape a seal key needs, so the gap is not
that the idea is hard; it is that one required secret in the provider/consumer handshake was
never given an owner. Left open, every provider converted to the runtime model inherits a
module that cannot come up as delivered, and the failure lands at assignment time on whoever
is standing up the node — far from the design decision that caused it.
There is also a **rule-with-no-check** here: the design states that a consumer receives a
sealed credential and unseals it. Nothing today establishes the key that makes "unseal"
possible, so the rule is, at present, enforced by nothing.
## Open questions
- Whose secret is the seal key — the mesh's, the node's, or the specific provider/consumer
grant's? The answer decides who generates it and who it is delivered to.
- Is it one key the mesh holds and delivers to both ends of every grant, or a per-grant key
minted when a grant is made? A per-grant key confines a leak to one consumer; a mesh-wide
key is one thing to deliver and rotate.
- Should it be delivered the way the broker account already is — a sealed, machine-bound
own-secret file the runtime reads — so a provider needs no new delivery channel, only a new
named secret?
- Does rotation of this key have to re-seal every outstanding credential, and if so, is that
the provisioner's reconcile loop's job or the control plane's?