# Proposed event contract, version 1 (AsyncAPI 3.0): the events this system publishes, their consumers, payloads and delivery
# guarantees, and the events it consumes. Status: proposal for review, not confirmed design.
asyncapi: 3.0.0
info:
  title: Access Events
  version: 1.0.0
  description: 'Changes to Organizations, identities, memberships, delegations and roles, which every other system
    consumes to keep its cached copy of who may do what; and the audit events every system publishes for access
    to consolidate. Envelope, delivery guarantees and webhook headers: `common/v1/events.yaml`. Status: proposal
    for review, not confirmed design.'
defaultContentType: application/cloudevents+json
servers:
  prod:
    host: pubsub.googleapis.com
    protocol: googlepubsub
    description: Pub/Sub in the project that hosts the system, prod.
  stage:
    host: pubsub.googleapis.com
    protocol: googlepubsub
    description: Pub/Sub in the project that hosts the system, stage.
channels:
  access.events.v1:
    address: access.events.v1
    description: Every event access publishes. Consumers filter by the `ce-type` attribute.
    messages:
      organization_created_v1:
        $ref: '#/components/messages/organization_created_v1'
      organization_updated_v1:
        $ref: '#/components/messages/organization_updated_v1'
      organization_closing_v1:
        $ref: '#/components/messages/organization_closing_v1'
      organization_closure_cancelled_v1:
        $ref: '#/components/messages/organization_closure_cancelled_v1'
      organization_closed_v1:
        $ref: '#/components/messages/organization_closed_v1'
      membership_granted_v1:
        $ref: '#/components/messages/membership_granted_v1'
      membership_revoked_v1:
        $ref: '#/components/messages/membership_revoked_v1'
      delegation_granted_v1:
        $ref: '#/components/messages/delegation_granted_v1'
      delegation_revoked_v1:
        $ref: '#/components/messages/delegation_revoked_v1'
      organization_role_updated_v1:
        $ref: '#/components/messages/organization_role_updated_v1'
      user_disabled_v1:
        $ref: '#/components/messages/user_disabled_v1'
      service_account_registered_v1:
        $ref: '#/components/messages/service_account_registered_v1'
      staff_membership_changed_v1:
        $ref: '#/components/messages/staff_membership_changed_v1'
      staff_role_updated_v1:
        $ref: '#/components/messages/staff_role_updated_v1'
    bindings:
      googlepubsub:
        messageRetentionDuration: 604800s
        schemaSettings:
          encoding: json
          name: projects/moonitoring-<env>-<project>/schemas/access.events.v1
  system.audit.v1:
    address: '{system}.audit.v1'
    parameters:
      system:
        description: The system that made the change, such as access, farm or releases; one topic per system.
    messages:
      platform_audit_event_recorded_v1:
        $ref: '#/components/messages/platform_audit_event_recorded_v1'
    description: 'Audit events of one system (decided 2026-10-30, D4): **one topic per system** (decided 2026-11-11),
      `<system>.audit.v1` in the project of that system, such as `access.audit.v1` or `farm.audit.v1`. Only the
      backend and the relay of that system may publish on it. Pub/Sub carries no identity of the publisher, so a
      topic shared by every system could not prove where an event came from. access-consumer has one subscription
      on the audit topic of every system and takes the system from the subscription the event arrived on, never
      from the event: an event whose data.system is not that system, or whose action does not start with
      `<system>.`, goes to the dead letter. access publishes its own rows on access.audit.v1 and skips them when it
      consumes. A Cloud Storage subscription on each audit topic copies it to the locked audit log bucket. Each
      system also keeps its own rows, so a lost message loses no audit. A message that reaches the dead-letter topic
      alerts the platform engineers: a lost audit event is an incident. A redelivered event is matched by
      (system, request_id).'
    bindings:
      googlepubsub:
        schemaSettings:
          encoding: json
          name: projects/moonitoring-<env>-<project>/schemas/audit.v1
        messageRetentionDuration: 604800s
