feat(authz): probe verdicts and listing-filter mechanics part 1/4 (S09 Enforcement plan: 19/20)

Part 1 of 4 of the S09 enforcement plan — Step 19: Permission-filtered repository listing.

The step is split into 4 stacked MRs to keep each within the review size limit (≈800 ideal). Each part targets the previous one; the stack sits on step 18 part 4 (!2146 (merged)), so part 1 becomes mergeable once that MR lands. Review and merge bottom-up.

Stacked MRs (review/merge bottom-up)

This part (~1,565 reviewable LoC: ~530 source, ~1,035 test, measured at 729e2c8a)

The foundations both later parts build on:

  • authz.Evaluator.Probe — the point-check verdict without booking the denial metric or log, for a caller that branches on the verdict rather than answering with it. denials_total keeps its meaning ("masked-404 requests the decision layer denied") because the listing branch decision no longer books a denial for requests that answer 200. The IAM-contract-violation WARN (non-empty tuples, empty principal) fires under both Evaluate and Probe.
  • The GLAZ BatchCheck call raises its per-call receive limit to 16 MiB, sized for a full listing chunk's response with populated reasons.
  • internal/managementapi's filter mechanics, not yet reachable from any route (fetchFilteredListPage carries a nolint:unused that part 2 removes when it wires the caller): chunked candidate enumeration (listingChunkSize = 9,998 — the IAM ReadRelationships objects cap is 10,000, protovalidate-enforced in third_party/iam-proto/proto/lookup/lookup.proto, and every chunk read also carries the namespace and organization ancestors), uncached tuple reads, greedy relationship packing under the GLAZ item and relationship caps, BatchCheck response validation matched on ItemIndex+Action with the object-echo check, cross-chunk survivor dedupe, the resume-walk for a page whose rows all vanish between enumeration and fetch, and fail-closed arms for every contract violation (503, never a partial list).

Unit coverage rides in the same part: internal/managementapi/list_authz_internal_test.go (packing, validation, chunk loop, fail-closed arms) and the internal/authz Probe-vs-Evaluate booking tests.

External dependencies the plan gates this step on, confirmed: the deployed GLAZ sidecar is v2.3.1 (.runway/fairway.yaml), which serves BatchCheck (v2.0.0+); the IAM request limit is the protovalidate cap above.

Size

The whole step is ~3,630 reviewable LoC (~675 source, ~2,955 test, measured at 729e2c8a plus the three parts stacked above it) against the plan's ≈230/≈550 estimate — the growth is the authz Probe groundwork, the wiring seams, and the review-hardened validation plus its test matrix. This part exceeds the 500 LoC guideline because the mechanics and their unit tests are one indivisible feature: the packing/validation invariants are only meaningful against the chunk loop that feeds them.

References

No e2e scenario is added or affected: no catalog covers the management API, and the listing filter's behavior is pinned by this step's handler tests (plan Testing Strategy).

Related to #861 (closed)

Edited by David Fernandez

Merge request reports

Loading
Loading