Beta deploys used to rename foo.gsc -> foo.OLD and write beta bytes to
a foo-beta.gsc sidecar, forcing the mod loader to know the naming
convention. Now the beta content lives at the actual target filename
(same as configs already did) and the pre-beta bytes are captured in
a new beta_file_snapshots table for rollback.
- schema.sql: new beta_file_snapshots(beta_id, server, rel_path,
prior_content BLOB, prior_sha256, prior_size). Handles scripts,
plugins, and the composed dedicated_sp.cfg uniformly.
- db/index.ts: assertSnapshotSchemeSafe boot guard refuses to start
if a legacy running/ready-promote beta is present on first upgrade.
A settings sentinel (snapshots_v1) makes it one-shot.
- beta.ts openBeta: read prior bytes, insert snapshot, overwrite
target directly.
- beta.ts rollbackBeta: restore from snapshot if had_original, else
delete the fresh file. Drop snapshot rows after restore.
- beta.ts promoteBeta: no more rm -beta / rm .OLD calls, pull prior
content from the snapshot table for the deployment audit, drop
snapshots after promote.
- files.ts: delete betaFile() and oldFile().
- drift.ts: docstring updated; no special-casing needed since beta
bytes and inventory now agree on the target rel_path.
- servers/[name]/+page.svelte: drop dead -beta/.OLD row filters.
- tests: plugin write asserts the target filename; unused
betaFile/oldFile tests removed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>