docs: deployment mode and conversion contract (S2 contract 6)
ci/woodpecker/pr/ci Pipeline was canceled
ci/woodpecker/pr/ci Pipeline was canceled
This commit is contained in:
@@ -0,0 +1,165 @@
|
|||||||
|
# Deployment Mode and Conversion Contract (D3)
|
||||||
|
|
||||||
|
Status: DRAFT — awaiting ratification (webui-audit S2, contract 6 of 9).
|
||||||
|
Authority: PRD D3 (Part I §3) — two modes chosen at install time,
|
||||||
|
Standalone and Enterprise, with the mode table (brains, user-data
|
||||||
|
isolation, secrets, conversion); Standalone → Enterprise conversion is
|
||||||
|
**one-way** and Enterprise is a **terminal state**. PRD D14 (Part I §7)
|
||||||
|
— the per-user brain split is optional in Standalone and keeping it is
|
||||||
|
the recommended default because it preserves forward-compatibility with
|
||||||
|
the one-way conversion. PRD D11 (Part I §9) — v1 ships the Standalone
|
||||||
|
flow only; Enterprise conversion is explicitly deferred. PRD D3
|
||||||
|
federation clause — federation is intentionally not fully designed,
|
||||||
|
deferred, and nothing in v1 may foreclose it.
|
||||||
|
|
||||||
|
This contract binds the mode as a canonical platform property (§2), the
|
||||||
|
per-mode obligations and which contract owns each (§3), the conversion
|
||||||
|
transition (§4), the v1 non-foreclosure obligations (§5), and their
|
||||||
|
witnesses (§6). Domain semantics stay with their owning contracts:
|
||||||
|
wizard mode choice and branching (contract 3 §2), identity/SSO
|
||||||
|
(`identity-lifecycle.md`), custody and per-user brain mechanics
|
||||||
|
(contract 7), tool mapping (`tool-gateway-mapping.md`).
|
||||||
|
|
||||||
|
## 1. Definitions
|
||||||
|
|
||||||
|
1. **Mode**: the platform-wide deployment mode, exactly one of
|
||||||
|
`standalone` or `enterprise`. The vocabulary is closed in v1;
|
||||||
|
extension (e.g. a federation mode) is by amendment to this contract,
|
||||||
|
never ad hoc.
|
||||||
|
2. **Conversion**: the one-way transition `standalone → enterprise`.
|
||||||
|
No other mode transition exists.
|
||||||
|
3. **Conversion preconditions**: the verifiable conditions of §4.2 that
|
||||||
|
must all hold before the mode record may change.
|
||||||
|
|
||||||
|
## 2. Mode is a canonical recorded property
|
||||||
|
|
||||||
|
1. Mode is recorded canonically in the platform database at bootstrap,
|
||||||
|
as the explicit operator choice contract 3 §2.3 requires. It is
|
||||||
|
never derived from feature state (presence of Vault, count of
|
||||||
|
brains, count of users), and no component may infer a different
|
||||||
|
mode than the record states.
|
||||||
|
2. The record is readable through the Gateway (and CLI, D8) by any
|
||||||
|
authenticated user; components branch on the read value only.
|
||||||
|
3. The record is immutable except by the §4 conversion transition.
|
||||||
|
Editing it by direct database access, config file, environment
|
||||||
|
variable, or wizard re-run is non-conformant (contract 3 §2.3:
|
||||||
|
changing mode later is conversion, not a wizard re-run).
|
||||||
|
|
||||||
|
## 3. Per-mode obligations (owner map)
|
||||||
|
|
||||||
|
The PRD mode table binds four rows; this contract assigns each an
|
||||||
|
owning contract so no obligation is unowned and none is bound twice:
|
||||||
|
|
||||||
|
| Obligation | Standalone | Enterprise | Owner |
|
||||||
|
| ------------------- | -------------------------------------- | -------------------------------------------------- | --------------------------------------------- |
|
||||||
|
| Brains | one mosaic-brain (system + user files) | system brain for config + one brain per user | contract 7 (custody/brain mechanics) |
|
||||||
|
| User-data isolation | single user | no user-data leakage between users; sharing opt-in | contract 7 (enforced by architecture, D14) |
|
||||||
|
| Secrets | OpenBao/Vault or flat files | OpenBao/Vault REQUIRED | this contract (§4.2 gate; steady-state check) |
|
||||||
|
| Conversion | may convert to Enterprise, one-way | terminal state | this contract (§4) |
|
||||||
|
|
||||||
|
In Enterprise steady state, a flat-file secrets backend is
|
||||||
|
non-conformant; the platform refuses to start Enterprise-mode
|
||||||
|
components against a flat-file secrets configuration (fail-closed, not
|
||||||
|
warn-and-run).
|
||||||
|
|
||||||
|
## 4. Conversion transition
|
||||||
|
|
||||||
|
1. **Direction and terminality.** The only transition is
|
||||||
|
`standalone → enterprise`. `enterprise → standalone` does not exist:
|
||||||
|
there is no command, no admin override, and no support path. An
|
||||||
|
attempt is refused with the precondition/state error class of the
|
||||||
|
command envelope (`tool-gateway-mapping.md` §4.2).
|
||||||
|
2. **Preconditions (all verified before the record changes):**
|
||||||
|
- Secrets: OpenBao/Vault is configured and reachable, and no
|
||||||
|
required secret is served from a flat-file backend. Secret
|
||||||
|
migration completes before conversion; this contract does not
|
||||||
|
define the migration tooling, only the gate.
|
||||||
|
- Brains: the per-user brain split required by the Enterprise row of
|
||||||
|
§3 is established for every existing user (or the deployment
|
||||||
|
already kept the split, the D14 recommended default). Brain
|
||||||
|
partitioning mechanics are contract 7; this contract binds only
|
||||||
|
that the split is complete before the mode flips.
|
||||||
|
- Identity: at least one platform administrator account exists and
|
||||||
|
the identity contract's registration controls are in a
|
||||||
|
deliberately chosen state (`identity-lifecycle.md` §2) — recorded
|
||||||
|
as re-affirmed at conversion, since Enterprise changes their
|
||||||
|
consequences.
|
||||||
|
3. **Atomicity of the flip.** The mode record changes in one
|
||||||
|
transaction, only after every §4.2 precondition verifies. An
|
||||||
|
interrupted or failed conversion leaves the record `standalone` and
|
||||||
|
the platform fully operational in Standalone semantics; there is no
|
||||||
|
intermediate mode and no half-converted state observable through
|
||||||
|
the record. Preparatory work (secret migration, brain partitioning)
|
||||||
|
is re-runnable and may complete across multiple attempts, in the
|
||||||
|
same at-most-once, keyed style contract 3 §4 binds for wizard
|
||||||
|
seeding.
|
||||||
|
4. **Authority and audit.** Conversion is a platform-administrator
|
||||||
|
command carrying an explicit irreversibility acknowledgment in its
|
||||||
|
request. It is an official Gateway/CLI command (D8): when built, it
|
||||||
|
is added to the tool↔Gateway mapping by amendment
|
||||||
|
(`tool-gateway-mapping.md` §3.3). The transition emits an audit
|
||||||
|
event (actor, prior mode, new mode, precondition evidence
|
||||||
|
reference) in the same transaction as the record change; the event
|
||||||
|
survives indefinitely.
|
||||||
|
|
||||||
|
## 5. v1 obligations (non-foreclosure)
|
||||||
|
|
||||||
|
v1 ships Standalone only (D11); the conversion command is deferred
|
||||||
|
work. v1 still MUST:
|
||||||
|
|
||||||
|
1. Record the mode per §2 (the wizard already binds the choice,
|
||||||
|
contract 3 §3.2) with `enterprise` a reserved, refused value for
|
||||||
|
bootstrap — v1 bootstrap accepts `standalone` only.
|
||||||
|
2. Keep the §2.3 immutability rule: no v1 surface mutates the mode
|
||||||
|
record.
|
||||||
|
3. Not foreclose conversion: v1 data layouts follow the custody
|
||||||
|
contract's pointer/consent structure (contract 7) so the per-user
|
||||||
|
brain split remains establishable, matching the D14 recommendation.
|
||||||
|
4. Not foreclose federation: the closed mode vocabulary is extensible
|
||||||
|
by amendment, and no v1 component may treat the mode enum as
|
||||||
|
exhaustive in a way that fails closed against a future added value
|
||||||
|
at parse time (unknown mode values are a refused configuration, not
|
||||||
|
undefined behavior).
|
||||||
|
|
||||||
|
## 6. Verification requirements
|
||||||
|
|
||||||
|
Binding on the implementing PRs:
|
||||||
|
|
||||||
|
1. **Mode-record witness (v1):** the mode is readable via Gateway and
|
||||||
|
CLI after bootstrap and equals the wizard-recorded choice;
|
||||||
|
bootstrap with mode `enterprise` is refused; no other write path to
|
||||||
|
the record exists (covered by a writer assertion in the style of
|
||||||
|
contract 1 §6.3, scoped to the mode record).
|
||||||
|
2. **Immutability witness (v1):** every mutation surface shipped in v1
|
||||||
|
leaves the mode record unchanged (asserted over the Gateway
|
||||||
|
command inventory); direct-write attempts through shipped code
|
||||||
|
paths do not exist.
|
||||||
|
3. **No-downgrade witness (conversion milestone):** with mode
|
||||||
|
`enterprise`, a conversion request to `standalone` (and any crafted
|
||||||
|
mode-write) is refused with the precondition/state error class and
|
||||||
|
no record change.
|
||||||
|
4. **Precondition witnesses (conversion milestone):** conversion with
|
||||||
|
(a) an unreachable Vault, (b) a required secret still flat-file
|
||||||
|
backed, or (c) an unpartitioned user brain is refused with no
|
||||||
|
record change and no partial mode effect.
|
||||||
|
5. **Interruption witness (conversion milestone):** fault injection
|
||||||
|
aborting conversion after preparatory work leaves the record
|
||||||
|
`standalone`, the platform operational, and a re-attempt able to
|
||||||
|
complete without duplicating prepared state.
|
||||||
|
6. **Audit witness (conversion milestone):** a completed conversion
|
||||||
|
has exactly one audit event, same-transaction with the record
|
||||||
|
change; a failed attempt has a refusal event and no mode-change
|
||||||
|
event.
|
||||||
|
|
||||||
|
## Ruling request
|
||||||
|
|
||||||
|
Ratify sections 1–6 as written, with one decision embedded:
|
||||||
|
|
||||||
|
- Decision (§5): v1 implements the **mode record and its immutability
|
||||||
|
only** — bootstrap records `standalone`, the `enterprise` value is
|
||||||
|
reserved and refused, and the conversion command itself is deferred
|
||||||
|
to the Enterprise milestone, consistent with D11's deferred list.
|
||||||
|
Alternative if rejected: build the conversion command inside v1 —
|
||||||
|
rejected because D11 scopes v1 to the Standalone slice and
|
||||||
|
conversion depends on contract 7 custody mechanics that are
|
||||||
|
themselves not in the v1 slice.
|
||||||
Reference in New Issue
Block a user