Restrict Semaphore acquisition to allowed slugs
Status: Implementation complete locally. Contract/unit/type checks pass; the public HTTP/DO behavior still needs its PR preview deployment before production rollout.
Goal#
Let callers constrain generic Semaphore acquisition to an explicit set of resource slugs, while keeping older preview clients safely limited to the original nine slots during the rollout.
Decisions and assumptions#
- Add optional
allowedSlugsto bothacquireandacquireSpecific; filtering happens atomically inside the Resource Coordinator. - Omitted
allowedSlugspreserves generic behavior for every resource type exceptenvironment-config-lease. - For
environment-config-lease, omission temporarily defaults topreview-1throughpreview-9, so older clients cannot acquire newly seeded slots. - A supplied list must be non-empty and contain unique, valid slugs.
- Waiting, least-recently-used selection, lease renewal, and force semantics operate only within the allowed set.
- This PR does not seed inventory or deploy preview applications.
Checklist#
- Specify the public acquisition behavior with failing integration-style tests. Added live API coverage for generic and specific acquisition plus contract fallback tests.
- Add
allowedSlugsto the public contract and Resource Coordinator inputs. Both acquisition endpoints accept a validated, unique, non-empty slug list. - Filter generic and specific acquisition atomically. The Resource Coordinator filters immediate/waiting candidates and rejects disallowed specific acquisition before eviction.
- Preserve the legacy-safe preview fallback for omitted input. Omitted input resolves to preview-1 through preview-9 only for environment-config leases; other resource types remain unrestricted.
- Verify focused tests, typecheck, lint, and formatting. Four unit tests, Semaphore typecheck, repository lint, and formatting pass locally; live E2E is delegated to the PR preview deployment.
- Deploy Semaphore production before any client requires the new input.
Implementation log#
- 2026-07-20: Split from preview-slot expansion so the server can accept the new field before PR #2161 starts sending it.
- 2026-07-20: Followed red→green slices for generic selection, specific selection, legacy fallback, and duplicate validation.
- 2026-07-20: PR preview review exposed head-of-line blocking between disjoint allow-lists. A live API test reproduced the timeout; dispatch now scans one FIFO pass and preserves unmatched waiter order.
- 2026-07-20: Refreshed review identified capacity freed by a waiter timing out during delivery. Dispatch now performs another bounded FIFO pass only when it freed capacity or received arrivals while scanning.