Skip to content

v0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 22 Oct 19:08
· 182 commits to master since this release

claustrum v0.2.0

This release follows v0.1.3. Its main reason: programs the subc supervisor did not start,
such as editor plugins, can now enroll with the vault and receive their own identity. A v0.1.3 vault answers unknown_method to
auth.enroll_propose, so the CortexKit auth plugins cannot connect to it. Upgrading fixes
that. The upgrade migrates the store forward, and v0.1.3 cannot open the result, so read
Upgrading from v0.1.3 before you start.

What's new

Consumer enrollment and scoped grants

  • A program the supervisor did not start enrolls over the same connection consumers use to
    read credentials. It proposes a name
    (auth.enroll_propose), an operator admits the name with ck auth enroll approve, and the
    consumer collects its own token by polling (auth.enroll_poll). Approval mints nothing,
    so only the process holding the request secret can collect the token. auth.enroll_rotate
    rotates a token. Operators manage enrollments with ck auth enroll list | approve | deny | revoke | reissue, and grant to enrolled:<name> like any other principal.
  • Grants name a principal, a selector and one operation. An exact selector matches one
    credential id byte for byte. A category selector matches every credential carrying that
    category and follows category assignments. Operations are separate and none implies another:
    read, sign, open (KEM keys), seal (exact selectors only), list (the account roster
    without tokens), deposit (browser cookies) and account_token (with the audience
    selector kind).
  • credential.list_scoped serves enrolled callers as well as supervised modules, and returns
    account identity only to callers holding list or read. auth.watch_scoped sends the
    current scoped view and then its changes, coalesced over 250 ms.
  • ck auth categories lists every category, how many credentials carry it, and which
    principals hold grants naming it. credential.deposit_cookie lets a granted module
    deposit a browser session cookie. credential.account_token mints short-lived account
    worker tokens for granted principals.

Provider catalog

  • API-key providers: abliteration, aiand, anthropic, baseten, charm-hyper,
    cline-pass, commandcode, deepinfra, firepass, gmi-cloud, meta, minimax-code,
    minimax-code-cn, nanogpt, novita, ollama-cloud, opencode-go, opencode-zen,
    qianfan, qwen-portal, sakana, siliconflow, siliconflow-cn, singularityapi-dev,
    singularityapi-tech, stepfun, synthetic, typesafe, umans, venice,
    vercel-ai-gateway, wafer-serverless, xiaomi-token-plan-ams, xiaomi-token-plan-cn,
    xiaomi-token-plan-sgp, yolo-auto, zenmux and zhipu-coding-plan, each stored as
    apikey:<name>.
  • Web search providers, classified web-search: apikey:tavily, apikey:kagi,
    apikey:exa, apikey:parallel, apikey:brave, apikey:firecrawl, apikey:jina and
    apikey:tinyfish.
  • apikey:inception (Mercury), apikey:cloudflare-workers-ai, and apikey:kiro, whose login
    checks the key against the provider's model list.
  • Meta: a device login, oauth:meta, alongside the apikey:meta key.
  • Gmail: oauth:gmail, an operator-owned OAuth login for sending mail.

Plan tiers and provider ids

  • ck auth set-providers attaches provider ids to a credential (up to 32), so a consumer can
    tell which providers one credential serves. They are operator metadata; the vault never
    derives them.
  • ck auth set-plan records a subscription tier. Login and refresh detect the tier for
    ChatGPT (plus, prolite, pro) and for recognised Claude profiles, and leave it unset
    rather than guess. An operator-set tier takes precedence over a detected one. Both appear in
    the scoped listing.

KEM keys: credential.open and credential.seal

  • ck auth mint-kem-key creates a vault-held X25519 key. Its public key is readable; its
    private key never leaves the vault.
  • credential.open decrypts an HPKE message addressed to that key for a principal holding
    open. credential.seal encrypts with the vault key as an authenticated sender for a
    principal holding seal on that exact key, and returns only the encapsulation and
    ciphertext.

Per-signature audit

  • A signing key minted with --audit-each-signature gets one entry in the HMAC-chained audit
    log for every signature, written before the signature is returned. If the entry cannot be
    written, no signature is returned. The flag is off by default.
  • ck auth sign signs exact payload bytes with a signing key minted with --operator-sign.
    That flag also turns on per-signature audit for the key.

