chore(config): ServerConfig proto + YAML loader (S01 Step 1)
Summary
Step 1 of the merged S01 implementation plan
(docs/plans/2026-05-20-s01-http-server-and-routing.md).
Ships the ServerConfig proto (with ServerTimeoutsConfig and
ShutdownConfig) plus the Go-side internal/config package — Load,
serverFromProto, ParseSize with typed DurationParseError and
SizeParseError. Tests cover AC #14 (config load + protovalidate) and
AC #15 (size-string parsing).
Refs #89 (closed).
Reviewability note (~917 reviewable LOC)
This MR exceeds the 500-LOC ceiling, but ~495 LOC of that is heavily mechanical test-table content:
internal/config/config_test.go— 5 table-driven tests + 3TestLoad_RequiredMessageRejectionsubtestsinternal/config/server_test.go— 1 typed-error-shape test + 1 table-drivenTestServerConfig_FromProto_InvalidDuration(8 rows)internal/config/size_test.go—TestParseSize(18 rows including the two overflow rows) + 1 envelope-shape test
The ~300 LOC of novel logic lives in:
internal/config/config.go—Load(LabKit v2 wrapper + error pathing)internal/config/server.go—serverFromProto+ the two private field-aware parse helpersinternal/config/size.go— publicParseSize+ the private field-awareparseSize(with the IEC suffix table)internal/config/errors.go—DurationParseError/SizeParseErrorenvelope types
The proto file gains three messages (~55 lines) per spec verbatim plus
three required = true markers on message-typed parents (see "Spec
adherence note" below). The regenerated gen/.../config.pb.go is
excluded from the reviewable count per
docs/dev/development-model.md (generated files don't count).
Resolved spec ambiguities
ParseSizesuffix semantics — IEC.KB=10³,MB=10⁶,GB=10⁹;KiB=2¹⁰,MiB=2²⁰,GiB=2³⁰. The spec admits both suffix sets without semantic specification; the plan listed both as accepted suffixes, forcing a choice. IEC is the only standard reading that distinguishes them.5MBparses to 5,000,000 bytes (~4.77 MiB).
Spec adherence note
The proto adds (buf.validate.field).required = true to
Config.server, ServerConfig.timeouts, and ServerConfig.shutdown.
The spec's proto block doesn't show these markers. The change is
purely additive (every YAML valid under the spec's schema remains
valid under the tighter schema; the spec's own YAML example sets all
three blocks explicitly). Intent: surface missing-block configs at
protovalidate time with a clear "field is required" message rather
than at parse time with a misleading leaf-field error. A follow-up
spec MR to mirror this in the spec's proto block is recommended but
not bundled into this MR.
There's also a pre-existing spec inconsistency: §Security
Considerations describes the default as "the 5 MiB default limit"
while the YAML default is "5MB". Under the IEC reading the
implementation parses "5MB" to 5,000,000 bytes (~4.77 MiB), tracking
the proto/YAML value. The spec prose needs a separate amendment.
Validation trail
/validate-step(first pass): ADVISORIES ONLY/review-branch: APPROVE with 2 WARN + 7 OBSERVATION; all actionable items fixed in196724c/validate-step(second pass): ADVISORIES ONLY (one spec-adherence WARN per the note above)- Full local
go test -race -short -count=1 ./...green golangci-lint run ./internal/config/... ./gen/artifactregistry/config/v1/...— 0 issuesgo mod tidyno-op (module tidy)
Test plan
- CI: build, vet, lint, format, tests all green
- CI: markdownlint, vale, lychee clean
- CI: proto-freshness check confirms
.pb.gois in sync with.proto - Reviewer: spot-check the IEC suffix table in
size.goagainst the test expectations insize_test.go - Reviewer: confirm the spec-adherence note (required-true markers
- 5MB vs 5 MiB) is acceptable as-is, or request a paired spec MR
- Reviewer: verify the test-table majority claim by sampling
config_test.go,server_test.go,size_test.go