diff --git a/MEMORY.md b/MEMORY.md index 7f87e59..b9bb036 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -192,6 +192,30 @@ - Verified: proxy build + frontend build + `svelte-check` all clean for `@shared/*` (svelte-check still reports pre-existing `qrcode` types + CSS warnings). - Docker note: runtime image only copies `frontend/build` + `proxy/dist` (both already bundle `shared/`), so `shared/` needn't be copied into the image. +### 2026-08-10 — Dev runtime cleanup (PB instances / containers) +- **Removed** test container `31e74178b3f0` (`famdone-service-app-1`, host :3010 + :8092). It ran **PB 0.39.10** and bound the **same host `pb_data`** as pb-dev → two PBs (v0.25 + v0.39) writing one SQLite DB = corruption/lock risk (likely source of dev instability/login lag). +- **Killed** 7 stale host `tsx watch` dev-proxy processes (Jul 28–Aug 5) + my throwaway 0.39 PBs. +- **Reset pb_data**: stopped pb-dev, wiped `/home/threejjjs/development/famchamp/pb_data`, **recreated** pb-dev container (fresh v0.25 store) with `--automigrate=false`, recreated dev superuser `debug@famchamp.dev`/`debug123`. +- **Why recreate pb-dev**: v0.25 automigrate had baked stale `pb_migrations` into the old container's writable layer; on a fresh store they failed (`Failed to apply migration ...: no rows in result set`). +- **Desired end state (confirmed)**: `8090` = pb-dev (v0.25, single instance, automigrate off); `3001`+`8091` = PROD app `cffd636cc772` (kept, not live); PROD pb_data at `/data/coolify/.../pb_data` (separate from dev). + +### 2026-08-10 — PB 0.25 → 0.39 migration (branch `feature/migrate-pocketbase`) +- **Decision**: keep our own `migrate.ts` schema-as-code (API-driven, does data migrations + rule locking), NOT PocketBase's built-in automigrate (schema-only, generates version-specific migration files, and generates conflicting snapshots on upgraded stores). Disable PB automigrate in the runtime. +- **Verified against 0.39.10** (throwaway binaries on `127.0.0.1:8098/8099`, temp data dirs): + 1. Fresh store: `migrate()` bootstraps all 14 `SCHEMA_PLAN` collections + every field migration cleanly (schema field builders are 0.39-compatible). + 2. Existing 0.25 `pb_data` → 0.39: opens & serves with **`--automigrate=false`** and no stale `pb_migrations` dir. (Without this, automigrate writes a snapshot to `./pb_migrations` relative to CWD that conflicts with existing collections → "Collection name must be unique".) + 3. JS SDK `pocketbase@^0.27.0`: `authWithPassword` + public reads OK; realtime SSE endpoint serves `PB_CONNECT`. +- **Code changes on branch**: + - `docker/Dockerfile` `POCKETBASE_VERSION` → `0.39.10`. + - `docker/Dockerfile.dev` → `0.39.10` + `CMD ... --automigrate=false`. + - `docker/entrypoint.sh` → `pocketbase serve ... --automigrate=false`. + - `proxy/src/env.ts` → added non-breaking `PB_ENDPOINT` env override (used to point migrate at a throwaway PB on another port; default dev/prod split unchanged). +- **⚠️ 0.39 schema breaking change**: PB 0.39 does **NOT** auto-add `createdAt`/`updatedAt` to **API-created** collections (0.25 did). The chat store filters/sorts on a custom `messages.createdAt`, so a fresh 0.39 store is missing it → raw PB 400. Fixed two ways: + - `shared/pb/schema.ts`: `messages` now declares `date("createdAt")` explicitly (source of truth → `ensureSchema`). + - `proxy/src/migrate.ts`: the "messages already exists" branch now adds `createdAt` if missing (idempotent hardening for drifted/upgraded stores). +- **Dev now on 0.39.10**: pb-dev rebuilt from branch `Dockerfile.dev` (0.39.10 + `--automigrate=false`), fresh store on :8090, superuser `debug@famchamp.dev` re-verified, `migrate()` bootstraps schema + applies `messages.createdAt` fix cleanly. +- **Prod upgrade steps**: backup `pb_data` → run the 0.39 image (automigrate off) → run `migrate()` → verify no drift (`messages.createdAt`, `id.autogeneratePattern`). + ### 2026-08-10 — Revert PB to 0.25.8 (backtrack from 0.39) - **Decision**: backtrack off the PocketBase 0.39 bump (introduced in commit `3725c54` via `ARG POCKETBASE_VERSION=0.39.10`) and work from a **0.25.8 baseline** in BOTH dev and prod, then migrate to 0.39 deliberately later. - Reverted `docker/Dockerfile` `POCKETBASE_VERSION` back to `0.25.8` (matches `docker/Dockerfile.dev`). Dev `pb-dev` and the docker app internal PB `:8091` share host `./pb_data`. diff --git a/docker/Dockerfile b/docker/Dockerfile index 7faa80a..1d7013b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,7 +35,7 @@ COPY --from=builder /app/proxy/dist ./proxy COPY docker/nginx.conf /etc/nginx/http.d/default.conf COPY docker/entrypoint.sh /entrypoint.sh -ARG POCKETBASE_VERSION=0.25.8 +ARG POCKETBASE_VERSION=0.39.10 RUN wget -qO /tmp/pb.zip \ "https://github.com/pocketbase/pocketbase/releases/download/v${POCKETBASE_VERSION}/pocketbase_${POCKETBASE_VERSION}_linux_amd64.zip" \ diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index fba82cf..773a387 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,8 +1,8 @@ FROM alpine:latest RUN apk add --no-cache curl unzip && \ - curl -L -o /tmp/pb.zip https://github.com/pocketbase/pocketbase/releases/download/v0.25.8/pocketbase_0.25.8_linux_amd64.zip && \ + curl -L -o /tmp/pb.zip https://github.com/pocketbase/pocketbase/releases/download/v0.39.10/pocketbase_0.39.10_linux_amd64.zip && \ unzip /tmp/pb.zip -d /usr/local/bin/ && \ rm /tmp/pb.zip && \ apk del curl unzip EXPOSE 8090 -CMD ["pocketbase", "serve", "--http=0.0.0.0:8090"] +CMD ["pocketbase", "serve", "--http=0.0.0.0:8090", "--automigrate=false"] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index e931313..9c75c86 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -12,7 +12,9 @@ if [ -n "$PB_EMAIL" ] && [ -n "$PB_PASSWORD" ]; then fi # Start PocketBase (internal only; published via loopback for admin UI). -pocketbase serve --http=0.0.0.0:8090 --dir="$PB_DATA" & +# --automigrate=false: we own schema via proxy migrate.ts; PB's built-in +# automigrate generates conflicting snapshots on upgraded stores. +pocketbase serve --http=0.0.0.0:8090 --dir="$PB_DATA" --automigrate=false & # Wait for PB to be healthy before starting the proxy (which runs migrate). echo "[entrypoint] Waiting for PocketBase..." diff --git a/proxy/src/env.ts b/proxy/src/env.ts index f78ecf2..14ae02b 100644 --- a/proxy/src/env.ts +++ b/proxy/src/env.ts @@ -7,8 +7,10 @@ // so SERVER_IP is unset → loopback below. const SERVER_IP = process.env.SERVER_IP; -export const PB_ENDPOINT = SERVER_IP - ? `http://${SERVER_IP}:8090` - : `http://127.0.0.1:8090`; +// PB_ENDPOINT can be overridden explicitly (used for migration step-through +// against a throwaway PB on another port). Defaults to the dev/prod split. +export const PB_ENDPOINT = + process.env.PB_ENDPOINT || + (SERVER_IP ? `http://${SERVER_IP}:8090` : `http://127.0.0.1:8090`); export const PB_EMAIL = process.env.PB_EMAIL || "debug@famchamp.dev"; export const PB_PASSWORD = process.env.PB_PASSWORD || "debug123"; diff --git a/proxy/src/migrate.ts b/proxy/src/migrate.ts index 2913d2e..049a322 100644 --- a/proxy/src/migrate.ts +++ b/proxy/src/migrate.ts @@ -1455,7 +1455,27 @@ export async function migrate(): Promise { }); } else { console.log(` ↳ messages already exists`); - await updateCollection("messages", { listRule: "", viewRule: "" }); + // PB 0.39 doesn't auto-add createdAt to API-created collections, and + // older stores may predate it. Chat filters/sorts on createdAt, so + // ensure the field exists even if the collection was created without it. + const msgsFields = msgsCol.fields?.map((f: any) => f.name) || []; + if (!msgsFields.includes("createdAt")) { + console.log(" ↳ adding missing createdAt field to messages..."); + msgsCol.fields.push({ + name: "createdAt", + type: "date", + required: false, + min: "", + max: "", + }); + await updateCollection("messages", { + listRule: "", + viewRule: "", + fields: msgsCol.fields, + }); + } else { + await updateCollection("messages", { listRule: "", viewRule: "" }); + } } // 9b. chat_typing (transient presence rows, one per actor) diff --git a/shared/pb/schema.ts b/shared/pb/schema.ts index b8e1aca..ae70c36 100644 --- a/shared/pb/schema.ts +++ b/shared/pb/schema.ts @@ -219,6 +219,9 @@ export const SCHEMA_PLAN: CollectionPlanEntry[] = [ text("authorName", true), text("authorColor"), text("content", true), + // Explicit createdAt: PB 0.39 does NOT auto-add createdAt to + // API-created collections (0.25 did). Chat filters/sorts on it. + date("createdAt"), ])(ids), }, {