|
| 1 | +{ |
| 2 | + "name": "quota — architecture SSOT", |
| 3 | + "summary": "Claude Code multi-account session vault + login-OTP fetcher. Compiled-hexa CLI; all I/O via exec() + json_parse. Credentials from the `secret` CLI only (never argv/logs/memory). One file: cli/quota.hexa.", |
| 4 | + "children": [ |
| 5 | + { |
| 6 | + "name": "commands", |
| 7 | + "role": "the CLI surface (dispatch in fn main)", |
| 8 | + "children": [ |
| 9 | + { "name": "code <n|email|login-url>", "role": "newest login OTP for ONE account", "detail": "resolve target -> Postmark scan(email) -> print bare code to stdout, context to stderr. --wait <sec> polls 5s and accepts only mail arriving after start (no stale replay). --json = one object. exit 0 ok / 1 bad-arg / 3 none." }, |
| 10 | + { "name": "inbox", "role": "group-wide scan (who got mail + code)", "detail": "scan ALL roster emails (from_hint OFF) -> table of index/email/code/subject, newest first. --json = array." }, |
| 11 | + { "name": "list (alias ls)", "role": "roster from the secret store", "detail": "claude<n>.email keys -> index/email rows, with a [saved] mark when a vault slot exists. --json = array." }, |
| 12 | + { "name": "save <n>", "role": "snapshot the live Claude session -> vault slot n", "detail": "copy ~/.claude/.credentials.json -> ~/.quota/vault/<n>.credentials.json (chmod 600). Fails if no live session." }, |
| 13 | + { "name": "use <n>", "role": "restore a vault slot as the live session", "detail": "backs up the live cred to vault/.live-backup first (never destroys the current login), then copies slot n -> ~/.claude/.credentials.json." }, |
| 14 | + { "name": "sessions / rm <n>", "role": "list / delete vault slots", "detail": "sessions lists saved slots (--json); rm deletes one slot file." }, |
| 15 | + { "name": "--version / help", "role": "version + usage", "detail": "usage lists every verb + the secret keys consumed." } |
| 16 | + ] |
| 17 | + }, |
| 18 | + { |
| 19 | + "name": "otp-flow", |
| 20 | + "role": "login URL/account -> OTP (the core job)", |
| 21 | + "children": [ |
| 22 | + { "name": "resolve_target", "role": "login-url -> account", "detail": "http(s) arg -> extract login_hint=/email= query param if present; else treat the arg as an index/email verbatim." }, |
| 23 | + { "name": "postmark_cfg", "role": "token -> curl -K header file", "detail": "writes silent/show-error + `X-Postmark-Server-Token: <token>` + Accept:json into a temp -K file; the token is pulled from `secret get` INSIDE the shell substitution, so it never enters process memory or argv." }, |
| 24 | + { "name": "scan", "role": "3-state inbound scan -> rows", "detail": "curl /messages/inbound for status in (processed, scheduled, failed) -> json_parse -> dedup by MessageID -> match To against roster -> code = 6-8 digit run from Subject, else from the /details TextBody/HtmlBody. Newest-first (list order)." }, |
| 25 | + { "name": "from_hint", "role": "soft sender preference", "detail": "anthropic.com is a preference, NOT a hard filter: dedicated per-account mailboxes mean any OTP to the account is its login code. `code` prefers a hint match, then falls back to any coded message." } |
| 26 | + ] |
| 27 | + }, |
| 28 | + { |
| 29 | + "name": "session-vault", |
| 30 | + "role": "swap accounts when one hits its quota", |
| 31 | + "detail": "State under ~/.quota/ (vault/ credential snapshots + quota.log JSONL audit). The account-distinguishing credential is ~/.claude/.credentials.json (file-based, portable). `use` always backs up the live session before overwriting." |
| 32 | + }, |
| 33 | + { |
| 34 | + "name": "roster-secrets", |
| 35 | + "role": "config = data, not code", |
| 36 | + "detail": "Postmark token key = postmark.dancinlab_server_token. Roster derived from secret keys claude<n>.email (n=1..20 probed). No account/provider literals in code — change the roster by changing the secret store. ~/.sidecar/accounts.json is NOT read (quota reads secret directly)." |
| 37 | + }, |
| 38 | + { |
| 39 | + "name": "distribution", |
| 40 | + "role": "hx install + native binaries + CI/release", |
| 41 | + "children": [ |
| 42 | + { "name": "hx install quota", "role": "primary setup path", "detail": "dancinlab is in HX_ORGS default -> probe github.com/dancinlab/quota -> clone -> shim cli/quota.hexa (compile-then-exec, cached). Manifest [package].entry + [[bin]] in hexa.toml." }, |
| 43 | + { "name": "ci.yml", "role": "push/PR gate", "detail": "install hexa toolchain -> hexa parse entry+lib -> hexa run tests/smoke.hexa -> block bare top-level main() in changed .hexa. ubuntu + macos." }, |
| 44 | + { "name": "release.yml", "role": "v* tag -> verified release", "detail": "install-smoke (fresh `hx install .` on ubuntu+macos, quota --help dispatches) gates the GitHub Release; then build-binaries AOT-compiles quota-darwin-arm64 + quota-linux-x86_64 via `hexa build` and uploads them (allgreen-promote)." } |
| 45 | + ] |
| 46 | + }, |
| 47 | + { |
| 48 | + "name": "hexa-notes", |
| 49 | + "role": "language gotchas (compiled)", |
| 50 | + "detail": "Entry = fn main() with NO args param (fn main(args) won't compile); argv via args() then slice past the .hexa. int->string = str(x); JSON via json_parse()+j[\"key\"]+map_contains_key; no += (reassign). Heavy `hexa build` is guard-blocked on the dev mac -> build binaries on CI only." |
| 51 | + } |
| 52 | + ] |
| 53 | +} |
0 commit comments