## ADDED Requirements

### Requirement: Phase 2 ingress is hard-gated by Phase 1 evidence
No Resource Booking-to-Timetabler production-code implementation or migration SHALL begin until the approved Phase 1 completion report proves that both Timetabler and Resource Booking/adapter completed and passed all required Phase 1 integration, regression, failure-injection, reconciliation, concurrency, security, and performance testing.

#### Scenario: Phase 1 report is missing or incomplete
- **WHEN** a Phase 2 implementation task is selected without a current approved report tied to the Phase 1 deployment commits
- **THEN** the task is blocked and no Phase 2 production file or migration is changed

#### Scenario: All Phase 1 evidence is approved
- **WHEN** both service owners approve the complete versioned Phase 1 report and record the dependency as satisfied
- **THEN** Phase 2 implementation may begin in the task order defined by this change

### Requirement: Resource Booking sends one canonical occurrence command
The RB-owned adapter SHALL send one authenticated canonical create/update/cancel command per expanded booking occurrence through a dedicated Kafka message role/topic. The RB transaction SHALL atomically record booking state, authoritative fenced reservation state, audit/workflow state, and the dedicated command outbox. The command SHALL include stable source and occurrence identities, monotonic source version, correlation/causation, UTC/local timezone data, Staff/Location Timetabler source IDs, duration/status, reservation/fencing evidence, and actor/audit metadata.

#### Scenario: Recurring RB booking is expanded
- **WHEN** Resource Booking commits/proposes a recurrence containing multiple occurrences
- **THEN** the adapter expands it using the agreed timezone/calendar rules and sends a distinct stable `occurrence_ref` command for each occurrence

#### Scenario: Complete resource assignment is submitted
- **WHEN** an occurrence uses both Staff and Locations
- **THEN** one command carries the complete Staff + Location + time assignment rather than invoking independent Timetabler resource-scheduling calls

### Requirement: Kafka command delivery is durable and role-isolated
The Resource Booking occurrence command SHALL use a dedicated Kafka command role distinct from generic lifecycle events. Timetabler SHALL consume with `read_committed` isolation, stable occurrence partition ordering, and manual durable-outcome-only offset handling. Kafka acknowledgement SHALL prove transport only; Resource Booking SHALL use the Timetabler receipt/status interface or correlated Phase 1 echo to establish application outcome.

#### Scenario: Command is redelivered after Timetabler commit
- **WHEN** Timetabler commits the native booking, receipt, and Phase 1 echo but crashes before storing or committing the Kafka offset
- **THEN** redelivery returns the recorded duplicate outcome without a second mutation or echo and the offset advances only after that durable outcome

#### Scenario: Generic lifecycle event reaches the command consumer
- **WHEN** a Resource Booking event lacks the dedicated command role or declares `timetabler_allocation_command=false`
- **THEN** Timetabler rejects or quarantines it without interpreting it as a native booking command

### Requirement: Internal ingress is authenticated and scoped
Timetabler SHALL consume the command through a dedicated Kafka consumer authenticated and authorized as the RB adapter for the configured integration tenant/environment. Timetabler SHALL also expose bounded authenticated receipt/status lookup for ambiguous delivery outcomes. It SHALL validate broker role/ACL context, replay protection, request size/rate limits where applicable, tenant/academic-term/resource scope, timezone/time consistency, booking type, command version/hash, and reservation evidence.

#### Scenario: Unauthorized caller submits a command
- **WHEN** a caller lacks valid service authentication or tenant scope
- **THEN** Timetabler rejects the command without creating a mapping, activity, outbox event, or audit mutation

#### Scenario: Resource belongs to another tenant/term
- **WHEN** a valid service credential references a Staff, Location, or academic term outside its configured scope
- **THEN** Timetabler rejects the complete command and records a safe security/audit event

#### Scenario: UTC and local time disagree
- **WHEN** the UTC timestamps, local timestamps, timezone/offset, duration, or occurrence date are inconsistent
- **THEN** Timetabler rejects the command before database mutation and reports a deterministic validation error

### Requirement: Native booking semantics are reused
Each accepted RB occurrence SHALL be represented initially by one native `TtActivity` whose configured `TtActivityType.booking` is true and whose `TtActivity.is_booking` is set. Timetabler SHALL NOT require the adapter to orchestrate `booking/create` followed by separate Staff and Location `booking/schedule` calls.

