# NextWorkspace — Agent Workflow Instructions

## Versioning

- Format: `MILESTONE.FEATURE.PATCH.BUILD` (e.g., `0.1.0.0032`)
- Bump VERSION file on every change before commit.
- Every commit must be tagged with the version: `git tag v$(cat VERSION)`

## Deployment Model (Unified Script)

The project uses a single unified script at `tools/nextwks.sh` for all operations.
The old `deploy.sh` and `install.sh` are deprecated.

**Key principles:**
- Source of truth is **git remote only**. No local `/opt/NextWks` repo.
- Building happens in `/tmp/nextwks-build/` via `git clone --depth 1` (fresh every time).
- Runtime goes to `/opt/nextworkspace/` (configs, compose, binary, lng).
- Secrets persist in `/opt/backup/.env` and survive `--destroy`.
- Stack runs on a shared `nextwks-net` podman bridge network.

### Script Flags

| Flag | What it does |
|------|-------------|
| `--install` | First-time setup on a bare VM: installs deps, prompts for config, builds binary, generates configs, deploys stack |
| `--update`  | Smart update: clones fresh, rebuilds binary, copies to target, bounces containers |
| `--destroy` | Full greenfield redeploy: tears down containers, wipes `/opt/nextworkspace/`, rebuilds from scratch using saved secrets from `/opt/backup/.env` |

### Workflow for Making Changes

1. Edit code in the development clone.
2. Test locally (e.g., `go build && go run .`).
3. Bump `VERSION` (increment BUILD).
4. Update `CHANGELOG.md`.
5. Commit: `git add -A && git commit -m "description"`
6. Tag: `git tag v$(cat VERSION)`
7. Push: `git push origin main --tags`
8. Deploy: `./nextwks.sh --update` (no sudo — script handles it per-command)

> **Note:** The deploy script is downloaded by users via `curl` from the repo. For production deployment, users run:
> ```bash
> curl -sL https://git.lohmar.co.uk/lexton-it/NextWks/raw/branch/main/tools/nextwks.sh | sudo bash -s -- --install
> ```

## Build Process

- Static Go binary: `CGO_ENABLED=0 go build -o nextworkspace .`
- Must run on Alpine in the container (no glibc dependency).
- Binary runs as PID 1 in the `launcher` container.

## Architecture

```
Caddy (:80/:443, host ports)
  ├── auth.{DOMAIN} → Authelia :9091 (internal)
  ├── app.{DOMAIN}  → Launcher :9000 (internal) with forward auth
  └── www.{DOMAIN}  → static files

All three containers on nextwks-net (podman bridge).
Only Caddy exposes ports to host.
```

## Config Template System

Config files use `{PLACEHOLDER}` syntax. The script substitutes values at deploy time:

| File | Placeholders |
|------|-------------|
| `config/caddy/Caddyfile` | `{DOMAIN}`, `{TLS_EMAIL}` |
| `config/authelia/configuration.yml` | `{DOMAIN}`, `{JWT_SECRET}`, `{SESSION_SECRET}`, `{SMTP_HOST}`, `{SMTP_PORT}`, `{SMTP_USER}`, `{SMTP_PASS}` |
| `config/authelia/users_database.yml` | `{ADMIN_PASSWORD_HASH}`, `{TLS_EMAIL}` |
| `compose/stack.yaml` | `{AUTHELIA_SECRET}` (same as `SESSION_SECRET`) |

## Env Vault (`/opt/backup/.env`)

Persisted secrets across destroys:
```
DOMAIN=nextwks.eu
TLS_EMAIL=admin@nextwks.eu
ADMIN_USERNAME=master
ADMIN_PASSWORD=<generated>
SMTP_HOST=smtp.openxchange.eu
SMTP_PORT=587
SMTP_USER=post@nextwks.eu
SMTP_PASS=<prompted>
JWT_SECRET=<auto-generated>
SESSION_SECRET=<auto-generated>
ADMIN_PASSWORD_HASH=<bcrypt hash>
```

## Health Check

After deploy, the script polls `podman exec launcher wget -qO- http://127.0.0.1:9000/health`
up to 10 times (2s interval). Expected response: `OK`.

## Commit Message Style

- Imperative mood ("Add", "Fix", "Update", "Bump")
- Reference the component if relevant ("launcher: add health endpoint")
- Keep under 72 chars for the first line
