# Provisioning CLI - Flow-Aware TTY Command Management

## Architecture Overview

The provisioning wrapper (`provisioning/core/cli/provisioning`) is a **flow controller** that manages three execution paths for command handling:

1. **Standalone TTY** - Interactive commands that exit after execution
2. **Pipeline TTY** - Interactive commands that output for piping to other commands
3. **Regular** - Standard Nushell command processing

This design enables:
- Interactive commands (TTY input) without blocking Nushell
- Inter-command piping of TTY output to subsequent commands
- Same-command flow (TTY input → Nushell processing in one execution)
- Daemon optimization for non-interactive commands

## How Flow Management Works

### Execution Flow

```text
User Command: provisioning <cmd> <args>
       ↓
Bash wrapper (provisioning)
       ↓
┌──────────────────────────────────────┐
│ Phase 1: TTY Command Detection       │
│ - Read tty-commands.conf registry    │
│ - Match command pattern              │
└──────────────────────────────────────┘
       ↓
       ├─→ Not a TTY command → Continue to Nushell (normal processing)
       │
       └─→ TTY command found → Check flow type
              ↓
              ├─→ flow=exit → Execute wrapper, exit immediately
              ├─→ flow=pipe → Execute wrapper, output to stdout, exit (allows piping)
              └─→ flow=continue → Execute wrapper, capture output, continue to Nushell
                                   ($env.TTY_OUTPUT available in Nushell)
```

### Flow Types Explained

#### 1. Standalone TTY Commands (flow=exit)

**Use case**: Interactive forms, setup wizards, authentication dialogs

**Example**: `provisioning setup wizard`

**Flow**:

```bash
Bash wrapper → TTY filter detects "setup wizard" → flow=exit
              ↓
Execute wrapper: core/shlib/setup-wizard-tty.sh
              ↓
User interaction (TypeDialog form)
              ↓
Exit wrapper → Exit bash wrapper
              ↓
Never reaches Nushell
```

**Registry entry**:

```bash
"setup wizard" "core/shlib/setup-wizard-tty.sh" "exit"
```

#### 2. Pipeline TTY Commands (flow=pipe)

**Use case**: Getting user input to pipe to another command

**Example**: `provisioning auth get-key | provisioning deploy --api-key-stdin`

**Flow**:

```bash
Bash wrapper → TTY filter detects "auth get-key" → flow=pipe
              ↓
Execute wrapper: core/shlib/auth-get-key-tty.sh
              ↓
User provides API key via TTY prompt
              ↓
Wrapper outputs API key to stdout
              ↓
Exit wrapper (process exits, pipe has captured output)
              ↓
Next command receives API key from stdin
```

**Registry entry**:

```bash
"auth get-key" "core/shlib/auth-get-key-tty.sh" "pipe"
```

**Wrapper requirements** (flow=pipe):
- Must output result to stdout
- Output must be newline-terminated
- Exit with proper code (0=success, non-zero=error)

#### 3. Continue-to-Nushell TTY Commands (flow=continue)

**Use case**: TTY input that needs further processing in Nushell

**Example**: `provisioning auth integrate --provider azure`

**Flow**:

```bash
Bash wrapper → TTY filter detects "auth integrate" → flow=continue
              ↓
Execute wrapper: core/shlib/auth-integrate-tty.sh
              ↓
User provides credentials via TTY prompt
              ↓
Wrapper outputs credentials (usually JSON) to stdout
              ↓
Filter CAPTURES output to $TTY_OUTPUT environment variable
              ↓
Set $env.PROVISIONING_BYPASS_DAEMON=true (skip daemon)
              ↓
Return 0 WITHOUT EXITING (continue to Nushell)
              ↓
Nushell dispatcher receives both:
  - CLI args: --provider azure
  - TTY output: $env.TTY_OUTPUT (credentials JSON)
              ↓
Nushell script processes both, completes integration
```

**Registry entry**:

```bash
"auth integrate" "core/shlib/auth-integrate-tty.sh" "continue"
```

**Wrapper requirements** (flow=continue):
- Must output result to stdout (usually JSON for structured data)
- Exit with proper code (0=success, non-zero=error)

**Nushell script requirements** (receives flow=continue output):

```nushell
export def "provisioning auth integrate" [--provider: string] {
    # Check if TTY output exists (guard pattern)
    let tty_output = ($env.TTY_OUTPUT? | default "")
    if ($tty_output | is-empty) {
        error make {msg: "No credentials provided via TTY"}
    }

    # Parse TTY output (credentials)
    let credentials = ($tty_output | from json)

    # Use both TTY input ($credentials) and CLI args ($provider)
    # Complete integration logic...

    # Clear sensitive data after use
    hide-env TTY_OUTPUT
}
```

