# v2 task 05: wiring, the smoke run, README **Branch:** `v2` (run `git switch v2`; `git status --short` must be empty, otherwise stop) **Commit subject:** `Wire wake and identity into crossbar; v2 smoke and README` ## Goal Put the pieces together: the proxy wakes a sleeping host when a route has no healthy host left, `main` builds the waker from config and wraps the proxy in the identity middleware when `identity` is on, the given fake upstream can be woken, and `tools/smoke.sh` proves the whole of v2 over real HTTP. ## Files - Copy (**replaces** v1's): `cmd/fakeupstream/main.go`, `tools/smoke.sh`, `example.toml` - Modify: `internal/proxy/proxy.go` (or a new file), `cmd/crossbar/main.go`, `README.md`, `docs/implementer-log.md` ## Rules 1. `proxy.Handler` gains `func (p *Handler) SetWaker(w Waker)` where `type Waker interface{ Wake(ctx context.Context, host string) bool }` (defined in `proxy`). When `leases.Acquire` returns `ErrNoHost` and a waker is set: for each candidate host of the route, in order, that has a wake target (ask `cfg.Hosts[h].Wake != nil`), call `Wake(r.Context(), h)`; on `true`, retry `Acquire` once; on `false` for every candidate, 503 `{"error":"no healthy host","woke":[""]}`. The context-guard's "no host fits" path (task 02) also tries waking a host whose `PerSlotCtx` is unknown or large enough, before answering 400. 2. `cmd/crossbar`: build `wake.New(targets, hosts)` from every host with `Wake != nil` (`hosts` is the `proxy.HostView`, which has `Healthy`), call `p.SetWaker(w)`. When `cfg.Identity != "off"`: `checker := identity.NewChecker(identity.TailscaleResolver{})` or `identity.NewHeaderChecker()`; wrap the proxy handler: `mux.Handle("/", identity.Middleware(checker, func(route string) ([]string, bool) { rt, ok := cfg.Routes[route]; return rt.Peers, ok }, p))`. Log at start which mode is active; with `"header"` log a warning that it is insecure. 3. Copy the three given files; `make build`; `make smoke` → `smoke: ok (…)`. The smoke's check 2 waits up to 40 s for the wake; the fake wakes in ~1 s. 4. README: sections stay; add under `## Operate` the wake behaviour and the identity modes with the `peers` example; under `## Configure` the three new keys; `## What v2 does not do`: `/slots`, request coalescing, TLS — `PLAN.md`. ## Steps - [ ] **1.** `git switch v2`; copy the three given files. - [ ] **2. Write the code** (proxy waker path, `main`). `gofmt -w .` - [ ] **3.** `go test -race -count=1 ./...` → all `ok`. **4.** `make smoke` → `smoke: ok`. - [ ] **5.** README. **6.** `make gate`. **7.** Row `v2/05-wiring-smoke`; commit. ```sh git add internal/proxy cmd/crossbar cmd/fakeupstream tools/smoke.sh example.toml README.md docs/implementer-log.md git commit ``` ## Done when - `make smoke` prints `smoke: ok (…)`; gate ok; the three copied files byte-identical. ## Stop and report if - `make smoke` fails twice in the same way; quote the failing check and the crossbar log.