id: CCR-2026-0009
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: qonto-assistant workload access to tenants/binky/qonto-api
status: proposed
created: '2026-07-24'
updated: '2026-08-13'
requester:
  agent: claude
  reason: >-
    qonto-assistant (QONTO-WP-0004, docs/SecurityPractice.md) needs its own
    running pod to fetch tenants/binky/qonto-api at cold-start, without
    reusing the existing human/OIDC admin lane from CCR-2026-0008 (which is
    scoped to net-kingdom-admins operators, not a workload identity). Mirrors
    CCR-2026-0003's llm-connect pattern: External Secrets Operator reads the
    KV path into a namespace-scoped Kubernetes Secret; qonto-assistant's pod
    consumes the resulting Secret, never the OpenBao token itself.
review:
  required: true
  required_approvers:
  - platform-operator
  - binky-tenant-owner
  comments: []
target:
  domain: financials
  tenant: binky
  workload: qonto-assistant
  rapp: rapp-qonto
  environment: production
  purpose: >-
    Workload (not human/admin) read access to the existing
    tenants/binky/qonto-api credential so qonto-assistant's own pod can fetch
    it via External Secrets, matching the isolation profile requested in
    qonto-assistant/docs/SecurityPractice.md #7 (I1 Reinforced minimum).
openbao:
  mount: tenants
  kv_path: tenants/binky/qonto-api
  fields:
  - API_KEY
  - API_USER
  policy_name: workload-kv-read-qonto-assistant
  policy_file: openbao/policies/workload-kv-read-qonto-assistant.hcl
  auth:
    method: kubernetes
    mount: kubernetes
    role: external-secrets-qonto-assistant
    bound_claims:
      service_account_names:
      - external-secrets
      service_account_namespaces:
      - external-secrets
    bound_claims_confirmed: false
    policies:
    - workload-kv-read-qonto-assistant
    ttl: 15m
access_frontdoor:
  type: ops-warden
  catalog_id: qonto-assistant-workload-kv
  selector: qonto-assistant workload Qonto API key
  command: warden access qonto-assistant-workload-kv --fetch API_KEY,API_USER
  resolvable: false
  readiness: pending-review
delivery:
  surface: external-secrets
  target: >-
    ExternalSecret to Secret qonto-assistant-qonto-api in the (new, dedicated)
    qonto-assistant namespace -- see
    qonto-assistant/deploy/k8s/qonto-assistant/externalsecret.yaml (draft,
    not yet applied).
risk:
  classification: high
  notes:
  - Same underlying bank credential as CCR-2026-0008; this CCR does not
    request a new secret value, only a second, workload-scoped access lane
    into the existing tenants/binky/qonto-api path.
  - The Kubernetes auth subject is the External Secrets Operator service
    account external-secrets/external-secrets, with ClusterSecretStore usage
    limited to the new qonto-assistant namespace (mirrors CCR-2026-0003's
    activity-core scoping) -- no other namespace can use this store to read
    this path.
  - qonto-assistant's own policy kernel (default-deny, no spend/volume-cost
    tools) is the downstream control on what the fetched credential is used
    for; this CCR only governs whether the pod can fetch it at all.
  - qonto-assistant's deployment isolation profile (namespace, NetworkPolicy,
    resource limits) should land before or alongside this CCR's approval, not
    after -- see qonto-assistant/deploy/k8s/qonto-assistant/.
verification:
  positive:
  - An approved qonto-assistant-namespace ExternalSecret can sync fields
    API_KEY/API_USER to Secret qonto-assistant-qonto-api without printing
    values.
  - The qonto-assistant runtime can consume the resulting Kubernetes Secret
    without exposing values (existing credentials.py env-injection path,
    unchanged).
  negative:
  - A namespace outside the approved ClusterSecretStore condition cannot use
    this store to read the path.
  - A service account outside external-secrets/external-secrets cannot
    authenticate through this OpenBao role.
  activation_conditions:
  - qonto-assistant namespace exists (see deploy/k8s/qonto-assistant/namespace.yaml,
    draft).
  - Policy and Kubernetes auth role applied with platform-admin/operator
    authority.
  - ClusterSecretStore openbao-qonto-assistant applied, scoped to the
    qonto-assistant namespace only (draft manifest alongside this CCR).
  - Positive and negative verification recorded with non-secret audit ids or
    timestamps.
  evidence: []
lifecycle:
  deactivate: Disable ops-warden catalog entry and remove or detach the
    external-secrets-qonto-assistant auth role policy. Does not affect
    CCR-2026-0008's separate human/OIDC admin lane.
  rotate: Shared with CCR-2026-0008 -- rotating the underlying API key in
    Qonto's dashboard and OpenBao rotates both access lanes simultaneously;
    no independent rotation exists for this lane alone.
  compromised: Immediately deactivate this access front door; the underlying
    key compromise/rotation procedure is CCR-2026-0008's, since both lanes
    share the same secret value.
state_hub:
  workplan_id: QONTO-WP-0004
