Storage connect from the WebUI: bootstrap layer, setup mode, and the wizard #160
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/Cairn#160
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Decided with Nikola 2026-08-09 (raised while reviewing the v0.6 scaffold): operators may deploy Cairn without configuring storage and connect an S3 bucket or an already-mounted share from the admin panel. Ships fully in v0.6 so the v0.7 beta tests the first-run experience end to end.
Three-layer model (amends #152's config/state line):
/data/.cairn/bootstrap.json, plaintext0600(same secret class and same trust level as the config sitting beside it; encrypting it to identities stored in that same config adds ritual, not security). Precedence: env > config > bootstrap > nothing.The line, final form: the pointer to your data lives locally; everything it points to lives with the data. Declarative instances stay fully stateless pods; UI-connected instances need one small local volume for the pointer — the personas map exactly onto the mechanisms.
Setup mode:
storage.driver: "setup"— the zero-config default (posix/data) is untouched; absence never means setup./setup) comes AFTER storage connect in the flow — local users are state and need somewhere to live.After connection: the panel shows the connection read-only (driver, endpoint/path, bucket, encryption mode) — the long-discussed storage card lands here. Changing the backend on a populated instance remains out of scope (supervised migration tool, v0.8+): it is a data migration wearing a settings costume.
Depends on #152 (statestore + boot order must accommodate setup mode) and #153. i18n en/de/fr/it for the wizard.
Shipped in v0.5.5 (PR #165). All three pieces landed per D11:
Bootstrap layer —
internal/config/bootstrap.go:/data/.cairn/bootstrap.json(0600, 0700 dir, temp+rename;CAIRN_BOOTSTRAP_PATHoverride), holding exactly the storage connection and never encryption/quota/trash. The"setup"sentinel delegates the whole connection to the pointer, then storage env overrides are re-applied — env > config > bootstrap, tested (TestReapplyStorageEnvWins). Absence of a driver still means the zero-config posix default; only the explicit sentinel enters this path.Setup mode —
cmd/cairnd/setupmode.go: with the sentinel and no pointer, the process serves ONLY the wizard;/redirects, every other path answers 503 with an honest label;/healthzstays up for probes. Apply = decode → constant-time token check → real write/read/delete probe with content verification ("connected" means writable, not pingable) → persist pointer → respond → graceful shutdown →os.Exit(0), restarting through the one normal boot path. No hot swap, as ratified.Wizard —
web/static/storage-setup.html, same first-run visual identity as/setup, full en/de/fr/it. Two honestly-labeled options: S3, and Directory with the mounting truth stated in the option itself ("Mounting NFS or disks is the host's job — Cairn never mounts anything"). After apply it polls and hands over to the app when the restarted server answers.Storage card — admin Settings now opens with a read-only card (driver, endpoint/bucket or path, encryption mode, and whether the connection came from the config file or this panel), backed by extended
/api/v1/admin/info(no credentials in the payload). Backend change on a populated instance stays out of scope per the issue — the card's own hint says why.One recorded deviation from D11: wizard access is the one-time log-printed token only; the "config-provided admins when auth is configured" path is not implemented in this cut. Building the full auth stack inside setup mode is real surface area for a persona (declarative IdP config + undeclared storage) that barely exists — an operator declaring OIDC declares a bucket. If the v0.7 beta surfaces that persona, this reopens.
Acceptance note: unit tests cover probe and bootstrap; the end-to-end first-run flow (fresh instance, sentinel, wizard, restart,
/setupuser creation after storage) will be exercised live as part of the #159 delete-the-volume rehearsal session, where a throwaway setup-mode instance costs nothing extra.