---
"$schema": http://json-schema.org/draft-07/schema#
"$id": https://github.com/edoxen/edoxen-model/schema/decision-collection.yaml
title: Edoxen Decision Collection Schema
description: |
  Schema for validating Edoxen decision-side YAML files.

  Accepts three top-level document kinds via `oneOf`:

    * `DecisionCollection` — the formal outcomes adopted by a Meeting.
    * `ContactRegister` — a scoped-URN registry of Contacts.
    * `VenueRegister`  — a scoped-URN registry of Venues.

  Mirrors the canonical LutaML information model in
  https://github.com/edoxen/edoxen-model/tree/main/models .

  The enum constants declared under `$defs` are the authoritative wire
  values. `spec/edoxen/schema_enum_sync_spec.rb` asserts each one is
  character-for-character identical to the corresponding `Edoxen::Enums::*`
  frozen array.

  Trade-off: json_schemer's `valid_values` is not populated when an
  `enum` is reached via `$ref`, so the validator's enum-violation
  message degrades to "value ... is not one of: (see schema)". This
  is documented in `Edoxen::SchemaValidator#format_message`.
type: object
oneOf:
- "$ref": "#/$defs/DecisionCollection"
- "$ref": "#/$defs/ContactRegister"
- "$ref": "#/$defs/VenueRegister"
- "$ref": "#/$defs/BodyRegister"
"$defs":
  DecisionCollection:
    type: object
    description: |
      Top-level container for a published decision collection: metadata
      plus the list of decisions.
    additionalProperties: false
    properties:
      metadata:
        "$ref": "#/$defs/DecisionMetadata"
      decisions:
        type: array
        items:
          "$ref": "#/$defs/Decision"
    required:
    - decisions
  StructuredIdentifier:
    type: object
    description: An identifier (prefix + number). A Decision carries 1..* of these.
    additionalProperties: false
    required:
    - prefix
    - number
    properties:
      prefix:
        type: string
      number:
        type: string
  EntityRef:
    type: object
    description: |
      Typed cross-reference between entities (1.0, TODO.refactor/1.0-design).
      Exactly one of `urn`, `identifier`, or `local_ref` should be set;
      the gem's `EntityRef#valid?` enforces this in Ruby.
    additionalProperties: false
    properties:
      urn:
        type: string
      identifier:
        "$ref": "#/$defs/StructuredIdentifier"
      local_ref:
        type: string
      kind:
        type: string
      role:
        type: string
      note:
        type: string
  MeetingIdentifier:
    type: object
    description: Identifies the meeting a Decision belongs to.
    additionalProperties: false
    properties:
      venue:
        type: string
      date:
        type: string
        format: date
  Url:
    type: object
    description: URL with a kind (access / report) and an optional format hint.
    additionalProperties: false
    required:
    - kind
    - ref
    properties:
      kind:
        "$ref": "#/$defs/UrlKind"
      ref:
        type: string
      format:
        type: string
  DecisionRelation:
    type: object
    description: Directed relation between two decisions identified by their StructuredIdentifier.
    additionalProperties: false
    required:
    - source
    - destination
    - type
    properties:
      source:
        "$ref": "#/$defs/StructuredIdentifier"
      destination:
        "$ref": "#/$defs/StructuredIdentifier"
      type:
        "$ref": "#/$defs/DecisionRelationType"
  DecisionDate:
    type: object
    description: Date with semantic kind (adoption / drafted / discussed).
    additionalProperties: false
    required:
    - date
    - type
    properties:
      date:
        type: string
        format: date
      type:
        "$ref": "#/$defs/DecisionDateType"
  Action:
    type: object
    description: A verb + one effective date + human-readable message.
    additionalProperties: false
    required:
    - type
    - message
    - date_effective
    properties:
      type:
        "$ref": "#/$defs/ActionType"
      date_effective:
        "$ref": "#/$defs/DecisionDate"
      message:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
  Approval:
    type: object
    description: 'Approval record: vote type, consensus degree, date, message.'
    additionalProperties: false
    required:
    - type
    - degree
    - date
    properties:
      type:
        "$ref": "#/$defs/ApprovalType"
      degree:
        "$ref": "#/$defs/ApprovalDegree"
      date:
        "$ref": "#/$defs/DecisionDate"
      message:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
  Consideration:
    type: object
    description: 'The basis for a Decision: a verb + one effective date + reasoning.'
    additionalProperties: false
    required:
    - type
    - message
    - date_effective
    properties:
      type:
        "$ref": "#/$defs/ConsiderationType"
      date_effective:
        "$ref": "#/$defs/DecisionDate"
      message:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
  LocalizedString:
    type: object
    description: |
      One language-specific value of a translatable String field.
      `spelling` is an ISO 24229 spelling/conversion system code.
      Always verbose — single-language data uses the same
      `[{ spelling, value }]` shape as multi-language data.
    additionalProperties: false
    required:
    - spelling
    - value
    properties:
      spelling:
        type: string
      value:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  LocalizedName:
    type: object
    description: |
      One language-specific value of a translatable Name field.
      Mirrors LocalizedString but carries a structured Name.
    additionalProperties: false
    required:
    - spelling
    - value
    properties:
      spelling:
        type: string
      value:
        "$ref": "#/$defs/Name"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  SourceUrl:
    type: object
    description: Per-spelling canonical source URL (e.g. one PDF per language).
    additionalProperties: false
    required:
    - ref
    properties:
      ref:
        type: string
      format:
        type: string
      spelling:
        type: string
        description: ISO 24229 spelling/conversion system code
      kind:
        "$ref": "#/$defs/SourceUrlKind"
  Decision:
    type: object
    description: |
      A formal Decision. 1.0: per-field Localized (every translatable
      field carries its own spelling tag). Removed `localizations[]`.
    additionalProperties: false
    required:
    - identifier
    properties:
      identifier:
        type: array
        minItems: 1
        items:
          "$ref": "#/$defs/StructuredIdentifier"
      kind:
        "$ref": "#/$defs/DecisionKind"
      status:
        "$ref": "#/$defs/DecisionStatus"
      body_type:
        type: string
      doi:
        type: string
      urn:
        type: string
      agenda_item:
        type: string
      dates:
        type: array
        items:
          "$ref": "#/$defs/DecisionDate"
      categories:
        type: array
        items:
          type: string
      meeting:
        "$ref": "#/$defs/MeetingIdentifier"
      relations:
        type: array
        items:
          "$ref": "#/$defs/DecisionRelation"
      urls:
        type: array
        items:
          "$ref": "#/$defs/Url"
      brought_by_motions:
        type: array
        items:
          type: string
      about_topics:
        type: array
        items:
          type: string
      made_in_component:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      subject:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      message:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      considering:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      considerations:
        type: array
        items:
          "$ref": "#/$defs/Consideration"
      approvals:
        type: array
        items:
          "$ref": "#/$defs/Approval"
      actions:
        type: array
        items:
          "$ref": "#/$defs/Action"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  DecisionMetadata:
    type: object
    description: Collection-level metadata (localized title, meeting date, source, source URLs, host venue).
    additionalProperties: false
    properties:
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      date:
        type: string
        format: date
      source:
        type: string
      source_urls:
        type: array
        items:
          "$ref": "#/$defs/SourceUrl"
      city:
        type: string
        pattern: "^[A-Z]{2}[A-Z0-9]{3}$"
      country_code:
        type: string
        pattern: "^[A-Z]{2}$"
      meeting_urn:
        type: string
      body_vocabulary:
        type: array
        items:
          "$ref": "#/$defs/BodyVocabularyEntry"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  BodyVocabularyEntry:
    type: object
    description: |
      One entry in a per-dataset body_vocabulary list. Maps a free-form
      body_type to a short canonical value. SSOT for body_type ->
      canonical_type resolution within the declaring collection.
    additionalProperties: false
    properties:
      body_type:
        type: string
      canonical_type:
        type: string
      definition:
        type: string
  Motion:
    type: object
    description: A procedural act that brings a Decision.
    additionalProperties: false
    properties:
      identifier:
        type: string
      urn:
        type: string
      text:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      mover:
        "$ref": "#/$defs/Person"
      seconders:
        type: array
        items:
          "$ref": "#/$defs/Person"
      status:
        "$ref": "#/$defs/MotionStatus"
      introduced_at:
        type: string
        format: date-time
      proposed_decision:
        type: string
      resulting_decision:
        type: string
      resulting_decision_ref:
        "$ref": "#/$defs/EntityRef"
      votings:
        type: array
        items:
          type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  VotingCounts:
    type: object
    description: Tally for a Voting instance.
    additionalProperties: false
    properties:
      ayes:
        type: integer
      noes:
        type: integer
      abstentions:
        type: integer
      absent:
        type: integer
  Voting:
    type: object
    description: State machine for a single vote on a Motion.
    additionalProperties: false
    properties:
      identifier:
        type: string
      urn:
        type: string
      on_motion:
        type: string
      status:
        "$ref": "#/$defs/VotingStatus"
      voting_method:
        "$ref": "#/$defs/VotingMethod"
      called_by:
        "$ref": "#/$defs/Person"
      called_at:
        type: string
        format: date-time
      result_declared_at:
        type: string
        format: date-time
      result:
        "$ref": "#/$defs/VotingOutcome"
      counts:
        "$ref": "#/$defs/VotingCounts"
      casting_vote:
        "$ref": "#/$defs/VoteRecord"
      vote_records:
        type: array
        items:
          "$ref": "#/$defs/VoteRecord"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  TopicDocument:
    type: object
    description: 'Text-bearing document about a Topic. 1.0: per-field Localized.'
    additionalProperties: false
    properties:
      identifier:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      version:
        type: string
      status:
        type: string
      url:
        type: string
      format:
        type: string
      spelling:
        type: string
        description: ISO 24229 spelling/conversion system code
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  TopicAsset:
    type: object
    description: 'Non-text resource about a Topic. 1.0: per-field Localized.'
    additionalProperties: false
    properties:
      identifier:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      kind:
        type: string
      url:
        type: string
      format:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Topic:
    type: object
    description: 'The subject of discussion at a Meeting. 1.0: per-field Localized.'
    additionalProperties: false
    properties:
      identifier:
        type: string
      urn:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      status:
        "$ref": "#/$defs/TopicStatus"
      resumption_of:
        type: string
      documents:
        type: array
        items:
          "$ref": "#/$defs/TopicDocument"
      assets:
        type: array
        items:
          "$ref": "#/$defs/TopicAsset"
      references:
        type: array
        items:
          "$ref": "#/$defs/Reference"
      motions:
        type: array
        items:
          type: string
      decisions:
        type: array
        items:
          type: string
      statements:
        type: array
        items:
          "$ref": "#/$defs/Statement"
      declarations:
        type: array
        items:
          "$ref": "#/$defs/Declaration"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Venue:
    type: object
    description: |
      Polymorphic place where a Meeting happens. `kind` discriminates
      physical vs virtual; all fields from both subtypes live here as
      optional siblings. 1.0: per-field Localized (name, label,
      description, address, building, floor, room, access_notes).
      Added `urn` (registry identity) and `ref` (reference-by-URN).
    additionalProperties: false
    properties:
      ref:
        type: string
      local_ref:
        type: string
      urn:
        type: string
        pattern: "^urn:edoxen:venue:[^:]+:[^:]+$"
      kind:
        "$ref": "#/$defs/VenueKind"
      name:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      label:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      capacity:
        type: integer
      url:
        type: string
      contact_methods:
        type: array
        items:
          "$ref": "#/$defs/ContactMethod"
      unlocode:
        type: string
        pattern: "^[A-Z]{2}[A-Z0-9]{3}$"
      iata_code:
        type: string
        pattern: "^[A-Z]{3}$"
      address:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      city:
        type: string
      country_code:
        type: string
        pattern: "^[A-Z]{2}$"
      lat:
        type: number
      lon:
        type: number
      building:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      floor:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      room:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      access_notes:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      uri:
        type: string
      features:
        type: array
        items:
          "$ref": "#/$defs/VirtualFeature"
      passcode:
        type: string
      meeting_id:
        type: string
      dial_in_numbers:
        type: array
        items:
          type: string
      waiting_room:
        type: boolean
      registration_required:
        type: boolean
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  PhysicalVenue:
    description: Marker — Venue with kind=physical. Wire shape is identical to Venue.
    allOf:
    - "$ref": "#/$defs/Venue"
  VirtualVenue:
    description: Marker — Venue with kind=virtual. Wire shape is identical to Venue.
    allOf:
    - "$ref": "#/$defs/Venue"
  RecurrenceByDay:
    type: object
    description: BYDAY part of a recurrence. `ordinal` is null for 'every', +1 for first, -1 for last.
    additionalProperties: false
    properties:
      ordinal:
        type: integer
      weekday:
        type: string
  Recurrence:
    type: object
    description: Structured ISO 8601-2 §13 recurrence.
    additionalProperties: false
    properties:
      freq:
        "$ref": "#/$defs/RecurrenceFreq"
      interval:
        type: integer
      count:
        type: integer
      until:
        type: string
        format: date-time
      by_day:
        type: array
        items:
          "$ref": "#/$defs/RecurrenceByDay"
      by_month_day:
        type: array
        items:
          type: integer
      by_month:
        type: array
        items:
          type: integer
      by_week_no:
        type: array
        items:
          type: integer
      by_year_day:
        type: array
        items:
          type: integer
      by_hour:
        type: array
        items:
          type: integer
      by_minute:
        type: array
        items:
          type: integer
      by_second:
        type: array
        items:
          type: integer
      by_set_pos:
        type: array
        items:
          type: integer
      week_start:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  ExtensionAttribute:
    type: object
    description: |
      One typed key/value pair within a MeetingExtension. Polymorphic on
      value type so consumers don't re-parse strings back into Int/Float/
      Bool/Date (1.0 tighten, TODO.refactor/1.0-design).
    additionalProperties: false
    properties:
      key:
        type: string
      type:
        type: string
        enum:
        - string
        - integer
        - float
        - boolean
        - date
        - datetime
      value:
        type: string
      intValue:
        type: integer
      floatValue:
        type: number
      booleanValue:
        type: boolean
      dateValue:
        type: string
        format: date
      dateTimeValue:
        type: string
        format: date-time
  MeetingExtension:
    type: object
    description: |
      Profile-specific extension. Adopters register their namespace via
      `profile` and discriminate via `kind`. Field semantics tightened
      1.0 (TODO.refactor/1.0-design): `kind` is the in-profile discriminator,
      `ref` is the URN of an external profile document, and the
      recursive `extensions[]` slot was removed (YAGNI — use dotted
      keys in `attributes[]` for nesting).
    additionalProperties: false
    properties:
      profile:
        type: string
      kind:
        type: string
      ref:
        type: string
      attributes:
        type: array
        items:
          "$ref": "#/$defs/ExtensionAttribute"
  ContactMethodKind:
    type: string
    description: Polymorphic communication channel kind.
    enum:
    - phone
    - mobile
    - fax
    - email
    - url
    - mail
    - pager
    - message
    - other
  ContactMethod:
    type: object
    description: |
      One polymorphic communication channel — phone, email, fax, url,
      mail, etc. `kind` discriminates the channel; `value` carries the
      address/number; `label` is a free-form display hint ("Office",
      "Front desk"). OCP: new channel kinds are added via the
      ContactMethodKind enum (or `other` + extensions).
    additionalProperties: false
    properties:
      kind:
        "$ref": "#/$defs/ContactMethodKind"
      value:
        type: string
      label:
        type: string
      primary:
        type: boolean
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  ContactIdentifierKind:
    type: string
    description: Polymorphic external identifier scheme for a Contact.
    enum:
    - orcid
    - isni
    - wikidata
    - ror
    - ringgold
    - github
    - other
  ContactIdentifier:
    type: object
    description: |
      One polymorphic external identifier — ORCID, ISNI, Wikidata QID,
      ROR, Ringgold, GitHub handle, etc. Replaces the hard-coded `orcid`
      field. OCP: new identifier schemes are added via the
      ContactIdentifierKind enum (or `other` + extensions).
    additionalProperties: false
    properties:
      kind:
        "$ref": "#/$defs/ContactIdentifierKind"
      value:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Name:
    type: object
    description: |
      Structured personal/organisational name (VCARD RFC 6350
      conventions). `formatted` is the pre-built display string (FN);
      the structured components (N) are stored separately for sorting,
      indexing, or locale-aware rendering.
    additionalProperties: false
    properties:
      formatted:
        type: string
      family:
        type: string
      given:
        type: string
      additional:
        type: string
      prefix:
        type: string
      suffix:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Contact:
    type: object
    description: |
      VCARD-like abstract contact. 1.0: per-field Localized
      (name, title, affiliation, address). Added `urn` (registry
      identity) and `ref` (reference-by-URN).
    additionalProperties: false
    properties:
      ref:
        type: string
      local_ref:
        type: string
      urn:
        type: string
        pattern: "^urn:edoxen:contact:[^:]+:[^:]+$"
      name:
        type: array
        items:
          "$ref": "#/$defs/LocalizedName"
      kind:
        type: string
      role:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      affiliation:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      contact_methods:
        type: array
        items:
          "$ref": "#/$defs/ContactMethod"
      identifiers:
        type: array
        items:
          "$ref": "#/$defs/ContactIdentifier"
      address:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Person:
    type: object
    description: |
      A Contact that is specifically an individual human. Schema
      duplicates Contact's properties because JSON-Schema draft-07
      doesn't support `extends`. Same shape; semantically a subclass.
    additionalProperties: false
    properties:
      ref:
        type: string
      local_ref:
        type: string
      urn:
        type: string
        pattern: "^urn:edoxen:contact:[^:]+:[^:]+$"
      name:
        type: array
        items:
          "$ref": "#/$defs/LocalizedName"
      kind:
        type: string
      role:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      affiliation:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      contact_methods:
        type: array
        items:
          "$ref": "#/$defs/ContactMethod"
      identifiers:
        type: array
        items:
          "$ref": "#/$defs/ContactIdentifier"
      address:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Reference:
    type: object
    description: Generic document reference.
    additionalProperties: false
    properties:
      ref:
        type: string
      kind:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
  VoteRecord:
    type: object
    description: One vote by one person on one decision/voting.
    additionalProperties: false
    required:
    - person
    - vote
    properties:
      decision_ref:
        type: string
      voting_ref:
        type: string
      person:
        "$ref": "#/$defs/Person"
      affiliation:
        type: string
      vote:
        "$ref": "#/$defs/VoteType"
      role:
        type: string
      notes:
        type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Officer:
    type: object
    description: A person holding a structural role in a Meeting.
    additionalProperties: false
    properties:
      role:
        "$ref": "#/$defs/OfficerRole"
      person:
        "$ref": "#/$defs/Person"
      term_start:
        type: string
        format: date
      term_end:
        type: string
        format: date
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  MeetingComponent:
    type: object
    description: 'Flat sub-event of a Meeting. 1.0: per-field Localized.'
    additionalProperties: false
    properties:
      identifier:
        type: string
      urn:
        type: string
      kind:
        "$ref": "#/$defs/ComponentKind"
      body_type:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      starts_at:
        type: string
        format: date-time
      ends_at:
        type: string
        format: date-time
      time_label:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      venue_refs:
        type: array
        items:
          type: string
      officers:
        type: array
        items:
          "$ref": "#/$defs/Officer"
      agenda_ref:
        type: string
      minutes_ref:
        type: string
      attendance_refs:
        type: array
        items:
          type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  MeetingSeries:
    type: object
    description: 'Parent of recurring Meeting instances. 1.0: per-field Localized.'
    additionalProperties: false
    properties:
      identifier:
        type: array
        items:
          "$ref": "#/$defs/StructuredIdentifier"
      urn:
        type: string
      name:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      recurrence:
        "$ref": "#/$defs/Recurrence"
      term:
        type: string
      contact:
        "$ref": "#/$defs/Contact"
      hosts:
        type: array
        items:
          "$ref": "#/$defs/HostRef"
      kind:
        type: string
      meeting_refs:
        type: array
        items:
          type: string
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
      body_type:
        type: string
  HostRef:
    type: object
    description: Typed reference to a hosting organization.
    additionalProperties: false
    required:
    - ref
    properties:
      ref:
        type: string
      type:
        "$ref": "#/$defs/HostType"
      role:
        type: string
      contact:
        "$ref": "#/$defs/Contact"
  ContactRegister:
    type: object
    description: |
      Registry of Contacts indexed by scoped URN. Members carry
      `urn: urn:edoxen:contact:{scope}:{local-id}`; the collection's
      `scope` MUST match the scope segment in member URNs.
    additionalProperties: false
    properties:
      scope:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      contacts:
        type: array
        items:
          "$ref": "#/$defs/Contact"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  VenueRegister:
    type: object
    description: 'Registry of Venues indexed by scoped URN. Mirrors ContactRegister.

      '
    additionalProperties: false
    properties:
      scope:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      venues:
        type: array
        items:
          "$ref": "#/$defs/Venue"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  ActionType:
    type: string
    description: |
      Action verb. Edoxen::Enums::ACTION_TYPE lists the canonical set
      (28 values). The schema is permissive — adopters may use
      body-specific verbs (e.g. "scopes", "directs", "establishes")
      outside the canonical set. The canonical set is advisory; the
      body_vocabulary mechanism (1.0, TODO.refactor/1.0-design) will
      eventually map body-specific verbs to canonical types.
  ConsiderationType:
    type: string
    description: |
      Consideration verb. Edoxen::Enums::CONSIDERATION_TYPE lists the
      canonical set. The schema is permissive — adopters may use
      body-specific verbs outside the canonical set (same rationale as
      ActionType).
  ApprovalType:
    type: string
    description: Edoxen::Enums::APPROVAL_TYPE.
    enum:
    - affirmative
    - negative
  ApprovalDegree:
    type: string
    description: Edoxen::Enums::APPROVAL_DEGREE.
    enum:
    - unanimous
    - majority
    - minority
  DecisionKind:
    type: string
    description: Edoxen::Enums::DECISION_KIND.
    enum:
    - resolution
    - order
    - ruling
    - determination
    - recommendation
    - statement
    - finding
    - opinion
    - other
  DecisionKindCanonical:
    type: string
    description: |
      Edoxen::Enums::DECISION_KIND_CANONICAL — short abstract set (1.0,
      TODO.refactor/1.0-design). Bodies extend via `body_type` + per-dataset
      `body_vocabulary[]`.
    enum:
    - decision
    - recommendation
    - statement
    - finding
    - other
  DecisionStatus:
    type: string
    description: Edoxen::Enums::DECISION_STATUS.
    enum:
    - draft
    - proposed
    - under_consideration
    - decided
    - negatived
    - withdrawn
    - deferred
  DecisionDateType:
    type: string
    description: Edoxen::Enums::DECISION_DATE_TYPE.
    enum:
    - adoption
    - drafted
    - discussed
    - proposed
    - decided
    - negatived
    - withdrawn
    - published
    - effective
  DecisionRelationType:
    type: string
    description: Edoxen::Enums::DECISION_RELATION_TYPE.
    enum:
    - annex_of
    - has_annex
    - updates
    - refines
    - replaces
    - considers
    - cites
  MotionStatus:
    type: string
    description: Edoxen::Enums::MOTION_STATUS.
    enum:
    - introduced
    - seconded
    - debating
    - question_put
    - voting
    - carried
    - negatived
    - withdrawn
    - lapsed
  VotingStatus:
    type: string
    description: Edoxen::Enums::VOTING_STATUS.
    enum:
    - called
    - in_progress
    - decided
    - withdrawn
    - deferred
  VotingMethod:
    type: string
    description: Edoxen::Enums::VOTING_METHOD.
    enum:
    - voice
    - division
    - show_of_hands
    - roll_call
    - electronic
    - secret_ballot
    - unanimous_consent
    - consensus
  VotingOutcome:
    type: string
    description: Edoxen::Enums::VOTING_OUTCOME.
    enum:
    - passed
    - negatived
    - tied
    - withdrawn
  TopicStatus:
    type: string
    description: Edoxen::Enums::TOPIC_STATUS.
    enum:
    - open
    - under_discussion
    - decided
    - deferred
    - withdrawn
  VenueKind:
    type: string
    description: Edoxen::Enums::VENUE_KIND.
    enum:
    - physical
    - virtual
  VirtualFeature:
    type: string
    description: Edoxen::Enums::VIRTUAL_FEATURE.
    enum:
    - audio
    - video
    - chat
    - phone
    - screen
    - feed
  Visibility:
    type: string
    description: Edoxen::Enums::VISIBILITY.
    enum:
    - public
    - private
    - confidential
  AttendanceRole:
    type: string
    description: Edoxen::Enums::ATTENDANCE_ROLE.
    enum:
    - chair
    - required
    - optional
    - non_participant
  AttendanceResponse:
    type: string
    description: Edoxen::Enums::ATTENDANCE_RESPONSE.
    enum:
    - pending
    - confirmed
    - declined
    - tentative
    - delegated
  ComponentKind:
    type: string
    description: Edoxen::Enums::COMPONENT_KIND.
    enum:
    - track
    - session
    - debate
    - breakout
    - bof
    - plenary_session
    - working_group_session
    - committee_of_the_whole
    - keynote
    - address
    - statement
    - question_time
    - opening
    - closing
    - break
    - reception
    - registration
    - networking
    - other
  ComponentKindCanonical:
    type: string
    description: |
      Edoxen::Enums::COMPONENT_KIND_CANONICAL — short abstract set
      (1.0, TODO.refactor/1.0-design).
    enum:
    - deliberative
    - working
    - ceremonial
    - break
    - other
  OfficerRole:
    type: string
    description: Edoxen::Enums::OFFICER_ROLE.
    enum:
    - chair
    - vice_chair
    - deputy_chair
    - secretary
    - treasurer
    - parliamentarian
    - presiding_officer
    - sergeant_at_arms
    - other
  RecurrenceFreq:
    type: string
    description: Edoxen::Enums::RECURRENCE_FREQ.
    enum:
    - secondly
    - minutely
    - hourly
    - daily
    - weekly
    - monthly
    - yearly
  UrlKind:
    type: string
    description: Edoxen::Enums::URL_KIND.
    enum:
    - access
    - report
  SourceUrlKind:
    type: string
    description: Edoxen::Enums::SOURCE_URL_KIND.
    enum:
    - agenda_pdf
    - minutes_pdf
    - decisions_pdf
    - report_pdf
    - register_url
    - landing_page
  HostType:
    type: string
    description: Edoxen::Enums::HOST_TYPE.
    enum:
    - national_body
    - liaison
    - associate
    - organizer
  VoteType:
    type: string
    description: Edoxen::Enums::VOTE_TYPE.
    enum:
    - affirmative
    - negative
    - abstain
    - absent
    - not_applicable
  DateTimeRange:
    type: object
    description: |
      Start + end pair with sub-day precision. Parallel to DateRange;
      use when day granularity is insufficient (e.g. a meeting that
      ran 09:00–11:30).
    additionalProperties: false
    properties:
      start:
        type: string
        format: date-time
      end:
        type: string
        format: date-time
  StatementKind:
    type: string
    description: |
      Discriminator for the three BS 0:2006 statement types. Adding a
      new kind is a one-line enum extension; the Statement model
      itself never needs to change (OCP).
    enum:
    - statement
    - comment
    - standpoint
  DeclarationKind:
    type: string
    description: |
      Discriminator for the two BS 0:2006 declaration types
      (conflict of interest, IPR).
    enum:
    - conflict_of_interest
    - ipr
  Statement:
    type: object
    description: |
      One remark made by one or more meeting members on a topic or a
      minutes section. Per-field Localized description; party is a
      list of Person references. The `kind` discriminator separates
      the three BS 0:2006 statement types.
    additionalProperties: false
    properties:
      kind:
        "$ref": "#/$defs/StatementKind"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      party:
        type: array
        items:
          "$ref": "#/$defs/Person"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Declaration:
    type: object
    description: |
      A formal declaration (conflict of interest or IPR) made by one
      or more meeting members. IPR-specific fields (`ipr_subject_ref`,
      `ipr_target_ref`) are populated only when `kind == "ipr"`.
    additionalProperties: false
    properties:
      kind:
        "$ref": "#/$defs/DeclarationKind"
      description:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      party:
        type: array
        items:
          "$ref": "#/$defs/Person"
      ipr_subject_ref:
        "$ref": "#/$defs/EntityRef"
      ipr_target_ref:
        "$ref": "#/$defs/EntityRef"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  Body:
    type: object
    description: |
      A committee, subcommittee, working group, or other organised body.
      Three-tier entity resolution (ref / local_ref / inline).
    additionalProperties: false
    properties:
      ref:
        type: string
      local_ref:
        type: string
      code:
        type: string
      name:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      kind:
        type: string
      parent_ref:
        "$ref": "#/$defs/EntityRef"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
  BodyRegister:
    type: object
    description: |
      Authoritative register of Bodies (committees, subcommittees,
      working groups).
    additionalProperties: false
    properties:
      scope:
        type: string
      title:
        type: array
        items:
          "$ref": "#/$defs/LocalizedString"
      bodies:
        type: array
        items:
          "$ref": "#/$defs/Body"
      extensions:
        type: array
        items:
          "$ref": "#/$defs/MeetingExtension"
