feat(modules): replay module schema fragments after core's (phase 2, PR 3) #130
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/modules-schema"
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?
Phase 2 PR 3 of
docs/website/MODULE_SYSTEM.md§2.7. Docs half: RunicGateway/docs#128.ensureSchema()now replays every installed module's schema fragment immediately after core'sschema.sql, perMODULE_API.md§2.6.The decision that shaped it
The work splits across two files on the line of whether a database is needed to know the answer.
modules/loader.js— validatesmodules/schema.js— executesThe alternative — check it all at replay time — would let a module with a plainly bad fragment mount, then 503 with whatever its fragment managed to execute already behind it.
Three smaller ones
DROPdenylist:CREATE,ALTER,INSERT,UPDATE, the four core's ownschema.sqluses. §2.6 words the rule as "noDROP", but this file is replayed on every boot —TRUNCATEandDELETEwould empty a table at every restart,RENAMEwould fail at the second one, and a denylist only ever bans what somebody thought of. The code says plainly that it is a leading-verb check and thatALTER TABLE x DROP COLUMN ypasses it. ACREATE TABLEmissingIF NOT EXISTSis rejected on the same grounds: it works once and fails every boot after, which reaches an operator as a module that broke on restart.utils/sqlStatements.jsso core's schema and a fragment are split by literally the same code — §2.6 promises that, and two copies would hold it only until one was edited. Its own file rather than an export ofutils/db.jsbecause the loader validates at require time and must not drag the mariadb pool intoapp.js's require chain.One thing found while wiring it
db/seed.jscallsensureSchema()standalone fornpm run seed, without ever requiringapp.js— so the loader has not scanned, andfragments()'s §7.6 throw would have broken seeding outright. The replay asksisLoaded()and logs the skip rather than swallowing it; a booting server quietly getting no module tables is the thing §7.6 exists to prevent, so the predicate is documented as having exactly this one sanctioned use.Verification
moduleSchema.test.jsinjects thequeryfn, so the exact statements and their order are asserted with the pool at a dead port like every other suite here.routes.manifest.jsonandroutes.guards.jsondiffs are zero lines, 229 routes — the Phase 2 exit criterion.swagger-output.jsonregenerates byte-identical.ALTER … ADD COLUMN IF NOT EXISTSand seeded its row (schema ensured for module "demo" {statements: 3});id NOTATYPE) marked only that modulestartup_failed, carrying MariaDB's own message as the reason;GET /api/v1/public/demo→ 200,GET /api/v1/public/brokendb→ 503, in the same process;ensureSchema()on the same database was a clean no-op. Fixture tables dropped afterwards.