#### Scenario: RB occurrence is created
- **WHEN** a valid create command is accepted
- **THEN** Timetabler creates one native booking activity with booking type, occurrence week/date/time/duration, and complete Staff/Location relations

#### Scenario: Existing booking behavior is queried
- **WHEN** the native booking is read through existing booking/schedule views and engine/resource-map paths
- **THEN** it remains compatible with established `TtActivity`/`is_booking` behavior and occupies the resources seen by Timetabler and the engine

### Requirement: Source mapping and version receipt are durable
Timetabler SHALL persist a unique mapping/receipt for integration tenant, source system, source booking reference, and occurrence reference. It SHALL record mapped activity, current version/hash/status, origin/correlation/causation, reservation/fencing identity, outcome, and audit timestamps.

#### Scenario: Duplicate command is delivered
- **WHEN** the same source identity, version, and payload hash is received again
- **THEN** Timetabler returns the recorded result without a second activity mutation, outbox event, or resource-map change

#### Scenario: Stale version is delivered
- **WHEN** a command version is lower than the mapping's current version
- **THEN** Timetabler rejects it as stale and leaves the current booking unchanged

#### Scenario: Same version has conflicting content
- **WHEN** the same source identity/version arrives with a different payload hash
- **THEN** Timetabler rejects/quarantines it, alerts on the protocol violation, and leaves the booking unchanged

#### Scenario: Out-of-order later version arrives first
- **WHEN** version N+1 commits before version N is delivered
- **THEN** the later version remains authoritative and subsequent version N is rejected as stale

### Requirement: Create, update, and cancel are atomic
Timetabler SHALL apply the mapping/receipt, native booking, all Staff/Location/week/time relations, database resource maps, audit state, and ordinary TT outbound event in one database transaction. Updates SHALL replace prior allocation scope atomically; cancellation SHALL be idempotent.

#### Scenario: Staff and Location booking is created
- **WHEN** a command assigns both Staff and Location
- **THEN** no reader can observe an activity containing only one resource class, and either the complete booking plus receipt/outbox commits or none does

#### Scenario: Booking is updated to another time/resources
- **WHEN** a later version changes time, Staff, or Location
- **THEN** the old complete allocation is replaced by the new complete allocation in one transaction and the event contains old/new scope

#### Scenario: Booking is cancelled twice
- **WHEN** the same cancellation version/hash is delivered repeatedly
- **THEN** the first applicable cancellation removes/releases native occupancy and later duplicates are successful no-ops with no duplicate tombstone/event

#### Scenario: Failure occurs after activity mutation
- **WHEN** a failure is injected after native activity/relation changes but before receipt/outbox/resource-map completion
- **THEN** the transaction rolls back entirely and no partial booking is visible

### Requirement: RB-originated mutation emits echo-safe TT event
An accepted RB command SHALL create the ordinary Phase 1 TT outbound replacement/tombstone event with `origin=resource_booking`, source/occurrence/version, correlation/causation, mapping receipt, and reservation identity in the same Timetabler transaction as the native booking. That event SHALL return through the Phase 1 Kafka path. The adapter SHALL recognize the matching event as an acknowledgement/echo and SHALL NOT issue another TT command or create another RB booking.

#### Scenario: Adapter consumes its own acknowledged mutation
- **WHEN** the TT outbound event matches the adapter workflow's source identity and version
- **THEN** the adapter marks the TT step acknowledged and does not re-enter the RB-to-TT command path

#### Scenario: Event lacks matching origin metadata
- **WHEN** an outbound event cannot be correlated to an RB-originated receipt
- **THEN** the adapter handles it as a normal TT-authoritative Phase 1/Phase 2 change according to source/version rules rather than assuming echo

### Requirement: Audit preserves service and originating actor
Timetabler SHALL record the authenticated adapter service identity and the supplied RB user/service actor metadata without impersonating an unrelated Timetabler user. Command, mapping, activity, outbox, and reservation correlation SHALL be traceable end-to-end.

#### Scenario: Operator investigates an occurrence
- **WHEN** an operator queries by source reference, occurrence reference, Timetabler activity ID, event ID, reservation ID, or correlation ID
- **THEN** the related command/version/outcome/audit records can be traced without exposing credentials or sensitive payloads
