Skip to content

Tech Story: Station-Bot administration authorization, org-to-guild mapping, and hidden navigation #242

@GitAddRemote

Description

@GitAddRemote

User Story

As a Station platform engineer, I need an explicit authorization model for Station-Bot administration so that only the right users can discover, view, and edit bot settings for the guilds they administer, while Station super admins retain tightly-scoped platform powers, impersonation-based support access, and emergency owner reassignment capability.

Definition of Done

  • Station has an explicit authorization model for Station-Bot administration that reflects the initial supported roles:
    • station_super_admin
    • guild_owner
    • guild_admin
    • guild_member
  • Guild-scoped bot administration is authorized through organization-scoped permissions, using a first-class mapping between a Station organization and a Station-Bot Discord guild
  • Operator/global bot administration is reserved to station_super_admin rather than being exposed to ordinary guild admins
  • There is exactly one guild_owner per mapped guild at a time
  • guild_owner can assign and remove guild_admin access for that guild
  • station_super_admin can perform emergency guild-owner reassignment as a break-glass recovery path
  • station_super_admin can enter explicit support impersonation mode for a guild instead of silently bypassing guild scoping
  • The frontend hides the Station-Bot nav entry, dashboard portlet, routes, tabs, guilds, and action controls when the user lacks the required permission, instead of merely allowing navigation and failing on save
  • The backend enforces the same permission model as the frontend, including guild-resource scoping, owner/admin distinctions, and super-admin-only runtime protections
  • Tests cover hidden navigation, direct-route denial, single-owner enforcement, admin-assignment limits, mixed-permission rendering, emergency owner reassignment, impersonation gating, dashboard visibility, and blocked cross-guild access attempts
  • pnpm typecheck passes

Acceptance Criteria

  • A user without Station-Bot admin permissions does not see a Station-Bot admin nav link or dashboard portlet and receives a 403 if they manually navigate to Station-Bot admin endpoints
  • A guild has exactly one guild_owner at a time
  • A guild_owner can grant and revoke guild_admin access for their guild but cannot create another owner without an explicit owner-transfer or super-admin recovery path
  • A guild_admin can manage the guild’s Station-Bot configuration but cannot access platform-wide runtime controls
  • A guild_member has no Station-Bot admin access
  • A station_super_admin can access platform-wide/runtime views, can impersonate a guild-admin context for support, and can perform emergency owner reassignment for a guild
  • Mixed pages render only the sections the current user is authorized to access. Example: a guild admin may see nomination digest controls while operator-only anti-abuse/worker controls remain hidden
  • Authorization checks are enforced on the backend even if the frontend is bypassed

Technical Elaboration

Current Constraint in Station

Station currently has:

  • Organization-scoped permissions stored in role.permissions JSONB
  • Aggregation through PermissionsService
  • PermissionsGuard that requires an organizationId in params/query/body

That works for organization resources like inventory, but it is not sufficient by itself for Station-Bot administration because the epic includes both:

  1. Guild-scoped bot config such as verification, manufacturing, nomination digest, and automation
  2. Global/operator runtime config such as runtime flags, exec-hangar, station-timer caps, and some nomination worker/anti-abuse controls
  3. Support-mode access where a platform-level actor must act within a guild-scoped context for customer support

Required Authorization Model

1. Organization/Guild mapping

Introduce a first-class mapping so Station knows which Station organization corresponds to which Station-Bot Discord guild. A reasonable initial model is a table/entity such as:

  • organizationId
  • discordGuildId
  • discordGuildNameSnapshot
  • isActive
  • lastValidatedAt

Only mapped guilds for organizations the user is authorized for should appear in the guild selector and should determine dashboard portlet visibility.

2. Initial guild role model

For this milestone, support only these effective guild roles:

  • guild_owner
    • exactly one per guild
    • full guild bot configuration control
    • can assign/remove guild_admin
  • guild_admin
    • full guild bot configuration control for that guild
    • cannot manage owner status
  • guild_member
    • no Station-Bot admin access

This can be implemented through Station org permissions so long as the resulting behavior matches the role model above.

3. Station super admin role

