ワンクリックで
ax-provider-credentials
Use when modifying credential storage — database-backed credential provider in src/providers/credentials/
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Use when modifying credential storage — database-backed credential provider in src/providers/credentials/
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use when modifying logging, error handling, or diagnostic messages — logger setup, transports, error diagnosis patterns in src/logger.ts and src/errors.ts
Use when modifying the trusted host process — server orchestration, message routing, IPC handler, request lifecycle, event streaming, file handling, plugin loading, or agent delegation in src/host/
Use when modifying the sandboxed agent process — runner, IPC client, local/IPC tools, tool catalog, prompt building, or identity loading in src/agent/
Use when modifying agent sandbox isolation -- Docker, Apple Container (macOS), or k8s providers in src/providers/sandbox/
Use when modifying IPC protocol between host and agent — schemas, actions, length-prefix framing, or Zod validation in ipc-schemas.ts and ipc-server.ts
AX project architecture and coding skills - use sub-skills for specific subsystems (agent, host, cli, providers, etc.)
| name | ax-provider-credentials |
| description | Use when modifying credential storage — database-backed credential provider in src/providers/credentials/ |
Credential providers store and retrieve secrets (API keys, tokens) for the host process. Credentials never enter agent containers -- the host injects them via the credential-injecting proxy at request time.
Defined in src/providers/credentials/types.ts:
| Method | Signature | Purpose |
|---|---|---|
get | (service: string, scope?: string) => Promise<string | null> | Retrieve a credential by service name and scope |
set | (service: string, value: string, scope?: string) => Promise<void> | Store a credential |
delete | (service: string, scope?: string) => Promise<void> | Remove a credential |
list | (scope?: string) => Promise<string[]> | List stored service names for a scope |
Credentials for skills live in a tuple-keyed table skill_credentials (agent_id, skill_name, env_name, user_id). user_id = '' is the agent-scope sentinel (shared across users); a non-empty user_id is per-user. Turn-time lookup prefers the user_id match and falls back to ''.
The legacy credential_store table (scope column) is retained for backward compat during the Phase 5-8 cutover. Dual-write from the approve handler keeps both populated until Step 8 removes the legacy table.
Tuple store API in src/host/skills/skill-cred-store.ts:
put({agentId, skillName, envName, userId, value}) — upsertget({agentId, skillName, envName, userId}) — prefers user_id match, falls back to ''listForAgent(agentId) — every row for the agent (turn-time injection reads this)listEnvNames(agentId) — distinct envNames for the agent (Approvals hint probe)| Name | File | Storage Mechanism | Security Level |
|---|---|---|---|
| database | src/providers/credentials/database.ts | Shared DatabaseProvider (SQLite or PostgreSQL) with process.env fallback | Medium -- durable across restarts, k8s-ready |
The provider exports create(config: Config): Promise<CredentialProvider>. Registered in src/host/provider-map.ts static allowlist (SC-SEC-002).
The database provider also accepts CreateOptions with a database field (like audit/database). Its migration is in src/providers/credentials/migrations.ts and uses migration table credential_migration.
Scoped storage: Uses the scope column in credential_store table. UNIQUE(scope, env_name) index handles isolation. process.env fallback only applies for unscoped (global) calls.
Modifying the credential provider:
src/providers/credentials/database.ts — implements all 4 methods: get, set, delete, list — all with optional scope parametersrc/host/provider-map.ts static allowlist (SC-SEC-002)tests/providers/credentials/database.test.ts including scoped isolation testssafePath() for any file path construction from inputDuring sandbox launch (server-completions.ts), the host builds a CredentialPlaceholderMap:
deps.skillCredStore.listForAgent(agentId) returns every row for the agent.userId match comes before the '' sentinel.credentialMap.register(envName, realValue) generates an opaque ax-cred:<hex> placeholder (or writes the real value to credentialEnv when web_proxy is disabled).credentialMap.toEnvMap() is merged into the sandbox's extraEnv — agents see placeholders, not real keys.src/host/web-proxy.ts) uses credentialMap.replaceAllBuffer() on decrypted HTTPS traffic to swap placeholders for real values.Semantic tightening (Phase 5+): Only credentials DECLARED by an enabled skill get injected. The old "inject everything in credential_store" loop is gone.
Key files:
src/host/credential-placeholders.ts — CredentialPlaceholderMap classsrc/host/skills/skill-cred-store.ts — SkillCredStore tuple-keyed APIsrc/host/server-completions.ts — turn-start injection loopWhen a skill requires a credential that isn't in the store, the host prompts the user via a non-blocking fire-and-forget flow (no blocking — sandbox is not held idle):
server-completions.ts detects missing credential during sandbox launchcredential.required event via event bus (contains envName, sessionId, agentName, userId)setSessionCredentialContext(sessionId, {agentName, userId})) so the provide endpoint can resolve scopes laterevent: credential_required with {envName, sessionId} → client shows modal → POST /v1/credentials/provide with {sessionId, envName, value}POST /admin/api/credentials/provide with {sessionId, envName, value}agentName/userId from session context, stores at correct scopesClient API is simple: The client only needs to echo back the sessionId from the SSE event. The host resolves agentName/userId internally — clients never see or send scope information.
Key files:
src/host/session-credential-context.ts — Session context registry (setSessionCredentialContext/getSessionCredentialContext)src/host/server-request-handlers.ts — SSE event emission + POST /v1/credentials/provide endpointsrc/host/server-admin.ts — POST /admin/api/credentials/provide endpointWhen the agent calls the standalone request_credential tool (credential_request IPC action, envName param), the handler:
envName in the session's requestedCredentials map{ ok: true, available: boolean } — the agent knows whether to tell the user the credential is still neededFile: src/host/ipc-handlers/skills.ts
ax-cred:<hex> placeholder tokens as env vars, not real credentials.(agent_id, skill_name, env_name, user_id) is the PK on skill_credentials. user_id = '' is the agent-scope sentinel; real userId for per-user rows.get() does NOT fall back to process.env. Only unscoped (global) calls do.CredentialPlaceholderMap is created before the web proxy starts and populated later (after workspace paths are set). Since it's passed by reference, the proxy sees updates.credential.required event and return early. No blocking, no idle sandboxes, no cross-replica coordination needed.{ ok: true, available: boolean } so the agent can inform the user when a credential is still needed.src/host/registry.ts./v1/credentials/provide endpoint accepts {sessionId, envName, value}. The host looks up agentName/userId from an in-memory session context map (populated during completions). If no session context is found (e.g., no prior credential.required event), the credential is stored at global scope for backward compat.setSessionCredentialContext() is called when the completion starts and is NOT cleared in the finally block — the user provides credentials after the completion returns.