Makoto
Menu
Protocol specification

One signed claim per event. One verifiable history at handoff.

Makoto is a source-first protocol for data provenance. It records an origin, appends independently signed transformation statements, lets data teams attach private JSON Schema rules by digest, and gives the recipient enough evidence to verify the history and the bytes it actually received.

The code this page is about. Repeated from What one record actually looks like below.
{
  "_type": "https://in-toto.io/Statement/v1",
  "predicate": {
    "event": {
      "id": "urn:uuid:11111111-1111-4111-8111-111111111111",
      "occurredAt": "2026-09-16T16:00:00Z"
    },
    "profiles": [],
    "schemaVersion": "0.2",
    "source": {
      "kind": "urn:makoto:demo:source:synthetic-file",
      "uri": "urn:makoto:demo:v0.2:source:customers-raw"
    }
  },
  "predicateType": "https://usemakoto.dev/predicate/v0.2/origin",
  "subject": [
    {
      "digest": {
        "sha256": "4e90181e7f75ccdf0e4d81c83d281f53806bed241787cdc751e22b2d4cd19919"
      },
      "name": "customers.raw.json"
    }
  ]
}

Publication status. The normative text and implementation are available for public review. They are not yet an immutable tagged release.

Normative textHosted schemasRaw specificationSchema catalogRunnable proof

Read the normative text

Everything below this section is orientation. The obligations themselves — encodings, digest and signature rules, the statement model, profile resolution limits, the handoff anchor, the trust-policy grammar, the ordered verification algorithm, and every diagnostic code — are fixed in one document, reproduced in full at the normative text and served raw at /spec/v0.2/spec.md.

SectionWhat it fixes
TerminologyThe exact words: subject, artifact, statement, predecessor, root, head, closure, handoff.
Guarantee modelWhat a conforming verifier may conclude, and the list of things it may never conclude.
Encoding and cryptographyJSON and DSSE rules, canonical digests, accepted signature algorithms, lexical limits.
Statement modelThe in-toto wrapper, the common predicate fields, and both predicate shapes.
ProfilesDigest-pinned closures, the bounded schema dialect, offline resolution, and content validation.
Handoff and bundleWhy completeness needs its own anchor, the manifest payload, and the reference layout.
Trust policyThe receiver-owned grammar: keys, roles, thresholds, freshness, and resource limits.
Verification algorithmThe ordered steps, the decision rules, and the per-check status contract.
CLI and library contractRequired commands, library operations, output shapes, and exit codes.
Hosted schemas and versioningWhich URLs are stable, what immutability means here, and how a correction is issued.
Security and privacyThreats in scope, required mitigations, and the privacy model.
Diagnostic mapEvery stable error and warning code, and the step that emits it.

The record has four parts

  1. OriginThe first producer states where and how the data was collected and binds that claim to one or more exact artifact digests. An origin has no predecessor.
  2. TransformationsEvery later producer creates a new statement. It names the exact predecessor payload and exact input artifact, describes the operation, and binds any outputs. Earlier statements are never edited.
  3. AttestationsEach statement is carried in a DSSE envelope. Signatures authenticate exact payload bytes; receiver-owned policy separately decides whether those keys were authorized for those claims.
  4. HandoffThe sender signs the exact statement set, roots, heads, final artifacts, recipients, and required profiles being transferred. That commitment lets a receiver distinguish a complete handoff from a merely continuous fragment.

What one record actually looks like

This is the origin statement from the runnable proof, decoded from the signed envelope that ships in the bundle. It is not an illustration written for this page: the digest below is the one the verifier recomputes, and the same bytes are what the transformation that follows names as its predecessor.

Origin statement, decoded from the published envelopejson
{
  "_type": "https://in-toto.io/Statement/v1",
  "predicate": {
    "event": {
      "id": "urn:uuid:11111111-1111-4111-8111-111111111111",
      "occurredAt": "2026-09-16T16:00:00Z"
    },
    "profiles": [],
    "schemaVersion": "0.2",
    "source": {
      "kind": "urn:makoto:demo:source:synthetic-file",
      "uri": "urn:makoto:demo:v0.2:source:customers-raw"
    }
  },
  "predicateType": "https://usemakoto.dev/predicate/v0.2/origin",
  "subject": [
    {
      "digest": {
        "sha256": "4e90181e7f75ccdf0e4d81c83d281f53806bed241787cdc751e22b2d4cd19919"
      },
      "name": "customers.raw.json"
    }
  ]
}

The envelope around it carries the signature. A signature authenticates these exact payload bytes and says nothing about whether that signer was allowed to make this claim — that is the receiver's policy decision, kept deliberately separate.

Core objects and their jobs

ObjectWhat it commits toWhat remains outside it
Origin statementSource claims, event identity and time, and exact observed subjects.Whether the source claim is truthful.
Transformation statementOperation metadata, predecessor payloads, input artifacts, and output subjects.Proof that the claimed code actually executed.
DSSE envelopeThe exact statement payload and one or more cryptographic signatures.Authorization to make the claim.
Profile referenceA public or private JSON Schema root and its complete digest-pinned closure.Ambient network retrieval or producer-controlled policy.
Handoff manifestThe exact evidence and artifacts intentionally transferred to named recipients.Independent freshness expectations.
Trust policyWhich keys may make which claims, under which thresholds and resource limits.It is supplied by the receiver, not trusted from the bundle.
Verification reportSeparate outcomes for structure, cryptography, authorization, profiles, graph, handoff, freshness, and artifacts.A single marketing-grade “trusted” badge.

