Testland
Browse all skills & agents

soc2-evidence-collector

Build-an-X for SOC 2 Type II evidence collection and auditor-facing packaging - per-Trust-Services-Criterion test artifacts (Common Criteria CC1.1 - CC9.2; plus Availability A1, Confidentiality C1, Processing Integrity PI1, Privacy P1 - P9 if in scope); auto-collection from CI logs + audit trails + access logs + change-management records; alignment with Vanta / Drata / Secureframe evidence shapes; observation-period sampling. Cross-framework evidence packaging (control-evidence matrix, timestamped bundles, chain-of-custody notes per NIST SP 800-72 - also for ISO 27001 / HIPAA / PCI DSS / GDPR / FedRAMP) lives in references/evidence-packaging.md. Use when the team is preparing for SOC 2 Type II audit and needs continuous evidence collection, or when any audit engagement requires auditor-ready evidence packages built from automated test output.

Install with skills.sh (any agent)

npx skills add testland/qa --skill soc2-evidence-collector
View source

soc2-evidence-collector

Overview

Scope decision - which Trust Services Criteria (TSC) this collector must cover:

CategoryTSC sectionsRequired?
Common CriteriaCC1 - CC9 (35 sub-criteria)Always required
AvailabilityA1Optional (recommended for SaaS uptime claims)
ConfidentialityC1Optional (typical for B2B SaaS)
Processing IntegrityPI1Optional (common for transaction-processing SaaS)
PrivacyP1 - P9Optional (common when handling PII at scale)

Type II is assessed over a 3 - 12 month observation period, so every in-scope control needs continuous evidence available for auditor sampling, not a point-in-time snapshot.

This is a build-an-X workflow - the per-criterion evidence collection script, not a standalone tool. Pair with Vanta / Drata / Secureframe (commercial GRC platforms) for evidence storage + auditor-facing dashboards.

When to use

  • Pre-audit: Type II observation period started; need continuous evidence.
  • Pre-pre-audit: identifying which controls + evidence are testable vs require manual attestation.
  • Post-finding remediation: a previous audit flagged an evidence gap.
  • Adopting a GRC platform (Vanta/Drata/Secureframe) and need evidence-feed configuration.

Step 1 - Identify in-scope criteria

Most SaaS engagements include CC + Availability + Confidentiality. Privacy criteria add when GDPR/CCPA also in scope. Processing Integrity adds for fintech / data-processing SaaS. The full per-criterion scope-decision table is in references/evidence-source-map.md.

Step 2 - Auto-collect evidence per criterion

Map each control to one or more automatable evidence sources; the full control-to-evidence-source table is in references/evidence-source-map.md.

okta_client, aws_iam, github_org, and slack in the examples are injected client interfaces - thin wrappers you provide over the vendor SDKs (okta-sdk-python, boto3, PyGithub, slack_sdk), not pip-importable modules.

Example collector script:

# evidence/cc6_1_logical_access.py
import okta_client, datetime, json

def collect_cc6_1_evidence(start_date, end_date):
    """Per CC6.1: collect user-access audit events for the period."""
    events = okta_client.get_audit_events(
        type='user.session.start',
        start_date=start_date,
        end_date=end_date,
    )
    evidence = {
        'control_id': 'CC6.1',
        'period_start': start_date.isoformat(),
        'period_end': end_date.isoformat(),
        'evidence_type': 'user_access_logs',
        'sample_size': len(events),
        'events': events[:100],   # auditor sample
        'collected_at': datetime.datetime.utcnow().isoformat(),
        'collector': 'soc2-evidence-collector v1.0',
    }
    with open(f'evidence/cc6_1_{start_date.date()}_{end_date.date()}.json', 'w') as f:
        json.dump(evidence, f, indent=2)

Step 3 - Per-control test patterns

Beyond raw evidence collection, write tests that verify the control operates correctly:

