Przejdź do treści

Agora Record v1

Source schema: doc/schemas/agora-record.v1.schema.json

Machine-readable schema for a signed, content-addressed, topic-addressed record ingested by an Agora topic relay. The envelope is backend-neutral and intentionally opaque about topic-key shape: the substrate does not type, parse, or split topic/key. Resource identity (proposal 026) is reachable through the optional record/about field and is never used as the primary key.

Governing Basis

Project Lineage

Requirements

Stories

Fields

Field Required Shape Description
schema yes const: agora-record.v1 Schema discriminator. MUST be the literal string agora-record.v1.
record/id yes string Content-addressed identifier of this record. Computed by the Orbiplex canonical sha256_base64url helper: sha256: followed by the unpadded base64url (RFC 4648 section 5) encoding of sha256(canonicalize(payload)), where payload is the record with record/id, signature, relay/received-at, relay/id, and relay/hops removed. Two records with the same canonical payload MUST yield the same record/id on every relay.
record/kind yes string Role label of this record. Application-visible discriminator used by query APIs and kind contracts. Examples: opinion, comment, annotation, public-log, whisper-durable. The substrate accepts any well-formed kind; it MAY mark unknown kinds as non-indexable until a kind contract is registered.
topic/key yes string Opaque topic identifier. The substrate MUST NOT parse, split, or type this value. Canonicalization rules: Unicode NFC, no control characters (C0/C1/DEL), no leading or trailing whitespace, non-empty, at most 512 bytes after UTF-8 encoding. Applications choose their own naming conventions (namespace-prefixed paths, content-derived identifiers, human-readable channel names). Topic keys derived from external resource identity are a convention of the record-kind contract, not a rule of the substrate.
author/participant-id yes string Participant identity or application-layer nym identity of the record author. Participant-authored records verify directly against the participant key or an explicit delegation proof. Nym-authored records MUST carry author/nym-proof, and the record signature verifies against the nym key certified by that proof.
author/nym-proof no ref: nym-authorship-proof.v1.schema.json Inline-first proof for nym-authored records. Required when author/participant-id starts with nym:did:key: and forbidden by the core verifier for participant-authored records. The proof context MUST match topic/key, record/kind, content/schema, and any relevant disclosure scope.
authored/at yes string Wall-clock timestamp asserted by the author at the moment of record creation. Relays enforce a clock skew window (default ±10 minutes) at ingest; out-of-window records are flagged and temporarily excluded from live query results.
content/schema yes string Identifier of the schema that describes the inner content payload. MUST follow the {slug}.v{n} shape. Examples: plain-comment.v1, public-log-entry.v1, resource-opinion.v1. The substrate does not require content/schema to be pre-registered; unknown schemas are stored and served but MAY be treated as opaque by indexers.
content yes object Payload object conforming to the schema named by content/schema. Kind contracts define field-level validation; the substrate performs envelope-level validation only.
record/about no array Optional secondary-index references to external subjects this record is about. Each entry follows the resource identity model from proposal 026. MUST NOT be used by the substrate to derive topic/key. A kind contract MAY require one or more entries for specific record kinds.
record/parent no string Optional parent record reference (reply, annotation, successor). MUST resolve to a record under the same topic/key. A record that references an as-yet-unknown parent is flagged dangling until the parent appears.
record/supersedes no string Optional prior record reference that this record revises or replaces. MUST resolve to a record under the same topic/key authored by the same author/participant-id, unless a kind contract explicitly relaxes the author constraint.
record/policy no string Optional policy record reference. For comment threads this SHOULD point to an Agora record with record/kind = thread-policy and content/schema = comment-thread-policy.v1. The policy record is part of domain authorization and is signed like any other Agora record; the substrate only validates the reference shape.
record/tags no array Optional short free-form tags for application-level grouping. The substrate does not interpret tag semantics.
record/lang no string Optional BCP 47 language tag describing the natural-language contents of the record. Informational only.
relay/received-at no string Wall-clock timestamp stamped by the relay that first ingested the record. MUST NOT appear in the payload the author signs. Stripped before record/id computation and signature verification.
relay/id no string Identifier of the relay that first ingested the record. MUST NOT appear in the payload the author signs. Stripped before record/id computation and signature verification.
relay/hops no integer Relay-local hop count stamped by relay implementations. The field is transport metadata, not author content: it MUST NOT appear in the payload the author signs and is stripped before record/id computation and signature verification.
signature yes ref: #/$defs/signature Ed25519 signature over the canonical payload of this record with signature, relay/received-at, relay/id, and relay/hops removed. Direct participant signatures verify with the participant key embedded in author/participant-id. Direct nym signatures verify with the nym key embedded in author/participant-id and require a verifier-usable author/nym-proof. Delegated signatures carry key/public (the proxy signing key) and key/delegation (an inline proof from proposal 032); verifiers first check the Ed25519 signature with key/public, then validate the delegation proof. Note that record/id is INCLUDED in the signed payload: the signature explicitly binds the content-address. record/id itself is a separate hash computed over a different canonical payload that additionally excludes record/id.

