WORKER_CALLBACK_URL accepts any scheme, so a missing http:// boots green and breaks callbacks #164
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lz/agent-nexus#164
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Surfaced during PR #163 (zod v4) and deliberately kept out of it — correctly, since folding a validation-behaviour change into a dependency bump means a post-merge boot failure cannot be attributed to either. This is not a zod 4 regression: it behaves identically on zod 3.
The trap
z.url()requires only a scheme, not an HTTP one. Verified:So
WORKER_CALLBACK_URL=host.docker.internal:3001— a scheme-less value that looks like a host:port — parses as a URL whose scheme ishost.docker.internal. Config validation passes, Nexus boots clean, and the value is injected into workers asNEXUS_URL.Nothing fails until a worker calls
notify-previewornotify-artifactagainst a URL that can never resolve. The operator sees a preview that never registers, with no error at the point of the mistake.Why this is a likely mistake rather than a theoretical one
AGENTS.md's environment table describes
WORKER_CALLBACK_URLas required on Docker Desktop (Windows/macOS) and gives the examplehttp://172.30.0.2:3001. An operator transcribing a host and port without the scheme is an ordinary slip, and the config layer — whose entire job is to catch exactly this at boot — waves it through.It is also the one env var where a silent failure is most expensive: it exists specifically for the deployment where the bridge-gateway derivation does not work, so there is no fallback behind it.
Fix
Constrain the scheme in
config.ts:Consider whether
public_urlwants the same treatment — it feedsresolveHostsand the preview advertise chain, and its own validator already rejects wildcards, so scheme-checking is consistent with how that field is already handled.Watch for
This changes what the container accepts at boot. An existing deployment with a scheme-less
WORKER_CALLBACK_URLis currently booting and half-working; after this change it will refuse to start. That is the right outcome — it converts a silent runtime failure into a loud startup one — but it is a breaking change for anyone in that state, and the error message should name the variable and show a correct example rather than emitting a bare zod message.PR #163 already ships a test pinning the current permissive behaviour, so whoever takes this will see it go red and know they are changing a known-and-recorded decision rather than an accident.
Note
Two related validation gaps were considered in #163 and also left alone, both pre-existing on zod 3 and both design decisions rather than migration ones:
COOKIE_NAME=yields an empty cookie name, andDATA_DIR=puts SQLite at''. Worth deciding on together with this, since the fix is the same shape (.min(1)).