Skip to content

Latest commit

 

History

History
182 lines (139 loc) · 10.2 KB

File metadata and controls

182 lines (139 loc) · 10.2 KB

Backend Permission Rules

Purpose

This document records the backend permission rules that are currently enforced by the Go API. It is a current-state reference for dashboard, agency, streamer, viewer, and internal service access.

It does not introduce new product policy. When this document conflicts with code, the code is the source of truth and this document should be updated in the same PR that changes the permission behavior.

Role Model

Backend user roles are stored on models.User.Role and carried in access token claims.

Role Current meaning
viewer Default account role for viewers and regular users.
streamer Channel operator role for dashboard channel, raffle, and airdrop work.
agency Agency operator role for agency-owned streamer/channel work.
admin Global operator role for administrative setup and cross-account access.

Enforcement Layers

The API uses two main permission gates:

Layer Mechanism Behavior
Authentication middleware.JWTAuth Requires Authorization: Bearer <token>, validates the access token, and stores claims in Gin context. Missing or invalid tokens return 401.
Role authorization middleware.RequireRole(...) Allows any listed role. Authenticated callers with a non-matching role return 403.

Handlers add ownership checks after the route-level role gate when the route is scoped to a channel, streamer, agency, or raffle owned by a specific user.

Public And Viewer Routes

The following surfaces are not dashboard role-gated:

