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.)
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
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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. Soemits/consumesare, 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 —
mesh.events+ configure/read on its own<node>.<module>.eventsqueue bound toconsumes;mesh.eventsrestricted tomodule.<self>.*(never another module's origin, never the reservedmesh.*/node.*);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_FILEoveramqps.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
Pull request closed