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.goNewHandler(resolver) http.Handler builds a method-scoped http.ServeMux for 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 — adds CodeNotFound (404) and CodeNotImplemented (501) plus their SafeMessage constants.
  • .golangci.yaml — the three ADR 023 depguard rules (format-isolation, no-direct-db, no-reverse-dependency), each scoped with both a top-level *.go and a subdir **/*.go glob.
  • internal/{format/npm,jobs}/depguard_negative_control.go + the .gitlab-ci.yml depguard:negative-control job — 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)

Merge request reports

Loading
Loading