03 — Claim Format
A MIR claim is a signed JSON document. It is the fundamental unit of the protocol.
Structure
{
"mir": 1,
"type": "mir.transaction.completed",
"domain": "marketplace.example.com",
"subject": "a55bea0a6788794ef1307951f98bc339db7ccf9309881180e9e6c080f63ae618",
"timestamp": "2026-02-16T15:30:00Z",
"metadata": {
"currency": "USD",
"count": 1
},
"keyFingerprint": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"sig": "base64url-encoded-ed25519-signature"
}
Encoding
All binary values in MIR claims MUST use base64url encoding without padding (RFC 4648 Section 5).
- Alphabet:
A-Z,a-z,0-9,-,_ - No padding characters (
=) - No
+or/characters (those are standard Base64)
Rationale: Base64url aligns with the JOSE/JWT/JWK ecosystem that IAM teams already use. It is URL-safe and unambiguous without padding since Ed25519 signatures are a fixed 64 bytes (always encodes to exactly 86 characters).
This applies to the sig field in claims and the pub field in .well-known/mir.json and DNS TXT records.
Fields
mir (required)
- Type: integer
- Value:
1 - Protocol version. Implementations MUST reject claims with unrecognized versions.
type (required)
- Type: string
- Claim type. See Claim Types and Type Extensibility below.
- Core types use the
mir.namespace:mir.{category}.{action}(e.g.,mir.transaction.completed). - Extension types use domain-scoped prefix:
{domain}:{category}.{action}(e.g.,shopify.com:loyalty.earned).
domain (required)
- Type: string
- The DNS domain of the issuing organization.
- This is the authority anchor. The domain controls the signing key.
- MUST be a valid DNS hostname. No wildcards. No IP addresses.
subject (required)
- Type: string
- Pseudonymous identifier for the participant. 64-character lowercase hex string.
- See Subject Identifier below for derivation rules.
- No plaintext PII is permitted.
timestamp (required)
- Type: string (ISO 8601)
- When the event occurred, as reported by the issuing domain.
- MUST include timezone. UTC recommended.
- MUST NOT be future-dated beyond 5-minute clock skew.
metadata (optional)
- Type: object
- Structured context specific to the claim type.
- Maximum: 4 KB serialized.
- MUST NOT contain PII.
- SHOULD use integers for numeric values. Decimal amounts SHOULD be represented as strings (e.g.,
"149.99") or as integer minor units (e.g.,14999for cents). See 04 — Signature Model for rationale. - Unknown fields are preserved.
keyFingerprint (required)
- Type: string
- SHA-256 hash of the 32-byte Ed25519 public key that signed this claim.
- 64-character lowercase hex string.
- Allows verifiers to select the correct public key when a domain publishes multiple keys.
sig (required)
- Type: string
- Ed25519 signature over the canonical form of the claim payload (all fields except
sig). - Base64url-encoded, no padding. Exactly 86 characters (64 bytes decoded).
Subject Identifier
The subject field is a pseudonymous hash that identifies a participant without exposing PII.
Basic Derivation (SHA-256)
subject = hex(SHA256("{domain}:{externalUserId}"))
Recommended Derivation (HMAC-SHA256)
For stronger privacy protection, domains SHOULD use HMAC-based derivation:
subject = hex(HMAC-SHA256(domainSecret, "{domain}:{externalUserId}"))
Where domainSecret is a stable, per-domain secret that is:
- Never published or shared.
- Never rotated per-user (must be consistent so the same user always produces the same hash).
- Stored securely by the domain.
HMAC derivation prevents brute-force reversal even when the user ID format is known.
Requirements
- The
externalUserIdinput MUST NOT be an email address, phone number, SSN, or other directly identifiable value — unless the domain uses HMAC derivation with a strong secret. - Domains SHOULD use opaque, sufficiently random internal identifiers (e.g., UUIDs, database IDs) as
externalUserId. - The same real-world person has different subject hashes on different domains. This is by design.
- Either SHA-256 or HMAC-SHA256 output is valid — both produce a 64-character lowercase hex string. The protocol does not distinguish between them.
Claim Types
Core Types (Protocol-Defined)
All core types use the mir. namespace prefix to prevent collisions with external taxonomies. The mir. prefix is reserved for protocol-defined types. New core types are added through protocol versioning.
The following types are defined by the protocol. They record structural participation events — not scores, ratings, or evaluations.
Transaction
| Type | Description |
|---|---|
mir.transaction.initiated |
Transaction started |
mir.transaction.completed |
Transaction completed |
mir.transaction.fulfilled |
Goods or services delivered |
mir.transaction.cancelled |
Transaction cancelled |
mir.transaction.refunded |
Transaction refunded |
mir.transaction.disputed |
Transaction under dispute |
mir.transaction.chargeback |
Chargeback filed |
Account
| Type | Description |
|---|---|
mir.account.created |
Account created |
mir.account.updated |
Account modified |
mir.account.verified |
Identity verified by platform |
mir.account.suspended |
Account suspended |
mir.account.closed |
Account closed |
Communication
| Type | Description |
|---|---|
mir.message.sent |
Message sent |
mir.message.received |
Message received |
mir.response.provided |
Response to inquiry |
Type Extensibility
Domains MAY define extension types for domain-specific events not covered by core types. Behavioral, evaluative, or policy-specific semantics belong here — not in core.
Extension type format: {domain}:{category}.{action}
shopify.com:loyalty.earned
university.edu:credential.issued
bank.example.com:kyc.completed
marketplace.example.com:review.submitted
marketplace.example.com:review.received
platform.example.com:policy.warning
platform.example.com:policy.violation
Rules:
- The domain prefix MUST be a valid DNS hostname.
- The
{category}.{action}suffix follows the same format as core types: lowercase alphanumeric, dot-separated. - Types starting with
mir.are reserved for the MIR protocol. Implementations MUST NOT createmir.-prefixed types outside of protocol versions. - Extension types are validated by format only. No central registry of extension types exists.
- Verifiers that do not recognize an extension type SHOULD still verify the claim's signature. Type recognition is independent of signature validity.
Immutability
Claims are append-only. A signed claim cannot be modified — the signature would invalidate. Corrections are expressed as new claims (e.g., mir.transaction.refunded follows mir.transaction.completed).