Skip to content
This repository was archived by the owner on May 13, 2026. It is now read-only.

feat(setup): canonical bootstrap endpoint + legacy migration - #903

Merged
shiba4life merged 1 commit into
mainfrom
kanban/973ff-bootstrap-collapse
May 6, 2026
Merged

feat(setup): canonical bootstrap endpoint + legacy migration#903
shiba4life merged 1 commit into
mainfrom
kanban/973ff-bootstrap-collapse

Conversation

@shiba4life

Copy link
Copy Markdown
Collaborator

Summary

Additive first step toward collapsing the three first-launch paths
(CLI wizard, web UI onboarding, silent auto-init in get_database_status)
into one canonical server-side handler. This PR introduces the new
endpoint and a boot-time migration; the existing paths keep working
alongside so we can validate before flipping clients over.

Tracks kanban task 973ff. Subsequent PRs (filed as separate tasks)
rename load_or_generateprovision, strip the auto-init branch,
and port the CLI + React clients.

What's in here

  • POST /api/setup/bootstrap (src/server/routes/setup.rs) — single
    handler for fresh-mint and recovery-phrase restore. Self-disables on
    .onboarding_complete (410 Gone). Atomic-on-failure: identity tree,
    credentials, anthropic key, and config files all roll back if any
    post-identity step fails.
  • Boot-time legacy migration (StartupCtx::boot) — re-encrypts
    plaintext identities (legacy CLI installs) under the keychain master
    key, synthesizes a missing .onboarding_complete marker when an
    identity already exists. Idempotent; conservative (no marker for
    never-set-up nodes).
  • Loopback bind invariant (bin/folddb_server.rs) — bind helper
    extracted, two tests assert 127.0.0.1 for default and arbitrary
    ports. The bootstrap auth model rests on this: no token, just one-shot
    marker file + loopback isolation.
  • Shared FOLDDB_HOME test lock (src/utils/test_lock.rs) — three
    test modules were racing each other on the env var via three private
    mutexes. Now they share one.

Out of scope (filed as follow-up kanban tasks)

  • Rename identity::load_or_generateidentity::provision and gate to bootstrap-only
  • Add NodeManagerError::NotProvisioned → HTTP 503 conversion
  • Strip the auto-init branch from get_database_status
  • Port the React onboarding wizard to a single bootstrap POST
  • Port the folddb setup CLI wizard to a REST client
  • Delete save_identity_card_via_local_node once the CLI port lands

Test plan

  • cargo check --workspace
  • cargo clippy --workspace --all-targets -- -D warnings -A dead_code
    (-A dead_code suppresses the pre-existing apple_import.rs:772
    warning that fires on macOS only — known issue, unrelated)
  • cargo test --lib — 934 pass
  • cargo test --bins — 11 pass
  • cd src/server/static-react && npm test — 676 pass, 6 skipped
  • New tests: marker 410 path, missing-invite-code 400, invalid
    birthday 400, marker_path resolves from FOLDDB_HOME, three
    migration regression tests (synthesize marker, idempotent, no-op
    on empty pool, re-encrypt under master key with os-keychain)
  • Loopback bind tests for default + arbitrary ports
  • Manual smoke: confirm fresh-install via UI/CLI still works
    end-to-end — those clients are unchanged in this PR; will be
    exercised more thoroughly when their respective port PRs land

🤖 Generated with Claude Code

@shiba4life
shiba4life enabled auto-merge May 6, 2026 01:07
@shiba4life
shiba4life force-pushed the kanban/973ff-bootstrap-collapse branch from 11336c1 to 1cb751c Compare May 6, 2026 01:10
Adds POST /api/setup/bootstrap as the additive foundation for collapsing
the three first-launch paths (CLI wizard, web UI onboarding, silent
auto-init in get_database_status) into one server-side handler.

Why:
- CLI wizard wrote plaintext identity; master key was never minted in its
  process.
- Auto-init in get_database_status silently provisioned a "ghost node"
  whenever a stale node_config.json existed.
- Recovery-phrase restore went through a separate code path with its own
  rollback logic.

This PR is the additive first step (one of five per the task plan):
the new endpoint + boot-time migration land alongside the existing
paths so we can validate them before flipping clients over.

Endpoint behavior (D1-D5 from the task):
- 410 Gone once .onboarding_complete exists (one-shot, no tokens)
- Single body shape, recovery_phrase optional => fresh-mint OR restore
- Atomic-on-failure: identity tree, credentials, anthropic key, and
  config files all roll back if any step after identity persistence fails
- ENC: blob in Sled when os-keychain is on, plaintext for dev builds
- 409 Conflict on cloud-mismatch, 503 not used in this PR (deferred)

Boot-time legacy migration (StartupCtx::boot):
- Re-encrypts plaintext identity under the keychain master key when
  os-keychain is enabled
- Synthesizes the missing .onboarding_complete marker when an identity
  exists but the file is absent
- Idempotent; conservative (no marker for never-set-up nodes)

Loopback bind invariant:
- bind_address_for() pulled out of folddb_server main; tests assert
  127.0.0.1 for the default port and a range of arbitrary ports. The
  bootstrap auth model rests on this — if the daemon ever binds 0.0.0.0,
  per-request caller auth must land alongside the change.

Out of scope (will land as separate kanban tasks):
- Renaming load_or_generate -> provision and adding NodeManagerError::NotProvisioned
- Stripping auto-init from get_database_status
- Porting the React onboarding wizard to a single POST
- Porting the CLI wizard to a REST client
- Removing dead helpers in src/bin/folddb/commands/setup.rs

Cross-module test races:
- Three test modules (auth, startup, setup) set FOLDDB_HOME concurrently
  and were racing each other through three separate per-module mutexes.
  Adds src/utils/test_lock.rs::folddb_home_env_lock so all three share
  the same lock.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant