Skip to main content

Compliance Pack

A Compliance Pack is a self-contained ZIP bundle DriftWise produces on demand for SOC 2 Type I / Type II evidence. One click produces a portable artifact your auditor can verify offline — no DriftWise login required for them to review, no screenshot dance, no manual CSV export.

Who it's for

  • Compliance leads collecting CC7.x (continuous monitoring) and CC8.x (change management) evidence against the DriftWise-managed control surface.
  • Auditors receiving the bundle from the customer and performing walkthrough / evidence inspection.

Plan requirements

PlanAvailabilityWindow
FreeUpsell only
TeamIncluded30-day window (matches plan retention)
EnterpriseIncludedUnlimited window

Free-plan users see an upsell prompt in the Compliance tab. Backend requests from a Free-plan org return 402 Payment Required with required_feature: "audit_compliance".

Generating a pack

In the DriftWise UI, navigate to Compliance in the nav rail. Pick a period_start and period_end (server re-validates against your plan's retention window), then click Generate Compliance Pack.

Generation is asynchronous. The row appears immediately with status pending, transitions to running while the worker builds the bundle, and lands at done when the artifact is ready for download. Expect 10–30 seconds for typical windows; 12-month enterprise exports can take up to a minute.

You can also generate via API:

curl -X POST "https://app.driftwise.ai/api/v2/orgs/$ORG_ID/audit-exports" \
-H "Authorization: Bearer $OIDC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-04-01T00:00:00Z"
}'

Returns 202 Accepted with the newly-created row. Poll GET /api/v2/orgs/$ORG_ID/audit-exports/$ID until status == "done".

Auth:

  • POST /audit-exports (generate), GET /audit-exports/:id/download, and DELETE /audit-exports/:id require OIDC authentication and owner or admin role. API keys are rejected with 403. Compliance-evidence generation, download, and deletion must be attributable to a specific human — the audit log entry records the actor's user UUID.
  • GET /audit-exports (list) and GET /audit-exports/:id (row metadata) accept any org member, including API-key callers. Read- only polling from CI is a supported workflow; the actual bundle bytes are still gated on OIDC owner/admin via /download.

What's in the bundle

compliance-pack-<org-slug>-<period-start>_<period-end>.zip
├── summary.pdf ← cover letter + headline metrics (see note)
├── data.json ← structured JSON of every section
├── coverage_monthly.csv ← per-month drift coverage %
├── findings.csv ← every drift_item in the period
├── scans.csv ← scan cadence record
├── remediation_sla.csv ← average time-to-resolve per risk level
├── custom_rules.csv ← custom detection rules at period end
├── state_sources.csv ← Terraform state sources at period end
├── chain-attestation.json ← verifiable audit-log chain snapshot
├── AUDIT_LOG_VERIFY.md ← auditor's walkthrough
└── MANIFEST.txt ← SHA-256 of every other entry

summary.pdf is emitted when the drift-worker has PDF rendering enabled (DRIFTWISE_PDF_ENABLED=true, which is required in production and enforced at boot). Local-dev or test deployments without Chromium omit the PDF; every other entry — including the CSVs, data.json, chain-attestation.json, and MANIFEST.txt — still ships, and MANIFEST.txt reflects exactly the set of files present.

Integrity verification

The bundle is designed to be verifiable without DriftWise assistance:

unzip compliance-pack-acme-2026-01-01_2026-04-01.zip -d bundle/
cd bundle
shasum -a 256 -c MANIFEST.txt

Every line prints OK when the bundle is intact. A FAILED line means a file was modified after bundle creation — either in transit or locally. Re-download from DriftWise and compare.

Chain attestation

chain-attestation.json captures the audit-log chain state at bundle generation time — head_seq, head_hash_hex, and the chain verify status. An auditor independently re-runs the verify endpoint and checks that:

  • response.status == "ok"
  • response.head_seq >= attestation.head_seq (chain only grows)
  • If equal, hashes match byte-for-byte

See AUDIT_LOG_VERIFY.md inside the ZIP for the copy-paste walkthrough.

What this proves — and what it doesn't. The attestation ties the bundle to the org's live audit-log chain: when the auditor re-runs /verify, a matching head_hash at equal head_seq shows the server's chain state at generation time was authentic. Bundle files (PDF, CSVs, data.json) are tied to each other through MANIFEST.txt SHA-256s, so tampering with one file without re-running shasum -c is detectable. The bundle is NOT offline-tamper-evident on its own — it is not cryptographically signed, so the live /verify round-trip is load-bearing. Don't treat an unchecked bundle as proof; the trust chain is bundle + live verify = evidence.

Audit log events

Every lifecycle transition emits a row to admin_audit_log, and those rows themselves are part of the hash chain the attestation covers:

ActionWhenDetail
audit_export.requestedPOST /audit-exports succeeded{ "export_id": "..." }
audit_export.downloadedGET /download succeeded{ "export_id": "...", "bytes": N }
audit_export.deletedDELETE succeeded{ "export_id": "..." }

Query them via the audit log endpoint.

Rate limit

Per-org: 5 Compliance Packs / rolling 24h. Exceeding the limit returns 429 Too Many Requests with retry_after in the body. The limit exists to cap worst-case Chromium + storage cost; typical auditor workflows generate 1–3 packs per audit cycle.

Retention

Artifacts live in storage for 90 days after the enqueue (request) timestamp — expires_at is stamped at request time, not at finished_at. In practice jobs finish in seconds, so the difference is negligible; the clock starts when you click Generate. After 90 days the scheduler GC job deletes the ZIP and transitions the row to status: "expired". The row itself remains for historical reference; re-generate to download again.

What's NOT included (intentional)

  • Login / sign-in events. DriftWise delegates authentication to Casdoor; login-level telemetry is outside the admin_audit_log boundary by design. Your Casdoor or SAML IdP is the authoritative source for session records.
  • SCIM provisioning events. Event names (scim.user.provisioned, etc.) are reserved in the audit catalog, but emission from the Casdoor webhook activates only for orgs with SCIM configured. If your org doesn't use SCIM, these events never fire — which is correct, not a gap.

The summary.pdf cover letter names both exclusions explicitly so an auditor doesn't expect them and then find them missing.

Frameworks

The v1 bundle positions as SOC 2 CC7/CC8 evidence. Most controls map naturally because the underlying data (drift snapshots, scan runs, audit log, custom rules) is what SOC 2 auditors actually ask for:

  • CC7.1 / CC7.2 (system monitoring)scans.csv, coverage_monthly.csv, state_sources.csv
  • CC7.3 (incident handling)findings.csv resolution column, remediation_sla.csv
  • CC8.1 (change management authorization) → audit log excerpt via the tamper-evident chain
  • CC8.1 (change management monitoring)findings.csv, custom_rules.csv

Cross-framework mapping (ISO 27001, PCI DSS, HIPAA, CIS) is on the roadmap — see the export plan for details.

See also

  • Audit Logs — the underlying hash-chained log the bundle's attestation covers.
  • Plans & Billing — plan comparison including Compliance Pack availability.