id: CCR-2026-0012
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: Scaleway scoped backup object-storage key
status: applied
created: '2026-08-14'
updated: '2026-08-14'
requester:
  agent: grok
  reason: >-
    RESOURCE-WP-0002 T04 needs a renewable, revocable, project-scoped
    Scaleway backup key in OpenBao. Custody is the resource-control
    procuring identity, not a Barman-specific application. First
    consumer is rapp-postgres (Secret platform-pg-backup-s3). The
    bootstrap key (CCR-2026-0011) must not be the runtime key.
review:
  required: true
  required_approvers:
  - platform-operator
  comments:
  - at: '2026-08-14T17:30:00+00:00'
    reviewer: bernd.worsch
    decision: approved
    comment: >-
      Approved in chat (Grok session): CCR-2026-0012 and “the backup
      key is in bao.” Founder used ACCESS_KEY/SECRET_KEY field names.
target:
  domain: financials
  tenant: railiance
  workload: backup
  rapp: rapp-postgres
  environment: production
  purpose: >-
    Object-store credentials for Railiance backup destinations.
    Secret keys ACCESS_KEY and SECRET_KEY (projected to Kubernetes as
    ACCESS_KEY_ID / ACCESS_SECRET_KEY). Org and project ids are
    non-secret companions. APPLICATION_ID can be added later for a
    bucket policy. Endpoint, bucket, prefix, and region stay on
    reef-storage.
openbao:
  mount: platform
  kv_path: platform/workloads/railiance/backup/object-storage
  fields:
  - ACCESS_KEY
  - SECRET_KEY
  - DEFAULT_ORGANIZATION_ID
  - DEFAULT_PROJECT_ID
  policy_name: workload-kv-read-backup-object-storage
  policy_file: openbao/policies/workload-kv-read-backup-object-storage.hcl
  auth:
    method: kubernetes
    mount: kubernetes
    role: external-secrets-backup-object-storage
    bound_claims:
      service_account_names:
      - external-secrets
      service_account_namespaces:
      - external-secrets
    bound_claims_confirmed: false
    policies:
    - workload-kv-read-backup-object-storage
    ttl: 15m
access_frontdoor:
  type: ops-warden
  catalog_id: backup-object-storage
  selector: resource-control scoped backup access
  command: warden access backup-object-storage --fetch ACCESS_KEY
  resolvable: false
  readiness: applied-pending-verify
delivery:
  surface: external-secrets
  target: >-
    ClusterSecretStore openbao-backup-object-storage (first namespace
    condition: databases) → ExternalSecret databases/platform-pg-backup-s3
    → Secret platform-pg-backup-s3 (ACCESS_KEY_ID / ACCESS_SECRET_KEY
    projected from ACCESS_KEY / SECRET_KEY). Drafts live
    under railiance-platform/argocd/platform-addons/openbao-secretstore/
    and rapp-postgres/helm/platform-pg-backup-s3.externalsecret.yaml.
    Do not apply until this CCR is approved and the KV values are real.
risk:
  classification: high
  notes:
  - Scaleway policies attach to the IAM application, not to one API key.
    Application resource-control must hold only backup-scoped keys.
  - The runtime key can write and delete backup objects. Compromise can
    destroy recovery points or fill the bucket.
  - The bootstrap key (CCR-2026-0011) must stay off this application and
    be revoked after this key works.
  - Do not enable continuous WAL archiving until the empty-archive
    preflight passes (RESOURCE-WP-0002 T05).
  - Values must not appear in Git, State Hub, logs, or chat.
verification:
  positive:
  - Field names present on the KV path; values not printed.
  - An approved databases-namespace ExternalSecret can project ACCESS_KEY
    and SECRET_KEY to Secret platform-pg-backup-s3 as ACCESS_KEY_ID and
    ACCESS_SECRET_KEY.
  - The scoped key can list/put/delete backup prefixes on the procured
    bucket.
  negative:
  - A token without this policy cannot read the KV path.
  - A namespace outside the ClusterSecretStore condition cannot use the store.
  - A second, unused key (or revoked key) cannot access the bucket.
  - The scoped key cannot create compute resources.
  activation_conditions:
  - Platform-operator approves this CCR.
  - Founder creates or reuses IAM application resource-control, binds
    policy Scoped backup access, mints the API key of that name, then
    puts ACCESS_KEY and SECRET_KEY in OpenBao. Done 2026-08-14.
  - ESO store and ExternalSecret applied only after values are real.
lifecycle:
  deactivate: Disable the catalog entry, delete consumer ExternalSecrets,
    revoke the Scoped backup access API key. Keep application
    resource-control if other backup keys remain.
  rotate: Overlap-first. Put a new key in OpenBao, wait for ESO refresh,
    revoke the old Scaleway key.
  compromised: Revoke the Scoped backup access key and the bootstrap key
    at Scaleway, rotate this path, review bucket contents, open incident
    follow-up.
state_hub:
  workplan_id: RESOURCE-WP-0002
  task_id: RESOURCE-WP-0002-T04
