diff --git a/crates/agentkeys-daemon/src/main.rs b/crates/agentkeys-daemon/src/main.rs index 11579b09..9b3d7a39 100644 --- a/crates/agentkeys-daemon/src/main.rs +++ b/crates/agentkeys-daemon/src/main.rs @@ -220,7 +220,9 @@ struct Args { /// W3 real-memory: the memory worker base URL (e.g. https://memory.litentry.org). /// Unset ⇒ master-memory plant/list use the in-memory fallback (dev/no-infra). - #[arg(long, env = "AGENTKEYS_MEMORY_URL")] + /// Canonical env `AGENTKEYS_WORKER_MEMORY_URL` (matches `--config-url`'s + /// `AGENTKEYS_WORKER_CONFIG_URL` + `scripts/operator-workstation.env`). + #[arg(long, env = "AGENTKEYS_WORKER_MEMORY_URL")] memory_url: Option, /// W3 real-memory: per-actor memory IAM role ARN for the STS relay (sourced from diff --git a/crates/agentkeys-mcp-server/README.md b/crates/agentkeys-mcp-server/README.md index ca1e3089..e2ef5a09 100644 --- a/crates/agentkeys-mcp-server/README.md +++ b/crates/agentkeys-mcp-server/README.md @@ -70,8 +70,8 @@ cargo run -p agentkeys-mcp-server -- \ docker build -t agentkeys-mcp-server -f crates/agentkeys-mcp-server/Dockerfile . docker run --rm -p 8088:8088 \ -e AGENTKEYS_BROKER_URL=https://broker.litentry.org \ - -e AGENTKEYS_MEMORY_URL=https://memory.litentry.org \ - -e AGENTKEYS_AUDIT_URL=https://audit.litentry.org \ + -e AGENTKEYS_WORKER_MEMORY_URL=https://memory.litentry.org \ + -e AGENTKEYS_WORKER_AUDIT_URL=https://audit.litentry.org \ -e MCP_VENDOR_TOKENS="magiclick:demo-tok" \ agentkeys-mcp-server ``` diff --git a/crates/agentkeys-mcp-server/src/config.rs b/crates/agentkeys-mcp-server/src/config.rs index cfa9989b..d31e948f 100644 --- a/crates/agentkeys-mcp-server/src/config.rs +++ b/crates/agentkeys-mcp-server/src/config.rs @@ -45,12 +45,15 @@ pub struct Cli { #[arg(long, env = "AGENTKEYS_BROKER_URL")] pub broker_url: Option, - /// Memory worker base URL. - #[arg(long, env = "AGENTKEYS_MEMORY_URL")] + /// Memory worker base URL. Canonical env `AGENTKEYS_WORKER_MEMORY_URL` + /// (legacy bare `AGENTKEYS_MEMORY_URL` still accepted as a fallback in + /// `Config::from_cli` for hosts whose `mcp.env` predates the rename). + #[arg(long, env = "AGENTKEYS_WORKER_MEMORY_URL")] pub memory_url: Option, - /// Audit worker base URL. - #[arg(long, env = "AGENTKEYS_AUDIT_URL")] + /// Audit worker base URL. Canonical env `AGENTKEYS_WORKER_AUDIT_URL` + /// (legacy bare `AGENTKEYS_AUDIT_URL` accepted as a fallback — see above). + #[arg(long, env = "AGENTKEYS_WORKER_AUDIT_URL")] pub audit_url: Option, /// Comma-separated `:` pairs that the HTTP @@ -224,14 +227,31 @@ impl Config { }, }; + // Worker base-URLs migrated to the canonical AGENTKEYS_WORKER_{MEMORY,AUDIT}_URL + // names (clap `env` above, or --memory-url / --audit-url). A remote MCP host + // deployed before this rename still carries the legacy bare names in + // /etc/agentkeys/mcp.env until its next setup-mcp-host.sh run, so accept those + // as a fallback when the canonical name is unset; the fallback drops out once + // mcp.env is rewritten with the canonical spelling. + let memory_url = cli.memory_url.or_else(|| { + std::env::var("AGENTKEYS_MEMORY_URL") + .ok() + .filter(|s| !s.is_empty()) + }); + let audit_url = cli.audit_url.or_else(|| { + std::env::var("AGENTKEYS_AUDIT_URL") + .ok() + .filter(|s| !s.is_empty()) + }); + Ok(Self { transport, backend, listen: cli.listen, mcp_endpoint: cli.mcp_endpoint, broker_url: cli.broker_url, - memory_url: cli.memory_url, - audit_url: cli.audit_url, + memory_url, + audit_url, vendor_tokens, default_daily_spend_cap_rmb: cli.default_daily_spend_cap_rmb, default_actor, diff --git a/docs/arch.md b/docs/arch.md index a8d19e78..bfcdb232 100644 --- a/docs/arch.md +++ b/docs/arch.md @@ -292,6 +292,7 @@ Pinned to disambiguate the same value showing up under different labels across c | `credential_kek` | 32-byte AES-256 key for one operator's credentials. Derived as `HKDF-SHA256(salt="agentkeys.kek-salt.v2", ikm=K3_v[epoch], info="agentkeys.user.v1" \|\| actor_omni)`. | `KEK`, `cred_kek`. | | `credential_envelope` | Wire format of one stored credential: `1B version (0x04) \|\| 1B k3_epoch \|\| 12B nonce \|\| ciphertext \|\| 16B tag`. Stored at `s3://$VAULT_BUCKET/bots//credentials/.enc` — **single-vault, master-sovereign** ([`docs/plan/single-vault-credentials.md`](plan/single-vault-credentials.md)): the operator's vault is the ONLY credentials vault. STORE is master-self only, hard-gated at BOTH the broker (`cred_store_not_master_self`, fires before any chain call) and the worker (defense-in-depth) — the former #228 agent-own vault was removed because a service-granular `cred:` fetch grant also implied store mintability, letting an agent vault a same-named key that silently shadowed the master-authorized one. A **fetch** — master-self or **delegated** (actor ≠ operator, #216) — reads that one vault: the delegated cap's verified on-chain `cred:` grant is the agent's authorization, and the S3 read runs under the caller-relayed operator-tagged STS (layer-3 IAM unchanged; agent-tagged STS cannot read the operator prefix). AAD binds `(operator_omni, vault_owner_omni = operator_omni, service, k3_epoch)`. Teardown/list stay actor-keyed (list is master-self-only; delegated teardown remains the cleanup verb for legacy pre-single-vault agent prefixes). | `envelope`, `AEAD blob`, `.enc` (S3 key suffix). | | `vault_bucket` / `memory_bucket` / `config_bucket` / `audit_bucket` / `email_bucket` / `payment_audit_bucket` | One S3 bucket per data class per §17. Per-actor prefix at `bots//` (config is per-operator + master-only, #201). | `$VAULT_BUCKET`, `$MEMORY_BUCKET`, `$CONFIG_BUCKET`, `$AUDIT_BUCKET`, `$EMAIL_BUCKET`, `$PAYMENT_AUDIT_BUCKET`. | +| `AGENTKEYS_WORKER__URL` | **The canonical env-var family for a worker's base URL** — `AGENTKEYS_WORKER_MEMORY_URL`, `AGENTKEYS_WORKER_AUDIT_URL`, `AGENTKEYS_WORKER_CONFIG_URL`, … Defined in `scripts/operator-workstation.env`; read by the daemon, MCP server, and CLI. (`AGENTKEYS_BROKER_URL` stays bare — the broker is not a worker.) | Legacy bare `AGENTKEYS_MEMORY_URL` / `AGENTKEYS_AUDIT_URL` — retired in code; the hosted MCP server still **accepts them as a fallback** until `setup-mcp-host.sh` rewrites its `mcp.env`. | | `policy` / `scope` / `namespace` / `category` / `service` (the authorization vocabulary) | **Distinct pipeline stages, NOT synonyms:** **policy** (human intent, off-chain, `DataClass::Config`) → COMPILE → **scope** (on-chain `(operator, actor, serviceHash)` grant, `AgentKeysScope` §19) over **categories/attributes** (the classifier's tag) → **service** (the signed cap string; for memory `service = memory:`, where **namespace** = the memory category). The unifying unit is the **policy attribute (category)** ([`research/universal-gate-pattern.md`](research/universal-gate-pattern.md) four primitives). Full table + pipeline: [`wiki/policy-scope-namespace.md`](wiki/policy-scope-namespace.md). | Confusions this resolves: "scope" used to mean "namespace" or "policy"; **"tag" = classifier *category*** (≠ the AWS **PrincipalTag** of §17 / [`wiki/tag-based-access.md`](wiki/tag-based-access.md)). | The most common confusion this table resolves: **`actor_omni` ≠ `current_master_wallet`**. The first is the immutable cryptographic anchor (Layer 1); the second is the rotation-volatile chain identity (Layer 2). Both are derived from K3, but only `actor_omni` survives K3 rotation unchanged. PrincipalTag, S3 paths, AAD, scope index — everywhere v2 keys identity off — uses `actor_omni`, never `current_master_wallet`. diff --git a/scripts/setup-mcp-host.sh b/scripts/setup-mcp-host.sh index 8b6227f4..eb565a02 100755 --- a/scripts/setup-mcp-host.sh +++ b/scripts/setup-mcp-host.sh @@ -374,8 +374,8 @@ MCP_TRANSPORT=mcp-endpoint MCP_BACKEND=http MCP_ENDPOINT=${XIAOZHI_ENDPOINT} AGENTKEYS_BROKER_URL=https://broker.litentry.org -AGENTKEYS_MEMORY_URL=https://memory.litentry.org -AGENTKEYS_AUDIT_URL=https://audit.litentry.org +AGENTKEYS_WORKER_MEMORY_URL=https://memory.litentry.org +AGENTKEYS_WORKER_AUDIT_URL=https://audit.litentry.org EOF ) else @@ -388,8 +388,8 @@ MCP_ENDPOINT=ws://127.0.0.1:${RELAY_PORT}/mcp_endpoint/mcp/?token=${TOKEN} # These three are placeholders — paste the live broker / worker URLs in # after running setup-broker-host.sh on the same host. AGENTKEYS_BROKER_URL=https://broker.litentry.org -AGENTKEYS_MEMORY_URL=https://memory.litentry.org -AGENTKEYS_AUDIT_URL=https://audit.litentry.org +AGENTKEYS_WORKER_MEMORY_URL=https://memory.litentry.org +AGENTKEYS_WORKER_AUDIT_URL=https://audit.litentry.org EOF ) fi