Release: backup restore, portable secret key, multi-arch image, CSRF, About dialog #14
Reference in New Issue
Block a user
Delete Branch "development"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Four commits since #13.
Backup restore — was a stub, now real
Every repository shares one connection pool, so the database cannot be swapped underneath a live server. Restore is two-phase:
RestoreBackupvalidates and stages the file beside the database;db.Newapplies it before the pool is opened, the only safe moment.<db>.replaced-<timestamp>.-wal/-shmare removed so SQLite cannot replay the old journal over the restored file.integrity_check+ schema probe) — applying an unrelated file would destroy the install.GET/DELETE /api/v1/backups/restoreinspect and cancel a staged restore.orchestrad backupwas also a stub and now works.Portable secret key
With nothing configured the key is generated once and persisted to
<data>/secret.key(owner-only; ACL-restricted on Windows), so restarts reuse it and moving the stack to another server is a matter of copying the data directory.Upgrades are handled deliberately: the MSI never set
ORCHESTRAD_SECRET_KEY, so existing installs have been running on the legacy built-in default. If a database already exists, that value is adopted and written out rather than replaced — generating a fresh key there would make every stored credential undecryptable. Startup logs where the key came from and warns to rotate the legacy one.Multi-arch container image
buildxnow emitslinux/amd64+linux/arm64, matching the architectures the release binaries already covered. The Dockerfile cross-compiles viaTARGETARCHinstead of emulating, so arm64 costs little. This is the one change that can only prove itself on a real CI run — it restructured build+push into a singlebuildx --push, so watch that job.Real CSRF
The middleware previously checked only that a header was present, and was never wired up;
/auth/csrfreturnedcsrf-token-placeholder. Tokens are now nonce + HMAC-SHA256 signed with the application secret, properly validated, and the middleware is mounted on/api/v1. Bearer and API-key requests are not CSRF-reachable and pass through untouched, so this is transparent to the SPA and to API clients.TLS
LocalMachine\Mywith its private key, and renewal replaces it rather than accumulating one cert per renewal. Only certificates issued by our own CA to our own subject are ever pruned.ensureWindowsStorereturned mid-enumeration without freeing the matchedCertContext, which also leaked the store handle (CertCloseStore(store, 0)defers until outstanding contexts are released).Ensure/Reloadare now serialized — reachable concurrently from the renewal loop and the settings handler, where a racing pair could prune the leaf the other just installed.CRYPT_EXPORTABLE(the store copy is not the source of truth), and the PFX password is written beside the bundle.UI
The notifications bell rendered hard-coded template data ("Roman Joined the Team!") with no backing feature. Replaced with an About dialog showing the running server's version, build time, and commit, with a copy button. Three other unreferenced template files went with it.
Verification
Full backend suite green; Linux cross-build clean. Verified live against the demo instance and the lab DC: backup → stage → restart applies and preserves the previous database; secret key generated, adopted, and read back across restarts with the credential check confirming decryptability; leaf published to the store and replaced on renewal; CSRF issues real signed tokens; version endpoint renders release values.
Merging this cuts a release (binaries, container image, MSI).
The bell rendered hard-coded template data ("Roman Joined the Team!", "New Payment received") — a demo artifact that had nothing to do with the product and no backing feature. In its place, an About dialog reports the running server's build: version, build time, and commit, read from GET /api/v1/version, with a copy button so the exact build can be quoted in a bug report without shelling onto the host. That probe predates the {success,data} envelope and returns bare snake_case JSON, so it is fetched directly rather than through the api client, accepting either shape in case it is ever normalised. Dev builds ("dev"/"unknown") degrade to a readable "—" rather than an invalid date. Removing the bell also stranded three other unreferenced template files, so Notification.tsx, AppLinks.tsx, QuickLinks.tsx and their shared data.ts (fake users, chat/ecommerce app links) are deleted with it. Also fixes the account button announcing itself to screen readers as "show 11 new notifications". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>