Skip to content

feat(cli): atem status, pair verify, host trust generation - #67

Merged
guohai merged 7 commits into
mainfrom
feat/status-pair-verify
Oct 16, 2026
Merged

guohai merged 7 commits into
mainfrom
feat/status-pair-verify

Conversation

@guohai

@guohai guohai commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Atem's side of the approved CLI workflow in designs/session-multiplexing.md §1, plus pairing safety from Astation's handoff.

  • atem status: one read-only, offline view: Account, Pairing (with trust generation, expired session), Verification, Credentials (incl. broken key files with recovery steps, other-build agent, storage key not escrowed), Authorization, Relay, Local agents. atem cred status is removed.
  • atem pair reports status and changes nothing on a paired profile; atem pair verify verifies only the existing binding; atem cred unlock never starts pairing or verification.
  • Host trust generation: pairing.json holds a durable generation and a random binding id; atem unpair commits the next generation before cleanup, so an interrupted unpair still cuts off the old pairing.
  • Replies bound to their pairing: authentication, re-authentication, credential sync, verification, unlock, storage-key and credential-report replies are applied only while the pairing they started under is current; a leftover session after an interrupted unpair is never used; token refresh can't undo an unpair.
  • Recovery advice moves key files aside instead of deleting them.

Testing

cargo test (unit + all tests/* binaries) passes; tests for every refusal path, an interrupted unpair, concurrent unpair during token refresh, and late replies after unpair/re-pair.

Generated with SMT smt@agora.build

🤖 Built with SMT <smt@agora.build>
- atem status (new src/status.rs): read-only, offline account / pairing /
  verification / credentials report; asks only an already running key
  agent; authorization and relay shown as unknown (stale). atem cred status
  prints the same (the old cred status report is removed).
- atem pair on a paired profile prints the status plus "Already paired..."
  and exits 0 without connecting or changing files.
- atem pair verify: verifies the existing pairing over the saved session
  (no pairing), no-op when already verified, refuses after a revocation.
- atem cred unlock on an unverified device stops offline.
- Revoked keys are no longer set aside by pair/verification; atem unpair
  does it, and now also removes saved Astation sessions.
- Hints that said "run atem pair" to verify now say atem pair verify.

🤖 Built with SMT <smt@agora.build>
…ed status

- atem status: "paired (<id>, session expired)"; "paired (no Astation id)";
  revoked only when the paired Astation revoked; Credentials shows
  broken (<problem>) with the reset steps, an older agent build, and an
  unlocked storage key Astation doesn't hold yet.
- atem cred status removed; atem status is the only status command.
- A paired profile whose session expired or was refused is told to run
  atem unpair, then atem pair (pairing gate, memory sync/history, TUI
  re-authentication, connect errors, pair verify).
- pair verify refuses a pairing without an Astation id.
- unpair: a failure to set revoked keys aside, or a revocation left
  recorded, is a notice; the unpair still completes.

🤖 Built with SMT <smt@agora.build>
- status::current_profile_paired has no test branch; advice builders take
  paired: bool (reauth_advice, memory sync/history, auth gate message) and
  AstationClient advises from its profile (with_profile; None = this
  user's profile, tests use their temp dir).
- Connect errors for a refused, missing or pairing-required session are a
  typed SessionError; pair verify's session_advice downcasts it instead
  of matching error text.
- connect_astation and unlock_command take the profile's Sources.

🤖 Built with SMT <smt@agora.build>
The reset advice for broken key files no longer says to delete them:
move them into a backup folder (device_keys.sealed holds the memory key
and its older keys), then atem unpair and atem pair, so the new trust is
set up explicitly. Per Astation's handoff (item 5).

🤖 Built with SMT <smt@agora.build>
… they started under

- pairing.json (0600, atomic, flock on pairing.lock): host_trust_gen plus
  the pairing binding (random id, Astation, generation). atem pair binds in
  the next generation; atem unpair commits the next generation without a
  binding before it removes credentials and sessions. A pairing from before
  the file is generation 1, computed by readers and recorded on first
  capture; atem status stays read-only and shows "trust gen N".
- Asynchronous Astation work captures the state and the session its proof
  used, and applies replies only while both are unchanged, under the lock:
  connect and re-authentication (no session refresh or relay code for a
  replaced pairing), credentialSync, encryptionMode/keyGrant, deviceVerified,
  unlock grants, storage-key acks/confirms and credential-project reports
  (key-agent requests through BoundAgent). Encryption messages on a
  connection without a binding yet are held.
- Unpair keeps memory, vault data, trust pins and keys.

🤖 Built with SMT <smt@agora.build>
… an unpair

- A saved session answers an Astation challenge (connect and
  re-authentication) only when the captured pairing binding is with that
  Astation: after an atem unpair that stopped before removing the sessions,
  the leftover session is never used and the user is told to run
  atem unpair, then atem pair (atem pair on an unpaired profile).
- Token refresh no longer saves the copy of the credential store it loaded
  before waiting: the paired refresh reloads the store and updates only an
  existing entry, inside apply_bound (pairing lock and binding check); the
  SSO refresh reloads right before saving. A concurrent unpair (or logout)
  is never undone.

🤖 Built with SMT <smt@agora.build>
@guohai
guohai merged commit cb385c4 into main Oct 16, 2026
3 checks passed
guohai added a commit that referenced this pull request Oct 16, 2026
main holds only the squash-merges of #67 and #68, whose original commits
this branch already contains (and builds on); this branch's tree is kept.

🤖 Built with SMT <smt@agora.build>
@guohai
guohai deleted the feat/status-pair-verify branch October 17, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant