Skip to content
Deployment
Skill

/audit-compliance

Audit trail and compliance on Control Plane. Use when the user asks about audit logs, who changed what, change tracking, audit contexts, writing custom audit events, security monitoring, SOC 2, HIPAA, or PCI compliance.

From plugin
ai-plugin
1030 skills2 agents2 commands1 MCP
Install
$ npx -y skills add controlplane-com/ai-plugin --skill audit-compliance --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/audit-compliance

Context preview

The summary Claude sees to decide when to auto-load this skill.

Audit trail and compliance on Control Plane. Use when the user asks about audit logs, who changed what, change tracking, audit contexts, writing custom audit events, security monitoring, SOC 2, HIPAA, or PCI compliance.

SKILL.md

audit-compliance.SKILL.md
name: audit-compliance
description: "Audit trail and compliance on Control Plane. Use when the user asks about audit logs, who changed what, change tracking, audit contexts, writing custom audit events, security monitoring, SOC 2, HIPAA, or PCI compliance."

Audit Trail & Compliance

> **Tool availability:** some MCP tools named here live in the `full` toolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with `?toolsets=full` (or use the `cpln` CLI fallback). Reads work on every profile via the generic `list_resources` / `get_resource` tools; `delete_resource` is on every profile except `readonly`.

Every mutation on every Control Plane resource — via Console, CLI, API, Terraform, Pulumi, or MCP — is recorded automatically in an append-only, tamper-proof audit trail; nothing to configure. Most tasks are answering **"who changed what, when"** with `mcp__cpln__query_audit_events`. Custom audit contexts exist for one purpose only: letting your own workloads write their own audit events.

The model

Events live in **audit contexts** (org-scoped namespaces):

| Context | Origin | Holds | |---|---|---| | `cpln` — built-in, one per org | `builtin` | every platform mutation, automatically | | custom — user-created | `default` | only events your workloads POST to it |

  • Platform events go **only** to `cpln`; custom contexts never receive them — querying one returns only what workloads wrote.
  • The `origin` value `default` means "user-created", not "default for the org".
  • **No audit context can be deleted** — there is no delete in the API, CLI, MCP, or Console, and `terraform destroy` only removes the context from Terraform state; events are append-only. The built-in `cpln` context can't be edited either. Creating a context is permanent.

Event anatomy

Each event carries `id`, `eventTime` / `postedTime` / `receivedTime`, `requestId`, `context` (`org`, audit-context `name`, `location`, `gvcAlias`, `podId`, `remoteIp`, `eventSource`), `subject` (`name`, `email`), `resource` (`id`, `type`, `name`, `data` — the resource snapshot), `action.type` (`create` / `edit` / `delete` / `exec`), and `result` (`status`, `message`).

Secret snapshots are scrubbed: `resource.data` for a secret never includes the payload, so the audit trail itself stores no secret values.

Querying events

MCP — `query_audit_events`

// all workload mutations in the last 24h
{ "kind": "workload", "org": "my-org", "since": "24h" }

// who changed a specific secret in the last 30 days
{ "kind": "secret", "name": "db-password", "since": "30d" }

// several policies in one call (merged, newest-first)
{ "kind": "policy", "names": ["admin", "readonly"], "since": "7d" }

// everything one subject touched across all secrets
{ "kind": "secret", "subject": "user@example.com", "since": "30d" }

// a custom context — kind matches the resource.type your workload wrote
{ "kind": "order", "context": "my-app-audit", "since": "7d" }

// a past window — relative from/to mean "that long ago from now"
{ "kind": "workload", "org": "my-org", "from": "3mo", "to": "1mo" }

Inputs: `kind` (required) · `name` **or** `names[]` (max 25, mutually exclusive; omit both for every resource of the kind) · `gvc` (**required** when `kind` is `workload` / `identity` / `dbcluster` / `volumeset` and a name is given) · `subject` (user email, full link, or bare service-account name) · `context` (default `cpln`) · `since` (default `7d`) **or** `from` / `to` (ISO 8601, or a relative duration meaning that long ago — units `m`, `h`, `d`, `w`, `mo`, `y`; months are `mo`, not `M`) · `limit` (default 50, max 1000). Results are merged, sorted newest-first, truncated to `limit`.

CLI

Every resource type has an `audit` subcommand with the same flags:

cpln workload audit my-app --gvc my-gvc --org my-org --since 24h
cpln secret audit db-password --org my-org --subject user@example.com
cpln workload audit --org my-org --since 24h     # omit the ref: every workload in the org
cpln workload audit my-app --gvc my-gvc \
  --from 2025-10-23T07:00:00Z --to 2025-10-24T07:00:00Z
cpln workload audit my-app --gvc my-gvc --from now-3M --to now-1M   # window: 3 months ago to 1 month ago

Flags: `--since` (default `7d`; mutually exclusive with `--from`/`--to`), `--from`/`--to` (ISO 8601, a relative duration like `7d` or `3M`, or `now-` prefixed like `now-30d` — the CLI accepts `M` for months; MCP only accepts `mo`), `--subject`, `--context` (default `cpln`), `--max` (default 50).

Managing audit contexts

  • **Create:** `mcp__cpln__create_audit_context` (`name`; `description` defaults to the name; `tags`). CLI: `cpln auditctx create --name my-app-audit --org my-org`.
  • **Read:** `mcp__cpln__list_resources` (kind="auditctx") / `mcp__cpln__get_resource` (kind="auditctx").
  • **Edit:** `mcp__cpln__edit_audit_context` — description and tags only; `origin` is immutable; the built-in `cpln` context rejects edits. CLI: `cpln auditctx update my-app-audit --set description="..."`.
  • **Delete:** impossible by design (see The model) — don't promise it.

Writing events from a workload

1. **Create a context** — `mcp__cpln__create_audit_context`. 2. **Create an identity** — `mcp__cpln__create_identity`. 3. **Grant `writeAudit`** — `mcp__cpln__create_policy` with `targetKind: auditctx`, the context in `targetLinks`, and a binding of `writeAudit` to the identity (binding shape: **access-control** skill). 4. **Attach the identity** to the workload via `spec.identityLink` — `mcp__cpln__update_workload`. 5. **POST from inside the container:**

curl -H "Content-Type: application/json" \
  -X POST "http://127.0.0.1:43000/audit/org/${CPLN_ORG}/auditctx/my-app-audit?async=true" \
  -d '{"resource": {"id": "order-1234", "type": "order"}, "action": {"type": "refund"}}'
  • The sidecar serves `127.0.0.1:43000` in every workload pod and attaches the workload's identity automatically — no token or auth h
Read more
Ships withai-plugin

Run containerized workloads across AWS, GCP, Azure, OCI, and your own hardware under one API.

Get the whole plugin

Other skills on ai-plugin.