---
sensitivity: public
schema_version: 1
last_validated: 2026-04-29
status: stable
---

# fastpace open audit schema

> Canonical schema for every artifact fastpace writes (F2.12). Third-party
> tools can verify a fastpace export without proprietary tooling — every
> field, every hash algorithm, every signature scheme is documented here.

This is the contract fastpace makes to auditors and procurement reviewers.
If a third party builds a verifier from this document, the verifier must
accept any fastpace export of the matching schema_version.

## 1. Crypto primitives

| Item            | Algorithm | Notes                                                     |
|-----------------|-----------|-----------------------------------------------------------|
| Install identity | Ed25519   | Per-install keypair at `~/.fastpace/identity/`            |
| Hash            | SHA-256   | Hex digest, prefixed `sha256:`                            |
| Canonical JSON  | sorted keys, no whitespace | See §6 below for the algorithm                |

Every hash field is the canonical-JSON form of the body **with `entry_hash`,
`signature`, and `signed_by` fields removed**. Verifiers recompute and
compare.

## 2. Audit chain (F0.2)

File: `<repo>/fastpace/audit.log` — one JSON object per line.

```json
{
  "seq":          0,
  "prev_hash":    "0000000000000000000000000000000000000000000000000000000000000000",
  "ts":           "2026-04-29T10:00:00.000Z",
  "tool":         "Bash",
  "phase":        "PostToolUse",
  "summary":      { "command": "echo hi" },
  "entry_hash":   "<hex sha256 over the canonical body sans entry_hash + signature>",
  "signature":    "<base64 Ed25519 signature over entry_hash bytes>"
}
```

- `seq` starts at 0 and monotonically increments.
- `prev_hash` is the previous entry's `entry_hash`; first line uses 64 zeros.
- `signature` may be empty when no install identity exists at append time.
- Verification: walk the file, recompute each `entry_hash`, check `prev_hash`
  linkage, verify each non-empty `signature` against the install public key.

## 3. Run manifest (F1.1)

File: `<repo>/fastpace/manifests/<iso-ts>-<short>.json` — one per AI call.

Required fields: `schema_version`, `manifest_id`, `ts`, `model`, `endpoint`,
`runtime`, `training_opt_out`, `prompt_hash`, `response_hash`, `entry_hash`,
`signed_by`, `signature`.

Optional fields: `prompt_byte_length`, `response_byte_length`, `params`,
`tool`, `phase`, `agent_id`, `installer`.

`signed_by` carries the F0.1 fingerprint that signed the manifest, so
historical manifests can be verified against an archived `public.pem` after
a key rotation.

## 4. Discovery manifest (F0.3)

Two files:

- `~/.fastpace/manifest.json` — machine-wide rollup
- `<repo>/fastpace/manifest.json` — per-repo

Required: `schema_version`, `fastpace_version`, `repo_name`, `repo_path`,
`install_id`, `fingerprint`, `created_at`, `last_activity_at`, `counts`,
`agents`, `hooks`, `skills`, `runtimes`, `mcp_servers`, `integrations`.

## 5. AI-BOM (F2.4)

File: `<repo>/fastpace/aibom/<release>-<ts>.json`.

Top-level: `bomFormat: "CycloneDX-AI"`, `specVersion: "1.6-aiml-draft"`,
`fastpace_schema_version: 1`, `serialNumber` (urn:uuid), `version`
(monotonic int), `metadata`, `components`, `services`, `formulation`,
`stats`, `provenance`, `entry_hash`, `signed_by`, `signature`.

Components dedup by `(model, runtime, endpoint)` with a `calls` counter.

## 6. Canonical JSON

```
canonicalJson(value):
  null              → "null"
  string            → JSON.stringify (RFC 8259 escaping)
  number (finite)   → JSON.stringify
  boolean           → "true" | "false"
  array             → "[" + map(canonicalJson).join(",") + "]"
  object            → "{" + sortedKeys.map(JSON.stringify(key) + ":" + canonicalJson(value[key])).join(",") + "}"
```

No leading/trailing whitespace. Numbers must be finite. Undefined values
must throw, not be elided. Arrays preserve element order; only object key
order is canonicalized.

## 7. Trailer block (F2.3)

AI-attributed git commits carry RFC-5322-style trailers separated from the
body by a blank line. Recognized keys (case-insensitive on read, canonical
on write):

- `AI-Model:`
- `AI-Prompt-Hash:`
- `AI-Manifest-Id:`
- `AI-Approver:`
- `AI-Agent:`
- `AI-Audit-Seq:`

A trailer block is recognized only when (a) every line in the tail block
matches `<key>: <value>` syntax and (b) the line immediately above the
block is blank or the block is the entire commit message.

## 8. Explanation bundle (F2.2)

File: `<repo>/fastpace/explanations/<sha-short>.json` (or `<manifest_id>.json`
when no commit exists yet).

Required: `schema_version`, `id`, `ts`, `prompt`, `response`,
`retrieval_context[]`, `approval_chain[]`, `correction_events[]`,
`entry_hash`, `signed_by`, `signature`.

`prompt` and `response` are objects of shape `{ hash, byte_length }`. The
plaintext is **never** persisted; only the digests.

## 9. Sensitivity tags (F1.10)

YAML frontmatter on `<repo>/fastpace/context/*.md` files:

```yaml
---
sensitivity: public | internal | restricted
---
```

Default when absent: `internal`. The F0.5 prompt redactor refuses to
include `restricted` files in any prompt.

## 10. Versioning

Top-level `schema_version: 1` on every artifact above. Increments for
breaking changes only; additive fields keep `1`. The current schema is
`1` for: audit chain, run manifest, discovery manifest, exception log,
correction log, explanation bundle, sensitivity tag.

The AI-BOM uses two version fields for clarity: `fastpace_schema_version`
(this file's contract) and `bomFormat / specVersion` (the public AI-BOM
shape, currently `CycloneDX-AI / 1.6-aiml-draft`).

---

`fastpace schema export [--format json]` emits a portable JSON Schema
bundle assembled from this document. Third parties: build a verifier
against the schema bundle, not against the fastpace source code.
