ADR 0052 — a step that runs once before a container (issue 037 / run-once primitive) #27

Merged
jschoubben merged 2 commits from feat/adr-0052-run-once-lifecycle into main 2026-09-05 22:05:04 +00:00
Owner

The architectural primitive for "a step that runs at a point in the lifecycle" (issue 037), which you framed as a shortcoming to fix, not an issue to track. Accepted.

run-once: true on the existing container shape: the host runs it to completion, requires exit 0, and gates the apply on it by declaration order (no dependency resolution — faithful to ADR 0005). Idempotent by recorded digest. Key insight: ADR 0047 already gives a module a way to run its own code in its own scoped container, so the mesh adds no new host shape and no arbitrary command — a run-once container is strictly less powerful than an action. Rejected alternatives (a host run shape, general per-phase hooks = the old flaky engine, a distinct one-shot type) recorded with reasons. Unblocks mosquitto's seed-before-start.

https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF

The architectural primitive for "a step that runs at a point in the lifecycle" (issue 037), which you framed as a shortcoming to fix, not an issue to track. Accepted. `run-once: true` on the **existing** container shape: the host runs it to completion, requires exit 0, and gates the apply on it by declaration order (no dependency resolution — faithful to ADR 0005). Idempotent by recorded digest. Key insight: ADR 0047 already gives a module a way to run its own code in its own scoped container, so the mesh adds **no new host shape and no arbitrary command** — a run-once container is strictly *less* powerful than an `action`. Rejected alternatives (a host `run` shape, general per-phase hooks = the old flaky engine, a distinct one-shot type) recorded with reasons. Unblocks mosquitto's seed-before-start. https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
jschoubben added 2 commits 2026-09-05 22:04:48 +00:00
A module can declare state but not a step that runs. mosquitto must seed its
dynsec admin into dynamic-security.json before the broker starts, or the plugin
aborts; the database providers need the same for first-boot migrations and
health gates (04-ISSUES/037). The old event-hook engine that did this was
powerful and flaky; this is the narrowest sound mechanism instead.

A run-once step is an ordinary container marked `run-once: true`: the host runs
it to completion, requires exit 0, and gates the apply on it — so what the
declaration places after it (the broker) starts only once it has finished.
Gating is by declaration order, not a resolved dependency (ADR 0005); the
completion marker is the recorded declaration digest (ADR 0018), so a re-apply
does not re-run it unless the declaration changed. No new host shape and no
arbitrary host command: strictly less powerful than an `action`.

Points 04-ISSUES/037 fixed-by/amended-design at the record; index regenerated;
records.py and index.py pass.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
The run-once lifecycle primitive: run-once:true on the existing container shape,
gated by declaration order + exit 0, idempotent by digest. No new host shape, no
arbitrary command — strictly less powerful than an action. Resolves issue 037.
Verified sound and faithful (ADR 0005/0047); status proposed->accepted.
jschoubben merged commit 897626a9f6 into main 2026-09-05 22:05:04 +00:00
jschoubben deleted branch feat/adr-0052-run-once-lifecycle 2026-09-05 22:05:04 +00:00
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#27