This repository was archived by the owner on May 13, 2026. It is now read-only.
refactor(identity): rename load_or_generate -> provision; route runtime callers through identity::load + 503 - #908
Merged
Conversation
…me callers through identity::load + 503 Bootstrap-collapse step 2. PR #903 made POST /api/setup/bootstrap the canonical first-launch endpoint, but NodeManager::create_node and ensure_default_identity still called load_or_generate, so a stale node_config.json could mint a ghost identity behind the user's back and orphan every previously-ingested record. - identity::load_or_generate -> identity::provision, documented bootstrap-only. A regression test enforces that only src/server/routes/setup.rs may call it. - NodeManagerError::NotProvisioned variant; create_node and ensure_default_identity now call identity::load and surface NotProvisioned when the tree is empty (test seed_identity is the only escape hatch in create_node). - HTTP layer maps NotProvisioned to the canonical 503 body {error: "node_not_provisioned", next: "POST /api/setup/bootstrap"} via utils/http_errors::node_not_provisioned_response, wired into routes::common::get_node_for_user (the require_node helper used by every handler) and routes::config::auto_identity. Matches the body shape the existing nodeProvisioning.ts UI interceptor watches for. - Tests: provision_only_called_from_setup_route grep enforcer, load_does_not_mint_on_empty_pool, NodeManager NotProvisioned probe, auto_identity 503 response shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bootstrap-collapse step 2 (PR #903 landed step 1).
Kanban task 19fce.
PR #903 made
POST /api/setup/bootstrapthe canonical first-launchendpoint, but
NodeManager::create_nodeandensure_default_identitystill called
identity::load_or_generate. That meant a stalenode_config.jsoncould mint a ghost identity behind the user's backand orphan every previously-ingested record. This closes that gap.
identity::load_or_generate→identity::provision, doc-commentedbootstrap-only. A regression test (
provision_only_called_from_setup_route)greps the source tree on every
cargo test --librun and fails if anyfile outside
src/server/routes/setup.rsreintroduces the call.NodeManagerError::NotProvisionednew variant.create_nodeandensure_default_identitynow useidentity::loadand returnNotProvisionedwhen the tree is empty.create_nodekeeps a singleescape hatch —
node_config.seed_identityset viawith_seed_identity— so existing test fixtures keep working withoutchanges; tests mirror the bootstrap flow exactly.
utils/http_errors::node_not_provisioned_responsewith the canonical body
{error: "node_not_provisioned", next: "POST /api/setup/bootstrap"}.Plumbed into
routes::common::get_node_for_user(used by everyrequire_nodecaller via the macro) and
routes::config::auto_identity. Body shapematches the existing
nodeProvisioning.tsUI interceptor exactly, so thefrontend's
folddb:node_not_provisionedevent will fire as designed.Audit notes
get_nodecallers and how 503 propagates:routes/common.rs:60(require_nodehelper)503 node_not_provisionedwith canonical bodyroutes/setup.rs:417(bootstrap)routes/admin.rs:210, 310(spawn jobs)handle.fail(); not HTTP-directroutes/config.rs:325(get_database_status)identity::loadpre-check still gates; behavior unchanged. OUT OF SCOPE per task prompt.ensure_default_identitycallers:routes/config.rs:77(auto_identity)503 node_not_provisionedhandlers/auth.rs:362(signed_register)handlers/auth.rs:927(finalize_restore)Test plan
cargo clippy --workspace --all-targets -- -D warnings -A dead_code— clean (-A dead_codesuppresses the macOS-onlyapple_importwarning per MEMORY.md)cargo test --lib— 977/977 pass, including newprovision_only_called_from_setup_route,load_does_not_mint_on_empty_pool,get_node_returns_not_provisioned_when_pool_empty_and_no_seed,auto_identity_returns_503_when_not_provisionedcargo test --bins— all bin suites passnpm test(frontend) — 732/732 pass, including existingnodeProvisioning.test.tsthat asserts the 503 contract