ak.schema.push_operations.v1
ak.schema.push_operations.v1 · file: schemas/push-operations.schema.json Closed request and response DTOs for Station device registration, trusted public-Gateway registration handoff, and push notification delivery.
* $ · anyOf[7]
Closed request and response DTOs for Station device registration, trusted public-Gateway registration handoff, and push notification delivery.
anyOf · anyOf[0] · object · $ref #/$defs/push_register_device_request_body
Account Station self-service registration. The authenticated exact AccountId supplies registration scope and its station_id must equal the receiving Station service identity. A push_gateway role cannot accept this operation on its own authority.
* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* push_gateway_url · allOf[2]
allOf · allOf[0] ·
string (uri) · format=uri · $ref #/$defs/uriallOf · allOf[1] ·
?pattern:
^https://* push_key ·
string · $ref #/$defs/push_keyplatform ·
string · $ref #/$defs/non_empty_stringapp_id · allOf[2]
allOf · allOf[0] ·
string · $ref #/$defs/non_empty_stringallOf · allOf[1] ·
? · $ref string-profiles.schema.json#/$defs/non_typed_identifier_floorLexical floor of every identifier value category that does NOT own the ak: namespace (opaque_correlation, document_local_symbol, external_system_identifier, registry_catalog_symbol, unregistered_object_identifier); see common-fields.md 2.1. The negative lookahead IS the floor: it mechanically proves the value cannot be an ak: typed id, which maxLength alone can never prove, while admitting every other value the field already accepted. It deliberately constrains nothing else - the per-field convergence direction (a registered typed kind, or a tighter opaque profile) is decided per object family, so a pattern-only floor composes with whatever profile the field already carries instead of pre-empting it.
pattern:
^(?!ak:)display_name ·
string (arkret-single-line-display-text) · format=arkret-single-line-display-text · $ref string-profiles.schema.json#/$defs/display_text_256NFC multilingual single-line display text; mixed scripts, emoji, and symbols are allowed.
pattern:
^[^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*[^\s\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF][^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*$visible_notification_opt_in ·
booleanReceiver device authorization state for ak.profile.push_gateway.visible_notification.v1. Missing or false means this device MUST receive only blind_wakeup output even if the caller service is plaintext-visible; visible metadata requires an explicit per-device opt-in.
example:
falseanyOf · anyOf[1] · object · $ref #/$defs/push_register_device_outcome
* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* registration_id ·
string · $ref #/$defs/registration_idStation-generated, high-entropy, pairwise registration identity scoped to one exact AccountId/device/push route and destination Gateway. It is not an Arkret typed ID, MUST NOT begin with ak:, MUST NOT encode account or provider material, and MUST never be reused after terminal revocation. A replacement allocates a new registration_id and names the exact predecessor through supersedes_registration_id.
pattern:
^(?!ak:)[A-Za-z0-9._~-]{22,128}$expires_at ·
string (date-time) · format=date-time · $ref #/$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$anyOf · anyOf[2] · object · $ref #/$defs/push_unregister_device_request_body
Account Station self-service unregistration under the same exact authenticated AccountId/device authority as registration; gateway notify authority is insufficient.
* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$push_key ·
string · $ref #/$defs/push_keyapp_id · allOf[2]
allOf · allOf[0] ·
string · $ref #/$defs/non_empty_stringallOf · allOf[1] ·
? · $ref string-profiles.schema.json#/$defs/non_typed_identifier_floorLexical floor of every identifier value category that does NOT own the ak: namespace (opaque_correlation, document_local_symbol, external_system_identifier, registry_catalog_symbol, unregistered_object_identifier); see common-fields.md 2.1. The negative lookahead IS the floor: it mechanically proves the value cannot be an ak: typed id, which maxLength alone can never prove, while admitting every other value the field already accepted. It deliberately constrains nothing else - the per-field convergence direction (a registered typed kind, or a tighter opaque profile) is decided per object family, so a pattern-only floor composes with whatever profile the field already carries instead of pre-empting it.
pattern:
^(?!ak:)anyOf · anyOf[3] · oneOf[2] · $ref #/$defs/push_registration_handoff_request_body
Station-to-Gateway desired registration state. The HTTP Message Signature binds exact Source-Service-ID, Destination-Service-ID and Content-Digest. The Gateway keys state by authenticated source tenant plus registration_id; a byte-identical replay returns the original receipt, different content for the same key is duplicate_conflict, and revoked is terminal.
oneOf · oneOf[0] · object · $ref #/$defs/push_registration_handoff_active
Immutable active installation submitted by the authenticated source Station to one trusted public Gateway. Source and destination service identities are carried only by signed HTTP headers. The source Station is the only notify source authorized by this minimal handoff contract; delegation is not inferred from profile claims or body fields.
* registration_id ·
string · $ref #/$defs/registration_idStation-generated, high-entropy, pairwise registration identity scoped to one exact AccountId/device/push route and destination Gateway. It is not an Arkret typed ID, MUST NOT begin with ak:, MUST NOT encode account or provider material, and MUST never be reused after terminal revocation. A replacement allocates a new registration_id and names the exact predecessor through supersedes_registration_id.
pattern:
^(?!ak:)[A-Za-z0-9._~-]{22,128}$* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* state ·
const "active"enum:
"active"* push_key ·
string · $ref #/$defs/push_keyProvider route secret disclosed only to the destination Gateway's authenticated Source-Service-ID tenant partition. It MUST NOT enter notify, receipts, logs, metrics, traces, cross-tenant indexes, or provider payload fields other than the provider address required for delivery.
platform ·
string · $ref #/$defs/non_empty_stringapp_id · allOf[2]
allOf · allOf[0] ·
string · $ref #/$defs/non_empty_stringallOf · allOf[1] ·
? · $ref string-profiles.schema.json#/$defs/non_typed_identifier_floorLexical floor of every identifier value category that does NOT own the ak: namespace (opaque_correlation, document_local_symbol, external_system_identifier, registry_catalog_symbol, unregistered_object_identifier); see common-fields.md 2.1. The negative lookahead IS the floor: it mechanically proves the value cannot be an ak: typed id, which maxLength alone can never prove, while admitting every other value the field already accepted. It deliberately constrains nothing else - the per-field convergence direction (a registered typed kind, or a tighter opaque profile) is decided per object family, so a pattern-only floor composes with whatever profile the field already carries instead of pre-empting it.
pattern:
^(?!ak:)* visible_notification_opt_in ·
booleanExact device opt-in derived by the source Station. False restricts the installation to blind wakeup even when the Gateway also advertises the visible-notification profile.
expires_at ·
string (date-time) · format=date-time · $ref #/$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$supersedes_registration_id ·
string · $ref #/$defs/registration_idStation-generated, high-entropy, pairwise registration identity scoped to one exact AccountId/device/push route and destination Gateway. It is not an Arkret typed ID, MUST NOT begin with ak:, MUST NOT encode account or provider material, and MUST never be reused after terminal revocation. A replacement allocates a new registration_id and names the exact predecessor through supersedes_registration_id.
pattern:
^(?!ak:)[A-Za-z0-9._~-]{22,128}$oneOf · oneOf[1] · object · $ref #/$defs/push_registration_handoff_revoked
Terminal handoff tombstone. It carries no provider route, application metadata, opt-in, account identity, or replacement value. The Gateway retains the minimal (source Station, registration_id, request digest, outcome) high-water needed to reject a delayed active install after private material is erased.
* registration_id ·
string · $ref #/$defs/registration_idStation-generated, high-entropy, pairwise registration identity scoped to one exact AccountId/device/push route and destination Gateway. It is not an Arkret typed ID, MUST NOT begin with ak:, MUST NOT encode account or provider material, and MUST never be reused after terminal revocation. A replacement allocates a new registration_id and names the exact predecessor through supersedes_registration_id.
pattern:
^(?!ak:)[A-Za-z0-9._~-]{22,128}$* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* state ·
const "revoked"enum:
"revoked"anyOf · anyOf[4] · object · $ref #/$defs/push_registration_handoff_outcome
* receipt · object · $ref #/$defs/push_registration_installation_receipt
Gateway-signed durable confirmation that the exact active installation or terminal tombstone was committed in the authenticated source Station tenant before success. The receipt grants no Account authority and contains no provider token.
* registration_id ·
string · $ref #/$defs/registration_idStation-generated, high-entropy, pairwise registration identity scoped to one exact AccountId/device/push route and destination Gateway. It is not an Arkret typed ID, MUST NOT begin with ak:, MUST NOT encode account or provider material, and MUST never be reused after terminal revocation. A replacement allocates a new registration_id and names the exact predecessor through supersedes_registration_id.
pattern:
^(?!ak:)[A-Za-z0-9._~-]{22,128}$* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* state ·
string (enum)enum:
"active" "revoked"* request_digest ·
stringSHA-256 of RFC 8785 JCS of the complete handoff request body. It binds provider route bytes without repeating them in the receipt.
pattern:
^sha256:[0-9a-f]{64}$* source_station_id ·
string · $ref ./common-ids.schema.json#/$defs/did_core_idCanonical stable DID-derived identity core. The lowercase DID method name follows ak:did_core:, and the remaining method-adapter-defined core is opaque to generic consumers. The did:web v1 adapter uses the complete canonical method-specific-id, never a digest or truncated host. Principal-core and service-core equality is byte-for-byte equality of the complete did_core_id. Event actor and Realm membership equality instead use the complete closed ActorId, and account-scoped equality uses the complete AccountId; neither may be reduced to a principal core. A did_core_id is not a DID and cannot be resolved without a did or AuthenticatedServiceResolution.
pattern:
^ak:did_core:[a-z0-9]+:[^\s/?#]+$* destination_gateway_id ·
string · $ref ./common-ids.schema.json#/$defs/did_core_idCanonical stable DID-derived identity core. The lowercase DID method name follows ak:did_core:, and the remaining method-adapter-defined core is opaque to generic consumers. The did:web v1 adapter uses the complete canonical method-specific-id, never a digest or truncated host. Principal-core and service-core equality is byte-for-byte equality of the complete did_core_id. Event actor and Realm membership equality instead use the complete closed ActorId, and account-scoped equality uses the complete AccountId; neither may be reduced to a principal core. A did_core_id is not a DID and cannot be resolved without a did or AuthenticatedServiceResolution.
pattern:
^ak:did_core:[a-z0-9]+:[^\s/?#]+$* stored_at ·
string (date-time) · format=date-time · $ref #/$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$* proof · object · $ref ./event-envelope.schema.json#/$defs/proof
Generic detached-JWS proof shape reused by non-Event schemas (snapshot signature, snapshot witness attestations, identity receipts, handle claims, etc.). MUST NOT be used as the shape of Event Envelope `producer_proof` — Event proofs reference $defs/event_proof and bind canonical Event bytes via `event_digest`. Non-Event signed objects MUST define an object-family signing-context constant and include it in the canonical proof binding object with payload_digest; the context constant is not a wire field in this generic shape. drift detection: `payload_digest#event_proof` in forbidden-wire-fields.json is the hard-reject mirror of this rule. New non-Event signed objects MAY $ref this shape; new signed Event-shaped objects MUST instead $ref event_proof.
* kind ·
string (enum)Generic detached JWS proof over a canonical non-Event payload binding object that includes an object-family context constant.
enum:
"detached_jws"* verification_method ·
stringDID URL of the signing key for this non-Event detached proof. Same pattern as $defs/event_proof.verification_method; semantics are decoupled from Event proof (see $defs/event_proof for the Event-only shape).
pattern:
^did:[a-z0-9]+:[^\s#?]+#[A-Za-z0-9._:-]+$* payload_digest ·
$ref #/$defs/digest · $ref #/$defs/digestGeneric non-Event detached-proof hash. This $defs/proof shape is reused by non-Event schemas; Event.properties.producer_proof references $defs/event_proof and MUST use event_digest instead.
* created_at ·
string (date-time) · format=date-time · $ref #/$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$domain ·
stringaudience · oneOf[2]
oneOf · oneOf[0] ·
stringoneOf · oneOf[1] · array<string>
items ·
stringproof_purpose ·
string (enum)Optional role discriminator for non-Event proofs. HandleClaim core, status and revocation carriers make issuer_attestation, holder_acceptance, status_attestation and revocation_authorization load-bearing. governance_authorization marks a resource-governance-key authorization (directory withdraw/takedown-appeal, discovery-directory.md 8.7.1). Generic proof consumers ignore it unless their object-family contract makes it load-bearing.
enum:
"issuer_attestation" "holder_acceptance" "status_attestation" "revocation_authorization" "governance_authorization"* jws ·
stringpattern:
^[A-Za-z0-9_-]+\.\.[A-Za-z0-9_-]+$anyOf · anyOf[5] · object · $ref #/$defs/push_notify_request_body
Closed Arkret notify body. Product-private notification bodies, provider adapter payloads, APNs/FCM/WebPush data dictionaries, `content`, `content_*`, `provider_payload`, DND/snooze state, and push-rule plaintext are outside this wire surface and MUST be consumed before this body is built. Provider-facing payloads are reconstructed by the gateway from this closed shape and MUST strip route_tokens / reason_code / event_kind / audit_envelope before provider dispatch.
* notification · oneOf[2]
oneOf · oneOf[0] · object · $ref #/$defs/blind_notification
* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* wakeup_kind ·
string (enum)enum:
"message" "mention" "assignment" "schedule" "reaction" "call_invite" "reminder" "scheduled_send" "expiry_invalidation"push_hint ·
string (enum)Sanitized hint sentinel. When the value is "l10n_key" the actual localization key MUST be carried in push_hint_l10n_key (this enum value is a form selector, not a literal display token). See push-notifications.md §5.1 / §4.5.
enum:
"new_message" "incoming_call" "mention_self" "l10n_key"push_hint_l10n_key ·
string · $ref #/$defs/non_empty_stringLocalization key value, only present (and required) when push_hint == "l10n_key". MUST be an l10n key token, never plaintext body or any identifying metadata.
evaluation_locus_unresolved ·
booleanSet true when the client has been woken but server-side rule matching is not yet resolved (E2EE client-side rule fallback). Pure local-evaluation signal; carries no metadata. See push-notifications.md §4.5.
counts · object · $ref #/$defs/counts
badge · oneOf[2]
Coarse unread indicator. Under blind_wakeup it MUST NOT carry a plaintext absolute unread count (activity side channel); only a boolean presence flag or a policy-declared bucket string is allowed. See push-notifications.md §5.1.
oneOf · oneOf[0] ·
booleanoneOf · oneOf[1] ·
stringpattern:
^(?:0|[1-9][0-9]*(?:-[1-9][0-9]*|\+)?)$unread_increment ·
integermissed_call · oneOf[2]
Coarse missed-call indicator. Under blind_wakeup it MUST NOT carry a plaintext absolute count; only a boolean presence flag or the policy-declared bucket string is allowed. See push-notifications.md §5.1.
oneOf · oneOf[0] ·
booleanoneOf · oneOf[1] ·
stringpattern:
^(?:0|[1-9][0-9]*(?:-[1-9][0-9]*|\+)?)$route_tokens · object · $ref #/$defs/route_tokens
Gateway-internal opaque routing fragment shared by blind and visible notifications. Every field here drives gateway-side routing / dedup / circuit-breaker state and MUST be stripped before the gateway calls any push provider; it MUST NOT be forwarded to a provider. Tokens are issued by the destination Principal Service and bound to that service DID, push gateway service DID, purpose, scope, and salt epoch.
realm_route_token ·
string · $ref #/$defs/push_route_tokenOpaque service-generated routing token. It MUST NOT contain, encode, or be reversibly derived from a DID, DID URL, Realm id, Circle id, Strand id, Message id, Event id, handle, platform push token, or stable cross-context correlation key.
pattern:
^[A-Za-z0-9._~-]{22,512}$scope_route_token ·
string · $ref #/$defs/push_route_tokenOpaque service-generated routing token. It MUST NOT contain, encode, or be reversibly derived from a DID, DID URL, Realm id, Circle id, Strand id, Message id, Event id, handle, platform push token, or stable cross-context correlation key.
pattern:
^[A-Za-z0-9._~-]{22,512}$* devices · array<$ref #/$defs/device_route>
Nonempty unique device_id set. Routes, platform, application and visible-notification opt-in are resolved exclusively from authenticated current device registrations.
items · object · $ref #/$defs/device_route
Per-notification device selector only. The gateway obtains provider token, application, platform and explicit visible-notification opt-in solely from authenticated durable registration, and derives timing from source service, selected route and declared profile.
* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$oneOf · oneOf[1] · object · $ref #/$defs/visible_notification
* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* wakeup_kind ·
string (enum)enum:
"message" "mention" "assignment" "schedule" "reaction" "call_invite" "reminder" "scheduled_send" "expiry_invalidation"push_hint ·
string (enum)Sanitized hint sentinel. When the value is "l10n_key" the actual localization key MUST be carried in push_hint_l10n_key (this enum value is a form selector, not a literal display token). See push-notifications.md §5.1 / §4.5.
enum:
"new_message" "incoming_call" "mention_self" "l10n_key"push_hint_l10n_key ·
string · $ref #/$defs/non_empty_stringLocalization key value, only present (and required) when push_hint == "l10n_key".
evaluation_locus_unresolved ·
booleanSet true when the client has been woken but server-side rule matching is not yet resolved. See push-notifications.md §4.5.
counts · object · $ref #/$defs/counts
badge · oneOf[2]
Coarse unread indicator. Under blind_wakeup it MUST NOT carry a plaintext absolute unread count (activity side channel); only a boolean presence flag or a policy-declared bucket string is allowed. See push-notifications.md §5.1.
oneOf · oneOf[0] ·
booleanoneOf · oneOf[1] ·
stringpattern:
^(?:0|[1-9][0-9]*(?:-[1-9][0-9]*|\+)?)$unread_increment ·
integermissed_call · oneOf[2]
Coarse missed-call indicator. Under blind_wakeup it MUST NOT carry a plaintext absolute count; only a boolean presence flag or the policy-declared bucket string is allowed. See push-notifications.md §5.1.
oneOf · oneOf[0] ·
booleanoneOf · oneOf[1] ·
stringpattern:
^(?:0|[1-9][0-9]*(?:-[1-9][0-9]*|\+)?)$route_tokens · object · $ref #/$defs/route_tokens
Gateway-internal opaque routing fragment shared by blind and visible notifications. Every field here drives gateway-side routing / dedup / circuit-breaker state and MUST be stripped before the gateway calls any push provider; it MUST NOT be forwarded to a provider. Tokens are issued by the destination Principal Service and bound to that service DID, push gateway service DID, purpose, scope, and salt epoch.
realm_route_token ·
string · $ref #/$defs/push_route_tokenOpaque service-generated routing token. It MUST NOT contain, encode, or be reversibly derived from a DID, DID URL, Realm id, Circle id, Strand id, Message id, Event id, handle, platform push token, or stable cross-context correlation key.
pattern:
^[A-Za-z0-9._~-]{22,512}$scope_route_token ·
string · $ref #/$defs/push_route_tokenOpaque service-generated routing token. It MUST NOT contain, encode, or be reversibly derived from a DID, DID URL, Realm id, Circle id, Strand id, Message id, Event id, handle, platform push token, or stable cross-context correlation key.
pattern:
^[A-Za-z0-9._~-]{22,512}$* devices · array<$ref #/$defs/device_route>
Nonempty unique device_id set. Routes, platform, application and visible-notification opt-in are resolved exclusively from authenticated current device registrations.
items · object · $ref #/$defs/device_route
Per-notification device selector only. The gateway obtains provider token, application, platform and explicit visible-notification opt-in solely from authenticated durable registration, and derives timing from source service, selected route and declared profile.
* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* event_id ·
string · $ref #/$defs/event_idpattern:
^ak:event:[A-Za-z0-9_-]{44}$* 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}$* sender_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_idstrand_id ·
string · $ref #/$defs/strand_idpattern:
^ak:strand:[A-Za-z0-9_-]{44}$message_id ·
string · $ref #/$defs/message_idpattern:
^ak:message:[A-Za-z0-9_-]{44}$sender_actor_display_name ·
string (arkret-single-line-display-text) · format=arkret-single-line-display-text · $ref string-profiles.schema.json#/$defs/display_text_256NFC multilingual single-line display text; mixed scripts, emoji, and symbols are allowed.
pattern:
^[^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*[^\s\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF][^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*$strand_title ·
string (arkret-single-line-display-text) · format=arkret-single-line-display-text · $ref string-profiles.schema.json#/$defs/display_text_512NFC multilingual single-line display text; mixed scripts, emoji, and symbols are allowed.
pattern:
^[^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*[^\s\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF][^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*$realm_title ·
string (arkret-single-line-display-text) · format=arkret-single-line-display-text · $ref string-profiles.schema.json#/$defs/display_text_256NFC multilingual single-line display text; mixed scripts, emoji, and symbols are allowed.
pattern:
^[^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*[^\s\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF][^\u0000-\u001F\u007F-\u009F\u202A-\u202E\u2066-\u2069\uFEFF]*$user_is_target ·
booleanpriority ·
string · $ref #/$defs/non_empty_stringmembership ·
string · $ref #/$defs/non_empty_stringevent_kind ·
string · $ref #/$defs/non_empty_stringOriginating Event kind (e.g. `ak.message`) used by the gateway to route Phase-P2 `ak.agent.*` lifecycle / actor-private kinds to a no-fanout aak. Coarse routing selector; carries no Realm / sender / event identifier.
reason_code ·
string · $ref #/$defs/non_empty_stringCaller-supplied wire-safe reason code. The well-known value `historical_only` marks a diagnostic replay that MUST NOT trigger a fresh push fanout (the gateway answers a 200 idempotency-style ack). Other values are honored only where the operation defines them.
audit_envelope · object · $ref #/$defs/audit_envelope
`ak.audit.accessed` envelope routing fragment carried alongside a notify request. When present, the request is an audit-pipeline event (e.g. an `e2ee_late_recovery` access notice), not a push notify: the gateway writes the audit event, acks 200, and skips the push pipeline.
* access_kind ·
string · $ref #/$defs/non_empty_stringak.audit.accessed.access_kind. The gateway branches on `e2ee_late_recovery` to skip the push pipeline.
late_recovery_original_event_id ·
string · $ref #/$defs/event_idREQUIRED (at the application layer) when access_kind == e2ee_late_recovery. References the original encrypted event for audit only; this marker does not prove historical membership or authorize plaintext disclosure.
pattern:
^ak:event:[A-Za-z0-9_-]{44}$anyOf · anyOf[6] · object · $ref #/$defs/push_notify_outcome
Closed notify response. outcomes[] is conserved against notification.devices[]: every input device_id appears exactly once, no device_id appears twice, and no device_id appears that was not requested. A target-level failure is expanded into one same-reason rejected outcome per input device rather than collapsing into a second response shape, so the conservation invariant holds unconditionally. Counts, if a deployment surfaces them, are derived from outcomes[] and are never an independent truth source.
* push_target_id ·
string · $ref ./common-ids.schema.json#/$defs/push_target_idCanonical typed pairwise push pseudonym. The suffix is the unpadded Base64URL encoding of the complete 32-octet HMAC-SHA256 output for one (recipient_id, principal_id, device_id, push_route, salt_epoch_id) tuple. Receivers MUST decode exactly 32 octets and require canonical re-encoding; it is never a DID, object id, raw provider token, or stable cross-service correlation key.
pattern:
^ak:pseudonym:push:[A-Za-z0-9_-]{42}[048AEIMQUYcgkosw]$* outcomes · array<$ref #/$defs/push_notify_device_outcome>
One entry per unique device_id in notification.devices[]. device_id MUST be unique across the array.
items · object · $ref #/$defs/push_notify_device_outcome
Gateway acceptance result for exactly one input device route. Identity is the (push_target_id, device_id) pair already carried by the request; no third route identifier exists. Provider delivery state, provider message ids, raw push tokens and token hashes MUST NOT appear here.
allOf · allOf[0] ·
?allOf · allOf[1] ·
?* device_id ·
string · $ref #/$defs/device_idpattern:
^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$* gateway_status ·
string (enum)Closed gateway acceptance result. accepted = this request durably took the device route over. duplicate = an earlier request already took it over, or the operation explicitly requires a no-fanout acknowledgement, and this request produced no new delivery. A no-fanout acknowledgement does not assert provider acceptance, queueing or new durable route ownership. rejected = the gateway did not take it over. accepted and duplicate both mean the caller MUST NOT resend this device; only rejected may be resent, and only when retry_after_ms is present. See push-notifications.md §5.2.
enum:
"accepted" "duplicate" "rejected"reason_code ·
string (enum)Closed rejection reason, all registered in error-code-registry.json. The first four are target-level or policy rejections; push_token_unknown / push_token_invalid tell the caller to drop this device registration; the last two are the only caller-retryable reasons. REQUIRED when gateway_status=rejected and MUST be absent otherwise.
enum:
"push_target_unknown" "push_payload_too_large" "unsupported_profile" "push_token_unknown" "push_token_invalid" "push_gateway_unreachable" "rate_limited"retry_after_ms ·
integerCaller-facing backoff. Present only when the gateway did not take the route over AND the reason is one the caller can retry; its presence is the sole wire signal that the caller — not the gateway — owns the next attempt. A durably accepted route is retried by the gateway and never carries this field.
Source
- registry row:
spec/v1/artifacts/registry/schema-registry.json - schema document:
spec/v1/artifacts/schemas/push-operations.schema.json