Surface Current access
/health Public liveness check.
/swagger/*any Public only when Swagger is enabled by config.
Public auth routes under /api/v1/auth Public, with rate limits on selected login/registration/reset paths.
GET /api/v1/claim/:token Public claim lookup.
POST /api/v1/claim/:token Requires a valid user JWT for the winner claim submission path.
/api/v1/extension/auth/login Public Twitch Extension login exchange.
/api/v1/extension/t-point/complete and /bits/complete Public completion callbacks with public endpoint rate limiting.
/api/v1/extension/raffles/:id/result Public raffle result read.
/api/v1/extension/watch/* Requires a valid tachigo JWT after extension login.
/api/v1/users/me/*, /api/v1/spend/redeem, provider unlink, email verification send, and address routes Require a valid user JWT and operate on the authenticated user.

Viewer JWTs do not pass dashboard, agency management, event, or admin role gates unless a route explicitly lists viewer, which the current dashboard and admin route groups do not.

Dashboard Routes

All /api/v1/dashboard/* routes require a valid JWT and one of admin, streamer, or agency before route-specific checks run.

Route Allowed roles Additional ownership behavior
POST /dashboard/streamers admin Creates streamer records for a supplied user/channel.
GET /dashboard/streamers agency, admin Admin lists all; agency lists streamers owned by that agency user.
GET /dashboard/streamers/:streamer_id/stats streamer, agency, admin Streamer must own that streamer record; agency must own the streamer; admin can access any. Non-admin unauthorized streamer IDs return 404 to avoid existence enumeration.
POST /dashboard/streamers/register streamer Registers the caller's own streamer channel.
GET /dashboard/streamers/channels streamer Lists channels owned by the caller.
GET /dashboard/channels/:channel_id/stats admin, streamer Non-admin callers must own the channel. Agencies are not route-level allowed here.
GET /dashboard/channels/:channel_id/config admin, streamer, agency Streamer or agency callers must own the channel.
PUT /dashboard/channels/:channel_id/config admin, streamer Streamer callers must own the channel. Agencies are not route-level allowed to update config.
POST /dashboard/channels/:channel_id/airdrop admin, streamer, agency Streamer or agency callers must own the channel.

Raffle management routes under /api/v1/dashboard/raffles are currently streamer-only at the route level. The raffle service then verifies the caller's ownership of the target raffle where a raffle ID is supplied.

Agency Management Routes

Agency management routes use JWT authentication and route-level role checks. Agency-scoped routes also check that an agency caller is operating on its own agency user ID.

Route Allowed roles Additional ownership behavior
POST /api/v1/agencies admin Creates an agency user and attempts setup email delivery.
GET /api/v1/agencies/:id agency, admin Agency callers can only read their own agency record.
PUT /api/v1/agencies/:id/settings agency, admin Agency callers can only update their own agency record.
GET /api/v1/agencies/:id/streamers agency, admin Agency callers can only list streamers for their own agency record.
POST /api/v1/agencies/:id/resend-setup admin Re-sends setup email for agencies that have not completed onboarding.

Event And Admin Stubs

The current event and admin groups are permission-gated, but their handlers are still placeholders.

Route group Allowed roles Current behavior
/api/v1/events/* streamer, agency, admin Stub handlers return 501 after authorization succeeds.
/api/v1/admin/* admin Stub handlers return 501 after authorization succeeds.

These stubs should not be treated as complete product APIs until their handlers are implemented and tested.

Internal Service Route

/api/v1/internal/tachiya/users/points/balance is not JWT-authenticated. It is registered only when the API has both a database handle and TACHIYA_SHARED_SECRET configured. Requests must include X-Tachiya-Internal-Secret matching the configured secret; otherwise the API returns 401.

This route is intended for Tachiya-to-tachigo service calls, not browser or dashboard traffic.

Status Code Conventions

Situation Current response
Missing bearer token on JWT route 401
Invalid or expired bearer token 401
Valid token but route-level role mismatch 403
Valid token and route role passes, but handler ownership check fails 403 or 404 depending on enumeration risk for that handler
Authorized caller reaches not-yet-implemented event/admin stub 501

Regression Matrix Source Of Truth

RBAC regression tests should treat this document as the expected-behavior reference and internal/router/router.go plus the relevant handler ownership checks as the implementation source of truth.

Every protected admin, streamer, or agency endpoint should have regression coverage for the route-level gate:

Case Expected assertion
No bearer token 401 before the handler runs.
Authenticated viewer where the route does not list viewer 403 before the handler runs.
Authenticated wrong dashboard/admin role 403 before the handler runs.
Authenticated allowed role The request reaches the handler: normal handler status for implemented routes, or 501 for event/admin stubs.

Routes that are scoped to channel, streamer, agency, raffle, user, or tenant data also need ownership coverage after the route-level role gate passes:

Case Expected assertion
Caller owns the target resource The request reaches the handler behavior for that route.
Caller does not own the target resource 403, or 404 where the handler intentionally avoids existence enumeration.
Agency caller manages the target streamer/channel The request reaches the handler behavior for that route.
Agency caller does not manage the target streamer/channel 403 or the documented 404 enumeration-safe response for that handler.
Admin caller Admin can access cross-account resources unless a route explicitly documents a narrower admin behavior.

services/api/internal/handlers/rbac_handler_test.go is the centralized home for route-level role matrices that can be expressed with lightweight stubs. Handler-specific tests remain the right place for ownership, tenant isolation, and implemented behavior that needs real database fixtures.

Current #646 coverage status (last refreshed 2026-05-31):

Surface Regression status
Dashboard role gates Centralized matrix rows cover the dashboard protected stubs registered by newRBACTestEnv, including streamer creation, streamer listing, and channel config read. Implemented dashboard handler behavior still belongs in focused handler tests.
Agency management Centralized route-level rows cover the lightweight agency protected stubs, while focused handler tests cover implemented agency ownership behavior such as create, detail, settings, streamer listing, and setup resend paths.
Event and admin stubs Centralized matrix rows cover the current 501-after-authorization behavior for event/admin stubs, including unauthenticated, wrong-role, and allowed-role cases.
Ownership and cross-tenant behavior Focused handler tests remain the source for own-resource, other-resource, managed, and unmanaged scenarios because they need real database fixtures and handler-specific enumeration behavior.
Coverage gate for newly protected routes TestRBACMatrix_CoversAllProtectedStubRoutes enforces that protected stubs registered by newRBACTestEnv have centralized matrix rows. This gate intentionally does not scan the full production router; newly implemented protected routes should add either centralized stub coverage or focused handler-specific ownership tests.

Change Guardrails

Permission changes should be handled in dedicated PRs when they do any of the following:

  • change which roles can access an existing route
  • change ownership checks for channel, streamer, agency, raffle, or user data
  • expose a route that was previously JWT or internal-secret protected
  • turn an event/admin stub into product behavior
  • change 401/403/404 behavior in a way that affects enumeration risk

Small documentation corrections can be made with the code change they describe, but this document should not be used to introduce policy that is not yet implemented in code.