Snapshot the code-bearing fields of routes (verb/path/handler), templates
(name/content/test_object), and db libraries (name/library) on every
content-changing save, so nothing edited is ever lost. Recorded in a new
`versions` table via recordVersion() hooked into the create/update functions
in db.js (the single write choke point), deduped against the latest snapshot
so no-op saves, error-flag-only route writes, and server-restart WS
re-bootstraps don't pile up. The live row stays current; old snapshots are the
undo trail. Read-only, no revert UI yet.
- migrations/004_add_versions.sql: versions table + indexes
- db.js: recordVersion/getVersions/getVersion + create/update hooks
- plumbing.js: /versions/:id and per-entity .../versions list endpoints
- bliss: `versions <type> <sid> <id>` and `version <id>` reads;
`update-settings` (edit route_prefix/head_injection, preserving the
untouched field); `use <url>` sticky target persisted to ~/.bliss/target
so BLISS_URL needn't be re-exported each call
- client.js: target-file precedence (BLISS_URL > ~/.bliss/target > localhost)
- SKILL.md: document the above
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Db library scripts are basically a JS module scoped to the db, and
handlers already get fetch — but runLibrary's own vm context only
bound sql/console, so any library calling fetch (e.g. the chat db's
OpenAI call) threw ReferenceError. Since library calls are often
fire-and-forget inside setTimeout (no rejection handler), that
crashed the whole process. Bind fetch in all three places a library
script runs: request-time (runLibrary), the library-editor save eval,
and repl.
Also add `bliss link` to bliss-cli for jumping straight to a
structure/route/template/db's workshop editor URL, including
resolving a db by its require('db')(alias) name.