Definitions

Definition Shape Description
signature object
delegationProof object Compact bearer credential copied from a key-delegation.v1 artifact and embedded beside a proxy-key signature. The full semantics live in proposal 032; Agora treats this as an inline proof for delegated record signing.

Conditional Rules

Rule 1

When:

{
  "properties": {
    "author/participant-id": {
      "pattern": "^nym:did:key:"
    }
  },
  "required": [
    "author/participant-id"
  ]
}

Then:

{
  "required": [
    "author/nym-proof"
  ]
}

Field Semantics

schema

  • Required: yes
  • Shape: const: agora-record.v1

Schema discriminator. MUST be the literal string agora-record.v1.

record/id

  • Required: yes
  • Shape: string

Content-addressed identifier of this record. Computed by the Orbiplex canonical sha256_base64url helper: sha256: followed by the unpadded base64url (RFC 4648 section 5) encoding of sha256(canonicalize(payload)), where payload is the record with record/id, signature, relay/received-at, relay/id, and relay/hops removed. Two records with the same canonical payload MUST yield the same record/id on every relay.

Maintainer note: Canonicalization rules (key sorting, number normalization, Unicode NFC) are defined by the orbiplex-agora-core library and MUST match across implementations. The sha256:<base64url-no-pad> shape matches the convention already used by node/capability/src/lib.rs::sha256_base64url for signed artifacts and passport hashes.

record/kind

  • Required: yes
  • Shape: string

Role label of this record. Application-visible discriminator used by query APIs and kind contracts. Examples: opinion, comment, annotation, public-log, whisper-durable. The substrate accepts any well-formed kind; it MAY mark unknown kinds as non-indexable until a kind contract is registered.

topic/key

  • Required: yes
  • Shape: string

Opaque topic identifier. The substrate MUST NOT parse, split, or type this value. Canonicalization rules: Unicode NFC, no control characters (C0/C1/DEL), no leading or trailing whitespace, non-empty, at most 512 bytes after UTF-8 encoding. Applications choose their own naming conventions (namespace-prefixed paths, content-derived identifiers, human-readable channel names). Topic keys derived from external resource identity are a convention of the record-kind contract, not a rule of the substrate.

Maintainer note: The ^\S(.*\S)?$ pattern rejects leading and trailing whitespace. Unicode NFC normalization and the byte-length bound are enforced by orbiplex-agora-core since JSON Schema cannot express them directly.

author/participant-id

  • Required: yes
  • Shape: string

Participant identity or application-layer nym identity of the record author. Participant-authored records verify directly against the participant key or an explicit delegation proof. Nym-authored records MUST carry author/nym-proof, and the record signature verifies against the nym key certified by that proof.

author/nym-proof

  • Required: no
  • Shape: ref: nym-authorship-proof.v1.schema.json

Inline-first proof for nym-authored records. Required when author/participant-id starts with nym:did:key: and forbidden by the core verifier for participant-authored records. The proof context MUST match topic/key, record/kind, content/schema, and any relevant disclosure scope.

