ak.schema.approval_signature.v1
ak.schema.approval_signature.v1 · file: schemas/approval-signature.schema.json The single approval evidence type of v1 (zh/authz/constraint-schema.md section 9.2). One approver signs one exact target: either a fully authored Event that has not been submitted yet, or the original typed RequestBody of one operation whose evidence carrier is registered in capability-action-registry.json. The object is not an Event, never enters Realm history, and MUST NOT be written into an EventEnvelope, a signed payload or an Event semantic_refs[] entry. It travels in the carrier registered for the approved action. It proves that an approver approved that target; it proves nothing about the initiator's own authority.
* $ · object
The single approval evidence type of v1 (zh/authz/constraint-schema.md section 9.2). One approver signs one exact target: either a fully authored Event that has not been submitted yet, or the original typed RequestBody of one operation whose evidence carrier is registered in capability-action-registry.json. The object is not an Event, never enters Realm history, and MUST NOT be written into an EventEnvelope, a signed payload or an Event semantic_refs[] entry. It travels in the carrier registered for the approved action. It proves that an approver approved that target; it proves nothing about the initiator's own authority.
* input · object · $ref #/$defs/approval_signature_input
The complete signed semantics. signing_bytes are UTF8("ak.approval.signature.v1") || 0x0A || JCS(input): the registered primitive is the signing input itself, never a JSON digest that is signed in a second step. JCS orders object keys, so this schema fixes no field order. Every member is required and the object is closed: a missing or extra member is a schema_violation, not a signature_invalid, and an absent member MUST NOT be reconstructed as null or as a local default.
allOf · allOf[0] ·
?* approval_context · oneOf[4] · $ref #/$defs/approval_context
Which independent requirement this signature answers. Grant, Realm governance and List WIP votes use the same signed input, proof, carrier and nonce rules; their quorums remain independent. A List WIP signature binds the exact List metadata current revision and cannot be counted as a grant or Realm governance vote (zh/models/space-hierarchy.md section 6; zh/authz/constraint-schema.md section 9.2).
oneOf · oneOf[0] · object
* context_kind ·
const "grant"enum:
"grant"* grant_id ·
string · $ref ./common-ids.schema.json#/$defs/grant_idThe approval requirement carried by one specific capability grant (zh/authz/constraint-schema.md section 9.1). It MUST be one of the satisfied dependency grants of this execution.
pattern:
^ak:grant:[A-Za-z0-9_-]{44}$oneOf · oneOf[1] · object
* context_kind ·
const "realm_governance"enum:
"realm_governance"oneOf · oneOf[2] · object
* context_kind ·
const "list_wip"enum:
"list_wip"* list_space_id ·
string · $ref ./event-payload.schema.json#/$defs/space_idpattern:
^ak:space:[A-Za-z0-9_-]{44}$* list_policy_revision · object · $ref ./typed-current-result.schema.json#/$defs/revision
* commit_id ·
string · $ref ./common-ids.schema.json#/$defs/realm_commit_idContent-addressed identity of a closed unsigned RealmCommit body. The suffix uses the fixed v1 digest suite and the same canonical 33-octet token encoding as Event IDs.
pattern:
^ak:realm_commit:[A-Za-z0-9_-]{44}$* stream_position ·
integeroneOf · oneOf[3] · object
* context_kind ·
const "management"enum:
"management"* management_operation ·
string (enum)enum:
"join" "publish" "create_bot" "map_ghost"* effective_scope · oneOf[2] · $ref ./applet-install-plan.schema.json#/$defs/effective_scope
oneOf · oneOf[0] · object
* kind ·
const "realm"enum:
"realm"* realm_id ·
string · $ref ./common-ids.schema.json#/$defs/realm_idRetyped ak.realm.create Event token. It therefore carries the same fixed current-v1 0x01/SHA-256 content-address identity and is not selected by Realm state.
pattern:
^ak:realm:[A-Za-z0-9_-]{44}$oneOf · oneOf[1] · object
* kind ·
const "circle"enum:
"circle"* realm_id ·
string · $ref ./common-ids.schema.json#/$defs/realm_idRetyped ak.realm.create Event token. It therefore carries the same fixed current-v1 0x01/SHA-256 content-address identity and is not selected by Realm state.
pattern:
^ak:realm:[A-Za-z0-9_-]{44}$* circle_id ·
string · $ref ./common-ids.schema.json#/$defs/circle_idpattern:
^ak:circle:[A-Za-z0-9_-]{44}$* request_id ·
string · $ref ./realm-join-intake.schema.json#/$defs/request_idpattern:
^ak:request:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* approval_target · oneOf[2] · $ref #/$defs/approval_target
The exact approved target, which also selects the original input of request_canonical_digest. An approval MUST NOT bind a bare principal, a displayable target name or part of a payload instead.
oneOf · oneOf[0] · object
* target_kind ·
const "event"enum:
"event"* event_id ·
string · $ref ./common-ids.schema.json#/$defs/event_idComplete Arkret Event cryptographic identity. The suffix is the canonical unpadded Base64URL encoding of exactly 33 octets: fixed current-v1 suite code 0x01 followed by all 32 octets of the SHA-256 Event digest. Regex validation is only lexical; receivers MUST decode, require 33 octets, require byte 0 == 0x01, canonical re-encode, and verify the full digest before use. Other registered digest suites remain available only to the typed domains that explicitly select them and MUST NOT appear in Event IDs.
pattern:
^ak:event:[A-Za-z0-9_-]{44}$oneOf · oneOf[1] · object
* target_kind ·
const "operation"enum:
"operation"* request_canonical_digest ·
string · $ref ./account-operations.schema.json#/$defs/sha256_digestSHA-256 over the RFC 8785 JCS bytes of the original input selected by approval_target: the complete authored Event including its own producer proof for the event branch, the original typed RequestBody for the operation branch. The evidence container is outside that original input and never contributes to this digest. This digest and the HTTP Content-Digest over the actually transmitted body, which does include the evidence container, are two independent checks; each MUST be performed and neither substitutes for the other.
pattern:
^sha256:[0-9a-f]{64}$* operation ·
stringThe registered operation token of the entry point that carries this execution, as listed in registry/operation-registry.json. An unregistered value is a schema_violation. It pins which entry point the approval was given for, so the same action replayed through another operation MUST fail.
pattern:
^ak\.[a-z0-9_]+(?:\.[a-z0-9_]+)*\.v1$* action ·
stringThe approved capability action token, identical to the element of the grant actions[] array that the execution matches (zh/authz/capabilities.md section 5).
pattern:
^ak\.[a-z0-9_]+(\.[a-z0-9_]+)*$* realm_id ·
string · $ref ./common-ids.schema.json#/$defs/realm_idRetyped ak.realm.create Event token. It therefore carries the same fixed current-v1 0x01/SHA-256 content-address identity and is not selected by Realm state.
pattern:
^ak:realm:[A-Za-z0-9_-]{44}$* initiating_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* approver_did ·
string · $ref ./common-ids.schema.json#/$defs/didCanonical bare DID used for registration, DID method resolution and owner-published current resolution. It contains no path, query or fragment and MUST project through the registered method adapter to exactly one did_core_id.
pattern:
^did:[a-z0-9]+:[^\s/?#]+$* approved_at ·
string (date-time) · format=date-time · $ref ./time.schema.json#/$defs/timestampCanonical Arkret-owned absolute instant. UTC Z form with exactly three millisecond digits. Whole seconds MUST use .000Z; offsets, missing/finer fractions, lowercase separators, leap seconds, and invalid Gregorian calendar dates are forbidden. Shape validation by this pattern is supplemented by semantic date validation.
pattern:
^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$* nonce ·
stringApprover-private, per-approval unique random string carrying at least 128 bits of entropy. Its namespace is (approval_context, approver_did) and it MUST NOT be shared with the ak.agent.action_approve confirmation nonce, with any challenge, or with any other signature evidence. It is consumed only when the target is successfully accepted, in that same transaction.
* proof · object · $ref #/$defs/approval_signature_proof
The single detached signature over signing_bytes. It is a locally anchored signing domain, not the shared event-envelope detached-proof leaf: that leaf signs a binding object carrying a payload_digest, whereas this domain registers the signing input itself. proof is never a member of input, so no container field outside input is covered. verification_method is not signed and carries no authority of its own: it only selects a key, and it MUST resolve through the signed approver_did, so substituting it yields an invalid signature.
* kind ·
const "detached_jws"enum:
"detached_jws"* verification_method ·
string · $ref ./common-ids.schema.json#/$defs/did_urlArkret verification-method DID URL profile (identity/did-usage-and-verification.md section 2.2): lowercase method name, no query, required fragment, fragment limited to ASCII [A-Za-z0-9._:-]. Every verification_method-family field and every kid/key_ref a schema declares to be a DID URL MUST resolve to exactly this definition; values compare byte-for-byte with no URI normalization or percent-decoding.
pattern:
^did:[a-z0-9]+:[^\s#?]+#[A-Za-z0-9._:-]+$* jws ·
stringCompact detached JWS whose payload is signing_bytes. The signature algorithm comes from registry/signature-alg-registry.json; this domain introduces no second proof suite and no locally assembled key material.
pattern:
^[A-Za-z0-9_-]+\.\.[A-Za-z0-9_-]+$Source
- registry row:
spec/v1/artifacts/registry/schema-registry.json - schema document:
spec/v1/artifacts/schemas/approval-signature.schema.json