docs(vercel): improve Codex prompts with progress trackers, preconditions, verification gates, and per-repo checklists
This commit is contained in:
parent
5fb5a7d468
commit
80e6268924
@ -1,16 +1,67 @@
|
||||
# Track A: Azure VM — Gateway, Dashboards & Security
|
||||
|
||||
> **Agent:** Codex on Azure VM (`/opt/bytelyst/`)
|
||||
> **Prompts:** 4 (run in order)
|
||||
> **Dependency:** None — this track runs first, unblocks Track B Prompt 4
|
||||
> **Prompts:** 4 (run in dependency order below)
|
||||
> **Unblocks:** Track B Prompt B4 (`.npmrc` migration — needs `gitea.bytelyst.com` live)
|
||||
> **Reference docs:**
|
||||
>
|
||||
> - [`SECURE_API_EXPOSURE.md`](../single_azure_vm/docker/SECURE_API_EXPOSURE.md) — Caddy decision + architecture
|
||||
> - [`DEPLOYMENT_STATUS_2026-03-29.md`](../single_azure_vm/docker/DEPLOYMENT_STATUS_2026-03-29.md) — current VM status
|
||||
> - [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) — full Vercel audit
|
||||
|
||||
---
|
||||
|
||||
## Progress Tracker
|
||||
|
||||
| # | Prompt | Status | Commit SHA | Verified |
|
||||
| --- | ------------------------ | :------------: | :--------: | :------: |
|
||||
| A1 | Caddy Gateway Setup | ⬜ Not started | — | ⬜ |
|
||||
| A2 | Gitea HTTPS Exposure | ⬜ Not started | — | ⬜ |
|
||||
| A3 | Dashboard Containers Fix | ⬜ Not started | — | ⬜ |
|
||||
| A4 | NSG Lockdown | ⬜ Not started | — | ⬜ |
|
||||
|
||||
**Execution order:**
|
||||
|
||||
```
|
||||
A1: Caddy Gateway ──→ A2: Gitea HTTPS ──→ A4: NSG Lockdown
|
||||
└──→ A3: Dashboard Fix (parallel with A2)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DNS Prerequisites (manual — do before starting)
|
||||
|
||||
These DNS records must exist before Caddy can obtain Let's Encrypt certificates:
|
||||
|
||||
| Record | Type | Value | Purpose |
|
||||
| ---------------------- | ---- | ---------------------- | ------------------- |
|
||||
| `api.bytelyst.com` | A | `<Azure VM public IP>` | Backend API gateway |
|
||||
| `gitea.bytelyst.com` | A | `<Azure VM public IP>` | Gitea npm registry |
|
||||
| `admin.bytelyst.com` | A | `<Azure VM public IP>` | Admin dashboard |
|
||||
| `tracker.bytelyst.com` | A | `<Azure VM public IP>` | Tracker dashboard |
|
||||
|
||||
**Verify DNS before starting A1:**
|
||||
|
||||
```bash
|
||||
dig +short api.bytelyst.com # must return VM IP
|
||||
dig +short gitea.bytelyst.com # must return VM IP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## A1: Caddy Gateway — Replace Traefik with Caddy
|
||||
|
||||
> **Depends on:** Nothing
|
||||
> **Depends on:** DNS records for `api.bytelyst.com`
|
||||
> **Blocks:** A2, A3, A4
|
||||
|
||||
### Preconditions
|
||||
|
||||
- [ ] `api.bytelyst.com` DNS A record resolves to Azure VM IP
|
||||
- [ ] All 13 backend services are healthy: `docker compose ps | grep -c healthy` → 13+
|
||||
- [ ] Ports 80 and 443 are open in Azure NSG
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
|
||||
|
||||
@ -18,34 +69,66 @@ TASK: Replace the existing Traefik gateway container with Caddy to provide HTTPS
|
||||
|
||||
CONTEXT:
|
||||
- The decision doc is at docs/devops/single_azure_vm/docker/SECURE_API_EXPOSURE.md in the learning_ai_common_plat repo
|
||||
- The domain is bytelyst.com
|
||||
- The domain is bytelyst.com — DNS A records already point to this VM
|
||||
- API hostname: api.bytelyst.com
|
||||
- Currently 13 backend services are healthy on ports 4003, 4005, 4007, 4010-4019
|
||||
- Traefik is running but only as a passthrough — no TLS, no path routing hardened
|
||||
- All backend containers are on a Docker network
|
||||
|
||||
DELIVERABLES:
|
||||
1. Create a Caddyfile with:
|
||||
TASK LIST:
|
||||
- [ ] 1. Create a Caddyfile at /opt/bytelyst/Caddyfile with:
|
||||
- api.bytelyst.com as the main host (automatic Let's Encrypt TLS)
|
||||
- Path-based routing to all 13 backends:
|
||||
/platform/* → platform-service:4003
|
||||
/extraction/* → extraction-service:4005
|
||||
/mcp/* → mcp-server:4007
|
||||
/peakpulse/* → peakpulse:4010
|
||||
/chronomind/* → chronomind:4011
|
||||
/jarvisjr/* → jarvisjr:4012
|
||||
/nomgap/* → nomgap:4013
|
||||
/mindlyst/* → mindlyst:4014
|
||||
/lysnrai/* → lysnrai:4015
|
||||
/notelett/* → notelett:4016
|
||||
/flowmonk/* → flowmonk:4017
|
||||
/platform/* → platform-service:4003
|
||||
/extraction/* → extraction-service:4005
|
||||
/mcp/* → mcp-server:4007
|
||||
/peakpulse/* → peakpulse:4010
|
||||
/chronomind/* → chronomind:4011
|
||||
/jarvisjr/* → jarvisjr:4012
|
||||
/nomgap/* → nomgap:4013
|
||||
/mindlyst/* → mindlyst:4014
|
||||
/lysnrai/* → lysnrai:4015
|
||||
/notelett/* → notelett:4016
|
||||
/flowmonk/* → flowmonk:4017
|
||||
/actiontrail/* → actiontrail:4018
|
||||
/localmemgpt/* → localmemgpt:4019
|
||||
- Strip the path prefix before forwarding (backends expect / not /platform/)
|
||||
2. Add a caddy service to docker-compose replacing or alongside the gateway service
|
||||
3. Stop publishing backend ports (4003, 4005, 4007, 4010-4019) publicly — only expose 80/443
|
||||
4. Verify all 13 backends respond via https://api.bytelyst.com/<service>/health
|
||||
5. Update docs/devops/single_azure_vm/docker/README.md with the new access model
|
||||
- [ ] 2. Add a caddy service to docker-compose replacing or alongside the gateway service
|
||||
- Image: caddy:2-alpine
|
||||
- Volumes: ./Caddyfile:/etc/caddy/Caddyfile, caddy_data:/data, caddy_config:/config
|
||||
- Ports: 80:80, 443:443
|
||||
- Network: same Docker network as all backends
|
||||
- [ ] 3. Remove published backend ports from docker-compose (4003, 4005, 4007, 4010-4019)
|
||||
— backends remain accessible internally via Docker DNS
|
||||
- [ ] 4. Restart the stack: docker compose up -d
|
||||
- [ ] 5. Wait for Caddy to obtain TLS certificates (check logs: docker logs caddy --tail 50)
|
||||
- [ ] 6. Update docs/devops/single_azure_vm/docker/README.md with the new access model
|
||||
|
||||
VERIFICATION (run all — every check must pass):
|
||||
# TLS certificate obtained
|
||||
curl -sI https://api.bytelyst.com/platform/health | head -5
|
||||
# Expected: HTTP/2 200 + valid TLS
|
||||
|
||||
# All 13 backends reachable via path routing
|
||||
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
|
||||
# Expected: all 13 print "ok"
|
||||
|
||||
# Direct port access blocked from outside
|
||||
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:4003/health && echo "FAIL: port still open" || echo "PASS: port closed"
|
||||
# Expected: "PASS: port closed"
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- All 13 health checks return "ok" via https://api.bytelyst.com/<service>/health
|
||||
- TLS certificate is valid (Let's Encrypt)
|
||||
- No backend ports (4003-4019) accessible directly from public internet
|
||||
- Traefik config preserved but not in use
|
||||
|
||||
ROLLBACK:
|
||||
If Caddy fails, revert docker-compose changes and restart Traefik:
|
||||
git checkout -- docker-compose*.yml
|
||||
docker compose up -d
|
||||
|
||||
DO NOT:
|
||||
- Delete the existing Traefik config — just stop using it
|
||||
@ -59,8 +142,16 @@ COMMIT: feat(gateway): replace Traefik with Caddy for HTTPS path routing
|
||||
|
||||
## A2: Gitea HTTPS Exposure via Caddy
|
||||
|
||||
> **Depends on:** A1 (Caddy must be running)
|
||||
> **Blocks:** Track B Prompt B4
|
||||
> **Depends on:** A1 ✅ (Caddy running + TLS working)
|
||||
> **Blocks:** Track B → B4 (`.npmrc` update across all repos)
|
||||
|
||||
### Preconditions
|
||||
|
||||
- [ ] A1 is complete — Caddy is running with valid TLS on `api.bytelyst.com`
|
||||
- [ ] `gitea.bytelyst.com` DNS A record resolves to Azure VM IP
|
||||
- [ ] Gitea container is running: `docker compose ps gitea` → healthy
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
|
||||
@ -69,66 +160,144 @@ TASK: Expose the Gitea npm registry over HTTPS via the Caddy gateway so that ext
|
||||
|
||||
CONTEXT:
|
||||
- Gitea is running on port 3300 inside the Docker network
|
||||
- Caddy is already configured for api.bytelyst.com (from A1)
|
||||
- Caddy is already configured for api.bytelyst.com (from A1) and has valid TLS
|
||||
- The Gitea npm registry URL pattern is: /api/packages/ByteLyst/npm/
|
||||
- Gitea needs its own subdomain because its internal routing expects to be at root
|
||||
- Target URL: https://gitea.bytelyst.com
|
||||
|
||||
DELIVERABLES:
|
||||
1. Add a gitea.bytelyst.com block to the Caddyfile:
|
||||
gitea.bytelyst.com {
|
||||
reverse_proxy gitea:3300
|
||||
}
|
||||
2. Ensure Gitea's ROOT_URL / SERVER__ROOT_URL is updated to https://gitea.bytelyst.com
|
||||
3. Verify https://gitea.bytelyst.com loads the Gitea web UI
|
||||
4. Verify npm registry is accessible:
|
||||
curl -s https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | head
|
||||
5. Remove port 3300 from public NSG rules (Gitea only accessible via Caddy now)
|
||||
6. Lock down other operational ports from public access where possible:
|
||||
- 8025 (Mailpit)
|
||||
- 8080 (Traefik dashboard — no longer needed)
|
||||
- 10000 (Azurite)
|
||||
TASK LIST:
|
||||
- [ ] 1. Add a gitea.bytelyst.com block to the Caddyfile:
|
||||
gitea.bytelyst.com {
|
||||
reverse_proxy gitea:3300
|
||||
}
|
||||
- [ ] 2. Reload Caddy: docker exec caddy caddy reload --config /etc/caddy/Caddyfile
|
||||
- [ ] 3. Update Gitea's ROOT_URL to https://gitea.bytelyst.com
|
||||
— Edit docker-compose env: SERVER__ROOT_URL=https://gitea.bytelyst.com
|
||||
— Restart Gitea container: docker compose restart gitea
|
||||
- [ ] 4. Remove port 3300 from docker-compose published ports (Gitea only via Caddy)
|
||||
- [ ] 5. Remove stale public NSG rules for ports that should not be exposed:
|
||||
- 3300 (Gitea)
|
||||
- 8025 (Mailpit)
|
||||
- 8080 (Traefik dashboard — no longer needed)
|
||||
- 10000 (Azurite)
|
||||
|
||||
VERIFICATION (run all — every check must pass):
|
||||
# Gitea web UI loads
|
||||
curl -sI https://gitea.bytelyst.com | head -3
|
||||
# Expected: HTTP/2 200 (or 302 redirect to login)
|
||||
|
||||
# npm registry returns package metadata
|
||||
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
|
||||
# Expected: "@bytelyst/errors"
|
||||
|
||||
# Authenticated npm install works
|
||||
export GITEA_NPM_TOKEN=<token>
|
||||
npm view @bytelyst/errors --registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||
# Expected: package info printed (version, description, etc.)
|
||||
|
||||
# Direct port 3300 access blocked from outside
|
||||
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:3300 && echo "FAIL" || echo "PASS: port closed"
|
||||
# Expected: "PASS: port closed"
|
||||
|
||||
# Internal Docker access still works
|
||||
docker exec platform-service curl -sf http://gitea:3300/api/v1/version | jq '.version'
|
||||
# Expected: Gitea version string
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- https://gitea.bytelyst.com serves Gitea web UI with valid TLS
|
||||
- npm registry API returns valid package metadata
|
||||
- Authenticated `npm view` succeeds
|
||||
- Port 3300 not accessible from public internet
|
||||
- Docker-internal access to gitea:3300 still works (other containers unaffected)
|
||||
|
||||
DO NOT:
|
||||
- Break existing Docker-internal Gitea access (other containers still use gitea:3300)
|
||||
- Remove the Gitea container or change its internal port
|
||||
|
||||
COMMIT: feat(gateway): expose Gitea npm registry via HTTPS at gitea.bytelyst.com
|
||||
|
||||
AFTER COMPLETING: Notify the operator that Track B → B4 (.npmrc migration) is now unblocked.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## A3: Fix admin-web and tracker-web Containers
|
||||
|
||||
> **Depends on:** A1 (Caddy gateway for subdomain routing)
|
||||
> **Blocks:** Nothing
|
||||
> **Depends on:** A1 ✅ (Caddy running for subdomain routing)
|
||||
> **Blocks:** Nothing (independent of Track B)
|
||||
> **Can run in parallel with:** A2
|
||||
|
||||
### Preconditions
|
||||
|
||||
- [ ] A1 is complete — Caddy is running
|
||||
- [ ] `admin.bytelyst.com` and `tracker.bytelyst.com` DNS A records resolve to VM IP
|
||||
- [ ] Source code for dashboards is available on the VM
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
|
||||
|
||||
TASK: Resolve the remaining admin-web and tracker-web containers so they are running and healthy.
|
||||
TASK: Resolve the remaining admin-web and tracker-web containers so they are running and healthy, then expose them via Caddy.
|
||||
|
||||
CONTEXT:
|
||||
- Per DEPLOYMENT_STATUS_2026-03-29.md, all 13 backend services are healthy
|
||||
- admin-web and tracker-web are the two remaining unresolved containers
|
||||
- Both are Next.js 16 apps from the learning_ai_common_plat repo under dashboards/
|
||||
- admin-web and tracker-web are the two remaining UNRESOLVED containers
|
||||
- Both are Next.js 16 apps from learning_ai_common_plat under dashboards/
|
||||
- Both use workspace:* dependencies resolved by pnpm
|
||||
- Both use the --webpack build flag
|
||||
- admin-web runs on port 3001, tracker-web on port 3003
|
||||
- The Docker build context is dashboards/admin-web/ and dashboards/tracker-web/
|
||||
- admin-web port: 3001, tracker-web port: 3003
|
||||
- Docker build context: dashboards/admin-web/ and dashboards/tracker-web/
|
||||
|
||||
DELIVERABLES:
|
||||
1. Diagnose why admin-web and tracker-web builds failed
|
||||
2. Fix the build issues (likely @bytelyst/* package resolution or standalone entrypoint)
|
||||
3. Rebuild and start both containers
|
||||
4. Verify health:
|
||||
curl -s http://127.0.0.1:3001 | head
|
||||
curl -s http://127.0.0.1:3003 | head
|
||||
5. Add Caddy routes for the dashboards:
|
||||
- https://admin.bytelyst.com → admin-web:3001
|
||||
- https://tracker.bytelyst.com → tracker-web:3003
|
||||
6. Update DEPLOYMENT_STATUS_2026-03-29.md to reflect the fix
|
||||
7. Mark Phase 7 as DONE if all services are now healthy
|
||||
TASK LIST:
|
||||
- [ ] 1. Check current container status:
|
||||
docker compose ps admin-web tracker-web
|
||||
docker compose logs admin-web --tail 100
|
||||
docker compose logs tracker-web --tail 100
|
||||
- [ ] 2. Diagnose the build/runtime failure (likely causes):
|
||||
- @bytelyst/* package resolution — may need .docker-deps/ tarballs
|
||||
- Standalone entrypoint not found
|
||||
- Missing env vars (COSMOS_ENDPOINT, COSMOS_KEY, JWT_SECRET)
|
||||
- [ ] 3. Fix the identified issues
|
||||
- [ ] 4. Rebuild and restart:
|
||||
docker compose up -d --build admin-web tracker-web
|
||||
- [ ] 5. Add Caddy routes for the dashboards to the Caddyfile:
|
||||
admin.bytelyst.com {
|
||||
reverse_proxy admin-web:3001
|
||||
}
|
||||
tracker.bytelyst.com {
|
||||
reverse_proxy tracker-web:3003
|
||||
}
|
||||
- [ ] 6. Reload Caddy: docker exec caddy caddy reload --config /etc/caddy/Caddyfile
|
||||
- [ ] 7. Update DEPLOYMENT_STATUS_2026-03-29.md to reflect the fix
|
||||
|
||||
VERIFICATION (run all — every check must pass):
|
||||
# Containers healthy
|
||||
docker compose ps admin-web tracker-web
|
||||
# Expected: both show "Up" and "healthy" (or at least "Up")
|
||||
|
||||
# Local port access
|
||||
curl -sf http://127.0.0.1:3001 | head -5
|
||||
curl -sf http://127.0.0.1:3003 | head -5
|
||||
# Expected: HTML response from each
|
||||
|
||||
# HTTPS via Caddy
|
||||
curl -sI https://admin.bytelyst.com | head -3
|
||||
# Expected: HTTP/2 200 (or 302)
|
||||
|
||||
curl -sI https://tracker.bytelyst.com | head -3
|
||||
# Expected: HTTP/2 200 (or 302)
|
||||
|
||||
# All containers now healthy
|
||||
docker compose ps | grep -E "(unhealthy|Exit)" | wc -l
|
||||
# Expected: 0
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- Both admin-web and tracker-web containers are running
|
||||
- Both respond on their ports (3001, 3003)
|
||||
- Both accessible via HTTPS at admin.bytelyst.com and tracker.bytelyst.com
|
||||
- DEPLOYMENT_STATUS doc updated with fix details
|
||||
- Zero unhealthy containers in the full stack
|
||||
|
||||
COMMIT: fix(deployment): resolve admin-web and tracker-web containers
|
||||
```
|
||||
@ -137,41 +306,126 @@ COMMIT: fix(deployment): resolve admin-web and tracker-web containers
|
||||
|
||||
## A4: NSG Lockdown — Reduce Public Port Exposure
|
||||
|
||||
> **Depends on:** A1 + A2 (Caddy handling all traffic)
|
||||
> **Depends on:** A1 + A2 + A3 all complete (all traffic routed through Caddy)
|
||||
> **Blocks:** Nothing
|
||||
> **Run this LAST in Track A**
|
||||
|
||||
### Preconditions
|
||||
|
||||
- [ ] A1 complete — all backends accessible via `api.bytelyst.com`
|
||||
- [ ] A2 complete — Gitea accessible via `gitea.bytelyst.com`
|
||||
- [ ] A3 complete — dashboards accessible via `admin.bytelyst.com` and `tracker.bytelyst.com`
|
||||
- [ ] All services verified working through Caddy (no direct port access needed)
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
TASK: Reduce the Azure NSG (Network Security Group) rules so only ports 80, 443, and 22 are publicly accessible.
|
||||
|
||||
CONTEXT:
|
||||
- The Azure VM currently exposes many service ports publicly (3000-3300, 4003-4019, 8025, 8080, 10000, 11434)
|
||||
- Caddy now handles all public HTTPS traffic on 80/443
|
||||
- Backend services, Gitea, Grafana, Mailpit, and Azurite are all accessed through Caddy
|
||||
- Caddy now handles ALL public HTTPS traffic on ports 80/443
|
||||
- All services (backends, Gitea, dashboards, monitoring) are accessed through Caddy subdomains
|
||||
- Only SSH (22) and HTTP/HTTPS (80/443) should remain publicly open
|
||||
- This follows the recommendation in SECURE_API_EXPOSURE.md
|
||||
|
||||
DELIVERABLES:
|
||||
1. List current NSG rules: az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table
|
||||
2. Remove or deny inbound rules for all ports except 22, 80, 443
|
||||
3. Verify Caddy still serves all routes correctly
|
||||
4. Verify SSH access still works
|
||||
5. Document the changes in DEPLOYMENT_STATUS_2026-03-29.md
|
||||
TASK LIST:
|
||||
- [ ] 1. Snapshot current NSG rules (save output for rollback reference):
|
||||
az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table > /opt/bytelyst/nsg-rules-before.txt
|
||||
cat /opt/bytelyst/nsg-rules-before.txt
|
||||
- [ ] 2. Identify rules to remove — everything except:
|
||||
- SSH (22/tcp)
|
||||
- HTTP (80/tcp)
|
||||
- HTTPS (443/tcp)
|
||||
- [ ] 3. Delete each unnecessary rule:
|
||||
az network nsg rule delete --resource-group <rg> --nsg-name <nsg> --name <rule-name>
|
||||
- [ ] 4. List final NSG rules to confirm only 3 remain:
|
||||
az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table
|
||||
- [ ] 5. Document changes in DEPLOYMENT_STATUS_2026-03-29.md
|
||||
|
||||
VERIFICATION (run all — every check must pass):
|
||||
# SSH still works
|
||||
ssh -o ConnectTimeout=5 <user>@<VM_IP> echo "SSH OK"
|
||||
# Expected: "SSH OK"
|
||||
|
||||
# Caddy still serves all routes
|
||||
curl -sf https://api.bytelyst.com/platform/health | jq '.status'
|
||||
# Expected: "ok"
|
||||
|
||||
curl -sf https://gitea.bytelyst.com/api/v1/version | jq '.version'
|
||||
# Expected: version string
|
||||
|
||||
curl -sI https://admin.bytelyst.com | head -1
|
||||
# Expected: HTTP/2 200 (or 302)
|
||||
|
||||
# Direct port access blocked
|
||||
for port in 3001 3003 3300 4003 4005 8025 8080 10000; do
|
||||
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:$port && echo "FAIL: $port open" || echo "PASS: $port closed"
|
||||
done
|
||||
# Expected: all "PASS: <port> closed"
|
||||
|
||||
# Only 3 NSG rules remain
|
||||
az network nsg rule list --resource-group <rg> --nsg-name <nsg> -o table | grep -c Allow
|
||||
# Expected: 3 (SSH, HTTP, HTTPS)
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- Only ports 22, 80, 443 open in NSG
|
||||
- SSH access confirmed working
|
||||
- All Caddy routes still functional
|
||||
- No direct port access possible from public internet
|
||||
- Before/after NSG snapshots saved
|
||||
|
||||
ROLLBACK:
|
||||
If services become unreachable after lockdown:
|
||||
# Re-add a rule temporarily
|
||||
az network nsg rule create --resource-group <rg> --nsg-name <nsg> \
|
||||
--name AllowTemp --priority 200 --access Allow --direction Inbound \
|
||||
--source-address-prefixes '*' --destination-port-ranges <port> --protocol Tcp
|
||||
# Then investigate Caddy routing
|
||||
|
||||
DO NOT:
|
||||
- Remove the SSH (22) rule
|
||||
- Remove the HTTP (80) or HTTPS (443) rules
|
||||
- Make changes without first listing the current rules
|
||||
- Remove the SSH (22) rule — you will lose access
|
||||
- Remove the HTTP (80) or HTTPS (443) rules — Caddy needs them
|
||||
- Make changes without first saving the current rules snapshot
|
||||
|
||||
COMMIT: chore(security): lock down Azure NSG to 22/80/443 only
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Track A Execution Order
|
||||
## Track A — Final Verification Checklist
|
||||
|
||||
```
|
||||
A1: Caddy Gateway ──→ A2: Gitea HTTPS ──→ A4: NSG Lockdown
|
||||
└──→ A3: Dashboards Fix
|
||||
After all 4 prompts are complete, run this full end-to-end verification:
|
||||
|
||||
```bash
|
||||
echo "=== Track A Final Verification ==="
|
||||
|
||||
echo "--- DNS ---"
|
||||
for d in api.bytelyst.com gitea.bytelyst.com admin.bytelyst.com tracker.bytelyst.com; do
|
||||
echo -n "$d → "; dig +short $d
|
||||
done
|
||||
|
||||
echo "--- Backend Health (13 services) ---"
|
||||
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
|
||||
|
||||
echo "--- Gitea npm registry ---"
|
||||
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
|
||||
|
||||
echo "--- Dashboards ---"
|
||||
curl -sI https://admin.bytelyst.com | head -1
|
||||
curl -sI https://tracker.bytelyst.com | head -1
|
||||
|
||||
echo "--- Port lockdown ---"
|
||||
for port in 3001 3003 3300 4003 4005 8025 8080 10000; do
|
||||
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:$port > /dev/null 2>&1 && echo "FAIL: $port open" || echo "PASS: $port closed"
|
||||
done
|
||||
|
||||
echo "--- Docker containers ---"
|
||||
docker compose ps --format 'table {{.Name}}\t{{.Status}}' | grep -E "(unhealthy|Exit)" | wc -l
|
||||
# Expected: 0
|
||||
```
|
||||
|
||||
A3 can run in parallel with A2. A4 runs last after everything is routed through Caddy.
|
||||
**All checks must pass before Track A is considered complete.**
|
||||
Once A2 verification passes, signal to Track B that Prompt B4 is unblocked.
|
||||
|
||||
@ -2,6 +2,29 @@
|
||||
|
||||
> **Agent:** Any Codex agent with repo access (local or cloud)
|
||||
> **Prompts:** 4 (B1–B3 run in parallel, B4 runs last after Track A completes A2)
|
||||
> **Reference docs:**
|
||||
>
|
||||
> - [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) — full Vercel audit + per-app status
|
||||
> - Individual `ROADMAP_*.md` files — per-app gaps, env vars, and deployment steps
|
||||
|
||||
---
|
||||
|
||||
## Progress Tracker
|
||||
|
||||
| # | Prompt | Repos | Status | Commits | Verified |
|
||||
| --- | ------------------------ | :---: | :--------------: | :-----: | :------: |
|
||||
| B1 | Fix `file:` refs | 7 | ⬜ Not started | 0/7 | ⬜ |
|
||||
| B2 | Fix `output: standalone` | 4 | ⬜ Not started | 0/4 | ⬜ |
|
||||
| B3 | EffoRise `vercel.json` | 1 | ⬜ Not started | 0/1 | ⬜ |
|
||||
| B4 | Update `.npmrc` | 12 | ⬜ Blocked on A2 | 0/12 | ⬜ |
|
||||
|
||||
**Execution order:**
|
||||
|
||||
```
|
||||
B1: Fix file: refs ──────┐
|
||||
B2: Fix standalone ──────┼──→ B4: Update .npmrc (blocked until Track A → A2 done)
|
||||
B3: EffoRise vercel.json ┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -10,15 +33,28 @@
|
||||
> **Depends on:** Nothing (packages are already published to Gitea)
|
||||
> **Blocks:** Nothing
|
||||
|
||||
### Per-Repo Checklist
|
||||
|
||||
| # | Repo | File | Packages to fix | Edited | Built | Committed | Pushed |
|
||||
| --- | ------------------------------ | ------------------------ | ----------------- | :----: | :---: | :-------: | :----: |
|
||||
| 1 | `learning_ai_clock` | `web/package.json` | design-tokens, ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 2 | `learning_ai_jarvis_jr` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 3 | `learning_ai_fastgap` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 4 | `learning_ai_flowmonk` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 5 | `learning_ai_notes` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 6 | `learning_ai_local_memory_gpt` | `web/package.json` | ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 7 | `learning_ai_local_llms` | `dashboard/package.json` | design-tokens, ui | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
TASK: Convert all file: references to @bytelyst/* packages into semver ^0.1.0 references across 7 web app repos.
|
||||
|
||||
CONTEXT:
|
||||
- 7 repos have web/package.json files that use file: references to ../../learning_ai_common_plat/packages/*
|
||||
- These fail on Vercel because the sibling repo doesn't exist
|
||||
- 7 repos have web/package.json (or dashboard/package.json) files with file: references to ../../learning_ai_common_plat/packages/*
|
||||
- These fail on Vercel because the sibling repo doesn't exist during build
|
||||
- The packages are already published to the Gitea npm registry
|
||||
- Each fix is: change "file:../../learning_ai_common_plat/packages/X" to "^0.1.0"
|
||||
- After changing, run pnpm install to update the lockfile, then verify pnpm build passes
|
||||
- Each fix: change "file:../../learning_ai_common_plat/packages/X" to "^0.1.0"
|
||||
|
||||
REPOS AND FILES TO FIX:
|
||||
|
||||
@ -45,17 +81,35 @@ REPOS AND FILES TO FIX:
|
||||
- "@bytelyst/design-tokens": "file:..." → "^0.1.0"
|
||||
- "@bytelyst/ui": "file:..." → "^0.1.0"
|
||||
|
||||
FOR EACH REPO:
|
||||
1. Edit the package.json — replace file: refs with ^0.1.0
|
||||
2. Run: cd web && pnpm install (or cd dashboard for LLM Lab)
|
||||
3. Run: pnpm build
|
||||
4. If build passes, commit: fix(web): convert file: refs to registry semver for Vercel compatibility
|
||||
5. Push to origin main
|
||||
FOR EACH REPO (repeat 7 times):
|
||||
- [ ] 1. Edit the package.json — replace file: refs with ^0.1.0
|
||||
- [ ] 2. Run: cd web && pnpm install (or cd dashboard for LLM Lab)
|
||||
- [ ] 3. Verify no file: refs remain: grep -r "file:.*common_plat" package.json
|
||||
Expected: no output
|
||||
- [ ] 4. Run: pnpm build
|
||||
Expected: build succeeds with exit code 0
|
||||
- [ ] 5. Commit: fix(web): convert file: refs to registry semver for Vercel compatibility
|
||||
- [ ] 6. Push to origin main
|
||||
|
||||
VERIFICATION (after all 7 repos):
|
||||
# Confirm zero file: refs remain across all repos
|
||||
for repo in learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_local_memory_gpt learning_ai_local_llms; do
|
||||
echo -n "$repo: "
|
||||
grep -rl "file:.*common_plat" $repo/web/package.json $repo/dashboard/package.json 2>/dev/null | wc -l | tr -d ' '
|
||||
echo " file: refs remaining"
|
||||
done
|
||||
# Expected: all show "0 file: refs remaining"
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- All 7 repos have zero file: references in their web/dashboard package.json
|
||||
- All 7 builds pass (pnpm build exits 0)
|
||||
- All 7 commits pushed to origin main
|
||||
- No other dependencies or source code modified
|
||||
|
||||
DO NOT:
|
||||
- Change any other dependencies
|
||||
- Modify any source code
|
||||
- Skip the build verification step
|
||||
- Skip the build verification step for any repo
|
||||
```
|
||||
|
||||
---
|
||||
@ -65,16 +119,28 @@ DO NOT:
|
||||
> **Depends on:** Nothing
|
||||
> **Blocks:** Nothing
|
||||
|
||||
### Per-Repo Checklist
|
||||
|
||||
| # | Repo | File | Pattern | Edited | Docker Build | Vercel Build | Committed | Pushed |
|
||||
| --- | ------------------------------ | -------------------- | --------------------- | :----: | :----------: | :----------: | :-------: | :----: |
|
||||
| 1 | `learning_ai_fastgap` | `web/next.config.ts` | output + tracing root | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 2 | `learning_ai_notes` | `web/next.config.ts` | output + tracing root | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 3 | `learning_ai_trails` | `web/next.config.ts` | output only | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 4 | `learning_ai_local_memory_gpt` | `web/next.config.ts` | output only | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
|
||||
> **Skip:** `learning_ai_local_llms/dashboard/next.config.ts` — LLM Lab not viable on Vercel (needs local Ollama)
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
TASK: Make the Next.js output mode Vercel-aware in 4 repos that currently hardcode output: 'standalone'.
|
||||
|
||||
CONTEXT:
|
||||
- Vercel manages its own output mode — hardcoded standalone breaks Vercel builds
|
||||
- The fix is: wrap standalone output in a process.env.VERCEL conditional
|
||||
- The fix: wrap standalone output in a process.env.VERCEL conditional
|
||||
- Docker builds (which don't set VERCEL env var) will still get standalone mode
|
||||
- 4 repos need this fix
|
||||
|
||||
REPOS AND FILES:
|
||||
REPOS AND EXACT CHANGES:
|
||||
|
||||
1. learning_ai_fastgap/web/next.config.ts
|
||||
Change:
|
||||
@ -87,7 +153,7 @@ REPOS AND FILES:
|
||||
}),
|
||||
|
||||
2. learning_ai_notes/web/next.config.ts
|
||||
Same pattern as above.
|
||||
Same pattern as #1 (output + outputFileTracingRoot).
|
||||
|
||||
3. learning_ai_trails/web/next.config.ts
|
||||
Change:
|
||||
@ -96,16 +162,36 @@ REPOS AND FILES:
|
||||
...(process.env.VERCEL ? {} : { output: 'standalone' }),
|
||||
|
||||
4. learning_ai_local_memory_gpt/web/next.config.ts
|
||||
Same pattern as #3.
|
||||
Same pattern as #3 (output only).
|
||||
|
||||
NOTE: learning_ai_local_llms/dashboard/next.config.ts also has this but LLM Lab is NOT viable on Vercel (needs local Ollama), so skip it.
|
||||
FOR EACH REPO (repeat 4 times):
|
||||
- [ ] 1. Edit next.config.ts with the VERCEL conditional
|
||||
- [ ] 2. Verify Docker build still works (standalone activates without VERCEL env):
|
||||
cd web && pnpm build
|
||||
# Check output: look for "Creating an optimized production build" + ".next/standalone/" dir
|
||||
ls -d .next/standalone/ && echo "PASS: standalone created" || echo "FAIL"
|
||||
- [ ] 3. Verify Vercel-mode build works (standalone skipped with VERCEL env):
|
||||
cd web && VERCEL=1 pnpm build
|
||||
# Check output: .next/standalone/ should NOT exist
|
||||
ls -d .next/standalone/ 2>/dev/null && echo "FAIL: standalone still created" || echo "PASS: no standalone"
|
||||
- [ ] 4. Commit: fix(web): make output mode Vercel-aware — conditional standalone
|
||||
- [ ] 5. Push to origin main
|
||||
|
||||
FOR EACH REPO:
|
||||
1. Edit next.config.ts with the conditional
|
||||
2. Verify Docker build still works: pnpm build (standalone should still activate without VERCEL env)
|
||||
3. Verify VERCEL=1 pnpm build also works (output should be default, not standalone)
|
||||
4. Commit: fix(web): make output mode Vercel-aware — conditional standalone
|
||||
5. Push to origin main
|
||||
VERIFICATION (after all 4 repos):
|
||||
for repo in learning_ai_fastgap learning_ai_notes learning_ai_trails learning_ai_local_memory_gpt; do
|
||||
echo "=== $repo ==="
|
||||
cd $repo/web
|
||||
grep -c "process.env.VERCEL" next.config.ts
|
||||
# Expected: 1 (the conditional)
|
||||
cd ../..
|
||||
done
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- All 4 next.config.ts files contain process.env.VERCEL conditional
|
||||
- Docker build (no VERCEL env) produces .next/standalone/
|
||||
- Vercel build (VERCEL=1) does NOT produce .next/standalone/
|
||||
- All 4 commits pushed to origin main
|
||||
- No other config options changed
|
||||
|
||||
DO NOT:
|
||||
- Change any other config options in next.config.ts
|
||||
@ -120,33 +206,63 @@ DO NOT:
|
||||
> **Depends on:** Nothing
|
||||
> **Blocks:** Nothing
|
||||
|
||||
### Checklist
|
||||
|
||||
| Step | Description | Done |
|
||||
| ---- | ------------------------- | :--: |
|
||||
| 1 | Create `vercel.json` | ⬜ |
|
||||
| 2 | Verify local build | ⬜ |
|
||||
| 3 | Verify SPA routing config | ⬜ |
|
||||
| 4 | Commit + push | ⬜ |
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
TASK: Create a vercel.json file for the EffoRise Vite SPA to handle client-side routing and API proxy configuration.
|
||||
|
||||
CONTEXT:
|
||||
- EffoRise is a Vite + React 19 SPA (not Next.js) in the learning_ai_efforise repo
|
||||
- The Vite config is at the repo root (vite.config.ts)
|
||||
- EffoRise is a Vite + React 19 SPA (NOT Next.js) in the learning_ai_efforise repo
|
||||
- The Vite config is at the repo root (client/ directory has the SPA)
|
||||
- Build output goes to dist/public/ (custom, not default dist/)
|
||||
- Uses wouter for client-side routing — all routes must serve index.html
|
||||
- The backend API is at https://api.bytelyst.com/efforise
|
||||
- Currently uses a dev proxy /api → localhost:4020
|
||||
|
||||
DELIVERABLES:
|
||||
1. Create vercel.json at the repo root with:
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"framework": "vite",
|
||||
"buildCommand": "pnpm build",
|
||||
"outputDirectory": "dist/public",
|
||||
"rewrites": [
|
||||
{ "source": "/api/(.*)", "destination": "https://api.bytelyst.com/efforise/$1" },
|
||||
{ "source": "/(.*)", "destination": "/index.html" }
|
||||
]
|
||||
}
|
||||
TASK LIST:
|
||||
- [ ] 1. Create client/vercel.json with:
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"framework": "vite",
|
||||
"buildCommand": "pnpm build",
|
||||
"outputDirectory": "dist/public",
|
||||
"rewrites": [
|
||||
{ "source": "/api/(.*)", "destination": "https://api.bytelyst.com/efforise/$1" },
|
||||
{ "source": "/(.*)", "destination": "/index.html" }
|
||||
]
|
||||
}
|
||||
- [ ] 2. Verify local build: cd client && pnpm build
|
||||
Expected: exit code 0, dist/public/index.html exists
|
||||
- [ ] 3. Verify vercel.json is valid JSON: cat client/vercel.json | jq .
|
||||
Expected: formatted JSON output, no parse errors
|
||||
- [ ] 4. Commit: feat(web): add vercel.json for Vite SPA deployment
|
||||
- [ ] 5. Push to origin main
|
||||
|
||||
2. Verify pnpm build still works locally
|
||||
3. Commit: feat(web): add vercel.json for Vite SPA deployment
|
||||
4. Push to origin main
|
||||
VERIFICATION:
|
||||
# Build works
|
||||
cd client && pnpm build && echo "BUILD: PASS" || echo "BUILD: FAIL"
|
||||
|
||||
# Output directory exists
|
||||
ls client/dist/public/index.html && echo "OUTPUT: PASS" || echo "OUTPUT: FAIL"
|
||||
|
||||
# vercel.json valid
|
||||
jq '.rewrites | length' client/vercel.json
|
||||
# Expected: 2
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- client/vercel.json exists with correct framework, build command, output directory, and rewrites
|
||||
- Local build still produces dist/public/index.html
|
||||
- vercel.json is valid JSON
|
||||
- Commit pushed to origin main
|
||||
|
||||
DO NOT:
|
||||
- Modify vite.config.ts
|
||||
@ -158,12 +274,44 @@ DO NOT:
|
||||
|
||||
## B4: Update .npmrc Across All Product Repos
|
||||
|
||||
> **Depends on:** Track A Prompt A2 (gitea.bytelyst.com must be live and accessible)
|
||||
> **Blocks:** Vercel deployment
|
||||
> **Depends on:** Track A → A2 complete (`gitea.bytelyst.com` live + verified)
|
||||
> **Blocks:** All Vercel deployments (this is the final gate)
|
||||
|
||||
### Pre-flight Check (must pass before starting)
|
||||
|
||||
```bash
|
||||
# Verify gitea.bytelyst.com is live and serving packages
|
||||
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
|
||||
# Expected: "@bytelyst/errors"
|
||||
# If this fails, DO NOT proceed — Track A → A2 is not complete
|
||||
```
|
||||
|
||||
### Per-Repo Checklist
|
||||
|
||||
| # | Repo | .npmrc locations | Updated | Install OK | Committed | Pushed |
|
||||
| --- | ----------------------------------- | -------------------------- | :-----: | :--------: | :-------: | :----: |
|
||||
| 1 | `learning_voice_ai_agent` | root, user-dashboard-web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 2 | `learning_ai_clock` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 3 | `learning_ai_jarvis_jr` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 4 | `learning_ai_fastgap` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 5 | `learning_ai_flowmonk` | root, web/, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 6 | `learning_ai_notes` | root, web/, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 7 | `learning_ai_trails` | root, web/, sdk/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 8 | `learning_multimodal_memory_agents` | root, mindlyst-native/web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 9 | `learning_ai_local_memory_gpt` | root, web/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 10 | `learning_ai_efforise` | root, mobile/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 11 | `learning_ai_local_llms` | dashboard/ | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
| 12 | `learning_ai_peakpulse` | root | ⬜ | ⬜ | ⬜ | ⬜ |
|
||||
|
||||
### Prompt
|
||||
|
||||
```
|
||||
TASK: Update .npmrc files in all product repos to point to the public Gitea npm registry at gitea.bytelyst.com.
|
||||
|
||||
PRE-FLIGHT (must pass before starting):
|
||||
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
|
||||
# Must return "@bytelyst/errors" — if not, STOP and report that Track A → A2 is not done
|
||||
|
||||
CONTEXT:
|
||||
- All product repos currently have .npmrc pointing to http://localhost:3300 (local Gitea)
|
||||
- Gitea is now accessible at https://gitea.bytelyst.com via Caddy reverse proxy
|
||||
@ -171,67 +319,126 @@ CONTEXT:
|
||||
- Auth token is passed via GITEA_NPM_TOKEN env var
|
||||
- This change enables Vercel builds to install @bytelyst/* packages
|
||||
|
||||
NEW .npmrc CONTENT (same for all repos):
|
||||
@bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||
//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
|
||||
TARGET .npmrc CONTENT (same for all repos):
|
||||
@bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||
//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
|
||||
|
||||
REPOS TO UPDATE (12 total):
|
||||
REPOS TO UPDATE (12 total — see checklist above for .npmrc locations):
|
||||
|
||||
1. learning_voice_ai_agent (user-dashboard-web, backend)
|
||||
2. learning_ai_clock (web, backend)
|
||||
3. learning_ai_jarvis_jr (web, backend)
|
||||
4. learning_ai_fastgap (web, backend)
|
||||
5. learning_ai_flowmonk (web, backend, mobile)
|
||||
6. learning_ai_notes (web, backend, mobile)
|
||||
7. learning_ai_trails (web, backend, sdk)
|
||||
8. learning_multimodal_memory_agents (mindlyst-native/web, backend)
|
||||
9. learning_ai_local_memory_gpt (web, backend)
|
||||
10. learning_ai_efforise (root, backend, mobile)
|
||||
11. learning_ai_local_llms (dashboard)
|
||||
12. learning_ai_peakpulse (backend)
|
||||
1. learning_voice_ai_agent (root .npmrc + user-dashboard-web/.npmrc)
|
||||
2. learning_ai_clock (root + web/)
|
||||
3. learning_ai_jarvis_jr (root + web/)
|
||||
4. learning_ai_fastgap (root + web/)
|
||||
5. learning_ai_flowmonk (root + web/ + mobile/)
|
||||
6. learning_ai_notes (root + web/ + mobile/)
|
||||
7. learning_ai_trails (root + web/ + sdk/)
|
||||
8. learning_multimodal_memory_agents (root + mindlyst-native/web/)
|
||||
9. learning_ai_local_memory_gpt (root + web/)
|
||||
10. learning_ai_efforise (root + mobile/)
|
||||
11. learning_ai_local_llms (dashboard/)
|
||||
12. learning_ai_peakpulse (root)
|
||||
|
||||
FOR EACH REPO:
|
||||
1. Find all .npmrc files (there may be multiple — root, web/, backend/, mobile/)
|
||||
2. Update the @bytelyst registry line to use gitea.bytelyst.com
|
||||
3. Add the auth token line if not present
|
||||
4. Run: GITEA_NPM_TOKEN=<token> pnpm install (verify packages resolve)
|
||||
5. Commit: chore: update .npmrc to public Gitea registry at gitea.bytelyst.com
|
||||
6. Push to origin main
|
||||
FOR EACH REPO (repeat 12 times):
|
||||
- [ ] 1. Find all .npmrc files: find . -name ".npmrc" -not -path "*/node_modules/*"
|
||||
- [ ] 2. In each .npmrc, replace the @bytelyst registry line:
|
||||
OLD: @bytelyst:registry=http://localhost:3300/api/packages/ByteLyst/npm/
|
||||
NEW: @bytelyst:registry=https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||
- [ ] 3. Ensure the auth token line exists:
|
||||
//gitea.bytelyst.com/api/packages/ByteLyst/npm/:_authToken=${GITEA_NPM_TOKEN}
|
||||
- [ ] 4. Verify no localhost:3300 references remain:
|
||||
grep -r "localhost:3300" . --include=".npmrc"
|
||||
Expected: no output
|
||||
- [ ] 5. Verify packages resolve:
|
||||
GITEA_NPM_TOKEN=<token> pnpm install
|
||||
Expected: exit code 0, all @bytelyst/* packages resolved
|
||||
- [ ] 6. Commit: chore: update .npmrc to public Gitea registry at gitea.bytelyst.com
|
||||
- [ ] 7. Push to origin main
|
||||
|
||||
VERIFICATION:
|
||||
After updating all repos, verify one end-to-end:
|
||||
VERIFICATION (after all 12 repos — run from parent directory containing all repos):
|
||||
echo "=== .npmrc Migration Verification ==="
|
||||
|
||||
# Check no localhost:3300 remains anywhere
|
||||
for repo in learning_voice_ai_agent learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_trails learning_multimodal_memory_agents learning_ai_local_memory_gpt learning_ai_efforise learning_ai_local_llms learning_ai_peakpulse; do
|
||||
count=$(grep -rl "localhost:3300" $repo/ --include=".npmrc" 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "$repo: $count old refs remaining"
|
||||
done
|
||||
# Expected: all show "0 old refs remaining"
|
||||
|
||||
# End-to-end build test on one repo
|
||||
cd learning_ai_clock/web
|
||||
GITEA_NPM_TOKEN=<token> pnpm install
|
||||
pnpm build
|
||||
GITEA_NPM_TOKEN=<token> pnpm install && pnpm build && echo "E2E: PASS" || echo "E2E: FAIL"
|
||||
# Expected: "E2E: PASS"
|
||||
|
||||
SUCCESS CRITERIA:
|
||||
- All 12 repos have zero localhost:3300 references in .npmrc files
|
||||
- All 12 repos can resolve @bytelyst/* packages via gitea.bytelyst.com
|
||||
- At least one repo verified with full pnpm install + pnpm build
|
||||
- All 12 commits pushed to origin main
|
||||
- No package versions changed, no auth tokens hardcoded
|
||||
|
||||
DO NOT:
|
||||
- Change any package versions
|
||||
- Remove any other registry configurations (e.g., npmjs.org for non-@bytelyst packages)
|
||||
- Hardcode the auth token — always use ${GITEA_NPM_TOKEN}
|
||||
- Proceed if the pre-flight check fails
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Track B Execution Order
|
||||
## Track B — Final Verification Checklist
|
||||
|
||||
```
|
||||
B1: Fix file: refs ──────┐
|
||||
B2: Fix standalone ──────┼──→ B4: Update .npmrc (waits for Track A → A2)
|
||||
B3: EffoRise vercel.json ┘
|
||||
After all 4 prompts are complete, verify the full picture:
|
||||
|
||||
```bash
|
||||
echo "=== Track B Final Verification ==="
|
||||
|
||||
echo "--- B1: file: refs (7 repos) ---"
|
||||
for repo in learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_local_memory_gpt learning_ai_local_llms; do
|
||||
count=$(grep -rl "file:.*common_plat" $repo/web/package.json $repo/dashboard/package.json 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "$repo: $count file: refs"
|
||||
done
|
||||
# Expected: all 0
|
||||
|
||||
echo "--- B2: standalone conditional (4 repos) ---"
|
||||
for repo in learning_ai_fastgap learning_ai_notes learning_ai_trails learning_ai_local_memory_gpt; do
|
||||
count=$(grep -c "process.env.VERCEL" $repo/web/next.config.ts 2>/dev/null)
|
||||
echo "$repo: $count VERCEL conditionals"
|
||||
done
|
||||
# Expected: all 1
|
||||
|
||||
echo "--- B3: EffoRise vercel.json ---"
|
||||
jq '.rewrites | length' learning_ai_efforise/client/vercel.json 2>/dev/null
|
||||
# Expected: 2
|
||||
|
||||
echo "--- B4: .npmrc migration (12 repos) ---"
|
||||
for repo in learning_voice_ai_agent learning_ai_clock learning_ai_jarvis_jr learning_ai_fastgap learning_ai_flowmonk learning_ai_notes learning_ai_trails learning_multimodal_memory_agents learning_ai_local_memory_gpt learning_ai_efforise learning_ai_local_llms learning_ai_peakpulse; do
|
||||
count=$(grep -rl "localhost:3300" $repo/ --include=".npmrc" 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "$repo: $count old .npmrc refs"
|
||||
done
|
||||
# Expected: all 0
|
||||
```
|
||||
|
||||
B1, B2, B3 can all run in parallel immediately. B4 must wait until `gitea.bytelyst.com` is live (Track A, Prompt A2).
|
||||
**All checks must pass before Track B is considered complete.**
|
||||
|
||||
---
|
||||
|
||||
## After Both Tracks Complete
|
||||
## After Both Tracks Complete — Vercel Project Setup (Manual)
|
||||
|
||||
```
|
||||
Manual steps (Vercel UI):
|
||||
→ Create Vercel projects for each app
|
||||
→ Set GITEA_NPM_TOKEN + other env vars per project
|
||||
→ Trigger first deploys and verify
|
||||
```
|
||||
Once Track A and Track B are both verified, the remaining work is manual in the Vercel UI:
|
||||
|
||||
See [`ECOSYSTEM_WEB_APPS_INVENTORY.md`](./ECOSYSTEM_WEB_APPS_INVENTORY.md) for the full app list and per-app environment variables.
|
||||
See individual `ROADMAP_*.md` files for per-app Vercel project setup details.
|
||||
| # | App | Vercel Root Dir | Framework | Key Env Vars | Roadmap |
|
||||
| --- | ----------------- | ------------------------ | --------- | ------------------------------------------------------ | ---------------------------------------------------------- |
|
||||
| 1 | Admin Dashboard | `dashboards/admin-web` | Next.js | `COSMOS_ENDPOINT`, `COSMOS_KEY`, `JWT_SECRET` | [ROADMAP_ADMIN_WEB.md](./ROADMAP_ADMIN_WEB.md) |
|
||||
| 2 | Tracker Dashboard | `dashboards/tracker-web` | Next.js | `JWT_SECRET`, `PLATFORM_SERVICE_URL` | [ROADMAP_TRACKER_WEB.md](./ROADMAP_TRACKER_WEB.md) |
|
||||
| 3 | User Dashboard | `user-dashboard-web` | Next.js | `PLATFORM_SERVICE_URL`, `ACTIONTRAIL_SERVICE_URL` | [ROADMAP_USER_DASHBOARD.md](./ROADMAP_USER_DASHBOARD.md) |
|
||||
| 4 | ChronoMind Web | `web` | Next.js | `GITEA_NPM_TOKEN` | [ROADMAP_CHRONOMIND_WEB.md](./ROADMAP_CHRONOMIND_WEB.md) |
|
||||
| 5 | JarvisJr Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_PLATFORM_URL` | [ROADMAP_JARVISJR_WEB.md](./ROADMAP_JARVISJR_WEB.md) |
|
||||
| 6 | NomGap Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_NOMGAP_WEB.md](./ROADMAP_NOMGAP_WEB.md) |
|
||||
| 7 | FlowMonk Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_FLOWMONK_WEB.md](./ROADMAP_FLOWMONK_WEB.md) |
|
||||
| 8 | NoteLett Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_NOTELETT_WEB.md](./ROADMAP_NOTELETT_WEB.md) |
|
||||
| 9 | ActionTrail Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_ACTIONTRAIL_WEB.md](./ROADMAP_ACTIONTRAIL_WEB.md) |
|
||||
| 10 | MindLyst Web | `mindlyst-native/web` | Next.js | `GITEA_NPM_TOKEN`, `COSMOS_ENDPOINT`, `OPENAI_API_KEY` | [ROADMAP_MINDLYST_WEB.md](./ROADMAP_MINDLYST_WEB.md) |
|
||||
| 11 | LocalMemGPT Web | `web` | Next.js | `GITEA_NPM_TOKEN`, `NEXT_PUBLIC_BACKEND_URL` | [ROADMAP_LOCALMEMGPT_WEB.md](./ROADMAP_LOCALMEMGPT_WEB.md) |
|
||||
| 12 | EffoRise Client | `client` | Vite | `GITEA_NPM_TOKEN`, `VITE_BACKEND_URL` | [ROADMAP_EFFORISE.md](./ROADMAP_EFFORISE.md) |
|
||||
|
||||
**Every Vercel project needs `GITEA_NPM_TOKEN` set.** See individual roadmap files for the complete env var list per app.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user