def test_cc6_3_offboarded_user_has_no_active_sessions():
    """CC6.3: deprovisioned users must lose all access immediately."""
    user = User.objects.get(email='alice@example.com')
    deprovision(user)

    # Verify across all systems:
    assert not okta_client.user_has_active_sessions(user)
    assert not aws_iam.user_exists(user.aws_username)
    assert not github_org.is_member(user)
    assert not slack.is_member(user)
    # Audit log records the deprovisioning event:
    assert AuditLog.objects.filter(
        actor='hr-system',
        action='deprovision',
        subject=user.email,
    ).exists()

These tests run in CI; their pass/fail history is itself evidence for the auditor.

Step 4 - GRC platform alignment

Default: Vanta - the broadest native-integration coverage (AWS / Okta / GitHub / GSuite / etc.) means the auto-collected evidence (Step 2) only needs to fill gaps the integrations don't cover. Use the alternatives when Vanta doesn't fit:

PlatformUse when
Vanta (default)Standard SaaS stack with mainstream identity / cloud / source-control providers
DrataMulti-framework engagement (SOC 2 + ISO 27001 + HIPAA) where Drata's templates lead
SecureframeBudget-constrained engagement where Vanta's pricing is prohibitive

Across all three, evidence ingest format is platform-specific but the auto-collected JSON (Step 2) feeds the platform's manual-upload UI when no native integration exists for your tooling.

Step 5 - Observation period sampling

Type II auditors typically request:

  • Population list (all instances of a control event during the period - e.g., all PRs merged, all access-grants)
  • Sample (auditor selects 25 - 40 random instances)
  • Per-sample evidence (the specific logs, tickets, approvals)

Your evidence collector should support both:

  • Population queries (SELECT * FROM audit_log WHERE date BETWEEN ...)
  • Per-instance evidence retrieval (full context for one event)

Step 6 - Continuous-monitoring controls

Some controls are continuous (e.g., CC7.1 threat detection) - the evidence is an alert-history feed, not point-in-time samples.

Pattern: daily collector cron job that:

  1. Queries the source system for the previous day's events
  2. Stores in append-only evidence storage (S3 with versioning, immutable)
  3. Records collector-run metadata (when, what, how many records)

Continuity gaps in collector runs are themselves audit findings - make collector failures alert-worthy.

Step 7 - Package evidence for the auditor

Raw collected evidence (Steps 2 - 6) still needs assembling into the deliverable an auditor or GRC platform receives: the control-evidence matrix, bounded log excerpts, chain-of-custody notes (SHA-256 hashed, per NIST SP 800-72), and a deterministic archive. The full cross-framework packaging workflow - it also handles ISO 27001, HIPAA, PCI DSS, GDPR, and FedRAMP control IDs - is in references/evidence-packaging.md; GRC-platform delivery and CI automation of the whole run is in references/grc-delivery-and-ci-automation.md.

Step 8 - End-to-end recipe

For each in-scope criterion:

  1. ✅ Map criterion to evidence source(s)
  2. ✅ Implement automated collector (Step 2)
  3. ✅ Write per-control test (Step 3)
  4. ✅ Wire evidence into GRC platform (Step 4)
  5. ✅ Verify continuous-collection has no gaps (Step 6)
  6. ✅ Package the evidence for delivery (Step 7)
  7. ✅ Run a mock auditor query (request a sample; verify response is complete + timely)

Worked example

The observation period opens and CC6.3 (access deprovisioning) is in scope. The collector exports offboarding tickets daily; the per-control test test_cc6_3_offboarded_user_has_no_active_sessions runs in CI. A mock auditor sample pulls one departed employee: the ticket and the Okta session-revoke event line up, but the test fails because the ex-employee is still an org member in github_org. GitHub was never wired into the deprovisioning job. The team adds it, the test goes green, and the passing run plus the daily offboarding export becomes the CC6.3 evidence the auditor samples.

Anti-patterns

