← All memos
May 1, 2026deliveryplatformsalesrevenueClosed

Adopting Platform's credit-event naming and updating the subtraction rule for the lock-aware availability projection

Tagstopology, domain-split, coaching, contracts, credit-reservation-lock, correction

Adopting Platform's credit-event naming and updating the subtraction rule for the lock-aware availability projection

Why

Platform's 2026-05-01 sub-thread response confirmed Coaching can stand up a day-one subscriber on the credit-reservation-lock event surface and corrected the event naming used in Delivery's prior position. The events live under the credit.* family per the contract, not lock.*. The correction has a substantive consequence beyond the rename: the contract's credit.reserved state sits before credit.locked and the prior subtraction rule did not account for it. This memo adopts Platform's naming, updates the subtraction rule against the actual event surface, and acknowledges the §12 consumer responsibilities Coaching inherits.

What

Naming adopted

The lock-aware availability projection in coach-availability v1.0.0 names the events it subscribes to using the canonical contract names: credit.reserved, credit.locked, credit.released, credit.forfeited. The contract README is the source of truth on event names; Delivery's prior reply used lock.* aliases that are not in the contract.

credit.consumed is intentionally omitted from the subscription set. The transition is terminal-past (a delivered lesson) and does not bear on future-window availability. Coaching's projection ages out past windows on a clock rather than on event signal, which is simpler and avoids a redundant subscriber.

credit.funded is also omitted. The funding sub-state is Revenue-internal and does not change whether the slot is claimed; the slot is claimed from credit.reserved regardless of funding state.

Subtraction rule restated against the real event surface

The contract has a state (reserved) that sits before lock with a multi-day duration in the typical case, since credit.locked fires only at the T-48h auto-job and only when the reservation is funded. If the projection only subtracted on credit.locked, two operators could legitimately see the same slot as available between credit.reserved and credit.locked, which is exactly the double-booking risk Sales raised in 2026-05-01-sales-coaching-split-confirmations. The corrected rule subtracts from the moment the slot is claimed.

credit.reserved subtracts. The slot is claimed at the moment the reservation is recorded, regardless of funding state.

credit.locked keeps the slot subtracted. This is a state transition with no projection delta; the slot was already subtracted on credit.reserved. The subscriber processes the event for idempotent state-tracking purposes and to advance the projection's per-window state from "reserved" to "locked" if the projection surfaces that distinction to consumers.

credit.released unsubtracts. The slot is back. Reason codes on the payload are passed through to consumers if useful but do not change the rule.

credit.forfeited unsubtracts. The slot is back, even though Sguild keeps the credit. Customer-side cancellation post-lock and no-show both land here per §9.7.

The "softly held" forward-looking hatch from Delivery's prior reply still applies, and is now namable: it would expose pre-credit.reserved operator-tooling reservations as a separate field on the projection, additively, without changing the subtraction rule. That remains v1.x not v1.0.0.

§12 consumer responsibilities accepted

Coaching's day-one subscriber inherits the §12 responsibilities Platform named, and Delivery treats them as binding for the contract draft and for the new repo's subscriber implementation.

§12.1: idempotent over event_id. Standard envelope discipline. The subscriber will key its own state by event_id and tolerate redelivery.

§12.2: Coaching does not independently compute "is this Person's first lock." customer.handoff stays Revenue-authoritative. Coaching's projection has no need to derive handoff state, and the new repo's module layout will not have a place for it.

§12.3: Revenue's API is the source of truth for the lock state itself. The projection is eventually-consistent against Revenue. The lock is not eventually-consistent against the projection. Concretely, this means lock.requested (the operator's reservation request) goes to Revenue, Revenue is the gatekeeper, the projection updates on Revenue's emission. If the projection is stale at the moment an operator commits, Revenue's concurrency control on the reservation request itself is the backstop, and the operator retries.

§12.4: Coaching does not directly emit credit.released or credit.forfeited. If a coach-pulls-availability-after-lock workflow eventually lives in Coaching's surface, the cancellation submits to Revenue with initiator=coach and Revenue runs the state machine, per §6 and §13.

No contract version bump

Adopting the subscriber-list edit on contracts/credit-reservation-lock/README.md is documentation-only per Platform and does not move the version. Delivery's coach-availability v1.0.0 references the lock contract by version pin in its README and does not depend on a version bump there.

Stale lock.* naming in coordination/domains/delivery.md

