ak.schema.read_receipt.v1
ak.schema.read_receipt.v1 · file: schemas/read-receipt.schema.json Closed decrypted Signal plaintext payload profile for ak.receipt.read, carried only inside ak.schema.signal_envelope.v1 with signal_class=session. It is a Strand timeline UI hint, NOT canonical truth, NOT a durable Event, and NOT a multi-device cursor (see read-cursor.schema.json for that). MUST NOT generate push notifications. Realm scope, sender identity and send time come from the enclosing signed envelope and are not duplicated here. Privacy is governed by Realm policy: Realms MAY allow public, members-only, or actor-private receipt sharing. See zh/discovery/read-receipts.md sections 2.1 / 6.2 and zh/sync/signal.md section 1.1.
* $ · object
Closed decrypted Signal plaintext payload profile for ak.receipt.read, carried only inside ak.schema.signal_envelope.v1 with signal_class=session. It is a Strand timeline UI hint, NOT canonical truth, NOT a durable Event, and NOT a multi-device cursor (see read-cursor.schema.json for that). MUST NOT generate push notifications. Realm scope, sender identity and send time come from the enclosing signed envelope and are not duplicated here. Privacy is governed by Realm policy: Realms MAY allow public, members-only, or actor-private receipt sharing. See zh/discovery/read-receipts.md sections 2.1 / 6.2 and zh/sync/signal.md section 1.1.
* kind ·
const "ak.receipt.read"enum:
"ak.receipt.read"* payload_sequence ·
integerStrictly increasing but non-contiguous u64 within (sender_actor_id, sender_device_id, canonical scope_ref), including the complete ActorId. Arbitrary forward gaps are accepted; a repeated or lower value is stale.
* actor_id · oneOf[2] · $ref ./common-ids.schema.json#/$defs/actor_id
Complete protocol identity for an Event author or Realm member: account carries the exact AccountId for every Station-hosted principal; service identifies a service acting as itself. The discriminator is validated against accepted registration and admission evidence; it never authorizes itself. Account and service are distinct, and no comparison may fall back to a bare principal_id. Agent and integration classification, provisioning, controller binding and credential authorization are independently verified facts, not identity variants. Account actors at different Stations MUST NOT share or inherit authority merely because their principal_id, DID controller or signing key matches, including membership, capability, RealmCommit-signing and recovery authority.
oneOf · oneOf[0] · object
* kind ·
const "account"enum:
"account"* account_id ·
$ref #/$defs/account_id · $ref #/$defs/account_idoneOf · oneOf[1] · object
* kind ·
const "service"enum:
"service"* service_id ·
$ref #/$defs/did_core_id · $ref #/$defs/did_core_id* event_id ·
stringID of the most recent Event the actor has read. Causality implies all causal predecessors are also read.
pattern:
^ak:event:[A-Za-z0-9_-]{44}$hlc ·
stringOptional. HLC of the read position; required when the Station sync surface compares receipts under merge / debounce rules across devices for the same actor.
pattern:
^[0-9a-f]{12}-[0-9a-f]{4}-[0-9a-f]{8}$* read_scope · object
allOf · allOf[0] ·
?allOf · allOf[1] ·
?allOf · allOf[2] ·
?allOf · allOf[3] ·
?allOf · allOf[4] ·
?allOf · allOf[5] ·
?* kind ·
string (enum)Read-scope discriminator from the same family as read-cursor.schema.json; each schema declares its own supported subset (receipt additionally supports view/message/morph; cursor additionally supports circle/space). kind='thread' selects the reply sub-timeline rooted at a message (zh/discovery/read-receipts.md §5); thread is a projection selector, not a first-class protocol object.
enum:
"realm" "strand" "thread" "view" "message" "morph"object_ref ·
stringRequired when kind is anything other than 'realm'. Thread read scopes reference the root message.
pattern:
^ak:(realm|strand|message|morph|view):[A-Za-z0-9_-]{44}$track_name ·
stringRequired when kind='strand' and the receipt scopes a single track.
pattern:
^[a-z][a-z0-9_]{0,63}$track_scope ·
string (enum)Only valid when kind='strand'. Use track_scope='all' for an entire Strand regardless of track.
enum:
"all"Source
- registry row:
spec/v1/artifacts/registry/schema-registry.json - schema document:
spec/v1/artifacts/schemas/read-receipt.schema.json