operations:
  publish_organization_created_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_created_v1'
    summary: 'An Organization became active: created by its owner and approved by staff (D8).'
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '2'
  publish_organization_closing_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_closing_v1'
    summary: 'A closure was requested: the Organization is frozen for its grace period. Products stop writes, sync runs and deliveries for it.'
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-gateway
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '138'
    - '2.7'
  publish_organization_closure_cancelled_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_closure_cancelled_v1'
    summary: 'A closure was cancelled during its grace period: the Organization is restored to its previous status.'
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-gateway
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '138.9'
  publish_organization_closed_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_closed_v1'
    summary: 'The closure ran: every system deletes or anonymizes what it keeps for the Organization and reports what it kept.'
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-gateway
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '138'
    - '138.11'
    - '138.13'
  publish_organization_updated_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_updated_v1'
    summary: 'An Organization''s profile changed: name, fiscal identifier, telephone, timezone, cooperative (after
      the cooperative accepted the link), owner or status.'
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '2'
    - '2.5'
    - '1002.7'
  publish_membership_granted_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/membership_granted_v1'
    summary: A user received a role in an Organization, directly, through a delegation or through a user group.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '5'
    - 5.*.1
    - 5.*.2
    - '133'
    - '134'
    - '1002.9'
  publish_membership_revoked_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/membership_revoked_v1'
    summary: A membership ended, or a user group stopped giving a role.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '5.4'
    - '5.5'
  publish_delegation_granted_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/delegation_granted_v1'
    summary: An Organization delegated a role to another, or changed the role of a delegation.
    description: A change of role publishes it again with the same delegation id and the new role, with
      membership.granted.v1 for every membership that depends on the delegation (decided 2026-11-11); consumers keep
      the latest by id.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '8'
    - '8.3'
    - '1002.6'
  publish_delegation_revoked_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/delegation_revoked_v1'
    summary: A delegation ended, with the delegated memberships that depended on it.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: true
    x-moonitoring-requirements:
    - '8.5'
    - '8.6'
  publish_organization_role_updated_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/organization_role_updated_v1'
    summary: A global Organization role was created or its capabilities or priority changed; it reaches every Organization
      at once.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '6'
    - '6.5'
    - '1006.4'
  publish_user_disabled_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/user_disabled_v1'
    summary: A user or service account was disabled; its tokens stop being issued.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    - moochat
    - grant
    - releases
    - ai-model-platform
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '1.6'
    - 1.*.2
  publish_service_account_registered_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/service_account_registered_v1'
    summary: A service account was created for an Organization, for example for a farm sync client.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - farm
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - 1.*.2
    - '67'
  publish_staff_membership_changed_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/staff_membership_changed_v1'
    summary: A Moonitoring user received or lost a staff role.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - moochat
    - releases
    - ai-model-platform
    - ai-gateway
    - news
    - farm
    - grant
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '24'
    - '24.5'
  publish_staff_role_updated_v1:
    action: send
    channel:
      $ref: '#/channels/access.events.v1'
    messages:
    - $ref: '#/channels/access.events.v1/messages/staff_role_updated_v1'
    summary: A staff role was created or changed.
    x-moonitoring-producer: access
    x-moonitoring-consumers:
    - moochat
    - releases
    - ai-model-platform
    - ai-gateway
    - news
    - farm
    - grant
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '25'
    - '25.5'
  publish_platform_audit_event_recorded_v1:
    action: send
    channel:
      $ref: '#/channels/system.audit.v1'
    messages:
    - $ref: '#/channels/system.audit.v1/messages/platform_audit_event_recorded_v1'
    summary: A privileged action was taken in the Console or through an admin API. Published by the system that
      made the change, in the same transaction, on its own topic `<system>.audit.v1`, and consumed by access, which
      consolidates the audit log.
    x-moonitoring-producer: every system
    x-moonitoring-consumers:
    - access
    x-moonitoring-webhook: false
    x-moonitoring-requirements:
    - '70'
