{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://real-life.org/rltp/v1/schemas/access-registration.schema.json",
  "title": "RLTP Service Registration (Access Layer 0.24 section 7.3)",
  "description": "The versioned wire artifact by which a group registers at a service (trust-on-first-use binding genesisDigest -> view chain). Signature input = JCS serialization with sig omitted; sig MUST verify under the named identity field (the seq-0 service identity, which MUST also sign the seq-0 view). service names the ONE service this registration is for — a service MUST reject a registration not naming itself (no cross-service replay). Durations use the profile day/time subset with fixed-seconds arithmetic (Access 7.3); divergenceQuota is the retained-full-artifact bound of Access 7.3 obligation 5 (the digest skeleton is hard-bounded at 8 x divergenceQuota entries with mandatory compaction). Out-of-range values, missing fields, or a failing signature make the registration invalid — services MUST NOT repair or default them.",
  "type": "object",
  "required": [
    "v",
    "type",
    "group",
    "genesisDigest",
    "identity",
    "service",
    "m",
    "stalenessBound",
    "terminalRetention",
    "divergenceQuota",
    "sig"
  ],
  "additionalProperties": false,
  "properties": {
    "v": {
      "const": "rltp-access-registration/0.24"
    },
    "type": {
      "const": "service-registration"
    },
    "group": {
      "$ref": "#/$defs/didKey"
    },
    "genesisDigest": {
      "$ref": "#/$defs/digest"
    },
    "identity": {
      "$ref": "#/$defs/didKey",
      "description": "the seq-0 derived service identity: sig verifies under it, and the seq-0 view MUST be signed by exactly it"
    },
    "service": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256,
      "description": "canonical identifier of the one service this registration is for; comparison is EXACT BYTE EQUALITY of the UTF-8 string, no normalization of any kind (no case folding, percent-decoding, default-port or trailing-slash equivalence, no alias or DID resolution) — a service is configured with exactly one canonical string (RECOMMENDED: a service DID or an absolute https URI) and MUST reject a registration whose service field is not byte-identical to it (Access 7.3)"
    },
    "m": {
      "const": 1,
      "description": "the initial quorum size is always 1 (the seq-0 identity seeds the chain); growth happens via the m field of later views (Access 7.3)"
    },
    "stalenessBound": {
      "$ref": "#/$defs/duration",
      "description": "maximum validUntil - issuedAt a view may claim (Access 7.3 obligation 1)"
    },
    "terminalRetention": {
      "$ref": "#/$defs/duration",
      "description": "terminal grace window, measured from the service's local acceptance of a terminal view (Access 7.3 obligation 5); RECOMMENDED default P30D"
    },
    "divergenceQuota": {
      "type": "integer",
      "minimum": 16,
      "maximum": 4096,
      "description": "bound on retained full view artifacts per group while fail-closed (Access 7.3 obligation 5); RECOMMENDED default 64"
    },
    "sig": {
      "type": "string",
      "pattern": "^z[1-9A-HJ-NP-Za-km-z]+$",
      "maxLength": 128,
      "description": "signature by the seq-0 service identity over the JCS serialization with sig omitted"
    }
  },
  "$defs": {
    "didKey": {
      "type": "string",
      "pattern": "^did:key:z6Mk[1-9A-HJ-NP-Za-km-z]{44}$"
    },
    "digest": {
      "type": "string",
      "pattern": "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$",
      "maxLength": 128
    },
    "duration": {
      "type": "string",
      "pattern": "^P(?!$)(\\d{1,3}D)?(T(?=\\d)(\\d{1,3}H)?(\\d{1,3}M)?(\\d{1,3}S)?)?$",
      "maxLength": 20,
      "description": "profile day/time subset: PnD and/or TnHnMnS in descending order, 1-3 digits each, no years/months/weeks; arithmetic is fixed-seconds (1D = 86400 s)"
    }
  }
}