Anti-patternWhy it failsFix
Manual evidence collection onlyDoesn't scale across observation period; misses sampling intervalsAutomated collector (Step 2)
Trust the auditor will only sample what we expectAudit fails on unexpected sample requestContinuous full-population collection (Step 6)
Evidence stored in mutable storageTampering risk; audit invalidatedAppend-only / immutable storage (Step 6)
Test pass-history not preservedLoses control-effectiveness evidencePersist test results for the period
Skip mock-audit dry runsFirst real audit reveals gapsMock-audit before observation period (Step 8)

Limitations

  • This is a build-an-X workflow. Tests use the team's existing test framework + cloud APIs.
  • SOC 2 has many criteria; this skill is a starting framework, not a complete control library.
  • Trust Services Criteria evolve (current TSP 2017, revised 2022); pin version per audit engagement.
  • GRC platforms are commercial; OSS alternatives (e.g., comply-soc2 / Drata-compatible scripts) exist but are less polished.
  • This skill doesn't replace a SOC 2 readiness consultant.

References

  • aicpa.org/topic/audit-assurance/audit-and-assurance-greaterthan-suitable-trust-services-criteria - AICPA Trust Services Criteria (paywalled; free abstract)
  • Cross-framework evidence packaging (carries the NIST SP 800-72 chain-of-custody + ISACA citations): references/evidence-packaging.md
  • GRC-platform delivery + CI automation (carries the PCI DSS retention citation): references/grc-delivery-and-ci-automation.md
  • vanta.com/solutions/soc-2 - Vanta SOC 2 product
  • drata.com/grc-central/soc-2 - Drata SOC 2 reference
  • secureframe.com/hub/soc-2 - Secureframe SOC 2 hub
  • gdpr-test-patterns, hipaa-test-patterns, audit-trail-test-author - sister test-pattern catalogs

Evidence packaging - auditor-facing evidence packages

View source (opens in new window)

Evidence packaging - auditor-facing evidence packages

Companion reference for soc2-evidence-collector. The host skill harvests raw per-criterion evidence; this workflow assembles that output (from any framework - SOC 2, ISO 27001, HIPAA, PCI DSS, GDPR, FedRAMP) into auditor-ready packages: control-evidence matrix, timestamped bundles, chain-of-custody notes.

Overview

Auditors need more than passing tests. They require structured artifacts that map each control to verified outcomes, carry timestamps, and establish chain of custody. Per the NIST Computer Security Resource Center glossary (csrc.nist.gov/glossary/term/chain_of_custody, sourced NIST SP 800-72), chain of custody is "a process that tracks the movement of evidence through its collection, safeguarding, and analysis lifecycle by documenting each person who handled the evidence, the date/time it was collected or transferred, and the purpose for the transfer."

Per ISACA's Interactive Glossary (isaca.org/resources/glossary), an artifact is "a form of objective evidence that is an output of the work being performed and the process being followed." Both definitions anchor this skill: the output is objective, output-of-work artifacts with documented custody - not raw logs and not mere coverage reports.

This workflow differs from its neighbors:

ComponentScope
soc2-evidence-collector (host skill)SOC 2 TSC-specific: harvests raw Okta/IDP/CI logs per TSC criterion
audit-trail-test-authorAuthors tamper-evident audit-log tests per framework
compliance-coverage-scoringRead-only gap analysis: scores coverage without producing artifacts
This referenceCross-framework: assembles auditor-ready packages from any test output

When to use

  • An audit engagement opens (SOC 2 Type II, ISO 27001 surveillance, PCI DSS annual ROC, HIPAA OCR inquiry, GDPR supervisory authority request).
  • A GRC platform requests evidence upload for controls that have no native integration.
  • CI now produces test results but they are not yet mapped to control IDs.
  • A previous audit finding cited "insufficient evidence" for a control that is actually tested.

Step 1 - Build the control-to-test map

Start by resolving which test (or test suite) owns each in-scope control. Controls come from the applicable framework:

