Skip to content

fix(bootstrap): auto-complete bootstrap when workspace self-trusts its signing key (#738)#598

Merged
dollspace-gay merged 1 commit into
developfrom
fix/738-bootstrap-auto-complete-on-register
May 14, 2026
Merged

fix(bootstrap): auto-complete bootstrap when workspace self-trusts its signing key (#738)#598
dollspace-gay merged 1 commit into
developfrom
fix/738-bootstrap-auto-complete-on-register

Conversation

@dollspace-gay
Copy link
Copy Markdown

@dollspace-gay dollspace-gay commented May 14, 2026

Summary

  • Fixes the post-#737/GH#585 deadlock where crosslink init + crosslink sync leaves meta/bootstrap.json at status: "pending" forever — trust pending shows nothing (the workspace key was already auto-trusted), and signing_enforcement: "enforced" bails every sync with guidance that's impossible to follow.
  • Treats workspace self-trust as the moral equivalent of trust approve on the operator's own key: when register_active_key_as_trusted actually adds a new entry while bootstrap is pending, flips bootstrap to complete and stages meta/bootstrap.json into the same atomic unsigned commit.
  • Adds "trust: register signing key" to BOOTSTRAP_MESSAGE_PREFIXES so the unsigned self-trust commit is correctly filtered by signing audit going forward.
  • sync_cmd snapshots bootstrap state before/after configure_signing and prints Bootstrap complete — signing enforcement is now active. for UX parity with trust approve.

Repro before the fix

$ crosslink init
... ✓ Initializing agent identity ... ✓
$ crosslink sync
Published agent key to hub (deferred from agent init).
Locks synced (commit ... is an unsigned bootstrap commit).
Error: Hub bootstrap incomplete — signing enforcement cannot proceed.
$ crosslink trust pending
No pending keys. All published keys are approved.   ← deadlock

Test plan

  • cargo build --lib clean
  • cargo fmt --check clean
  • cargo clippy --lib clean
  • cargo test --lib sync:: — 145/145 pass (includes two new GH#738 tests + GH#585 tests covering the same path)
  • Manual: in a fresh repo, crosslink initcrosslink sync no longer leaves bootstrap pending; a second crosslink sync succeeds with Signing audit: all N recent commit(s) are signed.

🤖 Generated with Claude Code

…s signing key (#738)

PR #597 (GH#585) made configure_signing() silently auto-add the
workspace's active signing key to trust/allowed_signers. Because
trust pending classifies a published key as "approved" when its
principal is in allowed_signers, every published key now reports
as approved — yet complete_bootstrap() was only called from
crosslink trust approve. Net result: after a fresh init+sync the
hub stays at bootstrap.status="pending" forever, and with
signing_enforcement="enforced" every subsequent sync bails with
guidance that is impossible to follow (trust pending shows nothing,
no agent-id to approve).

Treat the workspace self-trust event as the moral equivalent of
trust approve on the operator's own key: when register_active_key_as_trusted
actually adds a new entry while bootstrap is pending, flip
bootstrap to "complete" and stage meta/bootstrap.json into the
same atomic unsigned commit. Also extend BOOTSTRAP_MESSAGE_PREFIXES
so that commit ("trust: register signing key for ...") is correctly
filtered by signing audit going forward. sync_cmd prints the
parity message "Bootstrap complete — signing enforcement is now
active." when the flip happens on its watch.

Two new unit tests prove the flip happens on first call and that
completed_at is not rewritten on subsequent calls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dollspace-gay dollspace-gay self-assigned this May 14, 2026
@dollspace-gay dollspace-gay added the bug Something isn't working label May 14, 2026
@dollspace-gay dollspace-gay merged commit 31d2860 into develop May 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant