{
  "schema": "aaes/capability-pack/1",
  "provider": "redis",
  "version": "1.0.0",
  "description": "Redis Cloud REST API: read subscriptions and databases, create and update subscriptions and databases, and delete databases or entire subscriptions.",
  "notes": "The endpoint host 'redis-cloud.invalid' is a reserved non-production placeholder (an RFC 2606 reserved TLD): substitute the Redis Cloud REST API host the deployment actually uses (the documented API endpoint URI is https://api.redislabs.com/v1) before enabling, in every endpoint, in the resource locator and in every egress allowlist entry — the allowlist matches exactly, so all three must be substituted together, and substitution is a required deployment step. SUBSCRIPTION_ID and DATABASE_ID in the endpoint paths are placeholders the deployment binds to concrete resources before enabling.\n\nTwo-header contract: Redis Cloud authenticates EVERY API request with two headers — the account key in 'x-api-key' and a personal user key in 'x-api-secret-key' — and this pack declares the 'headers' injection mode, which parses the single stored JSON object and places both documented headers on every request; the credential note defines the exact stored value. The API is disabled on all accounts by default and must be enabled before any capability here works.\n\nProvisioning is asynchronous: create, update and delete operations return a task the caller polls (GET /v1/tasks/{taskId}) — this pack registers the initiating operations only, and task polling is a read of the same class the deployment may register separately.\n\nDocumented exclusions — this pack does not register: user and role management (creating users or assigning roles under /v1/users and ACL endpoints), payment methods and billing operations, cloud account management (cloud accounts hold the customer's own cloud-provider credentials used for Bring-Your-Own-Cloud provisioning), database backup scheduling and especially database import (an import overwrites current database content — destructive to live data and deserving its own review), CRDB / Active-Active subscription management, SSO and SAML configuration, and system log export.\n\nThe vendor's API reference renders as a client-side Redoc UI, but the OpenAPI 3.0.1 specification backing it was retrieved verbatim for this review and every registered route, method, operationId and the per-operation two-header security requirement were checked against it; the asynchronous TaskStateUpdate responses match the pack's provisioning note.",
  "credential": {
    "secret_ref_id": "secret-ref-redis-cloud-api-keys",
    "custody": "customer_vault",
    "inject": "headers",
    "inject_headers": [
      "x-api-key",
      "x-api-secret-key"
    ],
    "note": "Redis Cloud REST API credentials for the customer's own account, held in the client's own secret manager. Authentication requires TWO headers on every request: the account key as 'x-api-key' and a user (secret) key as 'x-api-secret-key'. The stored material is ONE exact value: a single JSON object of the form {\"x-api-key\":\"<account key>\",\"x-api-secret-key\":\"<user key>\"}. Presentation: this registration declares the 'headers' injection mode with inject_headers [x-api-key, x-api-secret-key]; the connector parses the stored object and places each named header on the request, refusing material whose keys are not exactly the declared pair and refusing any caller-supplied spelling of either header, so the two-header contract is what the injector implements.\n\nIssuance: the API is disabled by default; enabling it generates the account key once, and changing or deleting the account key requires contacting Redis support — there is no self-serve rotation of the account key. User keys are personal keys issued to users holding the Owner, Viewer, Billing admin or Logs viewer role, are shown only once at creation, and may be scoped to a CIDR allow list of source IPs.\n\nLeast privilege: create a dedicated user for this integration with the minimum role that covers the enabled capabilities (a Viewer-role key cannot perform the writes), issue it its own user key so system-log audit attributes requests to this integration, and set the CIDR allow list to the executor's egress addresses.\n\nExpiry and revocation: the reviewed documentation describes no automatic expiry; a user key stays valid until it is deleted in the console (or the owning user is removed), and disabling the ability to create NEW keys does NOT invalidate already-issued keys — revocation means deleting each issued key, and account-key replacement goes through support. Renewal and rotation ownership sits with an external deployment process; the executor injects the stored values verbatim and performs no key lifecycle itself.\n\nExecutor hygiene: the values must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "redis.cloud.subscriptions.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "read"
      ],
      "resource_id": "redis-cloud-account",
      "description": "List the subscriptions on the account: names, cloud providers, regions and status. The registered path covers the collection read only — single-subscription reads (GET /v1/subscriptions/{id}) are not registered.\n\nThe host is a reserved placeholder: substitute the real Redis Cloud API host before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.databases.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions/SUBSCRIPTION_ID/databases",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "read"
      ],
      "resource_id": "redis-cloud-account",
      "description": "List the databases in one subscription: names, memory limits, endpoints and status. Database endpoints reveal connection topology; database content is never exposed by this management API. The registered path covers the collection read only. SUBSCRIPTION_ID is a placeholder the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.subscription.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "create",
        "deploy"
      ],
      "resource_id": "redis-cloud-account",
      "description": "Create a subscription and provision live, billable infrastructure. The unrestricted body selects the cloud provider, regions, payment method reference, and initial database plan. Review ongoing costs through deployment budget controls; this file does not cap provider charges.\n\nProvisioning is asynchronous: the response identifies a task to poll. Registered as create and deploy at R3. Enforce any restriction to smaller plans separately; the registration does not enforce that intention.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.database.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions/SUBSCRIPTION_ID/databases",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "create",
        "deploy"
      ],
      "resource_id": "redis-cloud-account",
      "description": "Create one database in a subscription.\n\nThe request body is an unrestricted database definition — memory limit, throughput, modules, replication, persistence and the database password are settable — so the capability carries the full create effect; a password in the body is secret material the executor must keep out of logs exactly like the API keys themselves. Provisioning is asynchronous. Creating a database provisions live, billable infrastructure, so the capability declares create and deploy at the minimum R3 tier. SUBSCRIPTION_ID is a placeholder the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.database.update",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions/SUBSCRIPTION_ID/databases/DATABASE_ID",
      "method": "PUT",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "update",
        "deploy"
      ],
      "resource_id": "redis-cloud-account",
      "description": "Update a database's memory limit, throughput, alerts, replication, security settings, or password. The update body is unrestricted within the provider schema. A new password is secret material and must stay out of logs.\n\nResizing changes live, billable capacity, so the capability declares update and deploy at R3. The reviewed OpenAPI specification does not establish whether password changes disconnect existing clients or whether shrinking a plan can evict data. Verify both against the live deployment before relying on either outcome.\n\nBind SUBSCRIPTION_ID and DATABASE_ID before enabling. Review every permitted effect of the requested configuration change.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.database.delete",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions/SUBSCRIPTION_ID/databases/DATABASE_ID",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "delete"
      ],
      "resource_id": "redis-cloud-account",
      "description": "Delete one database. Deleting a database destroys its content — data not covered by a backup is gone, and re-creating a database later is a new database, not an undo of this call. Delete is one of the designated actions requiring human approval and registers at the minimum R3 tier.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. Deletion is asynchronous (the response is a task to poll). SUBSCRIPTION_ID and DATABASE_ID are placeholders the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "redis.cloud.subscription.delete",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "redis-cloud.invalid"
      ],
      "endpoint": "https://redis-cloud.invalid/v1/subscriptions/SUBSCRIPTION_ID",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-redis-cloud-api-keys",
      "inject": "headers",
      "inject_headers": [
        "x-api-key",
        "x-api-secret-key"
      ],
      "actions": [
        "delete"
      ],
      "resource_id": "redis-cloud-account",
      "description": "Delete a subscription. Verified prerequisite from the vendor's OpenAPI operation description (deleteSubscriptionById, retrieved verbatim): a subscription cannot be deleted while any databases remain in it — the deployment must delete every database first (registered separately above) — and deleting the subscription stops its billing; this registration claims NO cascade deletion of databases by this call. Delete is one of the designated actions requiring human approval and registers at the minimum R3 tier.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. Policy can raise the tier above the minimum. Deletion is asynchronous (the response is a task to poll). SUBSCRIPTION_ID is a placeholder the deployment binds before enabling.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "redis-cloud-account",
      "kind": "api",
      "locator": "https://redis-cloud.invalid/v1",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-23",
    "sources": [
      "https://redis.io/docs/latest/operate/rc/api/get-started/ (retrieved 2026-09-21)",
      "https://redis.io/docs/latest/operate/rc/api/get-started/use-rest-api/ (retrieved 2026-09-21)",
      "https://redis.io/docs/latest/operate/rc/databases/delete-database/ (retrieved 2026-09-21)",
      "https://redis.io/docs/latest/operate/rc/api/api-reference/openapi.json (retrieved 2026-09-23)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
