Known limitations & planned work
The ADRs record the trade-offs behind what is built; this page consolidates the deliberate gaps — what isn't built yet and why — so "what would you add next?" has one honest answer. Nothing here is an oversight; each is a boundary drawn on purpose, with the trigger that would justify closing it.
Technician registry & assignment — the next natural increment
Today, assigning a technician (PATCH /work-orders/:id/assign) stores an opaque assigneeId UUID on the work order and flips it to assigned — that's all:
- there is no technicians (or users) entity anywhere in the domain;
- the
assigneeIdis not validated against anything — any UUID is accepted; - there is no way to answer "who is working on what" through the API:
GET /work-ordersfilters bystatus,priorityandpropertyId, but not byassigneeId; - the JWT
technicianrole and theassigneeIdare disconnected — the role gates permission (a technician may change status), whileassigneeIdis just data on the row. Nothing links the logged-in technician (sub) to the UUID they were assigned.
This is the same "reference by id, no foreign key" pattern the system already uses for propertyId (ADR-0001) — a pointer to an entity that lives elsewhere, except that "elsewhere" (a technician service) does not exist yet. The system knows that someone was assigned; it cannot say who.
What closing this gap needs:
- A Technicians (or Users) service/entity as the source of truth for who technicians are — mirroring the Properties service.
assignvalidating theassigneeIdagainst it (exists? available? has the technician role?).- An
assigneeIdfilter onGET /work-orders, and/or a "my work orders" endpoint derived from the JWTsub, so a technician sees their own workload. - Optionally a roster / workload view (open work orders per technician) for managers.
Trigger: the moment assignment needs to be more than a label — validation, technician-facing views, or workload balancing. Until then, the opaque reference keeps the work-orders service free of a user domain it doesn't yet own.
Other known gaps
Each is discussed where the relevant decision was made; this table is the index.
| Gap | Why deferred | Discussed in |
|---|---|---|
| Refresh tokens / revocation | Stateless 1h JWT, re-login; no denylist | ADR-0008 |
| Resource-level authorization | Coarse roles — a tenant can read any work order, not only their own | phase-8 notes |
| Distributed tracing (OTel / Cloud Trace) | Correlation ids answer "which logs belong to this request" at this size | ADR-0005 |
| Outbox retention job | Published rows accumulate; prunable by published_at |
ADR-0007 |
| Circuit breaker | Gateway fails fast per request but never opens a circuit | ADR-0009 |
| LLM eval harness / observability | Prompt/model changes ship without a regression score — where Langfuse would fit | ADR-0010 |
| Notification recipient resolution | Recipients are deterministic placeholders (manager-of-…, tenant-of-…) |
phase-2 notes |
| Properties emits no events | The properties service is read/write only; a second producer needs its own outbox | services map |
How to read this list in review
Every entry follows the same discipline the codebase applies to infrastructure: adopt complexity when the use case demands it, not speculatively. The technician registry is first because it's the closest to justified — it's the natural next domain the system would grow into, and the reference-by-id seam is already in place to receive it.