Loading
feat(npm): S11 npm route table + ADR 023 depguard (Step 8a)
What
S11 npm-local Step 8a: the npm format HTTP route table + the ADR 023
depguard enforcement rules. Step 8b (the wireNPM composition-root wiring) is
a separate follow-up — npm.NewHandler has no production caller yet, so this
MR adds no runtime behavior.
internal/format/npm/handler.go—NewHandler(resolver) http.Handlerbuilds a method-scopedhttp.ServeMuxfor every route in S11's API Contracts, each wrapped by the Step 6 slug/repo middleware. Format routes return a 501 placeholder; audit/search routes return a 404 S01 envelope.internal/format/npm/transport.go— addsCodeNotFound(404) andCodeNotImplemented(501) plus theirSafeMessageconstants..golangci.yaml— the three ADR 023 depguard rules (format-isolation,no-direct-db,no-reverse-dependency), each scoped with both a top-level*.goand a subdir**/*.goglob.internal/{format/npm,jobs}/depguard_negative_control.go+ the.gitlab-ci.ymldepguard:negative-controljob — build-tagged probes that prove all three rules still fire, including on a top-level shared-infra file (the case a subdir-only glob silently missed).
Acceptance
- AC 63 — every route in S11's API Contracts resolves to a registered handler; ADR 023 depguard blocks cross-format imports.
- AC 64 — audit/search endpoints return 404 with the standard S01 envelope.
Reviewer note: diff size
~743 reviewable LOC, above the 500 ceiling, but test/config-dominated: ~443 is
one table-driven test file, ~134 is comment-heavy .golangci.yaml + the CI
job, and only ~55 lines are production Go. Step 8 was split into 8a (this:
route table + depguard) and 8b (wiring) precisely for size.
Plan: docs/plans/2026-05-11-npm-local.md (Step 8)
Related to #22 (closed)