FrameworkControl catalog
SOC 2AICPA Trust Services Criteria 2017 (rev. 2022 points of focus) - CC1-CC9, A1, C1, PI1, P1-P9
ISO 27001:2022Annex A controls (cited by ID: A.5 through A.8)
PCI DSS v4.0.1Requirements 1-12 and associated testing procedures
HIPAA Security Rule45 CFR Part 164 Subpart C safeguards (Administrative, Physical, Technical)
GDPRArt. 5(2), Art. 24, and Art. 30 accountability obligations per gdpr-info.eu
FedRAMP / NIST 800-53 Rev 5AU, AC, CM, SI, IR, and other control families

Produce a YAML or JSON mapping file, not a spreadsheet. Spreadsheets cannot be diff-reviewed or version-controlled cleanly:

# control-map.yaml
controls:
  - id: CC6.1            # SOC 2 Trust Services Criterion
    framework: soc2
    description: "Logical and physical access controls"
    tests:
      - suite: access_control_tests
        test_id: test_mfa_enforced_for_all_admin_accounts
      - suite: access_control_tests
        test_id: test_offboarded_user_revoked_within_sla
  - id: "ISO-A.8.3"       # ISO 27001:2022 Annex A
    framework: iso27001
    description: "Information access restriction"
    tests:
      - suite: rbac_tests
        test_id: test_role_least_privilege_enforced
  - id: PCI-10.2.1        # PCI DSS v4.0.1 Requirement 10
    framework: pci_dss
    description: "Audit log entries generated per 10.2.1"
    tests:
      - suite: audit_log_tests
        test_id: test_all_required_event_types_logged

One control may reference multiple tests. One test may satisfy multiple controls. Both are valid; record them.

Step 2 - Run tests and capture structured results

Test output must be machine-readable. Ad-hoc terminal output is not evidence. Accepted formats: JUnit XML, pytest JSON report (via pytest-json-report), Jest JSON (via --json), or any format parseable by the evidence assembler in Step 4.

# pytest with JSON output (pytest-json-report)
pytest --json-report --json-report-file=results/test-run-$(date -u +%Y%m%dT%H%M%SZ).json

# Jest with JSON output
npx jest --json --outputFile=results/test-run-$(date -u +%Y%m%dT%H%M%SZ).json

# JUnit XML (e.g., from Maven / Gradle / Robot Framework)
# output path depends on build tool - pass to Step 4 parser

Timestamp the file name at collection time (UTC). The collection timestamp is the first chain-of-custody data point.

Step 3 - Collect supporting evidence artifacts

Automated test results are the primary evidence. Supporting artifacts provide auditors with context:

Screenshots (UI controls tests)

# In Playwright / Selenium tests, save on pass as well as failure:
def capture_evidence_screenshot(page, control_id, test_name):
    path = f"evidence/{control_id}/{test_name}_{datetime.utcnow().isoformat()}.png"
    page.screenshot(path=path)
    return path

Log excerpts (access / audit / system logs)

Excerpts must be bounded and labeled. Unbounded log dumps are noise that increases auditor workload, not evidence:

def extract_log_excerpt(log_source, start_utc, end_utc, control_id):
    """Extract the log window relevant to a control test run."""
    return {
        "control_id": control_id,
        "log_source": log_source,
        "window_start": start_utc.isoformat(),
        "window_end": end_utc.isoformat(),
        "lines": fetch_log_lines(log_source, start_utc, end_utc),
        "collected_at": datetime.utcnow().isoformat(),
        "collector": "evidence-packaging",
    }

CI pipeline exports

Export the CI run as a permanent artifact (GitHub Actions: actions/upload-artifact, GitLab: artifacts:paths, CircleCI: store_artifacts). The artifact URL or download reference goes into the chain-of-custody record (Step 5).

Step 4 - Assemble the control-evidence matrix

The matrix is the auditor's index. It maps every in-scope control to its evidence files with pass/fail status and collection metadata.

import json, datetime, pathlib

