Admin Controls & Switches
Relevant source files
The following files were used as context for generating this wiki page:
Admin Controls & Switches provide a global mechanism to manage data source availability across all workspaces. Operators use these controls to pause or block specific platforms (e.g., Reddit, Hacker News) in response to API changes, service outages, or cost management requirements. When a source is modified via these controls, the system enforces the state across all collection pipelines and notifies end-users of the operator-defined reason.
Sources: app/admin/switches/page.tsx:21-23, lib/db/schema.ts:654-666
Security and Authentication
The system implements strict multi-layer protection for admin operations. Access to the administration interface and underlying API routes requires specific user identification stored in environment variables.
Admin Identification
The isAdmin function validates users by checking the VANTAGE_ADMIN_USER_IDS environment variable. This variable contains a comma-separated list of permitted IDs. The system trims whitespace and ignores empty entries during parsing to ensure exact matches.
Sources: test/source-switch-admin.test.ts:88-103
CSRF Protection
Privileged API routes, such as the source switch update endpoint, implement "Defense in Depth" against cross-site requests:
- Fetch Metadata: The system checks the
sec-fetch-siteheader and rejects any request where the value is notsame-originornone. - Origin Verification: For browsers that do not support Fetch Metadata, the system compares the request
Originheader against the application's base URL. - Request Rejection: If either check fails, the API returns a
403 Forbiddenresponse before performing any database operations.
Sources: app/api/admin/switches/route.ts:13-27, test/source-switch-admin.test.ts:46-72
Data Model
The system uses two primary tables to manage and audit global switches. All switch changes are written in a single database batch to ensure atomicity.
Database Tables
| Table | Fields | Description |
|---|---|---|
source_switch | sourceKey, state, reason, changedAt, changedBy | Stores the current global state of a source. sourceKey is the primary key (e.g., "reddit"). |
source_switch_log | id, sourceKey, fromState, toState, reason, changedAt, changedBy | An append-only audit trail tracking every state transition. |
Sources: lib/db/schema.ts:669-689, test/source-switch-admin.test.ts:121-131
Switch States
The source_switch_state enum defines the possible modes for any source:
- on: The source is fully functional.
- paused: Collection is temporarily halted; users see a "Paused by operator" message.
- blocked: The source is disabled; typically used for permanent provider restrictions.
Sources: lib/db/schema.ts:666, test/source-switch.test.ts:13-24
System Architecture
The following diagram illustrates the flow of a switch update from the Admin UI through the security layer to the database.
The update process uses revalidatePath to ensure the Admin UI and User Settings pages reflect the change immediately without a full deployment.
Sources: app/admin/switches/actions.ts:11-36, test/source-switch-admin.test.ts:121-131
Logic Enforcement
The decideSwitch function serves as the central logic gate for all data collection activities. Before a collector runs, it evaluates the global switch state.
- Default State: If no row exists in the
source_switchtable for a given key, the system treats it ason(enabled). - Execution Gate: Collectors only execute if
enabledistrue. - User Feedback: If a source is paused globally, the
displayCoveragefor that source in the workspace settings changes topaused_global.
Operator UI Implementation
The admin page (/admin/switches) provides a list of all available source keys defined in SOURCE_SWITCH_KEYS.
Key Features
- Dynamic Loading: The page is forced to
dynamic = "force-dynamic"to ensure operators see real-time data. - Batch Status: Displays the last change timestamp and the provided reason for every source.
- Safety Measures: The UI disables all "Save" buttons and input fields if the initial switch list fails to load from the database.
- Input Constraints: The
reasonfield is limited to 500 characters to prevent database overflow.
Sources: app/admin/switches/page.tsx:10-98, app/api/admin/switches/route.ts:51-53
Summary
Admin Controls & Switches act as a global circuit breaker for the Vantage platform. By integrating security checks, audit logging, and automated execution gates, the system allows operators to safely manage platform-wide dependencies and communicate service status to users directly through the interface.
Sources: app/admin/switches/page.tsx:21-23, test/source-switch-admin.test.ts:110-120