feat(oci): manifest push parsing, validation, and handler (S12 Step 12, 2/3)

Why

Second of three MRs splitting the OCI manifest push endpoint (S12 Step 12), stacked on the datastore layer in feat(datastore): container manifest persistence... (!518 - merged) • Hayley Swimelar. This slice is the format-layer logic: untrusted-payload parsing, media-type detection, the push-flow state machine, and the ManifestHandler running validation steps 1 to 5. This is the security-review slice (untrusted JSON parsing, fuzzing).

The original combined MR is feat(oci): manifest push endpoint (S12 Step 12) (!511 - closed) • Hayley Swimelar; the final slice (wiring and e2e) is feat(oci): wire manifest push endpoint with dat... (!520 - merged) • Hayley Swimelar.

What (non-obvious)

  • push_flow.go is a pure state machine: it accumulates inputs, outputs, and errors and performs no I/O. Side effects (SHA-256, existence queries, storage writes) live in the handler, which calls the flow for transitions, so the flow is unit-testable without fixtures.
  • The ErrManifestLimitExceeded / ErrTagLimitExceeded sentinels live here because the handler errors.Is-checks them. The concrete persister in the wiring MR references them from this layer, which is why store.go's diff there carries the cap-error construction but not the sentinel declarations.
  • FuzzManifestParse is wired into the fuzz:oci CI job.

Test plan

go test ./internal/format/oci/... covers the handler ACs, the rapid state-machine and tree-size property tests, and the fuzz seed corpus. go vet (default and integration tags) and golangci-lint 2.12 pass. The full S12 spec-coverage matrix is in feat(oci): manifest push endpoint (S12 Step 12) (!511 - closed) • Hayley Swimelar.

Related to #19 (closed)

Edited by Hayley Swimelar

Merge request reports

Loading
Loading