# Track A Handoff — 2026-03-29

This handoff captures the current state of Track A on the Azure VM at `/opt/bytelyst/`.

Architecture decision after this handoff:

- The VM should host only self-hosted infrastructure and backend APIs
- `api.bytelyst.com` and `gitea.bytelyst.com` should point to the VM
- `admin.bytelyst.com` and `tracker.bytelyst.com` should be Vercel-hosted frontends, not VM-hosted services

## What Was Completed

- Fixed a blocking parse error in [`docker-compose.ecosystem.yml`](/opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml) by removing a duplicate `efforise-web` service definition.
- Added [`/opt/bytelyst/Caddyfile`](/opt/bytelyst/Caddyfile) with path-based routing for the 13 backend services.
- Added a tracked template copy at [`docs/devops/single_azure_vm/docker/Caddyfile.bytelyst.example`](/opt/bytelyst/learning_ai_common_plat/docs/devops/single_azure_vm/docker/Caddyfile.bytelyst.example).
- Updated [`docker-compose.ecosystem.yml`](/opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml) to:
  - add a `caddy` service
  - place Traefik `gateway` behind a `legacy-gateway` profile
  - remove published backend ports for `4003`, `4005`, `4007`, `4010`-`4019`
- Updated dashboard Dockerfiles to use the Next.js standalone runtime:
  - [`dashboards/admin-web/Dockerfile`](/opt/bytelyst/learning_ai_common_plat/dashboards/admin-web/Dockerfile)
  - [`dashboards/tracker-web/Dockerfile`](/opt/bytelyst/learning_ai_common_plat/dashboards/tracker-web/Dockerfile)
- Updated deployment docs:
  - [`docs/devops/single_azure_vm/docker/README.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/single_azure_vm/docker/README.md)
  - [`docs/devops/single_azure_vm/docker/DEPLOYMENT_STATUS_2026-03-29.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/single_azure_vm/docker/DEPLOYMENT_STATUS_2026-03-29.md)
- Updated the Track A progress table to mark A1 in progress:
  - [`docs/devops/vercel/CODEX_PROMPTS_TRACK_A_AZURE_VM.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/vercel/CODEX_PROMPTS_TRACK_A_AZURE_VM.md)

## Blockers Found

### 1. DNS is not ready

At the time of the original session, these records did not resolve from the VM:

- `api.bytelyst.com`
- `gitea.bytelyst.com`
- `admin.bytelyst.com`
- `tracker.bytelyst.com`

For the revised architecture:

- `api.bytelyst.com` and `gitea.bytelyst.com` must resolve to the VM
- `admin.bytelyst.com` and `tracker.bytelyst.com` should resolve to Vercel, not the VM

Only the VM-hosted records are prerequisites for A1/A2/A4.

### 2. Azure CLI is installed, but the active subscription context still needs validation

Azure CLI is now installed and `az account show` succeeds.

Current observed context:

- subscription: `Azure subscription 1`
- tenant: `eScube`
- state: `Disabled`

This means A4 is no longer blocked by a missing CLI, but it may still be blocked until the correct active subscription is selected and has permission to manage the VM NSG.

### 3. Linux build host is still using the wrong Gitea registry hostname

Broad compose rebuilds hit repeated package fetch failures such as:

```text
GET http://host.docker.internal:3300/api/packages/bytelyst/npm/... error (ENOTFOUND)
```

The VM is Linux, and many builds still default to `GITEA_NPM_HOST=host.docker.internal`. On this VM the Gitea registry is reachable at `localhost:3300` on the host and via the detected Docker host IP used by `setup.sh`.

This blocks reliable rebuilds for A3 and potentially other services.

## Required Preconditions Before Resuming

1. Create or confirm VM DNS records for:
   - `api.bytelyst.com`
   - `gitea.bytelyst.com`
2. Confirm they resolve to the VM public IP from the VM:

```bash
dig +short api.bytelyst.com
dig +short gitea.bytelyst.com
curl -sf https://api.ipify.org && echo
```

3. Point `admin.bytelyst.com` and `tracker.bytelyst.com` at Vercel, not the VM.
4. Verify Azure account context and switch to the correct active subscription if needed:

```bash
az account show -o table
az account list -o table
az account set --subscription "<active-subscription-name-or-id>"
```

5. Export a Linux-safe Gitea host before rebuilds, for example:

```bash
export GITEA_NPM_HOST=172.17.0.1
```

Use the actual Docker-reachable host IP if it differs on this VM.

## Resume Steps

Run from:

```bash
cd /opt/bytelyst/learning_ai_common_plat
```

### A1

1. Confirm backend health:

```bash
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem ps
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem ps | grep -c healthy
```

2. Start or refresh only the gateway-related services first:

```bash
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem up -d caddy platform-service extraction-service mcp-server peakpulse-backend chronomind-backend jarvisjr-backend nomgap-backend mindlyst-backend lysnrai-backend notelett-backend flowmonk-backend actiontrail-backend localmemgpt-backend
docker logs caddy --tail 100
```

3. Verify A1:

```bash
curl -sI https://api.bytelyst.com/platform/health | head -5
for svc in platform extraction mcp peakpulse chronomind jarvisjr nomgap mindlyst lysnrai notelett flowmonk actiontrail localmemgpt; do
  echo -n "$svc: "
  curl -sf https://api.bytelyst.com/$svc/health | jq -r '.status // "FAIL"'
done
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:4003/health && echo "FAIL: port still open" || echo "PASS: port closed"
```

### A2

1. Reconfigure the standalone `gitea-npm-registry` container for HTTPS exposure. It is not managed by the ecosystem compose file.
2. Update its `ROOT_URL` to `https://gitea.bytelyst.com`.
3. Add a `gitea.bytelyst.com` block to `/opt/bytelyst/Caddyfile`.
4. Reload Caddy.
5. Verify:

```bash
curl -sI https://gitea.bytelyst.com | head -3
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
docker exec platform-service curl -sf http://gitea:3300/api/v1/version | jq '.version'
```

Note:
The current running container is:

```bash
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | grep -i gitea
```

Observed name during this session:

```text
gitea-npm-registry
```

### A3

1. Do not treat `admin-web` and `tracker-web` as VM-hosted production surfaces.
2. Deploy them to Vercel and configure them to use `https://api.bytelyst.com`.
3. Point `admin.bytelyst.com` and `tracker.bytelyst.com` to Vercel.
4. Do not add dashboard routes to `/opt/bytelyst/Caddyfile`.

### A4

1. Install Azure CLI if still missing.
2. Identify the resource group and NSG name for this VM.
3. Snapshot rules, then reduce inbound access to only `22`, `80`, and `443`.
4. Run the full A4 verification from the Track A prompt file.

## Suggested Commit Sequence

After each prompt passes, update the progress table in:

- [`docs/devops/vercel/CODEX_PROMPTS_TRACK_A_AZURE_VM.md`](/opt/bytelyst/learning_ai_common_plat/docs/devops/vercel/CODEX_PROMPTS_TRACK_A_AZURE_VM.md)

Suggested commits:

- `feat(gateway): replace Traefik with Caddy for HTTPS path routing`
- `feat(gateway): expose Gitea npm registry via HTTPS at gitea.bytelyst.com`
- `docs(architecture): move dashboards to Vercel and keep VM backend-only`
- `chore(security): lock down Azure NSG to 22/80/443 only`
