ADR 0048 — a module's broker account is scoped by its emits and consumes #17

Closed
jschoubben wants to merge 0 commits from worktree-adr-0048-module-broker-account into main
Owner

Closes the gap the events work surfaced: ADR 0046/0047 defined the event relationship and its wire shape, but nothing said how a module reaches the broker or what its account may do. Confirmed in code — the mesh can provision a node account and a builder account (build-queue-scoped), but has no generic module broker-account; a module declaring own-secrets:{broker} and nothing more gets 32 random bytes, not a credential. So emits/consumes are, on the broker, enforced by nothing — a scope declared in manifests and read by no code (04-ISSUES/003).

Proposes: on assign, a module gets a broker account whose permissions are its manifest —

  • read on mesh.events + configure/read on its own <node>.<module>.events queue bound to consumes;
  • write to mesh.events restricted to module.<self>.* (never another module's origin, never the reserved mesh.*/node.*);
  • nothing else.

consumes:["#"] (the audit logger) is called out as a deliberate, auditable privilege, not a default. The account is what turns the declaration into a rule the broker enforces rather than a comment — the discipline of "a rule states how it is checked."

Status proposed — this is a security-boundary decision (deciders: jochen); merging it ratifies the scope model, which then unblocks the control-plane work (a generic module account, replacing the builder special-case) and the runtime reading its credential from MESH_BROKER_FILE over amqps.

Extends ADR 0046; references 0047, 0039, 0043. (0046/0047 are their own in-flight PRs, same as when 0047 linked 0046.)

https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF

Closes the gap the events work surfaced: ADR 0046/0047 defined the event relationship and its wire shape, but **nothing said how a module reaches the broker or what its account may do**. Confirmed in code — the mesh can provision a *node* account and a *builder* account (build-queue-scoped), but has **no generic module broker-account**; a module declaring `own-secrets:{broker}` and nothing more gets 32 random bytes, not a credential. So `emits`/`consumes` are, on the broker, enforced by nothing — a scope declared in manifests and read by no code ([04-ISSUES/003](../04-ISSUES/003-firewall-scope-is-read-by-no-code/00-report.md)). **Proposes:** on assign, a module gets a broker account whose permissions **are** its manifest — - read on `mesh.events` + configure/read on its own `<node>.<module>.events` queue bound to `consumes`; - write to `mesh.events` restricted to `module.<self>.*` (never another module's origin, never the reserved `mesh.*`/`node.*`); - nothing else. `consumes:["#"]` (the audit logger) is called out as a **deliberate, auditable privilege**, not a default. The account is what turns the declaration into a rule the broker enforces rather than a comment — the discipline of "a rule states how it is checked." Status **proposed** — this is a security-boundary decision (deciders: jochen); merging it ratifies the scope model, which then unblocks the control-plane work (a generic module account, replacing the builder special-case) and the runtime reading its credential from `MESH_BROKER_FILE` over `amqps`. Extends ADR 0046; references 0047, 0039, 0043. (0046/0047 are their own in-flight PRs, same as when 0047 linked 0046.) https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
jschoubben added 1 commit 2026-09-03 23:19:31 +00:00
Events (0046) and their wire (0047) left open how a module reaches the
broker. The code has no generic module broker-account: only node and
builder scopes exist, so emits/consumes are enforced by nothing — a
manifest declaring a scope the broker does not draw (04-ISSUES/003).

Decides: on assign, a module gets a broker account whose permissions ARE
the manifest — read on mesh.events + its own queue bound to consumes;
write to mesh.events under module.<self>.* only; nothing else. Consuming
'#' is a deliberate, auditable grant. The account is what makes the
declaration a rule the broker enforces, not a comment.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
jschoubben added 1 commit 2026-09-03 23:22:49 +00:00
jschoubben closed this pull request 2026-09-05 01:18:01 +00:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/hq#17