authored/at

  • Required: yes
  • Shape: string

Wall-clock timestamp asserted by the author at the moment of record creation. Relays enforce a clock skew window (default ±10 minutes) at ingest; out-of-window records are flagged and temporarily excluded from live query results.

content/schema

  • Required: yes
  • Shape: string

Identifier of the schema that describes the inner content payload. MUST follow the {slug}.v{n} shape. Examples: plain-comment.v1, public-log-entry.v1, resource-opinion.v1. The substrate does not require content/schema to be pre-registered; unknown schemas are stored and served but MAY be treated as opaque by indexers.

content

  • Required: yes
  • Shape: object

Payload object conforming to the schema named by content/schema. Kind contracts define field-level validation; the substrate performs envelope-level validation only.

record/about

  • Required: no
  • Shape: array

Optional secondary-index references to external subjects this record is about. Each entry follows the resource identity model from proposal 026. MUST NOT be used by the substrate to derive topic/key. A kind contract MAY require one or more entries for specific record kinds.

record/parent

  • Required: no
  • Shape: string

Optional parent record reference (reply, annotation, successor). MUST resolve to a record under the same topic/key. A record that references an as-yet-unknown parent is flagged dangling until the parent appears.

record/supersedes

  • Required: no
  • Shape: string

Optional prior record reference that this record revises or replaces. MUST resolve to a record under the same topic/key authored by the same author/participant-id, unless a kind contract explicitly relaxes the author constraint.

record/policy

  • Required: no
  • Shape: string

Optional policy record reference. For comment threads this SHOULD point to an Agora record with record/kind = thread-policy and content/schema = comment-thread-policy.v1. The policy record is part of domain authorization and is signed like any other Agora record; the substrate only validates the reference shape.

record/tags

  • Required: no
  • Shape: array

Optional short free-form tags for application-level grouping. The substrate does not interpret tag semantics.

record/lang

  • Required: no
  • Shape: string

Optional BCP 47 language tag describing the natural-language contents of the record. Informational only.

relay/received-at

  • Required: no
  • Shape: string

Wall-clock timestamp stamped by the relay that first ingested the record. MUST NOT appear in the payload the author signs. Stripped before record/id computation and signature verification.

relay/id

  • Required: no
  • Shape: string

Identifier of the relay that first ingested the record. MUST NOT appear in the payload the author signs. Stripped before record/id computation and signature verification.

relay/hops

  • Required: no
  • Shape: integer

Relay-local hop count stamped by relay implementations. The field is transport metadata, not author content: it MUST NOT appear in the payload the author signs and is stripped before record/id computation and signature verification.

signature

  • Required: yes
  • Shape: ref: #/$defs/signature

Ed25519 signature over the canonical payload of this record with signature, relay/received-at, relay/id, and relay/hops removed. Direct participant signatures verify with the participant key embedded in author/participant-id. Direct nym signatures verify with the nym key embedded in author/participant-id and require a verifier-usable author/nym-proof. Delegated signatures carry key/public (the proxy signing key) and key/delegation (an inline proof from proposal 032); verifiers first check the Ed25519 signature with key/public, then validate the delegation proof. Note that record/id is INCLUDED in the signed payload: the signature explicitly binds the content-address. record/id itself is a separate hash computed over a different canonical payload that additionally excludes record/id.

Maintainer note: Two distinct canonical payloads are used in this schema: (1) the record/id payload excludes record/id + signature + relay fields; (2) the signature payload excludes only signature + relay fields and keeps record/id. This matches the Matrix event-signing pattern where event_id is embedded in the signed content and gives wider cross-transport compatibility.

Definition Semantics

$defs.signature

  • Shape: object

$defs.delegationProof

  • Shape: object

Compact bearer credential copied from a key-delegation.v1 artifact and embedded beside a proxy-key signature. The full semantics live in proposal 032; Agora treats this as an inline proof for delegated record signing.