Event kinds
canonical: spec/v1/artifacts/registry/contract-registry.json#event_kind_registry
· catalog version 2026-10-09.4
所有 active ak.* Event.kind。点击任意条目进入详情页。
account
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.account_data.set | account | actor_private_event | no | Actor-private account data update. The closed signed payload carries the integer expected_server_revision for server_revision_cas; expected_revision is the distinct shared-result revision type and is not an alias. |
agent
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.agent.action_approve | agent | durable_event | yes | Controller-signed one-shot publication authorization in the target Realm safety sequence. approved_event_id binds the complete pre-authored Event. The same confirmed command allocates (controller ActorId, approval_nonce) once; it is not a reusable private approval followed by receiver-local consumption. The original Event remains ordinary data and requires this exact confirmation only when its explicit approval constraint applies. |
ak.agent.action_reject | agent | actor_private_event | no | Controller rejection of one actor-private action request, named by request_id. The request transitions to rejected; the agent runtime MUST NOT continue publish attempts for it. Drafts are not rejection targets: their workflow_state is controller-encrypted Account Data. |
ak.agent.action_request | agent | actor_private_event | no | Agent-initiated action request. Carries proposed_action, target descriptor and request_canonical_digest, the digest of the complete pre-authored Event awaiting controller approval before it is submitted. |
ak.agent.draft.propose | agent | actor_private_event | no | Agent-initiated draft proposal. Acceptance creates one structured Station-private pending intent with HPKE content handoff after capability / policy / accountability / risk checks. A controller holder device later creates encrypted ak.agent.draft.v1 account data through the unique account-data CAS. Station MUST NOT generate ciphertext, hold the holder secret, treat the pending intent as account data, or enter it into shared Realm history. |
ak.agent.interaction.set | agent | durable_event | yes | Controller-only per-Realm interaction mode with exact expected_revision CAS; plaintext control, never a membership, Account Data or private participation write. Circle and Strand inherit the Realm mode and only narrow ordinary permissions. Verified never-written defaults to private; unknown fails closed. Mode transitions do not change membership or Sidecar MLS participants. models/agent-interaction.md sections 1-5. |
ak.agent.key.authorize | agent | durable_event | yes | Agent key authorization is a commit-ordered projection security command with complete explicit revocation set representation. Same-key replacement removes all authorization dots visible at the signed basis and adds one replacement dot, after exact revision and authority checks at execution. Competing replacements cannot survive as concurrent permission heads. Runtime replacement pairs a new raw key and revokes prior active keys in the same confirmed transaction. |
ak.agent.key.revoke | agent | durable_event | yes | Agent signing-key revocation. The current governance Station verifies the controller and active key, then commits the exact Event on its authority stream; the payload carries no RealmCommit or authorization basis. |
ak.agent.provision | agent | durable_event | yes | Controller-authored Agent provisioning fact. One Event proof binds the allocated Agent DID, the forward-declared Agent PCR realm id, controller delegation, immutable requested-scope digest, accountability scope and selector. Admission atomically projects the agent_provisioning, identity_accountability, agent_selector_claim and agent_pcr_genesis_declaration typed results; no nested payload proof or partial two-Event state is valid. The declared Agent PCR genesis arrives in a later separate submission whose admission reverse-looks-up the realm-id declaration. |
ak.agent.sidecar.exchange.control | agent | durable_event | yes | Controller-authored durable Sidecar exchange control. The outer payload binds the native Sidecar and source context plus an MLS encrypted payload whose plaintext validates as ak.schema.agent_sidecar_exchange_control.v1. It is accepted only in the matching native Sidecar scope from that Sidecar controller and is the sole truth source for coordinator reassignment and terminal exchange state. |
ak.self.agent.deactivate | agent | durable_event | yes | Agent lifecycle terminal state. One accepted controller-authorized Event is the unavoidable parent AND gate for every runtime key, session, pairing handle, capability grant, KeyPackage, presence and future submission. Cleanup is asynchronous and MUST NOT synthesize or require child revocation Events. Terminal — no transition out. |
ak.self.agent.pause | agent | durable_event | yes | Agent lifecycle transition to paused. Current controller authority and the active agent state are checked atomically when the governance Station commits the Event. |
ak.self.agent.resume | agent | durable_event | yes | Agent lifecycle transition from paused to active. The governance Station revalidates controller, agent key, capability, Realm policy and accountability state at commit. |
applet
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.applet.bridge_error | applet | durable_event | yes | Bridge failure |
ak.applet.discovery | applet | durable_event | yes | Applet discoverability state |
ak.applet.managed_actor.provision | applet | durable_event | yes | Immutable Applet-managed Bot/Ghost principal creation authority Collaboration Realm membership or a Profile association never grants source Event disclosure or replication of this private identity/control fact. Only the kind-specific source scope and registered authority/profile evidence disclosure contract may release authorized material, without underlying control-stream access. |
ak.applet.registration | applet | durable_event | yes | Applet registration |
audit
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.audit.accessed | audit | durable_event | yes | Auditable access marker for privileged reads or privacy-sensitive paired writes such as Circle metadata audit, watch_set_others, late recovery, and policy reads. |
ak.audit.erasure_receipt | audit | durable_event | no | Signed hard-erasure receipt. Attests deletion outcome and retained verification stub within an issuer-declared storage boundary; does not prove independent third-party copies disappeared. |
authz
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.capability.grant | authz | durable_event | yes | Capability Grant genesis. grant.id is omitted; GrantId is derived by retyping this Event's event_id and inserted only in the reducer projection. Dedicated owned_agent source admission follows authz/owned-agent-authority.md; ordinary capability admission is unchanged. |
ak.capability.relinquish | authz | durable_event | yes | Subject-authored release of the actor own capability grant |
ak.capability.revoke | authz | durable_event | yes | Capability revocation Dedicated owned_agent source admission follows authz/owned-agent-authority.md; ordinary capability admission is unchanged. |
call
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.call.create | call | durable_event | yes | Call genesis. call_id is omitted and derived by retyping event_id. This Event MUST be accepted before signaling, token issuance, Morph binding, or any ak.call.state Event references the call. |
ak.call.recording.start | call | durable_event | yes | Call recording / transcript capture start |
ak.call.state | call | durable_event | yes | Call state. The v1 call_state_payload schema rejects mute_override even when another delta is present; no call_mute_override result write can be admitted. Ordinary call state, roster, moderation, focus and capture axes remain available. |
circle
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.circle.archive | circle | durable_event | yes | Circle archive lifecycle facet (active -> archived). |
ak.circle.create | circle | durable_event | yes | Circle create (intra-Realm scoped event/message boundary). The Circle scope stays plaintext until its own ak.mls.genesis is accepted. |
ak.circle.history_access | circle | durable_event | yes | Dedicated per-Circle monotone history-access FSM transition; only all_history_for_current_members to since_join is state-changing after create. |
ak.circle.member.state | circle | durable_event | yes | Circle materialized membership state. Uses the same membership_state enum as ak.member.state (join/knock/leave/ban), scoped to a Circle. Invite remains a separate pending workflow. A join carries the producer-signed parent_membership_revision; admission MUST verify in the accepting cut that the complete member_id's parent Realm member_state current is `join` at exactly that revision, otherwise failed_precondition reason=circle_member_must_be_realm_member. Effective Circle membership additionally requires the parent current to still carry that revision; parent leave, ban or rejoin never synthesizes this Event and never revives an old Circle join. See zh/models/circle.md §9.1. Every illegal membership FSM edge, including an unregistered same-state transition, is rejected with failed_precondition reason_code=invalid_membership_transition and zero writes. An authorized Circle administrator may perform leave->join with ak.circle.member.add.others and the required same-unit audit, without a Circle invitation workflow; parent join revision, Circle active status, ban and MLS gates remain mandatory. |
ak.circle.restore | circle | durable_event | yes | Circle restore lifecycle facet (archived -> active). |
ak.circle.tombstone | circle | durable_event | yes | Circle tombstone (terminal). Triggers lifecycle cascade per zh/models/circle.md §9.2. |
ak.circle.update | circle | durable_event | yes | Circle metadata patch. history_access, realm_id and MLS identity fields are create-locked. |
consent
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.consent.grant | consent | durable_event | yes | Holder-private consent declaration: 'I consent to receive <consent_scope> from <peer>' |
ak.consent.revoke | consent | durable_event | yes | Revoke a previously granted consent (shares the ak.consent.grant typed current result; semantically a remove on the confirmed consent tagged set) |
contact
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.contact.accepted | contact | durable_event | no | Holder-signed normal Contact acceptance: closed peer XOR, exact request/receipt digest, stable contact round, lineage version 1 and full granted_to_peer_scopes. It never reads or writes Consent. Its durable effect is holder-Station private service state under ak.contact.admission.v1 (establishing the normal round and this issuer directional initial state), not a Realm typed current result. |
ak.contact.rejected | contact | durable_event | no | Holder-signed terminal rejection bound to the exact request Event and acceptance-receipt digest. It establishes no Contact round and carries no Consent or Contact round evidence fields. Its durable effect is holder-Station private service state under ak.contact.admission.v1 (terminating exactly the matching admission slot), not a Realm typed current result: the payload carries no round, version or lineage coordinate at all, and the never-revives guarantee is held by that slot CAS. |
ak.contact.requested | contact | durable_event | no | Requester-signed directional Contact request: closed peer XOR plus full granted_to_peer_scopes. It precedes every acceptance receipt and contact round and never reads or writes Consent. Its durable effect is holder-Station private service state under ak.contact.admission.v1 (freezing the exact (holder, peer) admission slot with its request and receipt), not a Realm typed current result: identity/contact-and-direct-conversation.md section 2 derives contact_round_id from a source-signed acceptance receipt whose core members never enter the Event stream, so replaying this Realm's committed Events cannot reconstruct the lineage key. |
ak.contact.scope.update | contact | durable_event | no | Holder-signed issuer-local full-set granted_to_peer_scopes replacement bound to the closed peer XOR, stable contact round, version and predecessor. Expansion and narrowing are both explicit; tombstone remains the only generation terminal. Its durable effect is holder-Station private service state under ak.contact.admission.v1, not a Realm typed current result. |
ak.contact.tombstone | contact | durable_event | no | Holder-signed issuer-local Contact generation terminal. It consumes the stable contact round and cannot carry scope replacement or write/revoke Private Consent. Its durable effect is holder-Station private service state under ak.contact.admission.v1, not a Realm typed current result. |
ak.direct_conversation.bound | contact | durable_event | yes | Participant endorsement of settled Direct Conversation coordinates and the first exact-pair state of the one scope-derived MLS group. The endorsed binding content is settled by the first accepted write and later group state advances only by ordinary Commit; the endorsements themselves are a set, and the second participant endorsement of the same binding MUST be acceptable. |
device
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.device.authorize | device | durable_event | yes | Device authorization |
ak.device.push_route | device | actor_private_event | no | Server-revision-CAS active binding or revoked tombstone for an (account_id, device_id, push_route) tuple. Every write carries expected_server_revision; active bindings carry push_target_id, push_gateway_id, encryption_key and capabilities, while revoked tombstones carry none of those secrets. Stored as actor-private state on account_id.station_id only; MUST NOT be replicated to another Station. |
ak.device.reanchor | device | durable_event | yes | PCR-policy recovery re-anchor. Accepted only as the first event of an atomic re-anchor plus replacement-authorize unit for the exact account-local lineage. It fences the old PCR generation against the complete accepted RealmCommit checkpoint. DID-root possession is accepted only as an explicitly enabled optional policy factor. |
ak.device.revoke | device | durable_event | yes | Device revocation. Every accepted proposal atomically persists a canonical EventCommitSubmissionAck and ak.schema.device_revocation_state.v1 revocation_pending record for the exact reducer-derived authority/device/generation. It is not eligible for the Ack-less self-principal PCR exception. |
ak.key_backup.active_series | device | durable_event | yes | Key backup active series selection for one principal and backup_kind. The signed payload has exactly one source-anchor member: source_commit_ref{realm_commit_id,device_generation_ref}; source_ref and nested CommittedEventRef shapes are invalid. |
discussion
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.pin.add | discussion | durable_event | yes | Shared pin add or update |
ak.pin.remove | discussion | durable_event | yes | Shared pin remove |
ak.pin.reorder | discussion | durable_event | yes | Shared pin rank update |
ak.strand.watch.set | discussion | durable_event | yes | Set or clear a per-(strand, actor) watch subscription. Writes a current-value projection typed current result keyed by (strand_id, watcher_actor_id). Payload carries level in {mentions_only, participating, all, muted} (or null to clear, equivalent to mentions_only). Default invariant: payload.watcher_actor_id MUST equal envelope actor_id, unless writer holds ak.strand.watch.set.others. Cross-actor writes MUST be paired with a same-batch ak.audit.accessed event with access_kind=watch_set_others; the audit event carries semantic_refs[role=audit_pair] plus the suite-bearing paired_event_id pointing at the write, and derives its digest from that ID. The write MUST NOT reference the audit event (encoding.md §3.1 forbids mutual preimages). The watches Relation (actor --watches--> strand) is a derived projection of this typed current result, not a separate truth source — direct ak.relation.create relation_kind=watches MUST schema_violation. See models/strand-and-message.md §8. |
e2ee
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.mls.commit | e2ee | durable_event | yes | MLS commit. governance_binding MUST bind the current key_access_revision. |
ak.mls.genesis | e2ee | durable_event | yes | MLS group genesis |
identity
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.identity.accountability_grant | identity | durable_event | yes | Issuer-signed endorsement that a subject DID (typically an agent / service / hosted actor) is accountable to the issuer for a declared scope (employment / contracted_service / agent_operator). Every Actor Profile.accountable_principal_ids[] entry requires a matching active record at profile admission; a missing one deterministically rejects the whole profile Event with accountability_grant_missing. See zh/models/actor.md section 3.3.1. expires_at is optional; absent means non-expiring, governed by grant_status revocation and controller lifecycle cascade. Ordinary issuer grants are admitted only in the issuer PCR with the issuer device method. The sole Service issuer exception is the closed Applet managed-actor creation aggregate: its grant resides in the exact provision Collaboration Realm and both proofs use the exact accepted registration-epoch Service method. No standalone Service grant ingress or cross-Realm search is authorized. Collaboration Realm membership or a Profile association never grants source Event disclosure or replication of this private identity/control fact. Only the kind-specific source scope and registered authority/profile evidence disclosure contract may release authorized material, without underlying control-stream access. |
ak.identity.resolution.update | identity | durable_event | yes | Owner-authored CAS update of the PCR current did resolution projection. Admission requires exactly one expected_revision guard for ak:result:identity_resolution:null whose value is the whole current resolution_projection; the payload carries only next and mirrors no predecessor coordinate. The Event remains the auditable history source. |
invite
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.invite.accept | invite | durable_event | yes | Invite accept. payload.previous_state names the non-terminal invite_lifecycle state this Event moves out of, which is pending for a directed invite and claimed for a third-party one. payload.invitee_account_id is present exactly when the target Invite stores an invite_directed_invitee record, that is for a directed invite and never for a third-party invite; it exists so the invite_live_target slot subject is derivable from the signed Event, and the registered pre_state_requirements row holds it against the stored record in both directions. For a claimed third-party invite, the reducer resolves the unique accepted ak.invite.claim Event exact ref and Commit at the same authority cut and requires its subject_account_id to match the accept author before member join; the claimed lifecycle value alone does not prove the subject. |
ak.invite.cancel | invite | durable_event | yes | Invite cancel. Directed invites only: the Event terminates the invite (rejected or revoked) and atomically releases the invite_live_target slot keyed by canonical_json(payload.invitee_account_id). payload.previous_state names the non-terminal state it moves out of; a non-terminal frozen pre-state that differs from it is a bare failed_precondition with no reason_code. The invitee declining and the still-joined inviter cancelling are authorized by the Invite binding alone; only a third actor needs an ak.invite.cancel grant. Both registered pre_state_requirements rows read the stored invite_directed_invitee record: an Invite with no stored invitee is a third-party or token invite and MUST be rejected with invite_kind_requires_revoke, and a stored invitee that is not byte-equal to the payload's is rejected with invite_directed_invitee_mismatch. |
ak.invite.claim | invite | durable_event | yes | Third-party invite claim. The reducer reads the unique accepted ak.invite.third_party create Event/Commit, pure invite_lifecycle and current Realm policy at one accepted authority cut. On acceptance, claim subject, nonce, commitment, verification and time material are derived from this exact accepted claim Event/Commit; a rebuildable index is not a second truth source. |
ak.invite.create | invite | durable_event | yes | Invite create. Directed v1 genesis payloads carry the exact invitee_account_id, introduction_evidence_digest and expires_at; the Invite ID is derived from this Event. Delivery resolves invitee_account_id.station_id outside durable Realm state. Raw locator tokens, route material and invite_receive_policy state MUST NOT enter the durable Realm event. The Event atomically opens the invite_lifecycle register at pending, writes the create-locked invite_directed_invitee record, and claims the Realm live-target slot invite_live_target keyed by canonical_json(payload.invitee_account_id); a second live directed invite for the same account is rejected with failed_precondition and reason_code invite_live_target_occupied, writes nothing and does not enter canonical history. |
ak.invite.revoke | invite | durable_event | yes | Invite revoke. Carries the terminal or send_failed transition of a directed or third-party invite. payload.previous_state names the non-terminal state it moves out of and is pinned to pending on the send_failed branch. payload.invitee_account_id is present exactly when the target Invite stores an invite_directed_invitee record and target_state is not send_failed; send_failed keeps the invite live, so the schema forbids the field there and no slot write is derived. The five non-send_failed target states each carry a pre_state_requirements row holding the payload's invitee against the stored record in both directions, which is why the requirement is keyed on target_state rather than on the field's presence: a directed invite MUST NOT keep its slot forever by omitting it. |
ak.invite.third_party | invite | durable_event | yes | Third-party identifier pending invite. Genesis payload omits invite/invite_id; the Invite ID is derived from this Event. It opens the pure invite_lifecycle register at pending and writes nothing else: a third-party invite has no exact invitee account, so it writes no invite_directed_invitee record and never touches an invite_live_target slot. Frozen public invite material is read from this exact accepted create Event/Commit at the same authority cut as lifecycle and Realm policy; it is not stored in invite_lifecycle. |
membership
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.member.identity.update | membership | durable_event | yes | Realm-scoped MemberIdentity segment replacement event. Append-only log entry that may supersede prior ak.member.identity.update events via payload.replaces[] without overloading ak.profile.update patch semantics. The event always enters the append-only log: proof and replacement validation are consumption/verification-surface semantics, not reducer rejection. When the MemberIdentity proof fails validation (payload_digest mismatch, signature failure, or verification_method not controlled by subject_id), receivers surface reason=member_identity_proof_invalid and MUST NOT promote the event to a verified display identity. When a replaces[] entry payload_digest or (realm_id, member_id, segment) does not match, only that replacement edge is invalid (surface member_identity_replacement_digest_mismatch); receivers MUST NOT remove the referenced event from the effective set on that basis. Only the optional expected_state_digest guard retains reducer semantics: when expected_state_digest does not equal the current effective-set digest, the server/reducer MUST reject or quarantine the event with reason=member_identity_state_mismatch. See zh/sync/client-sync.md §8.1. |
ak.member.state | membership | durable_event | yes | Realm membership state. Agent join/cleanup Events carry an exact agent_controller_binding. Effective Agent membership additionally AND-gates the controller authority pair and bound join Event generation, lifecycle and provision/accountability validity. Controller terminal transitions never synthesize this Event. The typed agent_membership_cascade exact-set model has no registered self-submit closed-union ingress in v1; such submissions fail closed, while loss of the exact controller join generation immediately invalidates effective Agent membership. A parent_membership join must revalidate co-governance, active join_gate_from links and source authoritative current member_state rows in the accepting transaction. Illegal membership FSM edges, including unregistered same-state transitions, are rejected with failed_precondition reason_code=invalid_membership_transition and zero writes. |
message
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.message.create | message | durable_event | yes | Message create. Payload MUST omit message_id; reducer materializes Message.id by retyping the creating Event's full 33-byte / 44-character content-bound token. |
ak.message.redact | message | durable_event | yes | Message-scoped redaction; does not grant generic redaction authority |
ak.message.revise | message | durable_event | yes | Message edit patch |
ak.reaction.add | message | durable_event | yes | Reaction add |
ak.reaction.remove | message | durable_event | yes | Reaction remove |
ak.redaction | message | durable_event | yes | Cross-object redaction envelope for non-Message objects/events and profile-declared content trimming. Message is excluded: it has its own registered ak.message.redact. |
mimi
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.mimi.room_binding | mimi | durable_event | yes | MIMI room binding state |
moderation
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.moderation.decision | moderation | durable_event | yes | committed moderation decision (writes moderation_state typed current result) |
ak.moderation.decision.lift | moderation | durable_event | yes | Lift a previously committed moderation decision (explicit revocation/supersede the referenced decision in moderation_state) |
ak.moderation.franking_proof | moderation | durable_event | yes | Receiving-service proof that one encrypted target Event was received. The payload is exactly moderation-evidence.schema.json#/$defs/franking_proof; payload.event_id identifies the proven Event and is the moderation_franking_proof typed current result subject. verification_method selects the exact service key, whose controller must project to received_by and be authorized at received_at. A proof is created independently of any later report, so report_id and target_ref are not payload fields. |
ak.self.moderation.report | moderation | durable_event | yes | Moderation report. A report authored by the reporter's own device admits as self_authored_proof (actor == subject == payload.reporter). An inbound MIMI report mapped by the provider facade sets payload.provenance=mimi_facade and admits as service_attested: the envelope actor is the facade service DID, payload.reporter carries the Arkret principal resolved under extensions/mimi-interop.md section 11 reporter_authority rules, payload.source_provider_id carries the origin MIMI provider, and the reducer MUST verify the actor service operates the MIMI facade for payload.realm_id. The facade MUST NOT author actor_id as the reporter principal. One accepted Event derives exactly one report and one moderation_queue_item; their full typed IDs differ although both retype the same complete event_id token. |
morph
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.morph.archive | morph | durable_event | yes | Morph archive |
ak.morph.create | morph | durable_event | yes | Morph create |
ak.morph.restore | morph | durable_event | yes | Morph restore |
ak.morph.stage.set | morph | durable_event | yes | Morph business-progression stage transition. Single source of truth for mutating Morph.stage / Morph.stage_changed_at; ak.morph.update patches on those paths MUST be rejected (forbidden-wire). The payload intentionally carries no reason / note / explanation field — rationale belongs in a Message on an associated discussion track that 'references' this event. Reducer enforces hard invariants from zh/models/common-fields.md §5.3.3: state=redacted yields failed_precondition reason=morph_already_terminal; state=archived yields morph_not_active; same-value self-transition is accepted but does NOT update stage_changed_at; reducer overwrites any wire-supplied stage_changed_at with the event's created_at. |
ak.morph.update | morph | durable_event | yes | Morph patch |
organization
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.organization.moderation_policy | organization | durable_event | yes | Organization moderation policy state |
policy
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.policy.action | policy | durable_event | yes | Policy-gated action approval configuration (writes the policy_action typed current result) |
ak.policy.set | policy | durable_event | yes | Policy object set Applet governance policy has the same exact-CAS mandatory expected_revision rule as Agent governance policy; kind cannot be rebound to bypass it. |
profile
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.profile.create | profile | durable_event | yes | Actor profile create Applet-managed public applet_interaction intent requires actual scope, subject signature, publish governance and applicable management approvals; all alternate creation/patch paths share the gate. |
ak.profile.realm_override | profile | durable_event | yes | Realm-scoped profile override. payload.target_realm_id is the target Realm and no Space boundary is created. |
ak.profile.update | profile | durable_event | yes | Actor profile update; resolution and every resolution.* path are forbidden because the PCR resolution typed current result is the sole write authority for that materialized projection. Setting Applet managed applet_service_intent to public additionally requires current publish governance and management ApprovalSignature when configured; subject signature is unchanged. Applet-managed public applet_interaction intent requires actual scope, subject signature, publish governance and applicable management approvals; all alternate creation/patch paths share the gate. |
read
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.read_cursor.advance | read | actor_private_event | no | Read cursor advance event (actor-private). Writes the actor's latest read position for a given (realm_id, read_scope) tuple. Was historically named ak.read.cursor; renamed to align the event_kind, capability action, schema id and typed ID prefix on a single noun root read_cursor. |
realm
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.realm.alias | realm | durable_event | yes | Realm alias declaration or durable value tombstone. The declaration is the ONLY wire carrier of a Realm alias: realm genesis and profile schemas are closed and carry no alias property. Declaration payloads and {tombstone:true} both set realm_alias through the registered commit-ordered projection effect; effective resolution treats the tombstone as absence of an alias and falls back to realm_id-only addressing. |
ak.realm.archive | realm | durable_event | yes | Explicit archive operation; no caller-supplied state or scheduling fields. |
ak.realm.asset_privacy_policy | realm | durable_event | yes | Realm asset privacy policy |
ak.realm.authority.reset | realm | durable_event | yes | Realm authority-root delegation generation reset |
ak.realm.create | realm | durable_event | yes | Realm create |
ak.realm.destroy | realm | durable_event | yes | Realm destroy lifecycle facet (terminal decommission marker); v1 production admission is closed pending an independent destructive-confirmation carrier |
ak.realm.discovery | realm | durable_event | yes | Realm discoverability state |
ak.realm.freeze | realm | durable_event | yes | Explicit freeze operation; no caller-supplied state or scheduling fields. |
ak.realm.governance_station.change | realm | durable_event | yes | Planned Realm governance Station transfer intent |
ak.realm.history_access | realm | durable_event | yes | Realm history visibility scope |
ak.realm.join_rule | realm | durable_event | yes | Realm join rule (public/invite/knock/restricted/knock_restricted/closed) When the accepted join_policy component is structurally inconsistent with this join_rule (restricted/knock_restricted without at least one auto_resolve gate, or a combinator that degenerates the gate set), the reducer MUST reject with failed_precondition reason_code=join_rule_policy_mismatch. See zh/governance/join-policy.md §2. |
ak.realm.link | realm | durable_event | yes | Typed Realm link graph edge. link_kind declares governance / discoverability / import-export / confidential-extension semantics; it is never generic parent/child containment and never implicitly propagates membership, capabilities, history, E2EE keys, retention, or federation policy. join_gate_from is only a Realm-local opt-in for parent_membership when source and target share the same verified current authority-tenure service_id. |
ak.realm.media_service | realm | durable_event | yes | Media Service (TURN/SFU/MCU + ICE) binding |
ak.realm.organization | realm | durable_event | yes | Organization-authorized Realm relationship statement or revocation |
ak.realm.owner.transfer | realm | durable_event | yes | Realm authority-root controller transfer |
ak.realm.plaintext_visible_services | realm | durable_event | yes | Plaintext-visible services declaration outside E2EE boundary |
ak.realm.policy_bundle | realm | durable_event | yes | Enabled Realm policy components set, written wholesale into the commit-ordered projection typed current result (every revision restates the complete component set). Payload MUST carry monotonic policy_revision; reducer rejects rollback or gaps and policy_revision MUST cover policy_revision. A bundle whose join_policy component conflicts with the accepted join_rule (restricted/knock_restricted without at least one auto gate, or a degenerate combinator) MUST be rejected with failed_precondition reason_code=join_rule_policy_mismatch. A parent_membership gate additionally requires current active join_gate_from links and source/target authority tenures with the same service_id at policy admission. See zh/governance/join-policy.md §2 and §3.1. |
ak.realm.preview_policy | realm | durable_event | yes | Realm preview / peek policy for directory card, stripped state, history stub, and plaintext history snippet projections |
ak.realm.profile | realm | durable_event | yes | The only reducer input for Realm title, summary and avatar. The complete closed profile value replaces the realm_profile singleton; create and policy Events cannot carry these fields. |
ak.realm.read_receipt_policy | realm | durable_event | yes | Realm-local read receipt disclosure policy (disclosure / visibility / scope_overrides_allowed); Realm links do not create a parent policy floor; see zh/discovery/read-receipts.md §2.5 |
ak.realm.restore | realm | durable_event | yes | Explicit restore operation on the same registered facet; other gates remain unchanged. |
ak.realm.schema | realm | durable_event | yes | Realm schema_refs declaration |
ak.realm.search_policy | realm | durable_event | yes | Realm privacy-preserving search policy |
ak.realm.set_default_strand | realm | durable_event | yes | Sets / changes the Realm's authoritative default discussion Strand pointer. payload = {realm_id, strand_id}; reducer projects payload.strand_id into the Realm projection default_strand_id (single authoritative pointer; avoids multi-default dirty state). Reducer MUST verify the referenced strand_id already exists in this Realm (a projected, non-tombstoned Strand); a dangling reference MUST be rejected with failed_precondition. Strand-side is_default is a derived marker (strand_id == realm.default_strand_id), never independent storage; clients discover the default Strand deterministically from the Realm projection default_strand_id or the Strand projection is_default, NOT from any shared-token implementation detail. Authorization is the standard Realm-admin gate (hold ak.realm.admin, or the same-name action ak.realm.set_default_strand). |
ak.realm.tombstone | realm | durable_event | yes | Realm tombstone lifecycle facet (terminal pointer to successor) |
ak.realm.unfreeze | realm | durable_event | yes | Explicit unfreeze operation on the same registered facet; other gates remain unchanged. |
relation
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.relation.create | relation | durable_event | yes | Relation create |
ak.relation.tombstone | relation | durable_event | yes | Irreversible Relation lifecycle transition. payload.primary_conflict_domain is the sole typed-result selector, payload.relation_id is the current value identity guard, and payload.expected_revision is the exact CAS guard. payload.target_ref and update-style payload.patch are forbidden. Optional payload.reason is retained on the Event, while the materialized Relation stores only state=tombstoned and state_changed_at=Event.created_at. |
ak.relation.update | relation | durable_event | yes | Relation patch |
schema
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.schema.define | schema | durable_event | yes | Schema definition |
sidecar
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.sidecar.context.attach | sidecar | durable_event | yes | Controller-signed versioned binding between a native Sidecar and an existing source Strand or Relation used as UI context. It creates no Strand or Relation object and contains a required SemanticRef role=after to the Sidecar create Event. |
ak.sidecar.create | sidecar | durable_event | yes | Controller-signed minimal native Sidecar creation intent. The Sidecar id is derived from the Event id; controller, Realm, lifecycle and timestamps are reducer-derived. It creates no Circle, membership, Strand or Relation object. See zh/models/sidecar.md §2-§5. |
space
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.space.archive | space | durable_event | yes | Space archive (UI-level grouping archive; contained Strands MUST be relocated or follow archive) |
ak.space.create | space | durable_event | yes | Space create (board / list / swimlane / calendar bucket / etc.) |
ak.space.parent | space | durable_event | yes | Space parent declaration. Parent is another ak:space: in the same actual Realm, or null. Cross-Realm parent is forbidden at create and reparent. Parent never propagates capabilities or Circle visibility. |
ak.space.restore | space | durable_event | yes | Space restore (transition state archived -> active; only valid when current state == archived; tombstoned Spaces MUST NOT be restored) |
ak.space.tombstone | space | durable_event | yes | Space tombstone (irreversible; contained Strands MUST be relocated before) |
ak.space.update | space | durable_event | yes | Space metadata update (title, rank, kind-specific fields) |
strand
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.rsvp.set | strand | durable_event | yes | Calendar event RSVP set |
ak.strand.archive | strand | durable_event | yes | Strand archive |
ak.strand.create | strand | durable_event | yes | Strand create |
ak.strand.move | strand | durable_event | yes | Board-scoped placement or explicit null unplace, preserving Strand identity and history. Unplace requires complete position CAS and no rank. |
ak.strand.reorder | strand | durable_event | yes | Rank-only causal update of the same placement typed current result as ak.strand.move. The signed basis list_space_id must match the projected list_space_id; concurrent writes select the fixed causal-register (depth,EventId) winner while losing Events remain historical provenance. This ordinary placement never grants scope access. |
ak.strand.restore | strand | durable_event | yes | Strand restore |
ak.strand.stage.set | strand | durable_event | yes | Strand business-progression stage transition. Single source of truth for mutating Strand.stage / Strand.stage_changed_at; ak.strand.update patch on those paths MUST be rejected (forbidden-wire). The payload intentionally carries no reason / note / explanation field — rationale belongs in a Message on the Strand's discussion track that 'references' this event, and the event log's own actor_id / created_at is the audit source. Reducer enforces hard invariants from zh/models/common-fields.md §5.3.3: state=redacted yields failed_precondition reason=strand_already_terminal; state=archived yields strand_not_active; same-value self-transition is accepted but does NOT update stage_changed_at; reducer overwrites any wire-supplied stage_changed_at with the event's created_at. v1 has no per-Realm workflow profile carrier: these hard invariants are the complete transition rule and receivers MUST NOT narrow admission from Realm-private configuration (zh/models/common-fields.md §5.3.4). |
ak.strand.tracks.update | strand | durable_event | yes | Track configuration patch with full Strand paths tracks.<registered_name>.<configuration_member>. Only enabled, is_primary, profile and metadata paths are admitted. Whole map or entry replacement and all content paths are forbidden; Synthesis content uses ak.strand.update exclusively. |
ak.strand.update | strand | durable_event | yes | Strand patch |
view
| event_kind | category | wire scope | reducer input | payload |
|---|---|---|---|---|
ak.view.create | view | durable_event | yes | View create |
ak.view.reconcile | view | durable_event | yes | View schema or definition sync |
ak.view.update | view | durable_event | yes | View update |