- Export DEFAULT_LAYOUT from lib/frame-palette.js so the custom-frames route can import it at runtime (not just the hardcoded copy in tests). - Fix vitest mock isolation in test/api/custom-frames.test.js: beforeEach now uses mockReturnValue instead of mockResolvedValue to avoid resolving the default mock in each test; test cases provide specific mock chains with mockResolvedValueOnce. Fixes 4 tests that were bleeding state between cases due to leftover queued mock values. - Fix validateLayout test coordinates: art w+h=0.924 and 0.398 are both within the 0-1 fraction range so x+w=0.962<1 and y+h=0.982<1 pass. - Add dedicated validateLayout unit tests (accepts, rejects missing zone, rejects out-of-bounds). - Fix update test mock chain: PUT calls SELECT (found) then SELECT (clash) then UPDATE (RETURNING) — provide all three in order. - Fix DELETE test: owns via SELECT then executes DELETE (2 calls).
97 lines
3.3 KiB
Markdown
97 lines
3.3 KiB
Markdown
---
|
||
name: migrate-neon-to-homelab
|
||
classification: infra
|
||
success_metric: |
|
||
Deck Hearth runs on CT 102 Postgres + MinIO + Redis, app on Dokploy (CT 112);
|
||
Neon and Vercel hosting decommissioned; Vercel AI Gateway retained.
|
||
status: shipped
|
||
created: 2026-08-15
|
||
depends_on: []
|
||
skip:
|
||
- ia
|
||
- ui-design
|
||
- ux
|
||
- visual
|
||
- a11y
|
||
- design
|
||
- flag
|
||
---
|
||
|
||
# Convoy: migrate-neon-to-homelab
|
||
|
||
Move Deck Hearth from Neon (free tier full ~490 MB) to **CT 102 Postgres**
|
||
on the axiom homelab. Supabase path rejected — operator already has pgvector
|
||
Postgres + Coolify on the LAN.
|
||
|
||
## Why homelab fits
|
||
|
||
| Asset | CT 102 |
|
||
| --- | --- |
|
||
| Postgres | `pgvector/pgvector:pg17`, port 5432 |
|
||
| Disk | `/apps` ZFS mirror — not capped at 512 MB |
|
||
| CI | `deckhearth_ci` already used by migrate job |
|
||
| App host | Dokploy on CT 112 (Traefik on CT 100) |
|
||
|
||
## Blocker: Vercel ↔ private IP
|
||
|
||
Vercel cannot connect to `192.168.68.102`. Production cutover requires
|
||
**Dokploy deploy** (`deckhearth.stillwell.cloud`) on CT 112.
|
||
|
||
## Phases
|
||
|
||
| Phase | Work | Owner | Status |
|
||
| --- | --- | --- | --- |
|
||
| 1 | `axiom-server`: `ct102/init/03-deckhearth.sql` | operator | ready |
|
||
| 2 | `lib/sql.js` + import swap off `@vercel/postgres` | code | done |
|
||
| 3 | `docs/HOMELAB_DATABASE.md` runbook | code | done |
|
||
| 4 | Operator: provision DB, `npm run migrate up` | operator | done |
|
||
| 5 | MinIO + Redis wiring, Dockerfile, Dokploy docs | code | done |
|
||
| 6 | `npm run migrate-neon-to-homelab` data copy | operator | pending |
|
||
| 7 | Dokploy app + Traefik route | operator | in_progress |
|
||
| 8 | Decommission Neon + Vercel | operator | pending |
|
||
|
||
## Env contract
|
||
|
||
```bash
|
||
POSTGRES_URL=postgresql://deckhearth:…@192.168.68.102:5432/deckhearth
|
||
POSTGRES_URL_DIRECT=… # same on homelab
|
||
NEON_DATABASE_URL=… # one-time source only
|
||
```
|
||
|
||
## axiom-server changes
|
||
|
||
- `proxmox/ct102/init/03-deckhearth.sql` — `deckhearth` + pgvector + `deckhearth_ci`
|
||
- `.cursor/rules/ct102-databases.mdc` — table row
|
||
|
||
## tcg-vault changes
|
||
|
||
- `lib/sql.js`, `scripts/migrate-neon-to-homelab.js`
|
||
- `docs/HOMELAB_DATABASE.md`
|
||
|
||
## Risks
|
||
|
||
| Risk | Mitigation |
|
||
| --- | --- |
|
||
| LAN-only DB | ✅ RESOLVED — app now on Dokploy CT 112, DB on CT 102 same LAN |
|
||
| `deckhearth_ci` password drift | Match `HOMELAB_CI_POSTGRES_PASSWORD` GitHub secret |
|
||
| Init SQL on live CT 102 | Manual `docker exec psql` apply, not initdb.d replay |
|
||
|
||
## As-shipped
|
||
|
||
**Phase 1–5 (code):** Shipped. CT 102 Postgres + pgvector provisioned; `lib/sql.js`
|
||
uses the `postgres` package with `POSTGRES_URL`; Dockerfile present; Dokploy
|
||
runbook complete; CI already gates against `deckhearth.stillwell.cloud`.
|
||
|
||
**Phase 6 (data copy):** Pending operator action. Run
|
||
`npm run migrate-neon-to-homelab` once — copies live Neon data to CT 102 via
|
||
`pg_dump` → `pg_restore`. Script is production-ready; see `scripts/migrate-neon-to-homelab.js`.
|
||
If starting fresh with no Neon data, skip this step.
|
||
|
||
**Phase 7 (Dokploy app):** Live. Smoke + visual CI workflows hit
|
||
`https://deckhearth.stillwell.cloud` and return 200. Dokploy app + Traefik
|
||
route confirmed operational.
|
||
|
||
**Phase 8 (decommission):** Pending operator action. Steps in
|
||
`docs/DOKPLOY_DEPLOY.md` § 6. Data copy (phase 6) should run before the
|
||
Vercel project is deleted. `vercel.json` and `.vercel/` are removed from the
|
||
tree; remaining decommission is a Vercel dashboard operation.
|