def build_evidence_matrix(control_map_path, test_results_path, artifact_dir):
    control_map = load_yaml(control_map_path)
    test_results = load_json(test_results_path)
    matrix = []

    for control in control_map["controls"]:
        row = {
            "control_id": control["id"],
            "framework": control["framework"],
            "description": control["description"],
            "status": "PASS",
            "tests": [],
            "artifacts": [],
        }
        for test_ref in control["tests"]:
            result = find_test_result(test_results, test_ref["suite"], test_ref["test_id"])
            row["tests"].append({
                "test_id": test_ref["test_id"],
                "outcome": result["outcome"],      # PASS / FAIL / SKIP / ERROR
                "duration_ms": result["duration"],
                "run_at": result["timestamp"],
            })
            if result["outcome"] != "PASS":
                row["status"] = "FAIL"
            # Attach any per-test artifact files
            for artifact in glob_artifacts(artifact_dir, test_ref["test_id"]):
                row["artifacts"].append(str(artifact))

        matrix.append(row)

    output = {
        "generated_at": datetime.datetime.utcnow().isoformat() + "Z",
        "generator": "evidence-packaging",
        "controls": matrix,
    }
    pathlib.Path("evidence/control-evidence-matrix.json").write_text(
        json.dumps(output, indent=2)
    )
    return output

Render the matrix as both JSON (machine-readable for GRC platform upload) and Markdown (human-readable for auditor review):

def render_matrix_markdown(matrix):
    lines = [
        "# Control-Evidence Matrix",
        f"Generated: {matrix['generated_at']}",
        "",
        "| Control ID | Framework | Description | Status | Tests | Artifacts |",
        "|---|---|---|---|---|---|",
    ]
    for c in matrix["controls"]:
        tests = ", ".join(t["test_id"] for t in c["tests"])
        artifacts = ", ".join(c["artifacts"])
        lines.append(
            f"| {c['control_id']} | {c['framework']} | {c['description']} "
            f"| {c['status']} | {tests} | {artifacts} |"
        )
    pathlib.Path("evidence/control-evidence-matrix.md").write_text("\n".join(lines))

Step 5 - Write chain-of-custody notes

NIST SP 800-72 (the source of the chain-of-custody definition used above) requires documenting each person who handled the evidence, the date/time of collection or transfer, and the purpose of the transfer. Apply this to each evidence file:

{
  "evidence_file": "evidence/CC6.1/test_mfa_enforced_20260604T143000Z.json",
  "control_id": "CC6.1",
  "collected_at": "2026-06-04T14:30:00Z",
  "collected_by": "ci-runner:github-actions:run-12345",
  "collection_method": "automated-test-result-export",
  "ci_run_url": "https://github.com/org/repo/actions/runs/12345",
  "artifact_url": "https://github.com/org/repo/actions/runs/12345/artifacts/67890",
  "transferred_to": "GRC platform evidence upload",
  "transferred_at": "2026-06-04T15:00:00Z",
  "transferred_by": "alice@example.com",
  "purpose": "SOC 2 Type II audit evidence submission - observation period Q2 2026",
  "hash_sha256": "abc123...",
  "notes": "Test run triggered by merge to main; no manual intervention."
}

Hash each artifact file (SHA-256) and record the hash in the custody note. Any tampering after collection breaks the hash and invalidates the artifact. This is the automated-evidence equivalent of the forensic-evidence integrity requirement in NIST SP 800-72.

Step 6 - Bundle the evidence package

The evidence package is the deliverable the auditor or GRC platform receives. Standard layout:

evidence-package-<engagement>-<date>/
  README.txt                          # engagement context, collection period, contacts
  control-evidence-matrix.json        # Step 4 machine-readable matrix
  control-evidence-matrix.md          # Step 4 human-readable matrix
  chain-of-custody/
    custody-<control-id>.json         # Step 5 per-control custody notes
  artifacts/
    <control-id>/
      <test-name>_<timestamp>.json    # test result excerpt
      <test-name>_<timestamp>.png     # screenshot (if applicable)
      <test-name>_<timestamp>.log     # log excerpt (if applicable)
  raw/
    test-run-<timestamp>.json         # full test results export (Step 2)