components:
  messages:
    organization_created_v1:
      name: organization.created.v1
      title: organization.created.v1
      summary: 'An Organization became active: created by its owner and approved by staff (D8).'
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization.created.v1
            subject:
              type: string
              description: The id of the entity the event is about.
            data:
              $ref: '#/components/schemas/OrganizationCreatedV1Data'
    organization_closing_v1:
      name: organization.closing.v1
      title: organization.closing.v1
      summary: 'A closure was requested: the Organization is frozen for its grace period. Products stop writes, sync runs and deliveries for it.'
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization.closing.v1
            subject:
              type: string
              description: The Organization id.
            data:
              $ref: '#/components/schemas/OrganizationClosureEventData'
    organization_closure_cancelled_v1:
      name: organization.closure_cancelled.v1
      title: organization.closure_cancelled.v1
      summary: 'A closure was cancelled during its grace period: the Organization is restored to its previous status.'
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization.closure_cancelled.v1
            subject:
              type: string
              description: The Organization id.
            data:
              $ref: '#/components/schemas/OrganizationClosureEventData'
    organization_closed_v1:
      name: organization.closed.v1
      title: organization.closed.v1
      summary: 'The closure ran: every system deletes or anonymizes what it keeps for the Organization and reports what it kept.'
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization.closed.v1
            subject:
              type: string
              description: The Organization id.
            data:
              $ref: '#/components/schemas/OrganizationClosureEventData'
    organization_updated_v1:
      name: organization.updated.v1
      title: organization.updated.v1
      summary: 'An Organization''s profile changed: name, fiscal identifier, telephone, timezone, cooperative (after
        the cooperative accepted the link), owner or status.'
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization.updated.v1
            subject:
              type: string
              description: The id of the entity the event is about.
            data:
              $ref: '#/components/schemas/OrganizationUpdatedV1Data'
    membership_granted_v1:
      name: membership.granted.v1
      title: membership.granted.v1
      summary: A user received a role in an Organization, directly, through a delegation or through a user group.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: membership.granted.v1
            subject:
              type: string
              description: The membership id.
            data:
              $ref: '#/components/schemas/MembershipGrantedV1Data'
    membership_revoked_v1:
      name: membership.revoked.v1
      title: membership.revoked.v1
      summary: A membership ended, or a user group stopped giving a role.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: membership.revoked.v1
            subject:
              type: string
              description: The membership id.
            data:
              $ref: '#/components/schemas/MembershipRevokedV1Data'
    delegation_granted_v1:
      name: delegation.granted.v1
      title: delegation.granted.v1
      summary: An Organization delegated a role to another, or changed the role of a delegation.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: delegation.granted.v1
            subject:
              type: string
              description: The delegation id.
            data:
              $ref: '#/components/schemas/DelegationGrantedV1Data'
    delegation_revoked_v1:
      name: delegation.revoked.v1
      title: delegation.revoked.v1
      summary: A delegation ended, with the delegated memberships that depended on it.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: delegation.revoked.v1
            subject:
              type: string
              description: The delegation id.
            data:
              $ref: '#/components/schemas/DelegationRevokedV1Data'
    organization_role_updated_v1:
      name: organization_role.updated.v1
      title: organization_role.updated.v1
      summary: A global Organization role was created or its capabilities or priority changed; it reaches every
        Organization at once.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: organization_role.updated.v1
            subject:
              type: string
              description: The role id.
            data:
              $ref: '#/components/schemas/OrganizationRoleUpdatedV1Data'
    user_disabled_v1:
      name: user.disabled.v1
      title: user.disabled.v1
      summary: A user or service account was disabled; its tokens stop being issued.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: user.disabled.v1
            subject:
              type: string
              description: The user id.
            data:
              $ref: '#/components/schemas/UserDisabledV1Data'
    service_account_registered_v1:
      name: service_account.registered.v1
      title: service_account.registered.v1
      summary: A service account was created for an Organization, for example for a farm sync client.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: service_account.registered.v1
            subject:
              type: string
              description: The user id.
            data:
              $ref: '#/components/schemas/ServiceAccountRegisteredV1Data'
    staff_membership_changed_v1:
      name: staff_membership.changed.v1
      title: staff_membership.changed.v1
      summary: A Moonitoring user received or lost a staff role.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: staff_membership.changed.v1
            subject:
              type: string
              description: The membership id.
            data:
              $ref: '#/components/schemas/StaffMembershipChangedV1Data'
    staff_role_updated_v1:
      name: staff_role.updated.v1
      title: staff_role.updated.v1
      summary: A staff role was created or changed.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: staff_role.updated.v1
            subject:
              type: string
              description: The role id.
            data:
              $ref: '#/components/schemas/StaffRoleUpdatedV1Data'
    platform_audit_event_recorded_v1:
      name: platform_audit_event.recorded.v1
      title: platform_audit_event.recorded.v1
      summary: A privileged action was taken in the Console or through an admin API. Published by the system that
        made the change, in the same transaction, on its own topic `<system>.audit.v1`, and consumed by access, which
        consolidates the audit log.
      traits:
      - $ref: ../../../common/v1/events.yaml#/components/messageTraits/Event
      payload:
        allOf:
        - $ref: ../../../common/v1/events.yaml#/components/schemas/EventEnvelope
        - type: object
          properties:
            type:
              type: string
              const: platform_audit_event.recorded.v1
            subject:
              type: string
              description: The audit event id.
            data:
              $ref: '#/components/schemas/PlatformAuditEventRecordedV1Data'
  schemas:
    OrganizationClosureEventData:
      type: object
      properties:
        organization:
          type: string
          format: uuid
        closure:
          type: string
          format: uuid
          description: ID of the OrganizationClosure.
        reason:
          type: string
          enum:
          - owner_request
          - staff_decision
          - never_approved
        scheduled_for:
          type: string
          format: date-time
        message:
          type: string
          description: Why staff closed it, for a staff decision.
      required:
      - organization
      - closure
      - reason
    OrganizationCreatedV1Data:
      type: object
      properties:
        organization:
          type: string
          format: uuid
        name:
          type: string
        type:
          type: string
          enum:
          - Farm
          - Cooperative
          - Insurer
          - Professional
        timezone:
          type: string
        cooperative:
          type: string
          format: uuid
      required:
      - organization
      - name
      - type
    OrganizationUpdatedV1Data:
      type: object
      properties:
        organization:
          type: string
          format: uuid
        changed_fields:
          type: array
          items:
            type: string
      required:
      - organization
      - changed_fields
    MembershipGrantedV1Data:
      type: object
      properties:
        membership:
          type: string
          format: uuid
          description: The membership id; for a role given through a user group, a stable id derived from the
            user's group membership and the group's role assignment, so the same pair always has the same id.
        user:
          type: string
          format: uuid
        organization:
          type: string
          format: uuid
          description: The Organization the membership gives access to.
        role:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - DirectMembership
          - DelegatedMembership
          - DirectGroupRole
          - DelegatedGroupRole
        delegation:
          type: string
          format: uuid
        user_group:
          type: string
          format: uuid
          description: The UserGroup that gives the role, when the role comes through a group.
      required:
      - membership
      - user
      - organization
      - role
      - type
    MembershipRevokedV1Data:
      type: object
      properties:
        membership:
          type: string
          format: uuid
          description: The membership id; for a role given through a user group, a stable id derived from the
            user's group membership and the group's role assignment, so the same pair always has the same id.
        user:
          type: string
          format: uuid
        organization:
          type: string
          format: uuid
        revoked_at:
          type: string
          format: date-time
        user_group:
          type: string
          format: uuid
          description: The UserGroup that gives the role, when the role comes through a group.
      required:
      - membership
      - user
      - organization
      - revoked_at
    DelegationGrantedV1Data:
      type: object
      properties:
        delegation:
          type: string
          format: uuid
        delegator:
          type: string
          format: uuid
        delegatee:
          type: string
          format: uuid
        role:
          type: string
          format: uuid
      required:
      - delegation
      - delegator
      - delegatee
      - role
    DelegationRevokedV1Data:
      type: object
      properties:
        delegation:
          type: string
          format: uuid
        delegator:
          type: string
          format: uuid
        delegatee:
          type: string
          format: uuid
        revoked_memberships:
          type: array
          items:
            type: string
            format: uuid
        revoked_members:
          type: array
          description: The same memberships with the user each one belonged to, so a copy that never held a
            membership can still remove the user's rights (decided 2026-11-05).
          items:
            type: object
            properties:
              membership:
                type: string
                format: uuid
              user:
                type: string
                format: uuid
            required:
            - membership
            - user
      required:
      - delegation
      - delegator
      - delegatee
    OrganizationRoleUpdatedV1Data:
      type: object
      properties:
        role:
          type: string
          format: uuid
        key:
          allOf:
          - $ref: ../../../common/v1/schemas.yaml#/components/schemas/OrganizationPredefinedRoleEnum
          description: The stable key of a predefined role (req 6.6), absent for any other role. Systems find a
            predefined role such as `sync_client` by this key in their copy, never by its name.
        name:
          type: string
        capabilities:
          type: array
          items:
            type: string
        priority:
          type: integer
      required:
      - role
      - name
      - capabilities
      - priority
    UserDisabledV1Data:
      type: object
      properties:
        user:
          type: string
          format: uuid
        type:
          type: string
          enum:
          - Person
          - ServiceAccount
        organization:
          type: string
          format: uuid
          description: For a service account.
      required:
      - user
      - type
    ServiceAccountRegisteredV1Data:
      type: object
      properties:
        user:
          type: string
          format: uuid
        organization:
          type: string
          format: uuid
        role:
          type: string
          format: uuid
        description:
          type: string
      required:
      - user
      - organization
      - role
    StaffMembershipChangedV1Data:
      type: object
      properties:
        membership:
          type: string
          format: uuid
        user:
          type: string
          format: uuid
        role:
          type: string
          format: uuid
        revoked:
          type: boolean
        account_kind:
          type: string
          enum:
          - person
          - service_account
          description: Whether the staff member is a person or a MoonitoringServiceAccount (decided 2026-11-05).
      required:
      - membership
      - user
      - role
      - revoked
      - account_kind
    StaffRoleUpdatedV1Data:
      type: object
      properties:
        role:
          type: string
          format: uuid
        name:
          type: string
        capabilities:
          type: array
          items:
            type: string
        priority:
          type: integer
      required:
      - role
      - name
      - capabilities
      - priority
    PlatformAuditEventRecordedV1Data:
      type: object
      properties:
        event:
          type: string
          format: uuid
        actor:
          type: string
          format: uuid
          description: ID of the MoonitoringUser who acted; exactly one of actor and user is set.
        user:
          type: string
          format: uuid
          description: ID of the User (an Organization user or ServiceAccount) who acted.
        organization:
          type: string
          format: uuid
          description: ID of the Organization the action concerns, when it concerns one; through a delegation, the
            subject, the farm acted on.
        acting_organization:
          type: string
          format: uuid
          description: ID of the Organization the user acted as, the token's active Organization (decided 2026-11-11);
            it differs from organization when they acted through a delegation.
        action:
          type: string
          description: <system>.<resource>.<verb>.
        capability:
          type: string
        target_type:
          type: string
        target_id:
          type: string
          format: uuid
        before:
          type: string
          description: JSON, changed fields only; never secrets or prompts.
        after:
          type: string
          description: JSON.
        request_id:
          type: string
        occurred_at:
          type: string
          format: date-time
        system:
          type: string
          description: The system that recorded it.
      required:
      - event
      - action
      - target_type
      - target_id
      - request_id
      - occurred_at
      - system
x-moonitoring-consumes:
- event: platform_audit_event.recorded.v1
  producer: every system
  why: Consolidates the audit log it serves in the Audit API, from one subscription on each system's topic `<system>.audit.v1`, which names the system.
- event: entitlement.*.v1
  producer: farm
  why: 'Nothing: access does not check entitlements. Listed for completeness.'
