Ankos
CLI Reference

Scan Output

What's in an Ankos evidence package — directory layout, manifest schema, per-collector JSON shape.

Every ankos scan writes an evidence package to disk: one directory containing JSON files per collector, an aggregate evidence.json, and a manifest.json with SHA-256 hashes. Everything is structured, stable, and parseable — nothing is human-prose-only.

Directory layout

ankos-evidence-20260526-153045/
├── manifest.json              # Hashes (incl. evidence.json) + scan metadata
├── manifest.sha256            # SHA-256 of manifest.json (self-integrity sidecar)
├── evidence.json              # Full package (all results in one document)
├── acm.json                   # Per-collector evidence
├── apigateway.json
├── athena.json
├── ... (one file per collector that ran)

A collector that ran but errored (for example, an AccessDenied from a too-narrow IAM role) still gets a file, with data: null and its error populated — the failure is recorded as evidence rather than silently dropped, so it can never be mistaken for "0 resources in scope".

The directory name defaults to ankos-evidence-<UTC-timestamp>/. Override with --output / -o.

manifest.json

The integrity record. Independently verifiable with shasum -a 256 — no Ankos dependency.

{
  "algorithm": "sha256",
  "scan_id": "a3f8e2c4-7b91-4d15-8e2a-f0c9b3d56e8a",
  "account_id": "123456789012",
  "regions_scanned": ["us-east-1"],
  "collectors_run": ["iam", "vpc", "kms", "..."],
  "ankos_version": "1.0.0",
  "commit": "9f2a1c0",
  "build_date": "2026-06-04",
  "generated_at": "2026-05-26T15:30:45Z",
  "duration_seconds": 7.229,
  "hashes": {
    "iam.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "vpc.json": "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e",
    "evidence.json": "...",
    "kms.json": "..."
  },
  "files": [
    { "filename": "iam.json", "sha256": "e3b0c4...", "size_bytes": 4823 },
    { "filename": "vpc.json", "sha256": "a591a6...", "size_bytes": 12109 }
  ]
}
FieldTypeMeaning
algorithmstringAlways "sha256" for v1 manifests
scan_idUUIDUnique per scan invocation; ties multiple files to one run
account_idstringAWS account ID, or GCP project ID for GCP scans
regions_scanned[]stringAWS regions (one or more); single project for GCP
collectors_run[]stringNames of collectors that produced an evidence file in this scan (including ones that errored — see each file's error field)
ankos_versionstringCLI version that produced this scan
commitstringGit commit of the CLI build (provenance)
build_datestringBuild date of the CLI build (provenance)
generated_atRFC3339UTC timestamp of manifest write
duration_secondsfloatWall-clock duration of the scan
hashesmapFilename → SHA-256 hex digest, including evidence.json (the authoritative integrity record)
files[]objectSame data as hashes plus size_bytes, for size reporting

A manifest.sha256 sidecar file (the SHA-256 of manifest.json itself) sits alongside the manifest so the manifest's own integrity is checkable. See ankos verify for verification.

evidence.json

The whole scan as a single JSON document — the manifest plus every collector result in one file. Use this when you want a single artifact to pass into another tool; use the per-collector files when you want to read or process one service at a time.

{
  "scan_id": "a3f8e2c4-7b91-4d15-8e2a-f0c9b3d56e8a",
  "account_id": "123456789012",
  "region": "us-east-1",
  "collected_at": "2026-05-26T15:30:45Z",
  "collectors": ["iam", "vpc", "kms", "..."],
  "results": [
    { "collector": "iam", "collected_at": "...", "data": { ... } },
    { "collector": "vpc", "collected_at": "...", "data": { ... } }
  ],
  "manifest": { ... same as manifest.json above ... }
}

Per-collector JSON

Each <collector>.json follows a common envelope:

{
  "collector": "iam",
  "collected_at": "2026-05-26T15:30:45.123Z",
  "region": "us-east-1",
  "account_id": "123456789012",
  "data": {
    // Collector-specific structured evidence — schema varies by collector.
    // For `iam`: users, roles, MFA status, credential report, etc.
    // For `vpc`: VPCs, subnets, security groups, NACLs, flow logs, etc.
  },
  "error": ""
}
FieldTypeMeaning
collectorstringCollector name (matches the registry — see Collectors)
collected_atRFC3339When this specific collector finished
regionstringAWS region or GCP project ID this evidence covers
account_idstringAWS account or GCP project
dataobjectCollector-specific evidence (schema differs per collector)
errorstringEmpty on success; populated if the collector hit a non-fatal error

What's NOT in the package

The CLI intentionally does not emit:

  • Compliance judgments. No "compliant"/"non-compliant", no pass/fail. Evidence is the facts; assessment is the QSA's determination. See the language rules in the Ankos Ledger docs for the full principle.
  • Customer credentials. AWS access keys, GCP service-account JSON, or session tokens never appear in any output file.
  • Human-prose narratives. Those live in the Ankos ledger (narrative field per entry) and are written by the team owning the evidence — the CLI only collects mechanical facts.

Stability

The manifest schema and per-collector envelope (collector, collected_at, region, account_id, data, error) are stable across minor versions. The shape of data is specific to each collector and may add fields between versions — treat unknown fields as ignorable.

Breaking changes to the envelope are flagged with a major version bump.

Uploading evidence into the ledger

When you run ankos scan --upload, the same files described above are uploaded to your Ankos ledger via the API key set with ankos auth set-key. The ledger routes each collector's data to the right entries automatically. Existing entries gain a new evidence row; nothing on the ledger is overwritten — the upload is additive.

See Ankos Ledger → Evidence sources for what happens after the upload lands.