---
id: WF-CMT-MTG-015
title: Count Started Appointments Against Openings
trigger: The appointment-started event reaches Committees native intake.
product_area: committees
module: meetings
revision: 1
status: draft
design_intent: proposed
implementation_evidence: inconsistent
inference: []
source_sha:
  services-committees: 36129c24daeaadcdb339218c38cdeaff9861359d
implements:
  - CAP-CMT-MTG-016
moves:
  - STATE-CMT-MTG-008
crosses:
  - SVC-CMT-MTG-recruitment
  - SVC-CMT-MTG-meetings
idempotency: >-
  Each opening retains the appointment references it has counted. Redelivery of
  the same appointment adds nothing.
concurrency: >-
  The intake locks the committee’s open openings before counting and changing
  them.
hops:
  - 'n': 1
    actor_or_service: Event intake
    action: >-
      Route the appointment-started message in its workspace to the fill
      subscriber.
    anchor: >-
      services-committees:modules/meetings/aws/lambda/EVENT_INTAKE.handler.ts:handler
    seam: event
    on_failure: Allow event delivery to retry.
    left_inconsistent: An opening can temporarily remain open after its last place is occupied.
    observer: Delivery dead letters.
    provenance: observed
    source: >-
      services-committees:modules/meetings/aws/lambda/EVENT_INTAKE.handler.ts:handler
  - 'n': 2
    actor_or_service: Recruitment service
    action: >-
      Count a matching seat-holder once in each eligible opening and mark full
      openings filled with their closed event.
    anchor: >-
      services-committees:modules/recruitment/services/openings/fill-openings.ts:fillOpeningsFor
    seam: sync
    on_failure: Roll back the intake transaction and retry delivery.
    left_inconsistent: Opening counts remain behind appointment state.
    observer: Native event-intake logs.
    provenance: observed
    source: >-
      services-committees:modules/recruitment/services/openings/fill-openings.ts:fillOpeningsFor
  - 'n': 3
    actor_or_service: Recruitment service
    action: Wake business-event dispatch after the fill commits.
    anchor: >-
      services-committees:modules/recruitment/services/openings/fill-openings.ts:fillOpeningsFor
    seam: event
    on_failure: Fall back to scheduled dispatch.
    left_inconsistent: The closed event is delivered later.
    observer: Event dispatcher logs.
    provenance: observed
    source: >-
      services-committees:modules/recruitment/services/openings/fill-openings.ts:fillOpeningsFor
branches: []
waits: []
evidence:
  - >-
    services-committees at 36129c24:
    modules/recruitment/services/openings/fill-openings.ts;
    services/rules/fill-rule.ts; aws/committees.events.ts
    (COMMITTEES_EVENT_SUBSCRIBERS)
controls:
  - TC-IAM-006
  - TC-AZ-001
  - TC-AZ-002
  - TC-AZ-003
  - TC-AZ-004
  - TC-AZ-006
  - TC-TEN-001
  - TC-TEN-002
  - TC-TEN-003
  - TC-TEN-004
  - TC-SEC-001
  - TC-SEC-004
  - TC-DAT-001
  - TC-DAT-002
  - TC-DAT-003
  - TC-DAT-004
  - TC-LOG-002
  - TC-LOG-003
  - TC-LOG-004
  - TC-LOG-005
  - TC-AVL-004
  - TC-AVL-005
  - TC-MON-001
  - TC-MON-002
  - TC-PI-001
  - TC-PI-002
  - TC-PI-003
  - TC-PI-004
  - TC-PI-005
  - TC-PRV-001
  - TC-PRV-002
---
# Count Started Appointments Against Openings

## What It Does

The appointment-started event reaches Committees native intake. Filling is eventual because the appointment commits first. Matching uses committee, participation kind and any specified seat or position, but does not enforce the advertised application window.

## The Flow

```mermaid
flowchart TD
  H1["Route the appointment-started message in its workspace to the fill subscriber."]

  H2["Count a matching seat-holder once in each eligible opening and mark full openings filled with their closed eve"]
  H3["Wake business-event dispatch after the fill commits."]
  H1 --> H2
  H2 --> H3
```

Route the appointment-started message in its workspace to the fill subscriber. Count a matching seat-holder once in each eligible opening and mark full openings filled with their closed event. Wake business-event dispatch after the fill commits.

## When Something Fails

Allow event delivery to retry. An opening can temporarily remain open after its last place is occupied. Roll back the intake transaction and retry delivery. Opening counts remain behind appointment state. Fall back to scheduled dispatch. The closed event is delivered later.

## Open Design Questions

Filling is eventual because the appointment commits first. Matching uses committee, participation kind and any specified seat or position, but does not enforce the advertised application window.
