Files
crossbar/docs/plans/v2.2/01-route-templates.md
T

4.6 KiB

v2.2 task 01: route templates

Branch: v2.2 (git switch -c v2.2 master if it does not exist, else git switch v2.2; git status --short must be empty, otherwise stop) Commit subject: Route templates: a route named x-* serves any request route x-<something>

Goal

PLAN.md §4a gives every OpenCode instance its own route (CROSSBAR_ROUTE="$(basename "$PWD")-$$"), but the config only knows explicit [routes.NAME] tables and everything else is 404 unknown route. After this task a route whose name ends in -* is a template: a request route that starts with the part before the star, with something non-empty after it, uses that route's hosts, default model and peers. Leases and accounting stay keyed by the concrete route name, so two instances never share a lease and each has its own usage row.

Files

  • Copy: internal/config/config_v22_test.go (its TestWakeBroadcasts belongs to task 02 and will fail to compile until then — see step 2), internal/proxy/template_test.go, internal/admin/admin_template_test.go
  • Create: internal/config/route.go — the template name pattern and Route() live here; config.go is already at the 400-line limit, so add nothing to it beyond what the new file needs from it (one-line hooks are fine)
  • Modify: internal/config/config.go (minimal), internal/proxy/proxy.go, internal/admin/admin.go, internal/admin/admin_ops.go, cmd/crossbar/main.go (the identity middleware's route→peers lookup), docs/implementer-log.md. If proxy.go would pass 400 lines, move route resolution (route, SplitRoute, allowedPath) into a new internal/proxy/route.go.

Interfaces

package config

// Route resolves a request route name: an exact entry wins; else the longest template
// "<prefix>-*" whose prefix (including the dash) starts name with a non-empty remainder;
// else ok is false. key is the config key that matched (the template's name for a template).
// A name that is not a valid route name (the pattern below) or contains '*' never matches.
func (c *Config) Route(name string) (r Route, key string, ok bool)

Rules:

  1. Config route keys match ^[a-z0-9][a-z0-9-]*$ (as before) or ^[a-z0-9][a-z0-9-]*-\*$ (a template). Anything else with a * is routes.<name>: must match … as today. A template alone satisfies "at least one route".
  2. Resolution order: exact, then longest matching template, then none.
  3. The proxy resolves both the path form and the X-Crossbar-Route header form through cfg.Route; the concrete name (not the template key) is the route used for leases, accounting rows, logs and headers. The "conflicting route" check compares concrete names.
  4. Admin: POST /_crossbar/routes/{route} resolves through cfg.Route — a concrete route under a template can be pinned/released even before its first request; the template name itself is 404 unknown route. GET /_crossbar/routes lists config keys (templates under their own name) and, for a template, the leases of every concrete route it matches.
  5. main.go: the identity middleware's func(route string) ([]string, bool) uses cfg.Route.

Steps

  • 1. Branch as above; copy the three given tests.
  • 2. See them fail. config_v22_test.go also references Wake.Addresses() (task 02); until then run the config package with -run 'TestRouteTemplate' after adding a temporary stub? No — do not add stubs. Instead implement task 01 and run go test -race -count=1 ./internal/proxy/ ./internal/admin/ for the behaviour, and go vet ./internal/config/ will fail only on the missing Addresses method until task 02: that is expected and is the one allowed red at the end of this task. Say so in the log row.
  • 3. config/route.go: the template pattern, Route(); the validation in config.go accepts template names. 4. proxy.go route resolution. 5. admin.go / admin_ops.go. 6. main.go.
  • 7. gofmt -w; go test -race -count=1 ./internal/proxy/ ./internal/admin/ ./internal/health/ ./internal/wake/ → ok.
  • 8. Row v2.2/01-route-templates; commit (the gate runs green after task 02).
git add internal/config internal/proxy internal/admin cmd/crossbar docs/implementer-log.md
git commit

Done when

  • TestRouteTemplateServesConcreteRoutes and TestRoutesViewAndPinWithTemplates pass under -race; every earlier proxy/admin test still passes; given files byte-identical; no file over 400 lines. internal/config is red only on Addresses (task 02).

Stop and report if

  • Passing needs a change to any earlier given test.