## ADDED Requirements ### Requirement: Protected typed admin routes The operations console SHALL expose explicit server-rendered routes and exact mutation forms behind the existing random admin path, Caddy Basic authentication, trusted edge marker, exact same-origin check, CSRF validation, no-store responses, and restrictive security headers. #### Scenario: Authorized operator opens a page - **WHEN** Caddy authenticates the request and injects the trusted marker and operator identity - **THEN** the requested operations page renders escaped server-side HTML with no client-side secret persistence #### Scenario: Direct backend request lacks marker - **WHEN** a request reaches an admin route without the trusted edge marker - **THEN** the backend rejects it regardless of supplied operator headers #### Scenario: Mutation has stale or invalid CSRF - **WHEN** a POST has a missing, duplicate, or invalid CSRF value or wrong Origin - **THEN** the backend rejects the mutation without side effects #### Scenario: Unknown route or form action is submitted - **WHEN** a request contains an unsupported method, route shape, action, field, or duplicate field - **THEN** it fails closed without invoking Supervisor, database mutations, or host operations ### Requirement: Trusted operator attribution Caddy SHALL strip any inbound operator identity header and inject the authenticated Basic-auth username, and the backend SHALL trust that identity only with the private edge marker. #### Scenario: Client spoofs operator header - **WHEN** a public request supplies its own operator identity header - **THEN** Caddy removes it and the audit actor is the authenticated Basic-auth user #### Scenario: Mutation is accepted - **WHEN** an authenticated operator performs a valid mutation - **THEN** the control or operation record and its audit event identify that operator ### Requirement: Exact production ingress profiles The production deployment SHALL use exactly one root-installed profile: `standalone-edge-v1` or `shared-host-edge-v1`. The selected profile SHALL NOT be supplied by an admin request, host-agent request, runtime document, or other unprivileged input. #### Scenario: Standalone edge is selected - **WHEN** `standalone-edge-v1` is installed - **THEN** the managed Truf edge remains the sole Truf listener on host port 443 and retains the exact runtime-network-namespace contract #### Scenario: Shared-host edge is selected - **WHEN** `shared-host-edge-v1` is installed - **THEN** the existing root-owned host Caddy remains the sole owner of ports 80/443 and proxies only fixed Truf routes to a managed edge bound at `127.0.0.1:18766` #### Scenario: A request attempts to select topology - **WHEN** a request supplies a deployment mode, upstream, port, Caddy path, unit, service, command, or Compose argument - **THEN** it is rejected before lifecycle work ### Requirement: Shared-host route confinement The shared-host profile SHALL install a fixed root-owned route-only host-Caddy snippet. It SHALL claim only `/api/v1/worker/*`, the exact random admin-prefix root, and that prefix's subtree. It SHALL strip inbound private and transit headers, inject an independent ingress marker and canonical client address, and preserve the managed edge's authentication, operator attribution, denylist, redacted logging, and security-header behavior without adding a listener, TLS policy, global error handler, trusted-proxy policy, catch-all, or unrelated route. #### Scenario: An unrelated host route is requested - **WHEN** a request does not match a Truf worker or admin path - **THEN** the Truf snippet does not handle or alter the request #### Scenario: The loopback Truf edge is unavailable - **WHEN** a matching route cannot reach `127.0.0.1:18766` - **THEN** host Caddy fails that Truf request without forwarding it to X-UI or another fallback upstream #### Scenario: A client supplies transit headers - **WHEN** a public request supplies an ingress marker, forwarded address, private edge marker, or operator identity - **THEN** host Caddy strips those values and injects only its reviewed ingress marker and observed client address ### Requirement: Runtime overview The overview page SHALL report bounded structured health for Supervisor, PostgreSQL, required pipeline workers, discovery producers, queue status, active remote assignments, result bundles, operation controls, and recent operation outcomes. #### Scenario: Runtime is healthy - **WHEN** all required components hold valid authority and health - **THEN** the overview reports the runtime active and identifies each required component without exposing secrets #### Scenario: Component is unavailable - **WHEN** a health source times out or returns malformed state - **THEN** the overview reports that component unavailable without blocking the rest of the page ### Requirement: Search controls The search page SHALL expose each core producer's structured state and typed start, stop, restart, pause, resume, and interval controls while clearly separating process lifecycle from the persistent discovery gate. #### Scenario: Operator pauses search - **WHEN** an operator submits pause with the current control revision - **THEN** the persistent discovery gate changes atomically and every producer stops admitting new discovered targets #### Scenario: Operator restarts one producer - **WHEN** an operator selects restart for an allowed producer ID - **THEN** only that managed discovery process restarts and the persistent pause state is unchanged ### Requirement: Dispatch and drain controls The workers/dispatch page SHALL expose persistent dispatch pause/resume, drain start/cancel, drain progress, compatible package state, worker users/devices, assignment counts, and upload availability. #### Scenario: Operator pauses dispatch - **WHEN** the current revision is submitted to the pause action - **THEN** no new worker assignment can commit while valid existing uploads remain accepted #### Scenario: Operator starts drain - **WHEN** drain is started - **THEN** the page reports draining progress from authoritative assignment and bundle counts until the state becomes drained #### Scenario: Stale page attempts resume - **WHEN** another operator has changed the control revision before resume is submitted - **THEN** the console reports a revision conflict and does not overwrite the newer state ### Requirement: Typed Supervisor operations The console SHALL use a closed Supervisor protocol for structured snapshot, allowlisted managed-source lifecycle actions, and bounded log tail, and SHALL NOT forward generic command strings. #### Scenario: Operator requests source status - **WHEN** the Supervisor page loads - **THEN** it displays structured source IDs, roles, phases, process state, restart state, and safe errors without parsing a text dashboard #### Scenario: Operator tails logs - **WHEN** an allowed managed source and bounded line count are submitted - **THEN** Supervisor returns only that source's bounded log tail #### Scenario: Input resembles a shell command - **WHEN** an operator submits command text, a path, or an unrecognized source ID - **THEN** the request is rejected and no generic Supervisor command or operating-system shell is called ### Requirement: Durable asynchronous operation status Long-running restart and apply actions SHALL create a PostgreSQL operation record before execution and SHALL remain queryable by operation ID across runtime/admin restarts. #### Scenario: Apply restarts the admin process - **WHEN** the process that accepted an apply request terminates during the coordinated restart - **THEN** the operator can reopen the operation URL and observe reconciled success, rollback, or failure state #### Scenario: Unknown operation is requested - **WHEN** an operator requests an operation ID that does not exist or is not canonical - **THEN** the console returns not found without searching filesystem paths or host-agent state by user input ### Requirement: Append-only audit view The audit page SHALL show bounded append-only events for accepted and completed controls, Supervisor actions, configuration/secrets operations, and managed-file mutations, including actor, action, logical target, time, result, and safe before/after identity. #### Scenario: Secret apply is audited - **WHEN** a secrets candidate is accepted and later applied or rolled back - **THEN** audit events record hashes and outcomes but no secret value, candidate bytes, authorization data, or CSRF value #### Scenario: Audit pagination is requested - **WHEN** an operator navigates audit history - **THEN** the backend returns a bounded deterministic page without unbounded database or browser output ### Requirement: Existing worker API availability Adding the operations console SHALL NOT weaken or couple public worker endpoints to admin page availability. #### Scenario: Admin feature is disabled or unhealthy - **WHEN** the admin console is disabled or a Supervisor/host-agent status dependency is unavailable - **THEN** authenticated worker status, upload, terminal report, and receipt paths continue under their existing authority