The current admin UI lives at /admin on the public worker and renders with the page title Beacon Admin.

Access

The public worker now enforces an admin check in code.

  • If ADMIN_TOKEN is set, requests must send a matching x-admin-token or authorization header.
  • If ADMIN_TOKEN is not set, the worker accepts cf-access-jwt-assertion.
  • Cloudflare Access is still the practical production setup because the browser UI makes many admin requests.

Unauthenticated requests to the deployed /admin route currently return 403.

The desktop UI uses a grouped sidebar. Mobile collapses this into four bottom-nav buckets.

GroupCurrent sections
OperationsOverview, Upload, Files, Regenerate, Advanced Ops
SetupCommunities & Sources
SystemAI Quota, Beacon Search Soon
Danger ZoneClear & Delete

Section Guide

Overview

The top section is a landing page with quick actions such as Upload Export, View Files, and Check Quota.

Communities & Sources

This area combines:

  • community creation and listing
  • source creation and editing inside a selected community
  • retroactive source assignment for exports that were uploaded without a source

If an export has no source, it can remain in Pending Source until assigned.

Upload

The current upload flow is explicitly step-based:

  1. Select a community and an optional recommended source
  2. Choose a file
  3. Review and upload

Current UI details:

  • file picker accepts .txt, .chat, and .zip
  • the checkbox label is Delete raw export after processing retention window
  • the helper text says extracted media and analysis stay while the original raw ZIP or text file is deleted later

Current worker behavior behind the UI:

  • smaller uploads go through POST /upload
  • large uploads use multipart R2 upload with 16 MiB parts
  • direct Worker uploads reject payloads over roughly 75 MiB

Files

Files is the operational view for uploaded exports.

Available filters:

  • source
  • status

Current status values exposed in the UI:

  • Completed
  • Processing
  • Weekly Processing
  • Media Processing
  • Queued
  • Failed
  • Pending Source

Available actions:

  • open details from /exports/details
  • copy the object key
  • delete the raw object and export record

The details modal is where operators can inspect estimated daily and weekly progress, media counts, and failure information.

Regenerate

This area contains four distinct tools.

Daily Digest

  • regenerate one day for a community
  • optional source_id scope

Regenerate AI Digests

  • regenerate one week or a week range
  • optional source_id
  • force option
  • compare_previous_week option

Bulk: All Weeks (All Sources)

  • queue weekly regeneration across all available weeks for a community

Pipeline Config

  • switch between serial and parallel
  • set daily concurrency from 1 to 10
  • set start stagger from 0 to 10000 ms

Advanced Ops

This section is tabbed and currently exposes:

Full Replay

  • re-enqueue exports from stored raw files
  • optional source_id
  • optional force_source_id
  • optional clear-first behavior for derived data

Retry Stuck Exports

  • manually re-enqueue exports stuck in processing
  • UI default is 10 minutes
  • the scheduled job also checks every 5 minutes and retries exports stuck for at least 10 minutes

Backfill

  • Concept Pillars
  • Strain Daily
  • Strain Weekly
  • Media Summaries

AI Quota

The quota area is broader than the old docs implied. It currently includes:

  • live status for text and media usage
  • usage graphs
  • manual Set Usage
  • configuration for text quotas, media quotas, and video-frame sampling
  • independent text and media Quota Bypass toggles

Beacon Search Soon

This is a placeholder card. It does not expose a usable search workflow yet.

Clear & Delete

This section is intentionally gated. The operator must first unlock irreversible actions before destructive controls are enabled.

Current destructive tools:

  • clear derived data for a date range
  • optionally scope that clear to one source
  • optionally clear message hashes
  • delete an entire community, including matching R2 objects and D1 records

Design Notes

The admin UI is a single-page app rendered inside handleAdminPage() in apps/pulse-public/src/index.ts (CSS ~line 18558, HTML ~line 21763, JS ~line 22661). All layout and behavior lives in that file — there is no build step or separate frontend bundle.

Density reduction. A global Hints toggle in the header hides all <small> help text and card header descriptions at once. State is persisted in localStorage. Default is hidden (experienced-admin mode).

Collapsible cards. Every .admin-card has a collapse button that hides its content. Collapsed state is persisted per card in localStorage. The regenerate card defaults to collapsed on first visit.

Mobile navigation. On screens ≤600px, the sidebar becomes a fixed bottom navigation bar with icons and truncated labels. First mobile visit defaults all cards collapsed except Community Management. Submit buttons are sticky above the bottom nav on long forms.

Layout classes. .form-grid is a 2-column CSS grid used in the Backfill sub-sections. .chat-sources-grid is a 3-column variant for the Chat Sources card. Both collapse to single column at narrow widths.

Backfill panel. The three backfill operations (Concept Pillars, Strain Daily, Strain Weekly, Media Summaries) are exposed as a segmented control — one button group, one panel visible at a time — rather than stacked forms.

Stability contracts. When modifying the admin page, do not change id attributes on forms or inputs (JS event listeners depend on them), the .sidebar-link/data-section tab pattern, the .toggle-button[role="switch"] structure, the admin-sidebar-collapsed localStorage key, #files-container mobile overrides, or the custom-dropdown system.

Operational Notes

  • Weekly summaries are only generated when a week has at least 3 days of data or 20 total messages.
  • Replaying or regenerating from raw exports only works while the raw object still exists in R2.
  • Raw export cleanup defaults are shorter than some older UI and docs copy. The code currently targets 72 hours for completed exports and 168 hours for failed exports when delete-after-processing is enabled.

Verified against the rendered admin UI and beacon-platform/apps/pulse-public/src/index.ts plus apps/pulse-ingest/src/index.ts on April 22, 2026.