Skip to content

feat(authz): owner-scoped authorizer with per-row visibility#360

Merged
aaliboyev merged 1 commit into
mainfrom
feat/owner-scoped-authz
Jul 2, 2026
Merged

feat(authz): owner-scoped authorizer with per-row visibility#360
aaliboyev merged 1 commit into
mainfrom
feat/owner-scoped-authz

Conversation

@aaliboyev

Copy link
Copy Markdown
Member

Adds an opt-in owner-scoped authorizer behind the existing authz.Authorizer seam.

  • authz.Resource gains Owner; new optional Scoper interface for row-level read filtering.
  • New OwnerScoped implementation: catalog rows (system/provider/host owners) readable by everyone, mutable by admins; user-owned rows visible/mutable only to their owner or an admin; mutations without owner context fail closed.
  • CRUD factory: lists filter through Scoper.Visible before pagination (total reflects the scoped set); get/update/delete return 404 for rows the caller may not see; create authorizes after owner stamping.
  • Cross-entity refs: relay-key spec.policyId and policy spec.hostKeyIds must reference rows visible to the caller.
  • Rotate, policy attach/detach, host-key health, and references get the same treatment; reload, master-key, settings, usage, logs, and debug endpoints authorize explicitly (master-key/reload/debug previously had no authorize call).
  • Selected via RELAY_MULTI_USER=on; the default remains AlwaysAllowAuthenticated (which does not implement Scoper), so existing deployments behave identically — covered by a regression test.

Tested: unit matrix over the ownership policy, httptest harness over the CRUD factory with both authorizers, full suite + lint-rules + test-integration.

authz.Resource gains Owner and an optional Scoper interface for
row-level read filtering. New OwnerScoped implementation: catalog rows
(system/provider/host owners) stay readable by everyone and mutable by
admins only; user-owned rows are visible and mutable only to their
owner (or admin); mutations without owner context fail closed.

Wiring:
- CRUD factory: lists filter through Scoper.Visible before pagination
  (Total reflects the scoped set); get/update/delete return 404 for
  rows the caller may not see; create authorizes after owner stamping.
- Cross-entity refs: relay-key spec.policyId and policy spec.hostKeyIds
  must reference rows visible to the caller.
- Rotate, policy attach/detach, host-key health, and references get
  the same treatment; reload, master-key, settings, usage, logs, and
  debug endpoints authorize explicitly.
- mutationGuard now receives ctx.

Selected via RELAY_MULTI_USER=on in the composition root; the default
remains AlwaysAllowAuthenticated (which does not implement Scoper), so
existing single-user deployments behave identically.
@aaliboyev aaliboyev merged commit 37bb602 into main Jul 2, 2026
1 check passed
@aaliboyev aaliboyev deleted the feat/owner-scoped-authz branch July 2, 2026 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant