feat: account-backed CLI with provider profiles and CLI device management - #1258
Merged
Conversation
ital0
force-pushed
the
ital0/cli-account-client
branch
2 times, most recently
from
September 2, 2026 22:03
77685ad to
1107cb4
Compare
Semgrep Security ScanNo security issues found. |
ital0
marked this pull request as ready for review
September 2, 2026 22:04
|
Preview environment destroyed 🧹 Stack |
PR Metrics
Updated Fri, 04 Sep 2026 02:46:44 GMT · run #2912 |
…es and a first-run TUI
…of a session expiry
…credential are given
ital0
force-pushed
the
ital0/cli-account-client
branch
from
September 3, 2026 21:46
eb5e31c to
2456279
Compare
There was a problem hiding this comment.
🔭 thunder-deep-review (advisory)
Complements the other bots — surfaces only what they did not flag. Never approves, never requests changes, never gates merge.
head: 24562797370c · mode: deep · deferred 0 item(s) already reported by other bots (best-effort dedup)
…clave - The proxy copied every inbound header except a short denylist, so X-App-Version, X-App-Language, X-Device-ID and X-Device-Name reached the external enclave even though they are outer-hop headers for our backend - Keep them out of the upstream request and pin the behaviour with a route test
- Sessions minted by the device-authorization grant were accepted by the inference, Tinfoil and usage-receipt routes without ever binding a CLI device, which let a modified client escape the device cap, the device list and device-scoped revocation - Mark grant sessions server-side, let only the CLI registration flow replace that marker, and gate the managed routes behind one shared check that answers 409 CLI_DEVICE_NOT_BOUND while the registration flag is on - Web sessions, personal access tokens, anonymous sessions and flag-off deployments are unaffected; integration tests cover each path
…ackend - The cli- prefix and canonical UUID check were spelled out twice, so the two contracts could drift independently - Move the validator into shared/ and import it from both sides
- A login that resolved to a different account reused the stored device id, hit 409 DEVICE_ID_TAKEN and could never recover; rotate the installation once on that conflict exactly like a revoked device - Logout now honours the compare-and-set result instead of claiming success over a newer credential, and handles 409 CLI_DEVICE_NOT_BOUND for legacy credentials that were never bound to a device
- The auth and provider-config writers only serialised mutations inside one process, so two concurrent CLI invocations could both match the same predecessor and overwrite each other's transition - Guard both files with an exclusive lock in secure-fs that recovers from dead owners without letting two contenders reclaim the same stale lock - Cross-process tests drive real child processes through a deterministic stdout/stdin barrier instead of polling the filesystem
- Only 127.0.0.1 counted as loopback, so valid local self-host endpoints such as 127.0.0.2 were rejected as insecure plain HTTP - Document backendHeaders while touching the module
…ntry - The confidential binding borrowed compatibility and thinking metadata from a hard-coded GLM 5.2 Pi model, so any other confidential catalog entry would silently be sent the wrong payload - Resolve the Pi model from the entry's own vendor and model identity instead
- A transient failure while submitting a confidential usage receipt dropped it for good, leaving the quota ledger under-counted - Queue completed receipts under THUNDERBOLT_HOME per installation, retry with bounded backoff, flush on the next run, and report persistence failures instead of swallowing them - Only 401 consults the authentication observer once and keeps the receipt; 403 means the receipt belongs to another user and is discarded without touching the current session
- The observer that persists credential status ran inside an empty catch, so a failed durable write left stale auth state with no trace - Log the failure while still returning the provider response; tests suppress and assert the expected error
- The one-line activity header rendered a model-controlled command through a sanitizer that preserves newlines and tabs, so a multiline command could draw fake status or prompt lines - Reuse the newline-safe sanitizer the permission renderer already uses
…r login - A one-shot prompt given in argv printed nothing and exited 0 when stdin was already closed, because readline EOF aborted the shared terminal signal; EOF now only settles pending reads, and a real interruption exits 130 - A clean-state `thunderbolt login` left no active provider, so the default managed prompt refused to run; login now activates Thunderbolt unless a provider was already chosen explicitly
- Replace promise-chain catches with try/catch in the catalog client and the rejection-capturing tests, await the steering-mode setup instead of floating it, and give the command switch a throwing never default so a new parser variant cannot silently do nothing - Wait on the disposal completion signal instead of a scheduler yield in the provider-stage test
- Assigning undefined to import.meta.env made Bun expose the string "undefined", so the client identity prompt rendered "App version: undefined" and the suite failed depending on file order - Restore the env in a Bun-safe way and normalise a missing version at the identity boundary for both the prompt and the X-App-Version header
- The one-call-site helper claimed to identify pairable device types but excluded bridges, so the caller patched it back; state the condition directly and drop the helper
- The CLI now imports shared/agent-core and shared/cli-device-id, so a change there must trigger the CLI typecheck, tests and build
ital0
force-pushed
the
ital0/cli-account-client
branch
from
September 4, 2026 02:00
4c09432 to
6bb631c
Compare
…rver - Bun 1.3.14 releases an AbortSignal.timeout timer once its only listener is removed, so the receipt submission hung when the 401 observer stalled and the CLI test suite timed out in CI - Hold a listener for the whole fetch-plus-observer operation, as the account client already does, and cover the two-phase deadline with a test
darkbanjo
added a commit
that referenced
this pull request
Sep 4, 2026
main landed the account-backed CLI (#1258), which conflicted in src/hooks/use-app-initialization.ts. One hunk, both sides wanted: main wrapped `cloudUrl` in `normalizeBackendUrl`, this branch added `experimental_feature_mini_apps` to the settings read. Kept both. Note that a conflicting PR runs no CI at all — GitHub computes a merge ref for `pull_request` workflows and can't produce one while the branch is dirty, so CI, E2E, Security, PR Metrics and thunder-deep-review are simply absent rather than failing. That is the second time this has stalled the branch silently, so it is worth checking mergeability whenever the checks look thinner than expected rather than assuming a partial green. Verification: tsc clean at root and backend, lint 0 errors, 5077 frontend tests pass with only the known pre-existing query-plan failure, 1353 backend tests pass, catalogs re-extracted.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.