166 lines
9.0 KiB
Markdown
166 lines
9.0 KiB
Markdown
# 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.
|