9.0 KiB
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-v1is 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-v1is 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