Files
T
2026-09-30 20:30:56 +03:00

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-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.

  • 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