Introduce an explicit platform-level role:

  • station_super_admin

Capabilities for this role in this milestone:

  • view and manage platform/operator-only Station-Bot surfaces
  • initiate support impersonation for a specific guild
  • perform emergency guild-owner reassignment

This role should not silently act as a guild admin at all times. It should have a visible support/impersonation workflow for per-guild customer support.

4. New organization-scoped permissions

Extend OrgPermission with Station-Bot admin keys aligned to the existing snake_case permission style:

  • can_view_station_bot_admin
  • can_manage_station_bot_verification
  • can_manage_station_bot_nominations
  • can_manage_station_bot_manufacturing
  • can_manage_station_bot_automation
  • can_manage_station_bot_guild_admins

These should be aggregated exactly like inventory permissions today through PermissionsService.

5. Platform/super-admin permissions

Introduce a separate explicit platform permission model for non-org-scoped Station-Bot controls and support operations. Recommended initial keys:

  • can_view_station_bot_operator_console
  • can_manage_station_bot_exec_hangar
  • can_manage_station_bot_station_timer
  • can_manage_station_bot_runtime
  • can_impersonate_station_bot_guild_admin
  • can_emergency_reassign_station_bot_guild_owner

Implementation options are acceptable so long as the result is explicit and testable:

  • a dedicated SystemPermission enum + user/system-role assignment model
  • or a similarly explicit platform-role mechanism

What is not acceptable is burying operator access in a one-off username allowlist or in frontend-only conditionals.

6. Permission matrix for the epic

Recommended access matrix:

  • Shell and dashboard visibility
    • show nav/link or dashboard portlet if user has can_view_station_bot_admin for at least one mapped org or can_view_station_bot_operator_console
  • Verification page
    • requires can_manage_station_bot_verification
  • Nomination page
    • guild digest/delegated-role section requires can_manage_station_bot_nominations
    • operator anti-abuse/worker section requires can_manage_station_bot_runtime
  • Manufacturing page
    • requires can_manage_station_bot_manufacturing
  • Automation page
    • guild purge/reminder delivery section requires can_manage_station_bot_automation
    • reminder cleanup section requires can_manage_station_bot_runtime
  • Exec Hangar page
    • requires can_manage_station_bot_exec_hangar
  • Station Timer page
    • requires can_manage_station_bot_station_timer
  • Runtime page
    • requires can_manage_station_bot_runtime
  • Guild admin assignment page/controls
    • requires can_manage_station_bot_guild_admins
  • Support impersonation
    • requires can_impersonate_station_bot_guild_admin
  • Emergency owner reassignment
    • requires can_emergency_reassign_station_bot_guild_owner

7. Hidden navigation and direct-route enforcement

The frontend should use the permission payload to:

  • hide the root nav item when inaccessible
  • hide the Station Bot dashboard portlet when inaccessible
  • hide guilds the user cannot administer
  • hide tabs/sections the user lacks permission for
  • hide operator-only controls from ordinary guild admins
  • show explicit support-mode state when impersonating
  • render read-only/degraded states only where intentionally supported

The backend must mirror the same rules with guards/service checks so direct API calls cannot bypass them.

Design Elaboration

This story defines who the product is for at every layer.

A guild owner has primary responsibility for the guild. Guild admins are delegated by that owner. A Station super admin is a platform support actor, not a silent omnipresent guild admin. That is why support access should be explicit impersonation and why owner recovery should be an emergency flow, not an everyday control.

The UI should make those boundaries feel natural: no teasing inaccessible tabs, no mystery 403s after clicking a visible control, no hidden cross-guild power through URL guessing, and no ambiguity about when support is acting inside a customer guild context.


Parent Epic: #231
Depends on: None. This is an authorization foundation story for the Station Bot Administration epic.
Blocks: #232, #233, #234, #235, #236, #237, #238, #239, #240, #243, #244, #245

Metadata

Metadata

Assignees

Labels

backendBackend services and logicconfigConfiguration and feature flagsfrontendFrontend app and dashboardorgsOrganization-related behaviorsecuritySecurity, auth, and permissionstech-storyTechnical implementation storyui-uxUser interface and experience

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions