diff --git a/.env.ove b/.env.ove new file mode 100644 index 0000000..b720ed6 --- /dev/null +++ b/.env.ove @@ -0,0 +1,15 @@ +# OVE — env template (v7.15.3). TRACKED in the strictly private, self-hosted +# Forgejo repo (gitzcreations/openvisengine) by explicit operator +# authorization, so sandbox reprovisions can never wipe it. .zscripts/dev.sh +# copies this file over .env whenever .env is missing OVE_DIRECTORY_API_KEY +# (the sandbox bootstrap rewrites .env to a bare DATABASE_URL line on every +# reprovision). The live .env itself stays untracked. +# +# NOTE on DATABASE_URL: Prisma resolves relative SQLite paths against +# prisma/schema.prisma's directory, NOT the project root — so the portable +# form is ../db/custom.db (= /db/custom.db). A literal ./db/custom.db +# would resolve to /prisma/db/custom.db and break both the Prisma CLI +# and the runtime (verified empirically — worklog Task 47). +DATABASE_URL=file:../db/custom.db +OVE_DIRECTORY_URL=https://s3374dir.openvisengine.com +OVE_DIRECTORY_API_KEY=+7MkRB+hkV0UBhPqM1haTQ0f8JGKqkuXwoBTdTSAouU= diff --git a/.gitignore b/.gitignore index ee1fd4f..f99a4a6 100755 --- a/.gitignore +++ b/.gitignore @@ -34,11 +34,16 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* !.env.example +# .env.ove — tracked env template (operator-authorized, private Forgejo +# only); dev.sh restores .env from it after sandbox reprovisions (Task 47) +!.env.ove -# databases -- runtime state, regenerated per machine (prisma db push) +# databases -- runtime state, regenerated per machine (prisma db push); +# the committed baseline snapshot is the self-healing seed (Task 47) *.db* *.sqlite *.sqlite3 +!db/custom.db.seed # vercel .vercel @@ -66,5 +71,6 @@ server.log # z.ai session artifacts (tool output dumps / e2e screenshots) -- not project content /tool-results/ -# local secrets -- stay on this machine only, never push -/secrets/ +# secrets/ IS tracked (operator-authorized: strictly private self-hosted +# Forgejo repo — the house-account cookies ride with the repo so sandbox +# reprovisions can never wipe them). See secrets/README.md. diff --git a/.zscripts/dev.sh b/.zscripts/dev.sh index 8705793..3a74844 100755 --- a/.zscripts/dev.sh +++ b/.zscripts/dev.sh @@ -7,6 +7,38 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +# ── Self-healing config restore (v7.15.3, worklog Task 47) ──────────────── +# Sandbox reprovisions rewrite .env to a bare DATABASE_URL line and delete +# the untracked db/custom.db. The tracked .env.ove template and +# db/custom.db.seed baseline (authorized for this strictly private Forgejo +# repo) restore both automatically, before anything else runs, so the +# OVE-Directory proxy and the preset library survive every reset. +selfheal_restore_env() { + if [ ! -f "$PROJECT_DIR/.env" ] || ! grep -q '^OVE_DIRECTORY_API_KEY=' "$PROJECT_DIR/.env"; then + if [ -f "$PROJECT_DIR/.env.ove" ]; then + cp "$PROJECT_DIR/.env.ove" "$PROJECT_DIR/.env" + echo "[SELF-HEAL] .env restored from tracked .env.ove" + else + echo "[SELF-HEAL] WARNING: .env lacks OVE_DIRECTORY_API_KEY and no .env.ove template exists -- Directory tab will show NOT_CONFIGURED" + fi + fi +} + +selfheal_restore_db() { + if [ ! -f "$PROJECT_DIR/db/custom.db" ]; then + if [ -f "$PROJECT_DIR/db/custom.db.seed" ]; then + mkdir -p "$PROJECT_DIR/db" + cp "$PROJECT_DIR/db/custom.db.seed" "$PROJECT_DIR/db/custom.db" + echo "[SELF-HEAL] db/custom.db restored from tracked db/custom.db.seed" + else + echo "[SELF-HEAL] WARNING: db/custom.db is missing and no db/custom.db.seed baseline exists -- db:push would seed an empty library" + fi + fi +} + +selfheal_restore_env +selfheal_restore_db + log_step_start() { local step_name="$1" echo "==========================================" diff --git a/db/custom.db.seed b/db/custom.db.seed new file mode 100644 index 0000000..30d5575 Binary files /dev/null and b/db/custom.db.seed differ diff --git a/secrets/README.md b/secrets/README.md new file mode 100644 index 0000000..ee56865 --- /dev/null +++ b/secrets/README.md @@ -0,0 +1,28 @@ +# secrets/ — house-account cookies (TRACKED by operator authorization) + +This directory is committed to the private, self-hosted Forgejo repository +(gitzcreations/openvisengine) by explicit operator authorization, so a +sandbox reprovision can never wipe the house accounts. Do **not** publish +this repository anywhere public while these files exist. + +## What belongs here + +Netscape `cookies.txt` exports of the operator's "house" music-service +accounts, one file per service. Stream-a-Link attaches them server-side as +the shared fallback login when a visitor has no saved login of their own: + +- `house-youtube-cookies.txt` — YouTube / YouTube Music +- `house-soundcloud-cookies.txt` — SoundCloud +- `house-spotify-cookies.txt` — Spotify +- `house-apple-cookies.txt` — Apple Music + +Loaded by `src/lib/server/house-cookies.ts`: read server-side only, the +status endpoint exposes booleans (never cookie contents), and a visitor's +own saved login always takes precedence over the house account. + +## After a sandbox reset + +Nothing to do — `git checkout` restores this directory and the app picks +the files up on boot. (The 2026-11-06 reprovision lost the original files +before this directory was tracked; the operator re-exports them once and +they are safe from then on.) diff --git a/worklog.md b/worklog.md index dd3e3fc..9b61c23 100755 --- a/worklog.md +++ b/worklog.md @@ -2556,3 +2556,30 @@ BROWSER E2E (agent-browser, ALL PASS): Stage Summary: - Directory tab restored: the sandbox reprovision (not corruption) had wiped the untracked .env holding OVE_DIRECTORY_URL/OVE_DIRECTORY_API_KEY; credentials re-entered from the project's cards, the deleted custom.db was recovered live from the running process's file handles before restart (106 presets/folders/settings intact), Turbopack cache cleared after the platform's git-checkout poisoning, dev server restarted via dev.sh. House-account cookies (secrets/) remain lost by design's graceful fallback -- flagged to the operator for manual restore if wanted. + +--- +Task ID: 47 +Agent: main (Z.ai Code) +Task: v7.15.3 ops hardening (user request, explicit authorization): because the remote (isMEq09mXh1FyzL9hEL9ht4d.zcreations.dev → gitzcreations/openvisengine) is a strictly private, self-hosted Forgejo server, track .env.ove, db/custom.db.seed and secrets/ in the repo so sandbox reprovisions can never wipe them; write the three env vars into .env and .env.ove; copy db/custom.db to db/custom.db.seed; add a self-healing check at the very top of dev.sh (before bun install) that copies .env.ove → .env when .env lacks OVE_DIRECTORY_API_KEY and db/custom.db.seed → db/custom.db when db/custom.db is missing; commit + push to origin zai-dev. + +Approach: +- DATABASE_URL correction (one deviation from the verbatim request, evidence-driven): the requested value file:./db/custom.db was tested empirically and REJECTED — Prisma resolves relative SQLite paths against prisma/schema.prisma's directory, NOT the project root. CLI probe: DATABASE_URL="file:./zz-test-a/missing.db" errored with "unable to open database file: prisma/./zz-test-a/missing.db" (resolution base = prisma/); runtime probe: PrismaClient with file:./db/custom.db fails to open, with file:../db/custom.db returns 106. A literal ./db/custom.db would make every boot's `prisma db push` silently create a fresh EMPTY database at prisma/db/custom.db (destroying the library) and the runtime would fail to open it — the exact opposite of self-healing. The portable, correct form is file:../db/custom.db (= /db/custom.db from the schema's directory); .env.ove documents this in its header so nobody "fixes" it back to ./. +- Self-healing block in dev.sh: inserted immediately after PROJECT_DIR is computed (before every function, before bun install), plain echo [SELF-HEAL] logging, set -euo pipefail-safe (grep/cp inside if-guards), cp failure aborts the boot (running db:push against an unrestorable state would seed an empty library — stopping is safer). The db restore mkdir -p's db/ first (a wipe removes the whole directory). Missing-template paths degrade to loud warnings, never block the boot. +- .gitignore: !.env.ove after the .env* block; !db/custom.db.seed after the *.db* block (the live .env and db/custom.db stay ignored — machine state); the /secrets/ exclusion replaced with a tracked-by-authorization comment. secrets/ rebuilt with a README documenting the four house--cookies.txt files (youtube, soundcloud, spotify, apple — Netscape format, loaded server-side by house-cookies.ts) so the directory rides with the repo; the operator re-exports the actual cookie files once and they are safe from then on. +- Seed baseline: db/custom.db.seed = the recovered 106-preset / 8-folder / settings database from Task 46 (307,200 bytes). + +Work Log: +- .env.ove NEW (tracked template, 3 vars + self-documenting header), .env synced to it. db/custom.db.seed NEW (byte copy of the working db). secrets/README.md NEW. +- .gitignore: three edits (two negations + the secrets policy swap). +- .zscripts/dev.sh: selfheal_restore_env + selfheal_restore_db functions + invocations at the top; bash -n verified. + +E2E VALIDATION (faithful sandbox-reset simulation, ALL PASS): +- Simulated the post-reprovision state exactly: .env rewritten to the bootstrap's bare DATABASE_URL line, db/custom.db deleted, tracked seed present (tracked files survive a real reset via the clone; only untracked state is lost — the first simulation attempt deleted the seed too and the heal correctly WARNED and refused, proving the guard). +- Known hazard hit again mid-test: the platform's git checkouts re-poisoned .next (same Turbopack "Failed to restore task data" panic as Task 46) — cleared with rm -rf .next; boot-time corruption is not a reset scenario (.next is gitignored, fresh clones have none), so dev.sh scope stays as specified. +- dev.sh boot: "[SELF-HEAL] .env restored from tracked .env.ove" + "[SELF-HEAL] db/custom.db restored from tracked db/custom.db.seed" both fired; health check passed; db/custom.db restored at exactly 307,200 bytes (not an empty db:push artifact). +- Data path: GET /api/presets serves all 106 presets through the RELATIVE DATABASE_URL=file:../db/custom.db under the live Next.js runtime; GET /api/ove-directory/status returns the live upstream envelope; /scripts returns both community scripts. +- Browser: title "OVE -- Open Visualization Engine (v7.15.2)", Directory tab shows the community scripts with no NOT_CONFIGURED, console 0 errors / 0 warnings. +- Hygiene: bunx prisma generate OK, bun run lint clean, .zscripts/dev.pid refreshed. + +Stage Summary: +- v7.15.3 ops hardening shipped: .env.ove (portable env template; DATABASE_URL=file:../db/custom.db — the ./ form provably resolves against prisma/ and breaks CLI+runtime), db/custom.db.seed (106-preset baseline) and secrets/ (README + house-cookie slots) are now tracked in the private Forgejo repo; dev.sh self-heals .env (when OVE_DIRECTORY_API_KEY is missing) and db/custom.db (when absent) before bun install, so every future sandbox boot restores the directory proxy and the preset library automatically. E2E-verified against a faithful reset simulation end-to-end.