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

fix(hive): recover explicitly when a managed identity key is lost - #73

Merged
100yenadmin merged 7 commits into
mainfrom
fix/72-lost-identity-rotation
Jul 29, 2026
Merged

fix(hive): recover explicitly when a managed identity key is lost#73
100yenadmin merged 7 commits into
mainfrom
fix/72-lost-identity-rotation

Conversation

@100yenadmin

Copy link
Copy Markdown
Member

Closes #72

Outcome

Adds an explicit lost-device fallback after Electric OAuth selects a membership whose durable Hive key is absent. Exact-key NIP-AB recovery remains the preferred path.

  • stages one replacement private key in the Hive Keychain service and proves an OS-backend read-back before server mutation
  • signs the dedicated identity-rotation challenge locally; no private key enters Supabase
  • reuses the staged key across ambiguous responses or restarts and promotes it only when the server binding matches
  • requires a two-step UI confirmation that explains old-key relay revocation and possible loss of old-key-only offline messages
  • leaves native Buzz collaboration and Hermes behavior unchanged

Focused proof

  • cargo test --manifest-path desktop/src-tauri/Cargo.toml --features evaos-teams-managed evaos_teams — 39 passed
  • node --import ./test-loader.mjs --experimental-strip-types --test src/features/evaosTeams/loginFallback.test.mjs src/features/evaosTeams/api.test.mjs — 6 passed
  • pnpm typecheck — passed
  • Biome focused check and git diff --check — passed

Server dependency: electricsheephq/electric-sheep-website-dashboard-6158a244#746 (merged; ordered production rollout tracked separately).

Proof boundary: source and focused tests only until exact-head CI, independent review, cumulative artifact, and installed canary complete.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a34c318f-ea7a-4f4a-9e38-50928e8a06cd

📥 Commits

Reviewing files that changed from the base of the PR and between e1522b8 and 04ca1bd.

📒 Files selected for processing (2)
  • desktop/src-tauri/src/evaos_teams.rs
  • desktop/src-tauri/src/secret_store/managed.rs
📝 Walkthrough

Walkthrough

Adds explicit managed identity replacement for lost devices, including strict challenge validation, local key staging, server rotation or recovery, atomic credential promotion, login coordination, and a confirmation-based desktop recovery flow.

Changes

Managed identity rotation

