auth-yes/tasks/complete/2026-0821.01.jul.story.setup-ts.headless-architecture-analysis-0105.md
Tyler Gillispie 474cc177ce chore: adopt dual licensing and import task history & scaffolding
- Add LICENSE-MIT and LICENSE-APACHE for dual MIT / Apache-2.0 distribution
- Update root LICENSE pointer, README.md, Deno workspace manifests, and Cargo.toml
- Add deno.lock dependency lockfile
- Format AGENTS.md system guidelines
- Import task lifecycle scaffolding and historical story specifications (extract-auth-yes, setup-ts architecture, modular workspace)
2026-08-21 15:20:36 -07:00

5.1 KiB

TASK METADATA

  • Target Files: infra/setup.ts
  • Core Objective: Design a robust, non-interactive (headless) execution mode for setup.ts with explicit guardrails to prevent VM hangs.
  • Dependencies: jsr:@cliffy/command or similar argument parsing library integration may be required for the CLI subcommands.
  • Additional Important Notes: Must preserve the existing interactive menu when run without arguments in a TTY environment. Must fail-fast if headless environment is detected without explicit headless flags.

1. Input Audit

The current interactive wizard in setup.ts requests the following inputs and configurations across its menus and sub-menus:

A. Main Menu Actions (Select.prompt)

The user is prompted to choose one of the following execution paths:

  • [Test Hub Connection] -> test
  • [Configure Central Hub] -> hub
  • [Configure Auth Yes API] -> auth
  • [Compile Protobuf Definitions] -> compile_proto
  • [Review Generated Configs] -> review
  • [Build and Push Hub Image] -> build
  • [Build and Push Auth Yes Image] -> build_auth
  • [Generate Edge Handshake] -> handshake
  • [Exit] -> exit

B. Hub Setup (handleHubSetup)

Requires the following inputs (SetupConfig):

  • Container Registry URL (Input.prompt): e.g., quay.atyg.org
  • System Domain Name (Input.prompt): e.g., system.local
  • Database Path on Host (Input.prompt): e.g., /volume1/docker/ed-droid/db
  • PostgreSQL Password (Secret.prompt): Hidden input, falls back to existing if left blank.
  • UI Modules (Checkbox.prompt): Multi-select options (route, roi, exo, log).

C. Auth Setup (handleAuthSetup)

Requires the following inputs (AuthSetupConfig):

  • Container Registry URL (Input.prompt): e.g., quay.atyg.org
  • Auth Domain Name (Input.prompt): e.g., auth.system.local
  • Database Path on Host (Input.prompt): e.g., /volume1/docker/auth-yes/db
  • App Secret for IDP (Secret.prompt): Minimum length 16.
  • PostgreSQL Password (Secret.prompt): Hidden input, falls back to existing if left blank.

2. Headless Architecture Proposal

To support non-interactive environments (like CI/CD or automated VM provisioning) without sacrificing the existing developer experience, a hybrid CLI Subcommand + Environment Variable approach is recommended.

A. Subcommand Routing

The interactive "Main Menu" should be mapped to explicit CLI subcommands. For example:

  • deno run -A setup.ts hub (corresponds to [Configure Central Hub])
  • deno run -A setup.ts auth (corresponds to [Configure Auth Yes API])
  • deno run -A setup.ts build (corresponds to [Build and Push Hub Image])

B. Configuration Injection (Hybrid Approach)

For subcommands that require configuration (like hub and auth), we should use a combination of CLI flags for non-sensitive data and environment variables for secrets.

Example for Hub Setup: deno run -A setup.ts hub --auto --registry="quay.atyg.org" --domain="system.local" --db-path="/var/lib/db" --modules="route,log" Secrets: The PostgreSQL password should be read from the environment (e.g., POSTGRES_PASSWORD), failing explicitly if it is not provided.

Example for Auth Setup: deno run -A setup.ts auth --auto --registry="quay.atyg.org" --domain="auth.system.local" --db-path="/var/lib/auth-db" Secrets: The PostgreSQL password and App Secret should be read from the environment (e.g., POSTGRES_PASSWORD, APP_SECRET), failing explicitly if not provided.

C. Fallback to Interactive

If setup.ts is executed without any subcommands or arguments (i.e., deno run -A setup.ts), the script should verify it is in a terminal (see Guardrails) and immediately launch the existing interactive runSetupWizard().

3. Execution Guardrails

To absolutely prevent the script from hanging headless VMs by accidentally blocking on a prompt(), we must implement strict, early-exit guardrails.

  1. Terminal Detection (fail-fast): At the very beginning of execution, check Deno.stdin.isTerminal(). If it is false (meaning we are running headless/non-interactive), the script must inspect the provided arguments. If explicit headless subcommands or a flag like --auto/--headless are not present, the script must abort immediately with a non-zero exit code and a clear error message (e.g., "Error: Non-interactive environment detected, but no explicit CLI subcommands or --auto flag were provided. Aborting to prevent hangs.").

  2. Clean Exit on Help/Version: By utilizing a robust CLI parsing library (like Cliffy's Command), flags such as --help or --version will be intercepted before any application logic or wizard is initialized, ensuring a clean exit(0).

  3. Strict Validation in Headless Mode: When running a subcommand in headless mode (e.g., setup.ts hub --auto), the script must validate that all required inputs (either via flags or environment variables) are present before proceeding. If any are missing, it must throw or Deno.exit(1) rather than falling back to an interactive prompt.