#### 4. Regular Commands

**Use case**: Standard provisioning operations

**Example**: `provisioning server list`

**Flow**:

```bash
Bash wrapper → TTY filter checks registry → Not found → Return 1
              ↓
Continue to normal processing:
  - Fast-path checks (help, workspace, env, etc.)
  - Daemon check (if applicable)
  - Nushell dispatcher
```

## Registry Format

**File**: `provisioning/core/cli/tty-commands.conf`

**Three-field format**: `"PATTERN" "WRAPPER_PATH" "FLOW_TYPE"`

```bash
# Exact command match (e.g., "setup wizard" matches "provisioning setup wizard")
"setup wizard" "core/shlib/setup-wizard-tty.sh" "exit"

# Paths are relative to $PROVISIONING
"auth get-key" "core/shlib/auth-get-key-tty.sh" "pipe"

# Flow types: exit | pipe | continue
"auth integrate" "core/shlib/auth-integrate-tty.sh" "continue"
```

### Flow Type Decision Matrix

| Interaction | Flow Type | Example |
| ----------- | --------- | ------- |
| Interactive form, no output needed | `exit` | Setup wizard, auth login |
| User input → pipe to next command | `pipe` | API key for piping to deploy |
| User input → same-command Nushell processing | `continue` | Credentials for integration |

## Adding New TTY Commands

### Step 1: Create Wrapper Script

Create wrapper in `provisioning/core/shlib/`:

```bash
#!/bin/bash
set -euo pipefail

main() {
    local input

    # Get input from user
    read -rsp "Prompt: " input
    echo  # Newline

    # For flow=pipe: output to stdout
    # For flow=continue: output to stdout (will be captured by filter)
    echo "$input"

    return 0
}

main "$@"
```

Make it executable:

```bash
chmod +x provisioning/core/shlib/your-wrapper-tty.sh
```

### Step 2: Add Registry Entry

Edit `provisioning/core/cli/tty-commands.conf`:

```bash
# Standalone TTY
"your command" "core/shlib/your-wrapper-tty.sh" "exit"

# Pipeline TTY
"get something" "core/shlib/get-something-tty.sh" "pipe"

# Continue-to-Nushell TTY
"setup something" "core/shlib/setup-something-tty.sh" "continue"
```

### Step 3: No Wrapper Modifications Required

The provisioning wrapper automatically:
- Reads registry
- Matches command pattern
- Routes based on flow type
- Handles all three flows

**No need to modify provisioning wrapper for new commands!**

## Wrapper Script Requirements

### For All Wrappers

- **Shebang**: `#!/bin/bash`
- **Safety**: `set -euo pipefail`
- **Arguments**: Accept `"${@}"` from wrapper
- **Exit codes**: 0=success, non-zero=error
- **Validation**: `shellcheck` passes without warnings

### For flow=exit Wrappers

- Complete all interaction in wrapper
- Exit with proper code (0=success, non-zero=error)
- Output shown directly to user (from wrapper)

### For flow=pipe Wrappers

- Get input from user (TTY)
- Output result to stdout
- Output must be newline-terminated
- Exit with proper code (0=success, non-zero=error)

### For flow=continue Wrappers

- Get input from user (TTY)
- Output result to stdout (usually JSON)
- Exit with proper code (0=success, non-zero=error)
- Filter captures output → $TTY_OUTPUT
- Nushell script reads $env.TTY_OUTPUT

## Environment Variables

### Exported by Filter (flow=continue only)

- **`$TTY_OUTPUT`**: Captured output from wrapper (available in Nushell as `$env.TTY_OUTPUT`)
- **`$PROVISIONING_BYPASS_DAEMON`**: Set to "true" to skip daemon (flow=continue automatically sets this)
- **`$TTY_WRAPPER_EXECUTED`**: Set to "true" when TTY wrapper was executed

### Usage in Nushell

```nushell
# Access TTY output in Nushell script
export def "provisioning auth integrate" [--provider: string] {
    let tty_output = ($env.TTY_OUTPUT? | default "")

    # Parse if JSON
    let creds = ($tty_output | from json)

    # Use both TTY output and CLI args
    integration-logic $provider $creds

    # Clear after use (security)
    hide-env TTY_OUTPUT
}
```

## Daemon Interaction

The flow filter intelligently manages daemon usage:

### For flow=exit and flow=pipe
- ✅ **Daemon can be used** - No stdin required
- No output needs to be captured and passed to Nushell
- Daemon optimization available (~100ms startup improvement)

### For flow=continue
- ❌ **Daemon MUST be bypassed** - stdin required for TTY interaction
- `PROVISIONING_BYPASS_DAEMON=true` automatically set by filter
- Direct Nushell execution (preserves stdin for TTY)
- Zero overhead (same as non-daemon path)