Layer / File(s) Summary
Challenge validation and signing
desktop/src-tauri/src/evaos_teams/identity_rotation.rs, desktop/src-tauri/src/evaos_teams/tests.rs
Defines identity-rotation challenge contracts, validates challenge fields and event templates, signs verified events, and tests tampering and timestamp rejection.
Replacement staging and rotation recovery
desktop/src-tauri/src/evaos_teams/identity_rotation.rs, desktop/src-tauri/src/evaos_teams/tests.rs
Stages deterministic replacement keys, performs rotation or entitlement recovery, promotes credentials, and verifies staged-key reuse and replacement behavior.
Atomic credential persistence and login coordination
desktop/src-tauri/src/secret_store/managed.rs, desktop/src-tauri/src/evaos_teams.rs, desktop/src-tauri/src/evaos_teams/tests.rs
Adds atomic managed-store mutations, selects matching staged identities, removes rotation markers during promotion, verifies persisted credentials, and serializes recovery with login operations.
Desktop recovery UI and command wiring
desktop/src-tauri/src/lib.rs, desktop/src/features/evaosTeams/*
Registers the Tauri command, adds the API wrapper, and exposes a confirmation-gated replacement flow with concurrency guards and wiring tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EvaosTeamsAuthGate
  participant replace_lost_evaos_teams_identity
  participant ManagedKeychain
  participant IdentityRotationServer
  EvaosTeamsAuthGate->>replace_lost_evaos_teams_identity: invoke replacement command
  replace_lost_evaos_teams_identity->>ManagedKeychain: stage replacement key
  replace_lost_evaos_teams_identity->>IdentityRotationServer: submit signed rotation challenge
  IdentityRotationServer-->>replace_lost_evaos_teams_identity: active entitlement or recovery state
  replace_lost_evaos_teams_identity->>ManagedKeychain: persist promoted credentials
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: explicit recovery for a lost managed identity key. Confidence 97%.
Description check ✅ Passed The description matches the implemented lost-identity rotation flow and UI/keychain changes. Confidence 97%.
Linked Issues check ✅ Passed The changes align with #72: explicit lost-key rotation, local signing, staged Keychain reuse, and recovery UI are all implemented. Confidence 88%.
Out of Scope Changes check ✅ Passed No obvious unrelated features were added; the secret-store helpers and tests directly support the recovery flow. Confidence 90%.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/72-lost-identity-rotation

Comment @coderabbitai help to get the list of available commands.

@100yenadmin

Copy link
Copy Markdown
Member Author

Exact-head gate summary for c0eac63846e3af7a53edd5ca36f7d97acc515264:

  • focused local proof: just desktop-check; default identity tests 35/35; managed identity tests 39/39; Tauri fmt check; TypeScript login/API tests and typecheck passed on the prior behavior head, with this delta limited to moving the Rust rotation unit into its own module
  • canonical CI 30409225518: success, including Desktop Core, four smoke shards, both relay-backed integration shards, macOS, Windows, Rust lint, and aggregate Desktop
  • CodeQL 30409223789: success for actions, Rust, JavaScript/TypeScript, and Python
  • independent semantic review: APPROVE on the behavior head; delta-only APPROVE on this exact head, with no findings
  • final PR surfaces: zero review threads; the only top-level bot comment is the draft-skip notice and has no finding

Proof boundary: source, CI, deployment, and review are proven. No artifact, installed identity rotation, internal canary, or customer rollout is claimed by this PR gate.

@100yenadmin
100yenadmin marked this pull request as ready for review July 29, 2026 00:02

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@desktop/src-tauri/src/evaos_teams/identity_rotation.rs`:
- Around line 77-81: Update the timestamp validation in the identity rotation
flow around created_at and now.timestamp() to use overflow-safe arithmetic, such
as checked subtraction followed by checked absolute-value handling. Convert any
arithmetic failure into the existing “managed identity replacement timestamp is
invalid” error, preserving fail-closed validation without panics.
- Around line 184-188: Update the recovery validation call in the identity
rotation flow to use the same relay-pinning validation as the success path,
passing the signed challenge’s relay host from the fallback call site instead of
calling bare validate_entitlement. Preserve the existing entitlement retrieval
and error propagation behavior.

In `@desktop/src-tauri/src/evaos_teams/tests.rs`:
- Around line 127-157: Extend the identity-rotation validation tests around
validate_identity_rotation_challenge and signed_identity_rotation_challenge to
cover every remaining rejection branch: mismatched expected_membership_id, a
replacement_public_key different from the locally staged key, expires_at both in
the past and beyond the allowed five-minute window, event_template.created_at
skewed by ten minutes, and relay_host values using http or embedded credentials.
Build each case from the existing identity_rotation_challenge helper and assert
signing returns Err, while preserving the current tag-canonicality and
valid-template tests.

In `@desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx`:
- Around line 460-479: Update the recovery action panel around
replaceLostIdentity so both buttons are disabled whenever recoveryWorking,
recoveryStarted, or working is true, matching the ghost trigger’s guard and
preventing competing recovery writes. Also add role="alert" to the warning
paragraph and autoFocus to the “Keep existing identity” button so focus and
announcement are restored when the panel appears.
- Around line 275-279: Update replaceLostIdentity to use a synchronous ref-based
in-flight latch in addition to the working state guard, setting it before
invoking run(replaceLostEvaosTeamsIdentity) and clearing it in a finally path.
This must prevent rapid double invocation before React commits state while
preserving the existing success cleanup and allowing future attempts after
completion.

In `@desktop/src/features/evaosTeams/loginFallback.test.mjs`:
- Around line 27-37: Add a lib.rs source read in the “lost-device identity
replacement is explicit, consequential, and command-backed” test and assert that
generate_handler! includes replace_lost_evaos_teams_identity, alongside the
existing authGateSource and apiSource assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 19a24158-1f85-44aa-8058-74ca3fe1eacc

📥 Commits

Reviewing files that changed from the base of the PR and between c58822b and c0eac63.

📒 Files selected for processing (7)
  • desktop/src-tauri/src/evaos_teams.rs
  • desktop/src-tauri/src/evaos_teams/identity_rotation.rs
  • desktop/src-tauri/src/evaos_teams/tests.rs
  • desktop/src-tauri/src/lib.rs
  • desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx
  • desktop/src/features/evaosTeams/api.ts
  • desktop/src/features/evaosTeams/loginFallback.test.mjs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Do not use unsafe code.
Do not introduce new unwrap() or expect() calls in production paths; use ? and proper error types instead.
New public Rust APIs must have doc comments.

Files:

  • desktop/src-tauri/src/lib.rs
  • desktop/src-tauri/src/evaos_teams/tests.rs
  • desktop/src-tauri/src/evaos_teams/identity_rotation.rs
  • desktop/src-tauri/src/evaos_teams.rs
desktop/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use rem-based Tailwind text tokens rather than arbitrary px, rem, or em text-size literals; prefer stock tokens, text-2xs, or text-3xs.

Files:

  • desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx
  • desktop/src/features/evaosTeams/api.ts
desktop/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

desktop/src/**/*.{ts,tsx}: Chat body and author text must use text-base; surrounding timeline elements should use deliberate steps on the stock text ramp.
When adding a community-scoped module-level cache, Map, or class instance, add its reset to resetCommunityState() in desktop/src/features/communities/useCommunityInit.ts.

