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

119 lines
5.1 KiB
Markdown

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