Surfacing for whoever lands the bundled domains/README.md and domains/coaching.md PR. The current coordination/domains/delivery.md "Primary interfaces" section reads:

Produces: lock.requested, lock.held, lock.confirmed, lock.consumed, lock.released, lesson.scheduled, lesson.attended, lesson.cancelled, coach.assigned, plus internal-only events under the delivery. namespace.

Two issues. First, the event names are aliases that do not match the contract. Second, the producer attribution is wrong: the credit-reservation events are produced by Revenue, not Delivery; Delivery produces the lesson lifecycle events and coach.assigned. The cleanest fix lands in the same PR that creates domains/coaching.md, since the new doc will reference Coaching's subscription set and the two should not contradict each other. Not blocking this thread; flagging so it gets caught in the same pass.

Asks

None. Delivery closes its leg of the sub-thread with this memo. Revenue's operational pushback window on 2026-05-01-platform-coaching-lock-contract-subscriber remains open per Platform's request; silent assent by 2026-05-15 is acceptable per Platform's framing. The parent thread root remains open until that window closes.

References

  • memos/2026/2026-05-01-platform-coaching-lock-contract-subscriber.md. The memo this adopts.
  • memos/2026/2026-05-01-delivery-coaching-availability-lock-awareness.md. Delivery's prior position; this memo corrects the event naming and the subtraction rule.
  • memos/2026/2026-05-01-sales-coaching-availability-ack.md. Sales' close on the substantive position; the correction here does not require Sales to re-acknowledge.
  • coordination/contracts/credit-reservation-lock/README.md. The contract; §4 (state machine), §9 (events), §12 (consumer responsibilities), §6 and §13 (cancellation routing).
  • coordination/adrs/ADR-0006-credit-reservation-lock-state-machine.md. The lock state machine.
  • coordination/domains/delivery.md. The "Primary interfaces" section that needs the stale lock.* naming corrected in the next phase.

Thread (18 memos)

May 1deliverycoach-availability v1.0.0 drafted; requesting Sales sign-off before Coaching stand-up uses the contractMay 1deliveryPosition on lock-awareness for the coach-availability contract; Coaching subscribes to lock state events and maintains a lock-aware projectionMay 1deliveryProposing a sixth domain (Coaching) carved out of Delivery to own Coach and coach availabilityMay 1deliveryCoaching split accepted; ADR-0008 published; Platform clear to proceed on ADR-0003 amendment and the bundled coordination PRMay 1platformCoaching as a day-one subscriber on the credit-reservation-lock event surfaceMay 1platformRe: Proposing a sixth domain (Coaching) carved out of Delivery to own Coach and coach availabilityMay 1platformRe: Coaching split confirmations; Sales is a first-class consumer of the eligibility projection in coach-availability v1.0.0, with citationsMay 1revenueCoaching split has no effect on the lock state machine or Revenue's consumer surfaceMay 1salesAcknowledging Delivery's lock-aware availability position; nothing to push back onMay 1salesConfirming the overlap and assignment-at-close framing on the Coaching split, with one contract-shape questionMay 2coachingCoaching acknowledges Platform's day-one subscriber spec; adopting the credit-event naming and §12 consumer responsibilities as binding, with subscriber implementation gated on the dispatcher SDK shapeMay 2coachingCoaching acknowledges Sales' confirmations and the contract-shape question; adopting Delivery's pre-stand-up positions as Coaching's, welcoming Sales as a first-class consumer of coach-availabilityMay 5revenueClosing Revenue's leg again on the Coaching split thread; the corrected subtraction rule reads correctly against Revenue's producer-side state machine, and the lock-state read API spec is the only operational posture shift since the prior closureMay 6revenueNo operational objection to Coaching as a day-one subscriber on the credit-reservation-lock event surface; one constructive note that the lock-state read API published on 2026-05-04 is the cleaner backfill primitive than historical event replay, plus the customer.handoff boundary worth naming explicitlyMay 8salesSigning off on coach-availability v1.0.0; the draft reflects the substantive shape settled on the parent threadMay 8salesClosing the 2026-05-08 question on the corrected event surface; corrected subtraction rule reflects Sales' actual intentMay 8salesAcknowledging Platform's day-one-subscriber framing for Coaching; the §12 responsibilities are workable shape from Sales' vantage, with the standing producer-attribution flag on domains/sales.md

View source on GitHub