5 KiB
saltcorn — dev environment for the dev-deploy plugin
This project root holds the dev-deploy Saltcorn plugin and the launcher
scripts + per-instance state needed to develop and test it against two local
Saltcorn instances. Upstream Saltcorn lives in saltcorn/ (a sibling git
checkout managed independently from this project).
Layout
saltcorn/ project root (this git repo)
├── dev-deploy/ the plugin (Saltcorn plugin, sc_plugin_api_version 1)
├── startServer.sh launch MAIN instance on :3000
├── startServerTest.sh launch TEST instance on :3001
├── devServer.sh launch MAIN under `saltcorn dev:serve` (tsc watch)
├── installSaltcorn.sh reproduce this dev environment from scratch
├── .dev-state/ MAIN instance: env.sh, saltcorn.sqlite, files/, sessions
├── .dev-state-test/ TEST instance: same shape, separate port + secret
└── saltcorn/ upstream Saltcorn checkout (its own .git, gitignored here)
The upstream subfolder, both .dev-state* directories, and node_modules/
are all gitignored — only the plugin + scripts + this README are tracked.
Prerequisites
git,curlnvm(auto-installed at~/.nvmif missing) → Node 20git-lfsfor the.gitattributesLFS filters (git lfs installonce per clone)
installSaltcorn.sh handles nvm + Node 20 install for you.
Fresh install
./installSaltcorn.sh [destination] # default: ./saltcorn
Clones upstream Saltcorn into <dest>/saltcorn/, runs npm install + npm run tsc, generates <dest>/.dev-state/env.sh with a fresh session secret,
initializes the SQLite schema, creates the admin user, and writes
<dest>/startServer.sh.
The script sets up the MAIN instance only. To add the TEST instance,
duplicate .dev-state/ as .dev-state-test/, edit its env.sh to use a new
SALTCORN_SESSION_SECRET and add export SALTCORN_PORT="3001", then:
source .dev-state-test/env.sh
saltcorn reset-schema -f
saltcorn create-user -a -e admin@local -p AdminP@ss1
The reference .dev-state-test/env.sh already in this repo shows the exact
pattern.
Running
./startServer.sh # MAIN → http://localhost:3000/
./startServerTest.sh # TEST → http://localhost:3001/
./devServer.sh # MAIN under `saltcorn dev:serve` (nodemon + tsc watch)
Login on either instance: admin@local / AdminP@ss1.
Each startServer*.sh runs saltcorn install-plugin -d ./dev-deploy on every
boot, so edits to dev-deploy/ go live on the next restart.
The dev-deploy plugin
dev-deploy/ migrates Saltcorn metadata (tables, fields, views, pages,
triggers, roles, library, tags, constraints, files, page groups, workflow
steps, plus selected config keys and plugin configuration) across Dev/Test/Prod
environments via an append-only ops journal with stable cross-environment
UUIDs and HMAC-authenticated peer endpoints. Concurrent edits surface as
conflicts in the admin UI with theirs/mine/per-field-merge resolution. User
row data is left alone unless an admin explicitly marks a table as managed
or starter.
Admin UI: /admin/dev-deploy/ (logged in as an admin). Machine API:
/dev-deploy/api/{journal,ingest,file/:uuid,health} (HMAC-signed peer requests).
Tests
# Both servers must be running first.
./startServer.sh & ./startServerTest.sh &
cd dev-deploy && npm test
Runs dev-deploy/test/e2e.js — ~50+ end-to-end tests covering pairing,
promote, pull, conflict resolution, constraints, files, page groups,
workflow steps, config propagation, managed/starter row data, revert, and
machine-endpoint security. Tests run in order and share state; don't reorder.
test/sc-exec.js is a shim used by the tests to run JS against Saltcorn's
models with full require() access (saltcorn's built-in run-js uses a vm
sandbox that hides Field/TableConstraint/File/etc.).
Notes
-
Per-instance
sessions.sqlite. Saltcorn's SQLite session store writessessions.sqliteat process cwd (packages/server/routes/utils.js).startServer.shandstartServerTest.shcdinto their respective state directory beforeexec saltcorn serve, so each instance gets its own sessions DB.devServer.shcannot do this (itsdev:serverunsnpm run tscwhich needs cwd=upstream root), so its sessions land insaltcorn/sessions.sqlite— don't rundevServer.shandstartServer.shagainst the MAIN instance simultaneously. -
SALTCORN_SESSION_SECRETis the pairing identity. dev-deploy derives its at-rest encryption key (KEK) for peer secrets via HKDF from this value. Rotating it invalidates every peer pairing on the instance. The secret is generated once per instance and persisted in that instance'senv.sh. -
Upstream Saltcorn updates. Pull from upstream via
git -C saltcorn pull— the project root is a separate repo and doesn't see those commits. After a pull, you may neednpm install && npm run tscinsidesaltcorn/.