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 }
]
}| Field | Type | Meaning |
|---|---|---|
algorithm | string | Always "sha256" for v1 manifests |
scan_id | UUID | Unique per scan invocation; ties multiple files to one run |
account_id | string | AWS account ID, or GCP project ID for GCP scans |
regions_scanned | []string | AWS regions (one or more); single project for GCP |
collectors_run | []string | Names of collectors that produced an evidence file in this scan (including ones that errored — see each file's error field) |
ankos_version | string | CLI version that produced this scan |
commit | string | Git commit of the CLI build (provenance) |
build_date | string | Build date of the CLI build (provenance) |
generated_at | RFC3339 | UTC timestamp of manifest write |
duration_seconds | float | Wall-clock duration of the scan |
hashes | map | Filename → SHA-256 hex digest, including evidence.json (the authoritative integrity record) |
files | []object | Same 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": ""
}| Field | Type | Meaning |
|---|---|---|
collector | string | Collector name (matches the registry — see Collectors) |
collected_at | RFC3339 | When this specific collector finished |
region | string | AWS region or GCP project ID this evidence covers |
account_id | string | AWS account or GCP project |
data | object | Collector-specific evidence (schema differs per collector) |
error | string | Empty 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
(
narrativefield 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.

