HOMELAB-1532: fix(plane): fail loudly on unknown project prefix #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "plane/HOMELAB-1532-unknown-prefix-fail-loud"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
parseTicketIdentifier()returnednullfor two unrelated reasons, and all 7 call sites treatednullas "this must be a raw UUID":The two
nullcases:PREFIX-Nwith an unknown prefix (SENDR-5, orSEND-49before HOMELAB-1531) → treating it as a UUID is wrong. The literal string goes to the API as a UUID against HOMELAB, producing an opaque 400/404 far from the root cause.Read paths fail confusingly; write paths (
plane_update_item,plane_comment,plane_create_relation) attempt writes against a bogus UUID.Changes
parseTicketIdentifier— throws a newUnknownProjectPrefixErrorwhen the input isPREFIX-Nbut the prefix is not inPROJECT_MAP, listing the available prefixes (message style matches the existingresolveProject(explicit)error). Still returnsnullonly for genuine non-identifiers, so the UUID path and bare-number default are unchanged.resolveProject()(no-arg) — silently fell back viaprojectMap[currentProject] ?? projectId; now throws. The explicit-arg path already threw.resolveProjectId()deleted — dead code (zero call sites, not imported byindex.ts) whose docstring advertised the same dangerous "Falls back to HOMELAB" behaviour. Deleting it denies future callers the landmine, which is the point of this change.Why a throw rather than a return value
The throw lives inside the one function every call site already funnels through, so all 7 are fixed without touching them — and any future call site inherits the protection automatically. That is the actual goal ("no issues with plane in the future"), not just patching today's callers.
Verification
13/13 cases:
Exact caller shape from
index.ts:Blast-radius check
fetchTicket()can only receive identifiers for projects the workspace actually returns — and every Plane project is already inPROJECT_MAP(verified against the API:APEX, GIQ, HOMELAB, INTL, SEND). So no legitimate sidebar path reaches the throw.PlaneSidebaralready wrapsfetchTicketintry/catchand renderse.message.Related
SENDdata. This fixes the behaviour, so the next unknown prefix fails loudly instead of silently resolving to the wrong project.parseTicketIdentifier() returned null for two unrelated reasons — "not an identifier at all" (a UUID) and "well-formed PREFIX-N with an unknown prefix" — and all 7 call sites treated null as "this must be a raw UUID": const parsed = parseTicketIdentifier(ref, currentProject); if (parsed) { ...resolve by prefix... } else { workItemId = ref; projectId = resolveProject(); } So plane_get_item("SENDR-5") sent the literal string "SENDR-5" to the API as a work-item UUID against the HOMELAB project, yielding an opaque 400/404 far from the root cause. Write paths (plane_update_item, plane_comment, plane_create_relation) did the same. Changes: - parseTicketIdentifier: throws UnknownProjectPrefixError when the input is PREFIX-N but the prefix is not in PROJECT_MAP, listing available prefixes. Still returns null ONLY for genuine non-identifiers, so the UUID path and the bare-number default are unchanged. - resolveProject(): the no-arg path silently fell back to HOMELAB (projectMap[currentProject] ?? projectId); it now throws instead. The explicit-arg path already threw. - Delete resolveProjectId(): dead code (zero call sites, not imported) whose docstring advertised the same dangerous "Falls back to HOMELAB" behaviour. Removing it denies future callers the landmine. Verified: 13/13 unit cases (known prefixes, lowercase, whitespace, bare number + ambient, UUID/free-text/date still null, unknown prefix throws with an actionable message) plus a caller-shape simulation.