Files:

  • desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx
  • desktop/src/features/evaosTeams/api.ts
🔇 Additional comments (11)
desktop/src-tauri/src/evaos_teams/identity_rotation.rs (3)

3-25: LGTM!


86-137: LGTM!


248-297: LGTM!

desktop/src-tauri/src/evaos_teams/tests.rs (2)

31-58: LGTM!


552-619: LGTM!

desktop/src-tauri/src/evaos_teams.rs (3)

46-64: LGTM!


641-647: LGTM!


679-679: LGTM!

desktop/src-tauri/src/lib.rs (1)

712-712: LGTM!

desktop/src/features/evaosTeams/api.ts (1)

84-87: LGTM!

desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx (1)

17-17: LGTM!

Also applies to: 46-46

Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs
Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs Outdated
Comment thread desktop/src-tauri/src/evaos_teams/tests.rs
Comment thread desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx
Comment thread desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx
Comment thread desktop/src/features/evaosTeams/loginFallback.test.mjs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0eac63846

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs
Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs Outdated
Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs
Comment thread desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a536e11c95

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 94fae8c9f0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/evaos_teams/identity_rotation.rs
Comment thread desktop/src/features/evaosTeams/EvaosTeamsAuthGate.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e640a7ae1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/evaos_teams.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1522b8032

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread desktop/src-tauri/src/evaos_teams.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 04ca1bd36d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +149 to +150
let encoded = managed_store()
.store_if_absent(&staging_key, &candidate)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve staged keys across all managed blob writes

When another Hive binary has a warm managed-store cache, the replacement key staged here can still be deleted by that binary's next verify_managed_store_writable, begin_managed_logout, or persist_signed_out_identities: each calls replace_all with a cached whole-blob snapshot, clearing the freshly locked map. If the rotating process has already verified the staged key and the server rotates before final persistence, a crash or Keychain write failure then loses the only replacement private key. Fresh evidence after the resolved scoped-promotion fix is that these remaining whole-blob writers were not converted to fresh scoped mutations.

AGENTS.md reference: AGENTS.md:L7-L10

Useful? React with 👍 / 👎.

@100yenadmin

100yenadmin commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Exact-head gate for 04ca1bd36d6a320f747da62ed8897ad2f78840ad is complete. Focused proof: managed secret-store 4/4, managed identity 39/39, login fallback 3/3, desktop-check, fmt, and diff checks. Canonical CI run 30414606830 passed all required desktop, Windows, integration, smoke, lint, and build jobs; CodeQL run 30414605071 passed. Final independent targeted semantic delta review approved the concurrent staged-identity fix with no P0/P1/gate-relevant P2 findings. All review threads are resolved. This proves source behavior only; cumulative signed artifact and installed primary operator/Benjamin/ATRIS runtime canary remain separate gates.

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.

Bug: recover a genuinely lost managed Hive identity through explicit rotation

1 participant