A small core; private rules without a fork

Core schemas close the portable protocol shapes. Organization-specific claims do not require a central registry or a public schema. A team can publish a profile, keep it on an authenticated internal catalog, or never publish it at all. The signed statement carries the profile URI plus the exact root and closure digests, so the receiver can resolve the bytes it has already authorized without trusting a live network lookup.

Profiles can constrain transformation metadata and, for supported structured artifacts, the artifact content itself: required fields, identifier formats, control characters, enumerated classifications, bounded string patterns, or the absence of disallowed fields. Passing a profile proves only that the inspected JSON matches those rules. It does not make the content truthful, safe, confidential, or legally compliant.

Verification is deliberately decomposed

QuestionRequired evidenceWhy it stays separate
Is the resource well-formed?Core schema and any required profile pass.Valid structure says nothing about identity.
Who controlled the signing key?DSSE signature verifies over exact payload bytes.A valid signature may belong to the wrong party.
Was that signer allowed?Receiver policy authorizes the key for the selected claim and role.Authorization is a consumer decision.
Does the history connect?Every transformation resolves exact predecessor and artifact digests back to an origin.Continuity does not prove that no branch was withheld.
Is this the complete handoff?An authorized signed manifest commits to exact roots, heads, statements, profiles, and final artifacts.An older complete handoff can still be replayed.
Are these the expected bytes?Independent expected manifest, head, nonce, age, or artifact constraints; plus a digest of the bytes received.Freshness and received-byte integrity are distinct.

Read the assurance model · Follow the verification sequence

Machine-readable resources

Thirteen resources are served at stable URLs and pinned by digest in the catalog. The schema index reproduces every one of them in full, next to its identifier and its catalog digest, so a claim on a page can be checked against the bytes a resolver will actually fetch. The release pointer resolves the name “latest” to the current catalog, as a convenience for people. It is not an immutable protocol identifier: it moves when a new version is published, so never cite it as a schema $id, a $schema, or a pinned reference. Pin the versioned resource and its digest instead.

ResourceConstrains
statement.schema.jsonThe common wrapper every predicate is carried in.
origin.schema.jsonSource claims, event identity and time, first-observed subjects.
transform.schema.jsonOperation metadata, exact predecessors, inputs, output subjects.
envelope.schema.jsonThe DSSE envelope and its signatures over exact payload bytes.
profile-reference.schema.jsonA profile root plus its complete digest-pinned closure.
profile-dialect.schema.jsonThe bounded schema dialect a private profile may use.
handoff.schema.jsonRoots, heads, statement set, required profiles, recipients.
bundle.schema.jsonThe on-disk layout a sender actually transfers.
dataset-manifest.schema.jsonA partitioned dataset described as one subject.
trust-policy.schema.jsonReceiver-owned keys, roles, thresholds, limits, and verification-summary trust inputs.
verification-report.schema.jsonPer-check outcomes, never one collapsed verdict.
catalog.schema.jsonThe index itself, so a resolver can validate it before trusting it.
catalog.jsonThe published index and the digests everything else is pinned by.

The runnable proof exercises an allowed handoff and seven deterministic denials against the pinned reference implementation.

Versions

Each protocol version is a separate family of identifiers. Evidence keeps the version it was written in, and a verifier never mixes two families in one verification.

VersionStatusText and schemas
0.2Current. Everything else on this site describes it.Normative text · Hosted schemas
0.3Published for review; not yet tagged or the default. Adds a standard licence-claim profile and record-level commitments.Normative text and hosted schemas

Assurance levels

Like SLSA, Makoto separates producer tracks from receiver results. The Origin and Transform tracks each define three cumulative levels a producer adopts one step at a time; what a receiver established about one handoff is a separate verified property, carried in a standard SLSA Verification Summary Attestation. Neither is an allow/deny score or a correctness claim.

LevelOrigin trackTransform track
L1Traceable capture: the first observed bytes have origin evidence.Traceable execution: every step binds exact inputs, predecessors, operation identity, and outputs.
L2Platform-authenticated capture: a hosted capture platform generates and signs that evidence.Platform-authenticated execution: a hosted pipeline generates and signs the evidence.
L3Policy-controlled capture: the platform continuously enforces declared capture controls.Hardened execution: isolated, ephemeral runs protect both execution and signing from user-controlled steps.

The verified properties are MAKOTO_AUTHORIZED, MAKOTO_GRAPH_COMPLETE, MAKOTO_FRESHNESS_ANCHORED, MAKOTO_SCHEMA_CONFORMANT, and MAKOTO_REPRODUCED. Read the assurance model for each level's evidence and each property's exact issuance rule, or Section 8 for the normative text.

What Makoto does not claim

Makoto does not certify a source as truthful, prove that transformation code ran, establish data quality, prevent disclosure, grant legal compliance, or discover copies that nobody recorded. Hardware-backed keys, software-build provenance, transparency logs, access control, semantic catalogs, and pipeline observability can complement the protocol; none is silently implied by a passing Makoto report.

Public technical review

Challenge the protocol with an actual handoff.

Bring a source, two transformations, a private rule, a signer boundary, and a receiving decision. The useful contribution is the smallest case that exposes an ambiguity or produces a new conformance fixture.