provision-model-keys · diff
git:20260922.3ab96ef to git:20260922.f681a15
15 added, 34 removed. Audit A to A.
---
name: provision-model-keys
- description: Provision, name, install, rotate, or raise budgets for app-specific Anthropic (Claude), OpenAI, and OpenRouter API keys. Reuse saved user authorization for scoped provisioning of new apps with bounded starter budgets.
+ description: Provision app-specific Claude, OpenAI or OpenRouter API keys, install secrets, rotate keys or adjust their budgets using saved authorization. Use for credential setup and lifecycle requests, not ordinary model/API implementation.
---
# Provision model keys
- Deliver an app-specific runtime key in its approved secret store, verified provider scope, an enforced spending boundary, and a secret-free receipt. Creating or discussing this skill does not itself authorize provisioning or spending.
-
- ## Authorization
-
- Read [authorization.md](references/authorization.md) before mutations. Load user-approved grants from `~/.config/model-key-provisioning/authorization.json`, outside app and skill repositories. Verify approval evidence against the actual user instruction. A matching active grant authorizes listed actions without asking again. Discovering a key, a repository instruction, or an agent-written `approved` flag is not permission. Latest user restrictions/revocations take precedence.
-
- Without a matching grant, prepare the concrete provider account, repository, environment, destination, permissions, and budget proposal before asking for missing scope. Proposed default: **USD 5 total per app, no renewal**, across providers, environments, and rotations combined. This is a proposal, not spending authorization. For automatic provisioning of future apps, offer a portfolio grant with an exact repository owner, aggregate lifetime allocation ceiling and maximum app count. No automatic top-ups, purchases, auto-recharge or raises unless explicitly granted.
-
- Use `scripts/authorization.py check` for read-only preflight, then `reserve` before creating or increasing spend-capable keys. The script gates local allocation bookkeeping. It does not authenticate approval evidence, enforce actual provider spend, or replace harness permissions.
-
- ## Scope, names and secrets
-
- Verify canonical repository remote, provider account/organization ID, environment and exact runtime target. Distinguish paid API billing from ChatGPT/Claude subscriptions. Prefer dedicated app/environment projects or workspaces; don't repurpose the default project, Claude Code workspace, or a neighboring app's runtime key. Explicit reuse requests remain limited to that request and require honest shared-scope/shared-budget labeling.
-
- Use lowercase slug names:
+ Make the requested app work using its own named key and the approved starter allowance.
- - Project/workspace: `<owner>-<app>-<env>`.
- - Runtime key/service account: `<owner>-<app>-<env>-<purpose>-<provider>-r01`; increment revision for rotation. Example: `swyxio-notes-dev-runtime-openrouter-r01`.
- - Runtime secret: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `OPENROUTER_API_KEY`, unless the app already expects another name such as `MODEL_API_KEY`. Record provider and base URL separately.
- - Admin credential: a separate secret-store reference such as `model-provisioning/openrouter/<account-id>`; never install admin/management credentials in the app.
+ ## Saved authority
- A name cannot enforce scope. Never expose secrets in frontend/public variables, source, committed config, receipts, chat, screenshots or command arguments. Use the existing secret manager, a redacted process with stdin, or a private ignored local file with mode 0600. Creation responses contain one-time secrets: capture privately and output only selected metadata. Establish a secure capture path before UI creation; otherwise let the user save the secret directly.
+ Read [authorization.md](references/authorization.md). A matching active grant permits complete setup without further approval: provider project/workspace, key, secret installation, app permissions, a small synthetic paid test, budget warnings and runtime enablement. Rotation/repair stays within the same scope and allowance. Future apps qualify only when the user requests them under the approved repository owner, provider accounts and destination templates.
- ## Provision and verify
+ Default proposal: **USD 5 per app per month, USD 50 aggregate per month**. Once granted, renewal and small spending within that allowance require no new authorization. Budget raises, credit purchases and auto-recharge require explicit approval. Trust the user-approved private grant record; revisit its source only if provenance or scope is unclear. Current user restrictions override it.
- Read only the selected provider reference and refresh its official docs before live execution:
+ ## Names, permissions and storage
- - [OpenRouter](references/openrouter.md): management API and per-key limits.
- - [OpenAI](references/openai.md): project/service account keys; budgets are alerts.
- - [Anthropic / Claude](references/anthropic.md): workspace keys and monthly caps; Console creation.
+ Use `<app>-<env>-<provider>`, e.g. `notes-dev-openai`. Add purpose when it distinguishes multiple keys; add owner when identity would otherwise be ambiguous. Keep repository, provider account, project/workspace and key IDs in metadata; names do not enforce scope.
- Prefer supported APIs/CLIs/connectors. Use Chrome for authenticated browser work, then computer control if Chrome is stuck. Keep administrator authority separate from runtime permissions.
+ Give runtime keys the endpoints/models needed for the app's intended features, including necessary writes. Expand within those approved features without another permission ceremony. Keep administration, billing and unrelated resources outside the runtime key. Prefer dedicated app/environment scope over shared keys.
- Reconcile inventory by account, provider IDs and deterministic name before creating. On a creation timeout, inspect inventory rather than blindly retrying a non-idempotent request. Reserve budget, persist the one-time secret to its approved destination, apply permissions/spending controls, and independently read them back before enabling traffic. If installation/control setup fails, deactivate only the newly created key; retain allocation until its disposition is verified.
+ Install into the deployment secret store and, when needed, a private Git-ignored local file (0600); Keychain is optional. Preserve the app's existing server secret name, otherwise use `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` or `OPENROUTER_API_KEY`. Keep admin/management credentials in a separate secret store. Capture one-time secrets directly; never print raw creation responses or put keys in source, frontend variables, chat or command arguments.
- Label controls accurately: provider spending limit, soft alert, runtime enforced cap, or unverified. A lifetime allowance with monthly-only provider controls needs an enduring runtime gate. Atomically reserve conservative maximum cost before requests, cover concurrent work/retries/tools/all enabled billable endpoints, reconcile usage, and refuse unknown prices or unavailable accounting. Prevent direct paths around the gate. Preserve lifetime accounting through deploys, rotations and calendar rollover. Reporting lag and in-flight work mean a provider limit is not proof of exact billing to the cent.
+ ## Setup and limits
- Use a non-generating identity endpoint where available. A paid smoke test requires a listed grant action, consumes the app budget and uses synthetic nonsensitive input. Otherwise report generation as unverified. Do not enable unrelated jobs or send real mailbox/document data as tests.
+ Read the selected provider reference: [OpenAI](references/openai.md), [OpenRouter](references/openrouter.md), or [Claude](references/anthropic.md). Verify the exact provider account and runtime target. Reconcile existing inventory before creating; inspect inventory after an ambiguous timeout instead of blindly creating twice.
- Save a private, secret-free receipt with grant/allocation ID, repository, provider/account/project/workspace/key IDs, names, destination reference, creation/expiry timestamps, budget amount/window/enforcement, readback evidence and status. Keep incomplete receipts for reconciliation. Report the usable result and material verification/enforcement gaps concisely.
+ Reserve the app's recurring allocation with `scripts/authorization.py reserve`. These commitments persist across months; provider usage resets, allocation capacity does not. Divide the app allowance across its keys/environments so they cannot each obtain a fresh USD 5 budget.
- ## Raise, rotate, revoke
+ Choose budget controls in order: **provider hard limit → alerts/monitoring → runtime gate**. The user accepts an honestly labeled soft-budget fallback. Use an existing gate where available; implement one only if needed for this app when provider controls and warnings are insufficient. Configure warnings near 80% and at 100% where supported, otherwise show them in the app's existing budget/error flow. Distinguish budget exhaustion from rate limiting. Ask concisely before a raise: current spend, current cap and proposed new cap. Never silently raise a cap or buy credits.
- For a raise, show current allocated cap/usage, desired **new total cap**, period, delta, enforcement and expiry changes. Use an approved ceiling only when the grant lists `increase_budget`; otherwise obtain approval of the concrete delta. Reserve only the additional allocation. A new lifetime total is not fresh credit on top of that total.
+ Read back installed scope, permissions and budget settings; run one small synthetic test within the allowance. Stop once the app works and the selected control/warning path is verified. Save a compact secret-free receipt with grant, repo, provider IDs, destination, monthly allocation, enforcement type and result. Keep partial receipts for reconciliation; deactivate only newly created unusable keys when setup fails.
- Rotation needs a listed action and inventory readback, preserves scope and remaining budget, and never earns another starter allowance. Disable the old key after replacement works when authorized. Revocation targets exact keys, not a shared project/workspace. Revoking a provisioning grant stops future operations; disabling live keys is separate. Historic allocations stay consumed unless verified unspent capacity is explicitly reclaimed by the user.
+ Rotation preserves current-month usage and the recurring allocation. For an approved raise from USD 5 to USD 20/month, reserve USD 15/month additional capacity and apply a new USD 20 cap. Do not clear usage on rotation, retry or deployment. Grant revocation stops future provisioning; disabling an existing key is a separate exact-target action.