Skip to content

v2 stage 1 — Foundation: sovereign sidecar + on-chain identity + credentials-service worker #89

@hanwencheng

Description

@hanwencheng

GH issue body — v2 stage 1: Foundation (sovereign sidecar + on-chain identity + credentials-service worker)

Title: v2 stage 1 — Foundation: sovereign sidecar + on-chain identity + credentials-service worker

File via:

gh issue create \
  --title "v2 stage 1 — Foundation: sovereign sidecar + on-chain identity + credentials-service worker" \
  --label "documentation,enhancement" \
  --body-file docs/spec/plans/v2-issues/issue-v2-stage-1-foundation.md

Stage 1 of the v2 architecture. Replaces #87 (client-side scope enforcement in S3CredentialBackend) with a sovereign sidecar + cap-token + worker architecture. After stage 1, credentials are stored at s3://$BUCKET/bots/<actor_omni_hex>/credentials/<service>.enc (actor_omni-keyed paths, stable across K3 rotation), and the broker has zero credential-decrypt authority.

Default mode: sovereign

Stage 1 ships sovereign mode as default:

  • Operator's wallet signs chain submissions directly (msg.sender = master_wallet)
  • master_wallet appears in chain history (audit events, scope mutations)
  • Block-explorer + ENS lookups work on the operator's wallet
  • Zero third-party trust required (no relay service)

Hosted-relay mode kept as opt-in for gas subsidy + tx batching only (not for privacy — actor_omni hash exposure does NOT weaken K3 due to 2^160 address-space rainbow infeasibility).

What ships in stage 1

Daemon as sovereign sidecar

  • Localhost HTTP proxy at $XDG_RUNTIME_DIR/agentkeys-proxy.sock (Unix socket; SO_PEERCRED for caller-auth)
  • Optional TCP localhost:9090 for container deployments
  • Lazy-fetch + short TTL (5 min) credential cache
  • Required controls before any proxy operation:
    • Caller auth via SO_PEERCRED (E1) / pod namespace (E2) / TEE caller pin (E3)
    • Per-caller scope binding: (uid, binary_path) → allowed_services
    • Service/method/path allowlist (e.g., POST /v1/chat/completions only)
    • Spend quotas: req/min, req/hour, daily $ budget per (caller, service)
    • Per-call audit row → local log + ship to chain audit-relay batch
    • Fail-closed on stale broker (60s threshold)
  • Writes ~/.config/agentkeys/env with proxy URLs + placeholder auth tokens
  • Operator adds single source ~/.config/agentkeys/env to shell rc (one-time)

Broker becomes cap-mint authority

  • New endpoints: /v1/cap/cred-fetch, /v1/cap/cred-store
  • Reads scope from on-chain ScopeContract (NOT local DB)
  • Verifies cap-mint requests against on-chain SidecarRegistry — including the actor-binding check per Codex finding docs: human-readable keychain metadata in manual tests + field-name translation design note #1
  • Verifies K3 epoch against on-chain K3EpochCounter
  • Co-signs caps with K1; relays results to workers
  • Removes: /credential/* endpoints (moved to creds-service worker)
  • Removes: scope DB (moved to ScopeContract on chain)

On-chain identity layer (3 contracts on Litentry chain; reserve EVM L2 as fallback)

  • ScopeContract: scope[operator_omni][agent_omni] → {services, read_only}
    • In stage 1, scope mutations require K10 sig only (K11 requirement deferred to stage 2)
  • SidecarRegistry: device_pubkey_hash → {operator_omni, actor_omni, role, attestation, k11_cred_id (zero in stage 1)}
  • K3EpochCounter: global counter, bumped by signer-governance multisig per K3 rotation event
    • One contract, one tx per rotation (O(1) regardless of operator count)
  • All chain submissions:
    • Sovereign default: operator's wallet signs (msg.sender = master_wallet)
    • Hosted-relay opt-in: relay-wallet pays gas + batches tx; only justified by gas subsidy

credentials-service worker

  • AWS Lambda + API Gateway (default for AWS deployments) OR self-hosted Rust microservice
  • Replaces broker's /credential/* endpoints
  • Reads s3://$BUCKET/bots/<actor_omni_hex>/credentials/<service>.enc
  • AWS PrincipalTag = agentkeys_actor_omni (NOT master_wallet — stable across K3 rotation)
  • Calls signer mTLS for KEK derivation
  • Verifies cap-token (broker_sig + K10 device-key sig) + scope + K3 epoch before AES-GCM operations
  • Per-invocation CloudTrail audit; on-chain audit anchor via audit-relay batch (stage 2)

Migration from #87

  • S3CredentialBackend (today) remains for backwards compat during transition
  • Add new SidecarCredentialBackend that uses localhost proxy URL
  • Operators opt-in via --credential-backend=sidecar
  • Stage 1 completion: sidecar is the default; S3CredentialBackend deprecated

Migration steps for existing #87 deployments

  1. Land contracts (ScopeContract, SidecarRegistry, K3EpochCounter) on Litentry chain
  2. Update broker to read scope from chain
  3. Update bucket policy: PrincipalTag from agentkeys_user_walletagentkeys_actor_omni
  4. Migrate S3 prefix from bots/<wallet>/ to bots/<actor_omni_hex>/:
    • Workers do lazy on-access copy (read from old path on miss; write to new path always)
    • Operator-driven eager migration tool available
  5. Ship daemon's sidecar proxy
  6. CLI: add --credential-backend=sidecar flag
  7. Make sidecar the default after one release of soak time
  8. Remove S3CredentialBackend after one release of sidecar-as-default

Tasks

  • Daemon: localhost HTTP proxy + lazy-fetch cache + controls (caller auth, allowlist, quotas, audit, fail-closed)
  • Daemon: ~/.config/agentkeys/env writer with proxy URLs + placeholders
  • Broker: new cap-mint endpoints (/v1/cap/cred-fetch, /v1/cap/cred-store)
  • Broker: scope chain-read + SidecarRegistry chain-read + K3EpochCounter chain-read
  • ScopeContract.sol + deployment to Litentry chain
  • SidecarRegistry.sol + deployment
  • K3EpochCounter.sol + governance multisig setup
  • credentials-service Lambda variant
  • credentials-service microservice variant (Rust, axum) — parallel deliverable
  • Signer: new typed endpoints (/derive-cred-kek, /sts-credentials) + K3 epoch verification + K10 verification helper
  • Bucket policy update: PrincipalTag from agentkeys_user_wallet to agentkeys_actor_omni
  • S3 prefix migration: lazy on-access for existing creds + optional eager pass tool
  • CLI: --credential-backend=sidecar flag
  • CLI: deprecation warning for --credential-backend=s3 (today's v2 stage 1 — sovereign sidecar + on-chain identity + credentials-service worker (#89) #87)
  • Test plan: end-to-end sidecar + broker + worker + signer flow against staging deployment
  • Operator runbook: stage 1 migration steps

Dependencies

Cross-reference

Design context: see consolidated arch.md v2.
Predecessor: today's S3CredentialBackend implemented in PR #87.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions