01What Mark answers
When an AI output appears, four questions matter:
- Who or what produced this?
- On whose behalf?
- Under what policy?
- When?
Until today, those questions had no answer. Now they have one. The answer is a small envelope attached to every AI output that Validiti products produce.
02What a Mark envelope looks like
A Mark envelope is a JSON object with the following top-level fields:
| Field | Type | Required | Carries |
|---|---|---|---|
| version | int | yes | Spec version (currently 1) |
| event_id | string | yes | Globally unique identifier for this envelope |
| event_type | string | yes | What kind of action this envelope attests to |
| category | string | yes | "agent" for AI; "human" and "machine" reserved |
| ts_unix | int | yes | UTC seconds at production |
| issuer | object | yes | Who/what produced this |
| for | object | optional | The person or org the issuer was acting for |
| installation | object | optional | The hardware the issuer ran on |
| policy | object | optional | The policy in force at production |
| descended_from | object | optional | Lineage chain back to the base model |
| previous | string | optional | The envelope before this one in the issuer’s chain |
| payload | object | yes | The actual signed content (shape per event_type) |
| seal | string | yes | The cryptographic seal that makes the rest verifiable |
03The issuer object
{
"id": "<a stable identifier for the issuer>",
"kind": "ai_agent" | "ai_model" | "ai_pipeline",
"key": "<reference to the issuer's published public key>",
"display_name": "<human-readable, optional>"
}
The seal is verified against the public key referenced by issuer.key. The key registry is public; anyone can publish a key, anyone can read any key.
04The for object
When an AI agent acts on behalf of a person or organization, the for object names them and the scope.
{
"principal_id": "<identifier for the human / org>",
"principal_kind": "human" | "organization" | "service",
"scope_id": "<the authorization scope>",
"scope_hash": "<hash proving the scope was granted>"
}
05The installation object
{
"device_id": "<stable identifier for the device>",
"binary_id": "<the Validiti product producing this>",
"binary_hash": "<sha256 of the producing binary>",
"runtime_state": "<runtime-attestation token>"
}
This is how a relying party confirms the envelope came from a known, untampered installation.
06The policy object
{
"policy_id": "<stable identifier>",
"policy_hash": "<hash of the full policy>",
"policy_version": "<semver or sequence>",
"policy_source": "<reference, or 'self'>"
}
The policy_hash lets a verifier confirm what policy was in force without exposing the policy’s contents. Required when event_type is inference_produced, action_taken, or policy_loaded.
07The descended_from object
{
"base_model_id": "<identifier>",
"base_model_hash": "<hash>",
"derivation_chain": [
{ "step_kind": "fine_tune" | "rlhf" | "dpo" | "distillation" | "merge",
"step_id": "<identifier>",
"step_hash": "<hash>",
"step_ref": "<reference, or null>" }
],
"training_corpus_ref": "<reference, or null>"
}
Optional. When present, anyone can walk the chain back to the base model.
08Event types
Mark v1.0 defines these event types for the agent category:
| event_type | What it means | Required payload |
|---|---|---|
| inference_produced | The issuer produced an output | output_hash, output_size_bytes |
| inference_refused | The issuer was asked to act but refused | reason_code |
| inference_partial | The issuer began but did not complete | output_hash, partial_reason |
| action_taken | The issuer caused an external side-effect | action_type, target_ref, result_code |
| action_refused | The issuer declined an authorized action | reason_code, action_type, target_ref |
| delegation_requested | The issuer handed off to another issuer | delegate_actor_id, delegation_scope |
| delegation_accepted | The issuer accepted a hand-off | delegator_actor_id, scope_accepted |
| policy_loaded | The issuer loaded or switched policy | policy_id, policy_hash |
| lineage_attested | The issuer published its lineage chain | (lineage object at top level) |
| revocation | A signing key is being revoked | revocation_target_actor_id, revocation_reason, revocation_effective_ts |
Additional domain-specific event types are valid Mark v1.0 agent events, used by specific Validiti products: challenge_issued, verification_attempt, verdict_labeled, signal_published, persona_action, persona_loaded, corpus_loaded, corpus_queried, lineage_claimed.
09How to verify an envelope
A Mark envelope is verified in eight steps:
- Check
versionis supported. - Strip
sealfrom the envelope. - Compute the canonical JSON of what’s left (sorted keys, no extra whitespace, no
sealfield). - Look up the public key referenced by
issuer.key. - Check the
sealcryptographically verifies the canonical body against that public key. - Optional: walk the
previouschain to confirm continuity. - Optional: confirm the
policy.policy_sourceis known. - Optional: walk the
descended_from.derivation_chainagainst the registry.
Steps 1–5 are mandatory. Steps 6–8 are optional checks that add stronger guarantees for relying parties that need them.
POST /api/mark/verify — try it on the Mark page. (2) Coming soon as a free sealed Validiti binary bundled with every Validiti product that touches AI, when each product ships. You can also implement your own verifier from this spec; the math is straightforward.
10Selective disclosure
You can present a subset of an envelope’s fields and prove the omitted fields existed in the signed original. Selective-disclosure presentations are a separate envelope shape, specified separately. Full-envelope presentation is what v1.0 requires; selective disclosure ships in v1.1.
11Revocation
To revoke a signing key (or a specific envelope), the issuer produces an envelope with event_type = "revocation" and the appropriate payload. Verifiers check their local revocation set before validating any seal. Revocations propagate through the same channel envelopes flow on; there is no central revocation server to call.
12What Mark is NOT
- Not a wallet you download.
- Not a service Validiti hosts.
- Not a registry Validiti controls.
- Not something you pay for.
Mark is a math layer over signed records that Validiti products already produce. You add the verifier to your software in five minutes. You don’t need an account, an API key, or a contract with anyone.
13What’s coming
Mark v1.0 is for AI agents. Mark v1.1 adds selective disclosure. Later versions add category = "human" (for people) and category = "machine" (for devices), using the same envelope shape. All three categories are free, forever. Identity should never be paywalled — not for AI, not for people, not for the devices people use.
Reference verifier: live now as a hosted service at
/api/mark/verify; the bundled sealed binary is Coming Soon. Solving tomorrow’s problems today — because we care.