Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions adoption/credential-inventory.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,26 @@
"rotation": "Create a new key at https://platform.claude.com/settings/keys, run tools/credentials/open_credential_terminal.sh anthropic-api and type replace at the hidden prompt, then delete the old key in the Console.",
"notes": "Added 2026-10-08 on the owner's direction: one Console API key, in a dedicated workspace with a spend limit, for local tools that have no identity provider (Anthropic's Console guidance). GitHub Actions use Anthropic workload identity federation through claude-code-action v1's federation inputs instead, so no Anthropic key is stored in GitHub. ANTHROPIC_API_KEY stays in must_not_be_set: exported in a shell it would override every Claude Code session's native sign-in, so it is injected per command only through credential_run.py."
},
{
"id": "anthropic-admin",
"label": "Anthropic Claude Console Admin API key",
"class": "provider_api_key",
"status": "optional",
"lane": "foundation",
"store": {
"kind": "private_env_file",
"path_template": "${XDG_CONFIG_HOME:-$HOME/.config}/native-agent-stack/anthropic-admin.env"
},
"variables": ["ANTHROPIC_ADMIN_KEY"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the Admin variable to the secret guard

Once an owner stores this full-access Admin key and runs a command through credential_run.py, the Claude command guard does not recognize ANTHROPIC_ADMIN_KEY: guard.check("echo $ANTHROPIC_ADMIN_KEY") and Python environment lookups both return no refusal, allowing commands to access or transform the key beyond the output masker's coverage. This also makes tests.test_secret_path_guard.SecretPathGuardTests.test_inventory_secret_names_are_all_guarded fail because the new inventory variable is absent from scripts/hooks/secret_path_guard.py::SECRET_NAMES; update the guard and its associated registrations alongside the inventory entry.

Useful? React with 👍 / 👎.

"optional_variables": [],
"pointer_variables": [],
"loaders": [
"tools/credentials/credential_run.py anthropic-admin -- <command>"
],
"environment_only_consumers": [],
"rotation": "The owner creates a replacement in Claude Console Admin keys, stores it through tools/credentials/open_credential_terminal.sh anthropic-admin, then revokes the previous key in the Console.",
"notes": "Inventory metadata only, added 2026-10-08 for CC 080508Z row 9. The owner stores the key later with tools/credentials/set_credential.py anthropic-admin. Only an organization admin can create a Claude Console Admin API key; Console Admin keys have no selectable scopes and carry full access to endpoints that accept them (https://platform.claude.com/docs/en/manage-claude/admin-api-keys). ANTHROPIC_ADMIN_KEY is the variable in Anthropic's official Usage and Cost API x-api-key examples (https://platform.claude.com/docs/en/manage-claude/usage-cost-api). No key value or live Admin API integration is included."
},
{
"id": "grafana-admin",
"label": "Local Grafana admin account and secret key (self-generated)",
Expand Down
2 changes: 1 addition & 1 deletion adoption/hooks/claude/SHA256SUMS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
c0979c22a701538a267e8f6b980dd2228e79db0c0b2b6bcf8d91dd2681735fb7 currency-due-notice.py
2a5f087f2c10437bab302e19469ae6b2e715828083a8bae07a7b177540b63e0e effort-default-guard.py
fd516d8b78de7e3a9da4917c8d126fc71d7ab216a014bb28fb8bd189d6b0fb7b ../../../scripts/hooks/secret_path_guard.py
a66433868a4ccf5daf1849cbf0c63de02a2ce367a28c652c664d84d535fbf99e ../../../scripts/hooks/secret_path_guard.py
d456fa0474c2aeb5662ae49dc9e489de1b47167303c306f1ce3cef84bd09b0cc token-lanes-block.md
a6858cbd0ddf171614b0f967dffc1e51817368960b8fcd938901cf03d0525d09 token-lanes-block.builder.md
71ce1ea778e04c3b888135182c832fd0f15f6985dcdaad69e779e40e39914509 token-lanes-block.main.md
Expand Down
14 changes: 14 additions & 0 deletions docs/secret-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -2523,3 +2523,17 @@ assertion on the mutant, in a scratch copy under `/tmp`.
and the network allowlist the runners need). The measurement must include a
check that sandboxed commands cannot reach the user systemd bus
(`systemd-run --user`).

## Anthropic Admin API inventory entry

The optional `anthropic-admin` foundation entry contains metadata only. Its
private file template is `<store>/anthropic-admin.env`, where `<store>` is
`${XDG_CONFIG_HOME:-$HOME/.config}/native-agent-stack`; its variable is
`ANTHROPIC_ADMIN_KEY`, as shown in the official
[Usage and Cost API examples](https://platform.claude.com/docs/en/manage-claude/usage-cost-api).
The owner stores the key later with
`tools/credentials/set_credential.py anthropic-admin` in their own terminal.
Anthropic's [Admin key documentation](https://platform.claude.com/docs/en/manage-claude/admin-api-keys)
requires an organization admin to create a Console Admin key and states that
Console keys have no selectable scopes: they carry full access to endpoints that
accept Admin API keys. No Admin API client or authenticated probe is introduced.
18 changes: 9 additions & 9 deletions manifests/evidence.json
Original file line number Diff line number Diff line change
Expand Up @@ -5036,8 +5036,8 @@
},
{
"path": "adoption/credential-inventory.json",
"sha256": "2115b56acbcbf6268ae98ef9aef49325d3b9ebdefc67225393e5ccceca708266",
"bytes": 25686
"sha256": "bbab281700a7ba2d8569bef8f82e38c097b0f9a3e840832249b6ba81500e1a6f",
"bytes": 27127
},
{
"path": "adoption/hardware-profiles.json",
Expand All @@ -5046,7 +5046,7 @@
},
{
"path": "adoption/hooks/claude/SHA256SUMS",
"sha256": "d13a02c67ef551437c21de11b85352cda58ac6a1cfac1167336158fc992d11b5",
"sha256": "1d7af5962eb220f86c6f74d6b26b15ff5daabf514929f61db2827658b285bc2e",
"bytes": 1137
},
{
Expand Down Expand Up @@ -18172,8 +18172,8 @@
},
{
"path": "docs/secret-storage.md",
"sha256": "61039915b9fe31c5931f3cffbd60bdc686fa3433a495ce91dd56501bb67b0ef7",
"bytes": 184073
"sha256": "077f66be1488afb0d6d850f46ce6b3cc346eea66da4211d75bd8b1df37b6b8d5",
"bytes": 184938
},
{
"path": "docs/stack.md",
Expand Down Expand Up @@ -56662,8 +56662,8 @@
},
{
"path": "scripts/hooks/secret_path_guard.py",
"sha256": "fd516d8b78de7e3a9da4917c8d126fc71d7ab216a014bb28fb8bd189d6b0fb7b",
"bytes": 296975
"sha256": "a66433868a4ccf5daf1849cbf0c63de02a2ce367a28c652c664d84d535fbf99e",
"bytes": 296998
},
{
"path": "scripts/host_receipts.py",
Expand Down Expand Up @@ -57337,8 +57337,8 @@
},
{
"path": "tests/test_credential_run.py",
"sha256": "3cb959529bb6b26848e66cbc60de9560820964f78430df44027246b1b54d8338",
"bytes": 128524
"sha256": "cca5a7a9f79efdddc568c83b1adfcaa8e3fde7e9a99f531d1e6b5d9eb30f8192",
"bytes": 128543
},
{
"path": "tests/test_credential_status.py",
Expand Down
2 changes: 1 addition & 1 deletion scripts/hooks/secret_path_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def gh_status_token_scan(text: str) -> bool:
"DATABENTO_API_KEY", "TYPESAFE_API_KEY", "OMNIROUTE_API_KEY", "MASSIVE_API_KEY",
"GF_SECURITY_ADMIN_PASSWORD", "GF_SECURITY_SECRET_KEY",
"GH_TOKEN", "GITHUB_TOKEN", "HF_TOKEN", "HUGGING_FACE_HUB_TOKEN", "OPENAI_API_KEY",
"ANTHROPIC_API_KEY",
"ANTHROPIC_API_KEY", "ANTHROPIC_ADMIN_KEY",
"CODEX_API_KEY", "OPENROUTER_API_KEY", "MISTRAL_API_KEY", "QDRANT_API_KEY",
"PREFECT_API_KEY", "MC_API_KEY", "MSB_API_KEY", "PAPERCLIP_API_KEY",
"TWS_USERNAME", "TWS_PASSWORD", "TWS_ACCOUNT", "IBKR_ACCOUNT_ID",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_credential_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import set_credential as writer # noqa: E402

INJECTABLE_IDS = {"alpaca-paper", "alpaca-paper-2", "sec-contact", "databento", "typesafe", "omniroute", "tavily",
"claude-oauth-token", "canary-e2e", "anthropic-api"}
"claude-oauth-token", "canary-e2e", "anthropic-api", "anthropic-admin"}
NOT_INJECTABLE_IDS = ("grafana-admin", "nativestack-generation-key", "openhands-session", "claude-native",
"codex-native", "gh-native", "huggingface-native", "huggingface-native-stored", "ibkr-gateway",
"github-actions")
Expand Down
Loading