Produce the bundle as a deterministic archive (tar + gzip or zip with stable sort order) so the archive hash is reproducible from the same inputs. Record the archive hash in the final custody note.

# Reproducible archive (GNU tar with --sort)
tar --sort=name -czf \
  "evidence-package-${ENGAGEMENT}-$(date -u +%Y%m%d).tar.gz" \
  evidence-package-*/
sha256sum "evidence-package-${ENGAGEMENT}-$(date -u +%Y%m%d).tar.gz" \
  > "evidence-package-${ENGAGEMENT}-$(date -u +%Y%m%d).tar.gz.sha256"

Delivery and CI automation - deep reference

Once the package is bundled (Step 6), deliver it to the GRC platform and automate the whole run in CI. Both operational steps - the per-platform manual upload paths (Vanta, Drata, Secureframe) and the CI workflow with its PCI DSS 12-month retention window - live in grc-delivery-and-ci-automation.md (opens in new window).

GDPR accountability note

GDPR Art. 5(2) (gdpr-info.eu/art-5-gdpr) places the burden of proof on the controller: it "shall be responsible for, and be able to demonstrate compliance with, paragraph 1." Art. 24 (gdpr-info.eu/art-24-gdpr) requires controllers to "implement appropriate technical and organisational measures to ensure and to be able to demonstrate that processing is performed in accordance with this Regulation." Art. 30 (gdpr-info.eu/art-30-gdpr) requires maintaining a written record of processing activities available to supervisory authorities on request. The evidence package is the primary mechanism for satisfying all three provisions when controls are tested by automated means.

Anti-patterns

Anti-patternWhy it failsFix
Attaching full CI logs instead of excerptsHigh noise, low signal; auditors rejectBound log excerpts to the test window (Step 3)
No control-ID mappingAuditor cannot match evidence to controlsBuild control-map.yaml before collecting (Step 1)
Evidence in mutable storageTampering risk; custody note hash breaksUse immutable store or append-only artifact (Step 6)
Evidence package without READMEAuditor lacks engagement contextAlways include README.txt with dates, scope, contacts (Step 6)
Manual collection onlyDoes not scale for Type II observation periodsAutomate in CI with a nightly schedule (delivery reference)
Generating evidence for every control manuallyMisses the point of test automationMap controls to existing tests first (Step 1)

Limitations

  • This is a build-an-X workflow. The control-map file and assembler script must be authored per engagement; there is no universal control catalog that maps to all frameworks without customization.
  • NIST IR 8011 Vol 1 (csrc.nist.gov/publications/detail/nistir/8011/vol-1/final) defines automated assessment using "testable defect checks" against SP 800-53 determination statements. This skill follows the same pattern (desired state vs. actual state from test results) but does not implement NIST IR 8011's full sub-capability taxonomy.
  • GRC platform ingestion formats vary and change; verify the target platform's current upload requirements at the time of the engagement.
  • Some controls (e.g., physical access, vendor risk) cannot be tested automatically; those require manual attestation and are out of scope here.
  • AICPA Trust Services Criteria (2017 with 2022 revised points of focus) are behind a registration wall at aicpa-cima.com - cited by stable document title per authoring guidance; readers should access via AICPA account.