## Testing TTY Commands

### Test Standalone (flow=exit)

```bash
provisioning setup wizard
# Expected: TypeDialog form, user interaction, exits
```

### Test Pipeline (flow=pipe)

```bash
provisioning auth get-key | wc -c
# Expected: Prompts for API key, outputs to pipe
```

### Test Continue (flow=continue)

```bash
provisioning auth integrate --provider azure
# Expected: Prompts for credentials, passes to Nushell with $env.TTY_OUTPUT
```

### Test Regular Command

```bash
provisioning server list
# Expected: Normal Nushell processing
```

## Troubleshooting

### Command Not Executed
- **Check**: Is command in tty-commands.conf?
- **Check**: Does pattern exactly match command?
- **Check**: Is wrapper path correct and executable?

### Wrapper Not Found
- **Error message**: `Warning: TTY wrapper not found or not executable: /path/to/wrapper`
- **Check**: File exists at `$PROVISIONING/wrapper-path`
- **Check**: File is executable: `chmod +x wrapper-path`

### Output Not Piping (flow=pipe)
- **Check**: Wrapper outputs to stdout (not stderr)
- **Check**: Output is newline-terminated: `echo "output"`
- **Check**: No daemon interference (PROVISIONING_BYPASS_DAEMON not set)

### Nushell Not Receiving Output (flow=continue)
- **Check**: `$env.TTY_OUTPUT` accessible in Nushell: `echo $env.TTY_OUTPUT`
- **Check**: Output format (usually JSON): `echo $env.TTY_OUTPUT | from json`
- **Check**: Wrapper exits with 0: `echo $?`

## Implementation Details

### Filter Location and Function

**File**: `provisioning/core/cli/tty-filter.sh`
**Function**: `filter_tty_command()`
**Lines**: ~104 (includes documentation and three flow paths)

### Integration in Wrapper

**File**: `provisioning/core/cli/provisioning`
**Lines**: ~20 (sources filter, calls function, continues to Nushell)

### Registry Parsing

- **File**: `provisioning/core/cli/tty-commands.conf`
- **Method**: Line-by-line bash read (no jq dependency)
- **Format**: Three-field bash array (bash-compatible)
- **Sections**: Organized by flow type for clarity

## Performance Implications

### startup time
- **flow=exit/pipe**: Daemon available for startup optimization (~100ms improvement)
- **flow=continue**: Daemon bypassed (stdin needed), ~500ms traditional path
- **Regular commands**: Normal daemon/non-daemon path selection

### Memory
- **flow=continue**: Wrapper output stored in `$TTY_OUTPUT` environment variable
- Typical size: < 1KB (credentials, keys, etc.)
- Cleared after Nushell processing (or via `hide-env`)

## Security Considerations

### Sensitive Data in $TTY_OUTPUT

- **Credentials** captured in `$TTY_OUTPUT`
- **Nushell scripts should clear after use**: `hide-env TTY_OUTPUT`
- **Wrapper output may be logged**: Use standard Unix conventions (hide passwords from output)

### Wrapper Location Restriction

- Wrappers should be in `provisioning/core/shlib/` or `provisioning/scripts/`
- Registry reads only wrappers from these trusted locations
- Pattern validation prevents arbitrary script execution

### No Shell Injection

- All variables quoted: `"$variable"`
- No eval or command substitution with user input
- Pattern matching uses exact string match (no regex)

## Related Files

- **Filter**: `provisioning/core/cli/tty-filter.sh`
- **Registry**: `provisioning/core/cli/tty-commands.conf`
- **Wrapper**: `provisioning/core/cli/provisioning`
- **Example wrappers**: `provisioning/core/shlib/auth-get-key-tty.sh`, `provisioning/core/shlib/auth-integrate-tty.sh`

## Key Insights

The provisioning wrapper is not just a pass-through - it's a **flow controller** that:

1. **Detects TTY requirements** (registry matching)
2. **Manages execution paths** (three flows: exit, pipe, continue)
3. **Controls exit behavior** (standalone vs pipeline vs same-command)
4. **Enables inter-command piping** (TTY output to pipes)
5. **Supports Nushell integration** (TTY→Nushell continuation)
6. **Optimizes with daemon** (skip when stdin needed)

This solves:
- "el tema no es sólo un filter" → ✅ Flow controller with three execution paths
- "cómo gestionar el flow por medio del provisioning command" → ✅ Registry + flow types
- "usamos tty para input de una API key, se lo pasamos a un script de nushell" → ✅ Pipeline + continue flows

---

**Version**: 1.0.0
**Last Updated**: January 2026
**Status**: ✅ Production Ready
