Vetrix Docs

Search permission matrix

The permission-matrix tests enumerate every actor × repo-visibility × entity combination the search surface supports, asserting the correct HIT / MISS outcome. This document lists the matrix and points at the test coverage.

Matrix

Actor Repo visibility Entity (code/symbols/issues/mrs/comments/pages/site) Expected
owner private all HIT
collaborator private all HIT
group-member (via grant) private all HIT
non-member private all MISS
admin private (not owned) all HIT
anonymous private all MISS/401
any public all HIT

Page-scoped addenda

Actor Access grant Expected
user not on repo ACL page_permission_user_ids includes user HIT
user not on repo ACL page_permission_group_ids ∩ user.groups HIT
anonymous share_token presented + matches HIT
anonymous share_token missing MISS
anonymous share_token expired MISS

Test coverage

Clause-level (pure, go test ./... green)

Every matrix cell has a dedicated assertion in internal/search/authfilter/permission_matrix_test.go. The tests build an *authfilter.Filter / *authfilter.PageFilter for the matrix actor and assert the emitted OpenSearch bool.filter clauses encode the correct outcome. The hostile non-member case (non-member + ?repo=<private UUID>) is pinned as TestPermissionMatrix_FOR201Regression_NonMemberWithRepoParam.

These tests are cheap, run in the default unit-test suite, and guard the invariant that a drift in the clause builders cannot silently change the ACL semantics.

Live-cluster matrix (deferred — testcontainers harness)

The full HTTP round-trip matrix — actor auth + real repository fixtures + real vetrix-* indexes + OpenSearch cluster — is the remaining piece. Ship plan:

  1. Add github.com/testcontainers/testcontainers-go to go.mod.
  2. New internal/integration/search_matrix_test.go with a TestSearchPermissionMatrix that:
    • Spins an OpenSearch container via testcontainers.
    • Reuses the existing Postgres-integration test infra.
    • Seeds the six fixture actors (owner / collaborator / group-member / non-member / admin / anon) + two fixture repos (one private, one public).
    • Indexes fixtures into both backends.
    • Runs every matrix cell against both the OpenSearch _msearch path and the Postgres fallback, asserting the same HIT/MISS outcome for each cell — any mismatch fails the build (parity-gate).
    • Targets < 10 min wall for the full matrix on CI.
  3. CI job naming: search-integration parallel to existing go test -tags integration jobs; runs on PR + on main.

Hostile non-member live regression

Until the testcontainers harness ships, the hostile non-member regression is covered by:

  • TestBuildCodeSearchQuery_FOR201Regression_NonMemberCannotSlipByRepoID (pure, in internal/opensearch/) pins the AuthFilter envelope on the OpenSearch code-search body.
  • TestCodeSearch_Unauthenticated401 + TestSearchCodeInRepos_EmptyAllowListReturnsNoHits (in internal/api/ + internal/search/) pin the Postgres handler ACL gate.

Deferred follow-ups

  • testcontainers-backed live-cluster matrix (the substantial piece listed above).
  • CI job spec + runtime budget enforcement.
  • Shared fixture loader so the Postgres and OpenSearch halves of the parity gate consume the same seed data.