References

  • csrc.nist.gov/glossary/term/chain_of_custody - NIST SP 800-72 chain-of-custody definition (fetched 2026-06-04)
  • isaca.org/resources/glossary - ISACA "artifact" and "audit evidence" definitions (fetched 2026-06-04)
  • csrc.nist.gov/publications/detail/nistir/8011/vol-1/final - NIST IR 8011 Vol 1: automated assessment of SP 800-53 controls via testable defect checks (fetched 2026-06-04)
  • gdpr-info.eu/art-5-gdpr, gdpr-info.eu/art-24-gdpr, gdpr-info.eu/art-30-gdpr - GDPR accountability obligations (fetched 2026-06-04)
  • AICPA Trust Services Criteria 2017 (rev. 2022 points of focus) - available at aicpa-cima.com (paywalled; registration required)
  • PCI DSS v4.0.1 Requirement 10 - 12-month retention requirement; source: pcisecuritystandards.org
  • Delivery + CI automation operational depth (carries the PCI DSS retention citation): grc-delivery-and-ci-automation.md (opens in new window)
  • soc2-evidence-collector - host skill: SOC 2-specific raw log collection
  • audit-trail-test-author - authoring tamper-evident audit log tests

SOC 2 evidence source map

View source (opens in new window)

SOC 2 evidence source map

In-scope criteria decision

Most SaaS engagements include CC + Availability + Confidentiality. Privacy criteria add when GDPR/CCPA also in scope. Processing Integrity adds for fintech / data-processing SaaS.

Criterion categoryTypical scope decision
CC1 Control EnvironmentAlways
CC2 Communication & InformationAlways
CC3 Risk AssessmentAlways
CC4 MonitoringAlways
CC5 Control ActivitiesAlways
CC6 Logical & Physical AccessAlways
CC7 System OperationsAlways
CC8 Change ManagementAlways
CC9 Risk MitigationAlways
A1 AvailabilityIf uptime SLA committed
C1 ConfidentialityTypical for B2B SaaS
PI1 Processing IntegrityIf data-processing accuracy matters
P1 - P9 PrivacyIf handling PII at scale

Control to evidence source

Map each control to one or more automatable evidence sources:

ControlEvidence sourceCollector pattern
CC6.1 Logical accessIDP audit logs (Okta/Auth0/Keycloak)Daily export of user-access events
CC6.2 Access provisioningOnboarding workflow logsPer-hire ticket + access-grant audit
CC6.3 Access deprovisioningOffboarding workflow logsPer-departure ticket + access-revoke audit
CC7.1 Threat detectionSIEM (Datadog, Splunk) alert logsContinuous alert-history feed
CC7.2 System monitoringAPM (Datadog, New Relic) uptime dataDaily uptime report
CC8.1 Change managementGit PR history + CI deploy logsPer-PR audit (reviewer attribution)
A1.1 Availability monitoringSLO dashboardsMonthly availability report
C1.1 Encryption at restCloud KMS audit logsQuarterly attestation
C1.2 Encryption in transitTLS config auditQuarterly attestation

GRC-platform delivery and CI automation

View source (opens in new window)

GRC-platform delivery and CI automation

Deep reference for soc2-evidence-collector's evidence-packaging workflow (evidence-packaging.md (opens in new window)). Consult once the evidence package is bundled (evidence-packaging Step 6) and you need to deliver it to a GRC platform and automate the whole run in CI.

Upload to the GRC platform

The assembled package feeds into whichever GRC platform the engagement uses. All three major platforms accept manual evidence upload when no native integration covers the control:

PlatformManual upload path
VantaControls -> Select control -> "Add evidence" -> upload file
DrataControls -> Control detail -> Evidence tab -> Upload
SecureframeControls -> Evidence -> Attach