Linux and Windows

  • Native master-key storage: Windows Credential Manager (per-user, DPAPI-protected) and the
    Linux Secret Service (GNOME Keyring or KWallet, already unlocked, over the session bus). A
    new vault uses its platform's store by default. A key file (--key-path or
    CK_MASTER_KEY_PATH) remains an explicit choice, for example on headless Linux, and is
    never a silent fallback when the native store is missing or locked.
  • The vault records its key choice in <data_dir>/key-source, so later runs of the daemon
    and ck auth need no override. An override that disagrees with the record is refused.
  • Owner-only files: the key file is checked on every load (on Unix a regular file owned by
    the current user with no group or other bits; on Windows the handle's owner and DACL), and
    on Windows the data directory and the vault's own files get owner-only DACLs.
  • Process hardening: on Linux both programs make themselves non-dumpable at startup; on
    Windows they restrict the process DACL.
  • ck auth login on Linux with no display goes straight to the paste flow.

Refresh cooldown

  • A consumer's stale report no longer triggers an immediate refresh if the credential was
    written less than 60 seconds ago. The current token is served, the stale mark is kept, and
    the first read after the window refreshes. A token that is expiring, empty, or shorter than
    the caller's min_ttl_ms still refreshes at once. This protects providers that revoke the
    whole token family when a refresh token is reused.

Upgrading from v0.1.3

v0.1.3 stores are at schema 9. v0.2.0 applies migrations 10 through 18 the first time either
binary opens the store. Migrations run forward only. Once migrated, v0.1.3 refuses the store
("store schema 18 is newer than this binary's 9"), so rolling back means restoring a copy
taken before the upgrade.

  1. Upgrade the supervisor first. subc-core 0.20.83 (ck 0.20.83) is the oldest
    supervisor this release is supported and tested on. If your subc is older, upgrade it
    before you install v0.2.0 rather than after.
  2. Check your grants while still on v0.1.3: run ck auth grants. Migration 10 converts
    each prefix grant to an exact grant on the one credential it covers today. A prefix grant
    that covers no credential, or more than one, makes the migration refuse
    (migration 10 refused prefix row ...), and the store is left at schema 9. Revoke such
    grants with v0.1.3's ck auth revoke-grant before upgrading, and re-create them afterwards
    as exact or category grants. Category grants carry over unchanged in reach.
  3. Stop the vault module in your supervisor.
  4. Copy the whole data directory (by default ~/.local/share/cortexkit/claustrum) to a
    place outside ~/.local/share/cortexkit, as described in
    Reading the store directly.
    Copy the directory, not store.db alone. The copy does not contain the master key; keep
    the key where it is (Backups and restore).
  5. Replace both binaries together, ck-claustrum and ck-auth. Whichever runs first
    migrates the store.
  6. If you used a key file on v0.1.3 (the only option there on Linux and Windows), keep
    CK_MASTER_KEY_PATH (or --key-path) set for the first start. The first successful key
    load records that file in key-source, and the vault keeps using it.
  7. Start the module and verify: ck-auth --version reports 0.2.0, then
    ck auth verify-audit, ck auth status and ck auth grants.

To go back, restore the copied directory together with the v0.1.3 binaries; see
Roll back.

Behaviour changes you may notice

  • ck auth grant --prefix is gone. It is refused with guidance. --selector-kind is now
    required (exact, category or audience); there is no default.
  • Selectors match differently. exact compares the credential id byte for byte, where
    v0.1.3 matched a prefix. A category selector is the bare category name (--selector <category>), not category:<name>. Existing grants are converted by migration 10 without
    changing what they reach (see step 2 above).
  • Key-source record. --key-path and CK_MASTER_KEY_PATH still work, but must agree
    with the vault's recorded key-source. A different file, or a file for a native-store
    vault, is refused with both choices named.
  • Stale reports wait out the 60-second refresh cooldown described above.
  • Devin: a token the provider will not renew now needs a fresh login; the vault no longer
    extends it locally.
  • GitHub App: an App installed on more than one account is refused at refresh instead of
    silently using the first installation, and installations are re-discovered on every
    refresh.
  • Scoped replies carry more. credential.get_scoped and credential.list_scoped accept
    an enrollment token, and list rows include provider ids, plan tier and authentication
    method. See the wire contract.

No existing ck auth verb or wire method was removed or renamed.

Windows: update ck first

subc-core 0.20.121 fixes two Windows setup bugs: ck setup claustrum failing on a clean
machine, and ck upgrade being unable to replace a running daemon. If your ck is older,
update it before anything else:

  1. Rerun the installer in PowerShell: irm https://cortexkit.io/install/win | iex. This
    replaces ck.exe with 0.20.121 or newer.
  2. Run ck upgrade.

Running ck upgrade straight from an older ck can still hit the running-daemon bug once.

Requirements

  • subc-core 0.20.83 (ck 0.20.83) or newer.
  • Platforms: macOS arm64, Linux x64, Windows x64. Each asset is built on its own platform.
  • A native key store (macOS Keychain, Windows Credential Manager, an unlocked Linux Secret
    Service) or an operator key file outside the data directory.

Assets are built on the platform they run on. Each zip has a SHA-256
sidecar holding the digest of the zip bytes.

The macOS binaries are ad-hoc signed, not notarized: a browser-downloaded
zip carries a quarantine attribute and Gatekeeper will refuse it.
Installing via curl does not apply that attribute.

claustrum does not self-initialize. Run ck auth bootstrap before enabling
the module, or the daemon will exit with 'no master key has been provisioned'.
A new vault keeps its master key in the OS key store: the Keychain on
macOS, Credential Manager on Windows, and the Secret Service (GNOME Keyring
or KWallet, already unlocked) on Linux. Where no unlocked Secret Service is
reachable, as on a headless Linux server, bootstrap with --key-path <file>
or CK_MASTER_KEY_PATH= instead: a file outside the data directory,
owned by the vault user, with owner-only permissions. A missing or locked
OS store is refused; there is no automatic fallback to a file. Bootstrap
records the choice in the vault's key-source file, so later runs of the
daemon and ck auth need no key-path override.

REQUIRES subc-core 0.20.83 OR NEWER (ck 0.20.83). Upgrade the supervisor
before installing this release.