{
  "schema": "aaes/capability-pack/1",
  "provider": "dbt",
  "version": "1.0.0",
  "description": "dbt Cloud Administrative API v2: read jobs, runs and environments, create and update job definitions, trigger job runs (deploy-equivalent), and cancel runs.",
  "notes": "The endpoint host 'dbt-cloud.invalid' is a reserved non-production placeholder (an RFC 2606 reserved TLD): substitute the customer's own dbt access URL before enabling — dbt serves the Administrative API from the account's unique access URL — current dbt accounts are issued cell-based prefix URLs (for example abc123.us1.dbt.com; emea.dbt.com for EMEA multi-tenant, au.dbt.com for APAC, and vanity URLs for single-tenant/VPC deployments), listed in Account settings below the Account information pane, while the legacy multi-tenant host cloud.getdbt.com is documented as slated for future removal, 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.\n\nACCOUNT_ID, JOB_ID and RUN_ID in the endpoint paths are placeholders the deployment binds to concrete resources before enabling. Triggering a job run is treated as deploy-equivalent in this pack: a dbt job run compiles and executes the project's models against the target data platform — it changes what the warehouse serves — so dbt.job.run.trigger registers the deploy action at the minimum R3 tier, not as an ordinary execute.\n\nThis pack registers Administrative API v2 routes only: dbt documents v3 as the recommended newer API with a smaller route set, and the deployment should re-review when migrating. The interactive v2 endpoint reference (docs.getdbt.com/dbt-cloud/api-v2) is a client-side-rendered explorer that did not yield retrievable operation content in this review; the registered routes follow the long-documented v2 URL shapes (jobs, runs, environments, POST.../jobs/{id}/run/ to trigger, POST.../jobs/{id}/ to update, POST.../runs/{id}/cancel/ to cancel) and each route was verified on 2026-09-21 against the retrieved dbt documentation and corroborating official sources listed in the review block (see the review record).\n\nScheduled execution is provider-side: a job's cron schedule fires inside dbt Cloud and never traverses an AAES capability, which is exactly why job create and update themselves declare the deploy verb — dbt.job.run.trigger governs manual API triggers only.\n\nExcluded operations: service account token or personal access token issuance and deletion (credential lifecycle stays in Account settings under direct human control), user invitation and group or permission-set management, connections (which carry warehouse credentials — writing a connection writes the database sign-in itself), repository and git credential management, account settings and billing, audit-log access, run artifact downloads (artifacts contain compiled SQL and run results — sensitive payloads deserving their own review), the Discovery (metadata) API, the Semantic Layer API, and all v3 endpoints.",
  "credential": {
    "secret_ref_id": "secret-ref-dbt-service-token",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A dbt service account token for the customer's own account, held in the client's own secret manager. The stored material must be the complete Authorization header value — scheme, one separating space, then the token — and the injector injects the stored value verbatim. Header format: the fetched user-tokens page explicitly shows personal access tokens used as 'Authorization: Bearer <your-token>'; the fetched service-tokens page does not state the wire scheme for service account tokens, so 'Bearer <token>' is registered here as the expected-but-unverified scheme for service tokens and must be confirmed against the live reference before enabling.\n\nIssuance: service tokens are created in Account settings > Service Tokens by an account admin, are shown only once at creation, belong to the account rather than to any user, and carry the permission sets the issuer assigns.\n\nLeast privilege: assign the minimum permission sets for the capabilities actually enabled — dbt's own sets map cleanly (Read-only or Job Viewer for the reads, Job Admin for job create and update, Job Runner for triggering runs) — and scope them to specific projects rather than all projects where the deployment allows; Account Admin tokens have full read+write on the account and this pack does not need one.\n\nExpiry and revocation: the reviewed documentation describes no automatic expiry — a token remains valid until it is deleted in Account settings, and dbt's rotation guidance is to create a replacement token with the same permissions, put it in place, and only then delete the old token; older tokens remain valid until deleted, so disabling the ability to create new tokens does not invalidate already-issued ones.\n\nRotation ownership sits with an external deployment process; the executor performs no token lifecycle itself. Personal access tokens (which inherit a human user's permissions) are documented for individual use — prefer service account tokens for this integration so access does not track one employee's account.\n\nExecutor hygiene: the value 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": "dbt.jobs.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/jobs/",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "List the job definitions in the account: names, schedules, environment references and execution settings.\n\nThe registered path covers the collection read only — single-job reads are not registered.\n\nACCOUNT_ID is a placeholder the deployment binds before enabling; the host is a reserved placeholder to substitute with the account's access URL.",
      "requires_review": true
    },
    {
      "capability_id": "dbt.runs.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/runs/",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "List job runs in the account: statuses, trigger causes, git references and timing. Run records can name the user or token that triggered them; this pack registers the class as internal on the deployment's account metadata — reclassify if the deployment treats trigger attribution as personal data.\n\nThe registered path covers the collection read only; run artifact downloads are deliberately not registered (see the pack notes).",
      "requires_review": true
    },
    {
      "capability_id": "dbt.environments.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/environments/",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "List the environments in the account: names, deployment types and connection references.\n\nThe registered path covers the collection read only. Environment records reference connections but never expose the stored warehouse credentials.\n\nACCOUNT_ID is a placeholder the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "dbt.job.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/jobs/",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "deploy"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "Create one job definition.\n\nThe request body is an unrestricted job spec — environment, execution steps, schedule, triggers and settings are all settable — so the registered capability carries the full create effect, and an installer's intention to create only unscheduled jobs is not a restriction the registration can enforce. A created job with an active schedule will later execute models against the data platform entirely provider-side: dbt's own scheduler fires the run, and that execution never traverses dbt.job.run.trigger or any other AAES capability, so the deploy-class effect is incurred at job-creation time and the capability declares create and deploy at the minimum R3 tier.\n\nACCOUNT_ID is a placeholder the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    },
    {
      "capability_id": "dbt.job.update",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/jobs/JOB_ID/",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "update",
        "deploy"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "Update one job definition. The v2 API updates a job by POSTing to the job resource (not PUT or PATCH), and the body is an unrestricted job spec — steps, schedule and triggers are all rewritable — so the capability carries the full update effect, including pointing an existing scheduled job at different steps. Editing a scheduled job re-arms provider-side execution of whatever the new spec names: dbt's scheduler fires inside dbt Cloud without traversing dbt.job.run.trigger or any other AAES capability, so the capability declares update and deploy at the minimum R3 tier.\n\nACCOUNT_ID and JOB_ID are placeholders the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    },
    {
      "capability_id": "dbt.job.run.trigger",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/jobs/JOB_ID/run/",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "deploy"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "Trigger a run of one job. A dbt job run compiles and executes the project's models against the target data platform — it changes what the warehouse serves — so triggering is deploy-equivalent and registers the deploy action at the minimum R3 tier; deploy is one of the designated actions requiring human approval.\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.\n\nRequest limits: the trigger body is unrestricted and can override the job's saved configuration (for example the git branch and the execution steps), so the governed effect is a deploy of whatever the body names, not merely the job's stored definition — an installer's intention to send an empty body is not a restriction the registration can enforce. The run is asynchronous: this call starts it, and dbt.run.cancel governs stopping it.\n\nACCOUNT_ID and JOB_ID are placeholders the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "dbt.run.cancel",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "dbt-cloud.invalid"
      ],
      "endpoint": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID/runs/RUN_ID/cancel/",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-dbt-service-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "dbt-cloud-account",
      "description": "Cancel a queued or running job. Already executed steps are not rolled back. Interrupting a production deployment can leave warehouse models partially built, and a new run does not undo the cancellation. The historical run record remains.\n\nClassification: delete, minimum R3, because cancellation irreversibly terminates the run’s in-flight execution. Bind ACCOUNT_ID and RUN_ID before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "dbt-cloud-account",
      "kind": "api",
      "locator": "https://dbt-cloud.invalid/api/v2/accounts/ACCOUNT_ID",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://docs.getdbt.com/docs/dbt-cloud-apis/admin-cloud-api (retrieved 2026-09-21)",
      "https://docs.getdbt.com/docs/dbt-cloud-apis/service-tokens (retrieved 2026-09-21)",
      "https://docs.getdbt.com/docs/dbt-cloud-apis/user-tokens (retrieved 2026-09-21)",
      "https://docs.getdbt.com/blog/making-dbt-cloud-api-calls-using-dbt-cloud-cli (retrieved 2026-09-21)",
      "https://docs.getdbt.com/docs/cloud/about-cloud/access-regions-ip-addresses (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