For controls with native integrations (e.g., Vanta's GitHub integration for CC8.1 change management), prefer the integration over manual upload. Use this skill only to fill gaps the integration cannot cover, or when the GRC platform is not yet in use.

CI integration

Evidence generation should run automatically on every merge to main (or nightly for continuous-monitoring controls):

# .github/workflows/compliance-evidence.yml
name: Compliance Evidence
on:
  push:
    branches: [main]
  schedule:
    - cron: "0 2 * * *"     # nightly UTC

jobs:
  evidence:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run compliance test suite
        run: pytest compliance_tests/ --json-report --json-report-file=results/test-run.json
      - name: Build evidence package
        run: python scripts/build_evidence_package.py
      - name: Upload evidence artifact
        uses: actions/upload-artifact@v4
        with:
          name: compliance-evidence-${{ github.run_id }}
          path: evidence-package-*/
          retention-days: 365   # retain for full observation period + buffer

Set retention-days to cover the audit's observation period plus a buffer. PCI DSS v4.0.1 Requirement 10 requires log and evidence retention of at least 12 months with the most recent 3 months immediately available (source: pcisecuritystandards.org).

Related skills

audit-trail-test-author

Build-an-X for audit-log tests across compliance frameworks - required-events catalog (auth events / privilege change / data access / admin action / config change / export / impersonation); structured-log-format assertions per OWASP A09:2021; tamper-evident chain (hash-chain + signed-batch patterns) for HIPAA §164.312(b) + PCI Req 10 + SOC 2 CC7.3; immutability + retention per framework; query-replay tests for forensic reconstruction. Use when authoring audit log tests for any compliance framework (HIPAA / PCI / SOC 2 / GDPR / etc.).

compliance-coverage-scoring

Scores existing tests and evidence against a named compliance framework's criteria list (GDPR, CCPA/CPRA, SOC 2 Trust Services Criteria, HIPAA Security Rule, PCI DSS, ISO/IEC 27001), marking every criterion met, partial, not met, or not applicable with a stated evidence requirement per state, and recording each scope exclusion with its criterion reference, reason, named approver, and re-review date. Includes an adversarial readiness-review mode with hard refusal rules (never "ready" with an unjustified gap), and the ISO/IEC 27001:2022 Annex A per-control test-pattern catalog in references/iso27001.md. Produces a readiness self-assessment only: not certification, not an audit opinion, not legal advice. Use when a framework version has been named and an evidence set already exists, and someone needs a per-criterion readiness score before an observation period opens, before a qualified assessor arrives, or in response to a regulator inquiry.

gdpr-test-patterns

Reference catalog of GDPR-aligned test patterns - data-subject-rights workflows (Art. 15 access, Art. 16 rectification, Art. 17 erasure / "right to be forgotten", Art. 18 restriction, Art. 20 portability, Art. 21 objection); consent recording + revocation per Art. 7; data-residency assertions per Art. 44 - 50 international transfers; breach-notification timing tests per Art. 33 (72 hours); data-minimization assertions in fixtures per Art. 5(1)(c). The California analogue - CCPA/CPRA patterns by Cal. Civ. Code section, including Global Privacy Control (GPC) opt-out, right-to-know, deletion, right-to-correct, and sensitive-PI limits - lives in references/ccpa.md. Use when authoring GDPR- or CCPA/CPRA-readiness tests for any product processing EU or California personal data.

hipaa-test-patterns

Reference catalog of HIPAA Security Rule-aligned test patterns - administrative safeguards (45 CFR §164.308: workforce training, access management, contingency planning), physical safeguards (§164.310: facility access, workstation security, device disposal), technical safeguards (§164.312: access control, audit logs, integrity, transmission security); PHI handling assertions in fixtures; minimum-necessary tests per §164.502(b); BAA-scope boundary verification. Use when authoring HIPAA-readiness tests for any product handling Protected Health Information.

pci-dss-control-test-author

Build-an-X for PCI DSS v4.0 scope verification - cardholder data environment (CDE) boundary tests, segmentation tests (PCI Req 1), prohibited-data-storage assertions per Req 3 (no full track data, no CVV/CAV2/CVC2/CID, no PIN/PIN block post-authorization), key-management tests per Req 3.6, encryption-of-transmissions per Req 4; includes the scope catalog (SAQ A / A-EP / D levels, PAN-storage rules, hosted-fields / tokenization scope-reduction patterns) in references/pci-scope.md. Use when authoring PCI DSS scope-reduction + control tests for any system handling payment-card data, or when determining a payment integration's SAQ level.