Skip to content

feat(proxy): N1 — Caddy route table + labels (spec 05) - #15

Merged
gustavobertoi merged 1 commit into
mainfrom
nightly/N1
Jun 29, 2026
Merged

feat(proxy): N1 — Caddy route table + labels (spec 05)#15
gustavobertoi merged 1 commit into
mainfrom
nightly/N1

Conversation

@gustavobertoi

Copy link
Copy Markdown
Contributor

Chunk N1 (M5) — proxy route table

internal/proxy is the single source of truth for routing (spec 05).

  • BuildRoutes derives a deterministic []Route{project,service,host,port,tls} from every port-exposing project service when the workspace declares a Caddy proxy (network.proxy.engine: caddy). Host = <service>.<project>.localhost; primary port = the http port if named, else the lowest.
  • CaddyLabels renders the caddy-docker-proxy labels (caddy=<host>, caddy.reverse_proxy={{upstreams <port>}}, caddy.tls=internal when httpsLocal) to merge onto each service → adding/removing a project reloads Caddy with no central-config edit.
  • Routing is opt-in (no engine → no routes → up unaffected).

The same []Route will render the cloudflared ingress in internal/tunnel (N4) so local + public routing can't drift; the generate wiring (emit the labels) is N5/generate.

Tests

Enabled detection (caddy only), disabled→no routes, primary-port + httpsLocal selection, deterministic ordering, label rendering (±TLS), URL scheme.

Gate

make ci green (race).

🤖 Generated with Claude Code

internal/proxy is the single source of truth for routing: BuildRoutes derives a
deterministic []Route{project,service,host,port,tls} from every port-exposing
project service when the workspace declares a Caddy proxy (network.proxy.engine:
caddy). CaddyLabels renders the caddy-docker-proxy labels (caddy=<host>,
caddy.reverse_proxy={{upstreams <port>}}, caddy.tls=internal when httpsLocal) to
merge onto each service so adding/removing a project reloads Caddy with no
central-config edit. Host is <service>.<project>.localhost; the primary port is
the "http" port if named else the lowest.

Routing is opt-in (no engine → no routes → `up` unaffected). The same []Route
will render the cloudflared ingress in internal/tunnel (N4) so local and public
routing can't drift; generate wiring (emit the labels) is N5/generate.

Unit-tested: enabled detection (caddy only), disabled→no routes, primary-port +
httpsLocal selection, deterministic ordering, label rendering (with/without TLS),
URL scheme.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gustavobertoi
gustavobertoi merged commit 50e6686 into main Jun 29, 2026
9 checks passed
@gustavobertoi
gustavobertoi deleted the nightly/N1 branch June 29, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant