Holds the anthropic-licence-manager seat. One binary: the seat's verbs and the daemon in one launched bundle; prepare is the run-once schema step.
Reads every node's claude-code.holdings state; a report with a refresh token it does not hold is a candidate.
Asks that node's claude_code_grant with its public key; the grant comes back sealed (same box as claude-code's TypeScript, byte for byte, tested both ways).
Adopts by refreshing: newest login first, once per account; failure records the login dead; the vendor's account, if named, must match the node's report.
One rotation source: every exchange under a lease per licence in postgres; cadence/floor/failure-notify/cooldown/refresh-expiry warning as in design 39.
bindings state per consumer with a monotonic generation; current answers the access token only, sealed to the consumer's key.
Verbs: licences, bindings, bind, switch, release, refresh, usage, adopt (API key from a file), current. Events: licence.adopted/refused/failing, usage.read — no token anywhere.
Tests: 9 rule tests on a memory store with a stub vendor, the store against real postgres, race detector clean. Built on the real builder from this branch (build-1791109141611090924).
claude-code
Reports what the node holds as holdings state at start and on every credentials change (fingerprints and account, never a token).
claude_code_grant hands the full grant over only when asked, sealed.
Watches claude-licence-manager.bindings for its node; a newer generation fetches current; writes access-token-only.
Licence events and login push removed. ask now reads the runtime's answer as a value, and seats are addressed as seat:… (the old form addressed a module subject nothing answers). Tests 28/28.
Not done here
Nothing is assigned. Going live adopts real logins: the first refresh spends each node's refresh token.
novox/hq ADR 0206 (with ADR 0183, design 39, design 36).
## claude-licence-manager (new, Go)
Holds the `anthropic-licence-manager` seat. One binary: the seat's verbs and the daemon in one launched bundle; `prepare` is the run-once schema step.
- Reads every node's `claude-code.holdings` state; a report with a refresh token it does not hold is a candidate.
- Asks that node's `claude_code_grant` with its public key; the grant comes back sealed (same box as claude-code's TypeScript, byte for byte, tested both ways).
- **Adopts by refreshing**: newest login first, once per account; failure records the login dead; the vendor's account, if named, must match the node's report.
- One rotation source: every exchange under a lease per licence in postgres; cadence/floor/failure-notify/cooldown/refresh-expiry warning as in design 39.
- `bindings` state per consumer with a monotonic generation; `current` answers the access token only, sealed to the consumer's key.
- Verbs: licences, bindings, bind, switch, release, refresh, usage, adopt (API key from a file), current. Events: licence.adopted/refused/failing, usage.read — no token anywhere.
- Tests: 9 rule tests on a memory store with a stub vendor, the store against real postgres, race detector clean. Built on the real builder from this branch (build-1791109141611090924).
## claude-code
- Reports what the node holds as `holdings` state at start and on every credentials change (fingerprints and account, never a token).
- `claude_code_grant` hands the full grant over only when asked, sealed.
- Watches `claude-licence-manager.bindings` for its node; a newer generation fetches `current`; writes access-token-only.
- Licence events and login push removed. `ask` now reads the runtime's answer as a value, and seats are addressed as `seat:…` (the old form addressed a module subject nothing answers). Tests 28/28.
## Not done here
Nothing is assigned. Going live adopts real logins: the first refresh spends each node's refresh token.
claude-licence-manager holds the anthropic-licence-manager seat: it reads
every node's holdings state, adopts a login it does not hold by refreshing
it (newest first, once per account), keeps each grant alive under a lease,
publishes what each consumer should hold as its bindings state with a
generation, and answers current sealed to the consumer's key. Postgres
store prepared by a run-once step; grants encrypted with the vault's key.
claude-code reports what its node holds (fingerprints and account, never a
token), hands its grant over only when the manager asks, watches its
binding and fetches the token on a newer generation, and writes
access-token-only. Its ask now reads the runtime's answer as a value and
addresses seats as seats.
The module is one Go binary the runtime launches: the renderer (its
instruction file held byte for byte to the TypeScript one it replaces),
the credentials and identity files, the licence flow of ADR 0206 and the
MCP servers in state. Keeps the TypeScript module's key files, so a node
moving to it keeps its key. The npm package, its tests and its build go.
Both binaries were run together under the real runtime on a test bus with
postgres and a stub vendor: a login was adopted by one exchange, the node
bound and handed an access token, its file left with no refresh token, and
no token in either state.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
novox/hq ADR 0206 (with ADR 0183, design 39, design 36).
claude-licence-manager (new, Go)
Holds the
anthropic-licence-managerseat. One binary: the seat's verbs and the daemon in one launched bundle;prepareis the run-once schema step.claude-code.holdingsstate; a report with a refresh token it does not hold is a candidate.claude_code_grantwith its public key; the grant comes back sealed (same box as claude-code's TypeScript, byte for byte, tested both ways).bindingsstate per consumer with a monotonic generation;currentanswers the access token only, sealed to the consumer's key.claude-code
holdingsstate at start and on every credentials change (fingerprints and account, never a token).claude_code_granthands the full grant over only when asked, sealed.claude-licence-manager.bindingsfor its node; a newer generation fetchescurrent; writes access-token-only.asknow reads the runtime's answer as a value, and seats are addressed asseat:…(the old form addressed a module subject nothing answers). Tests 28/28.Not done here
Nothing is assigned. Going live adopts real logins: the first refresh spends each node's refresh token.