- 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).
3.3 KiB
| name | classification | success_metric | status | created | depends_on | skip | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| migrate-neon-to-homelab | infra | Deck Hearth runs on CT 102 Postgres + MinIO + Redis, app on Dokploy (CT 112); Neon and Vercel hosting decommissioned; Vercel AI Gateway retained. | shipped | 2026-08-15 |
|
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
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.jsdocs/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.