@bongos/core 1.19.941 → 1.19.942
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +21 -16
- package/docs/module-api-changelog.md +2 -0
- package/docs/recipes/upgrading-the-core.md +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/run-unit-tests.js +3 -0
- package/scripts/migrate.sh +49 -16
- package/src/bongos/schema-lag.js +0 -3
- package/src/module-api.js +1 -1
- package/tests/migrate_module_overrides_db.mjs +91 -0
- package/tests/schema_lag.mjs +2 -2
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.942",
|
|
6
|
+
"core_contract": "1.19.942",
|
|
7
|
+
"source_commit": "1e45821468069b9d8f26ed2f7dbf1bbf647ea4b8",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-21T21:46:27.727Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 511,
|
|
13
13
|
"agent_docs_stubbed": 26,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2340,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2877,
|
|
20
|
+
"tree_sha256": "5e3c476a60b0631f79c68b199ba47f437ab6295e2518dfc86e7104e8fe0e9bfe",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2677,7 +2677,7 @@
|
|
|
2677
2677
|
{
|
|
2678
2678
|
"path": "docs/module-api-changelog.md",
|
|
2679
2679
|
"mode": "0000644",
|
|
2680
|
-
"sha256": "
|
|
2680
|
+
"sha256": "cf5f371ef80387f8344682a639e736c8cc3240debb4ee97106dfc2525e402e97"
|
|
2681
2681
|
},
|
|
2682
2682
|
{
|
|
2683
2683
|
"path": "docs/modules-contract.md",
|
|
@@ -2927,7 +2927,7 @@
|
|
|
2927
2927
|
{
|
|
2928
2928
|
"path": "docs/recipes/upgrading-the-core.md",
|
|
2929
2929
|
"mode": "0000644",
|
|
2930
|
-
"sha256": "
|
|
2930
|
+
"sha256": "0df57ea34114fb1ae81389458334b392d768fc83d9e82eb00fa917219189de87"
|
|
2931
2931
|
},
|
|
2932
2932
|
{
|
|
2933
2933
|
"path": "docs/recipes/windows-builders.md",
|
|
@@ -8002,12 +8002,12 @@
|
|
|
8002
8002
|
{
|
|
8003
8003
|
"path": "package-lock.json",
|
|
8004
8004
|
"mode": "0000644",
|
|
8005
|
-
"sha256": "
|
|
8005
|
+
"sha256": "04da7afdf07b5eacb7b5d8e18f034a45e62c318eed546facfa4e65480f5a6292"
|
|
8006
8006
|
},
|
|
8007
8007
|
{
|
|
8008
8008
|
"path": "package.json",
|
|
8009
8009
|
"mode": "0000644",
|
|
8010
|
-
"sha256": "
|
|
8010
|
+
"sha256": "79d643dab7e8bf794763c95cfa6f05200054d4aa2be271b61805954b1b82eb83"
|
|
8011
8011
|
},
|
|
8012
8012
|
{
|
|
8013
8013
|
"path": "public-docs/index.html",
|
|
@@ -9107,7 +9107,7 @@
|
|
|
9107
9107
|
{
|
|
9108
9108
|
"path": "scripts/gds/run-unit-tests.js",
|
|
9109
9109
|
"mode": "0000644",
|
|
9110
|
-
"sha256": "
|
|
9110
|
+
"sha256": "b536a889714c7f1ddc027b3f29602351d6942e1e52157469a5f82400490ee1d4"
|
|
9111
9111
|
},
|
|
9112
9112
|
{
|
|
9113
9113
|
"path": "scripts/gds/runner-drift.js",
|
|
@@ -9617,7 +9617,7 @@
|
|
|
9617
9617
|
{
|
|
9618
9618
|
"path": "scripts/migrate.sh",
|
|
9619
9619
|
"mode": "0000644",
|
|
9620
|
-
"sha256": "
|
|
9620
|
+
"sha256": "6f927d08ea67e4a7081972fb78fd6131c9eee569730932621d1e1ee6334ddd3a"
|
|
9621
9621
|
},
|
|
9622
9622
|
{
|
|
9623
9623
|
"path": "scripts/migrate_cost_ledger.sh",
|
|
@@ -9972,7 +9972,7 @@
|
|
|
9972
9972
|
{
|
|
9973
9973
|
"path": "src/bongos/schema-lag.js",
|
|
9974
9974
|
"mode": "0000644",
|
|
9975
|
-
"sha256": "
|
|
9975
|
+
"sha256": "b84a237b9fe9ce9f905ae0ca72e7f82eb08670397eb7e6c88c114c62afcf81a8"
|
|
9976
9976
|
},
|
|
9977
9977
|
{
|
|
9978
9978
|
"path": "src/bongos/secret-box.js",
|
|
@@ -10012,7 +10012,7 @@
|
|
|
10012
10012
|
{
|
|
10013
10013
|
"path": "src/module-api.js",
|
|
10014
10014
|
"mode": "0000644",
|
|
10015
|
-
"sha256": "
|
|
10015
|
+
"sha256": "ea1889449a3dab8921a6d4ce4fc539c8c550aef3eedc14d22493a26cd6af1bcc"
|
|
10016
10016
|
},
|
|
10017
10017
|
{
|
|
10018
10018
|
"path": "src/module-loader/catalog.js",
|
|
@@ -12509,6 +12509,11 @@
|
|
|
12509
12509
|
"mode": "0000644",
|
|
12510
12510
|
"sha256": "a1179788640c3959e21573817e386eece65067ecbe9bda6cd350e16118ac61f1"
|
|
12511
12511
|
},
|
|
12512
|
+
{
|
|
12513
|
+
"path": "tests/migrate_module_overrides_db.mjs",
|
|
12514
|
+
"mode": "0000644",
|
|
12515
|
+
"sha256": "a998b59c0a6d28a0c0d1fe617059631cff052c68afe954265e92a0cca8ce04e4"
|
|
12516
|
+
},
|
|
12512
12517
|
{
|
|
12513
12518
|
"path": "tests/migrate_root_resolution.mjs",
|
|
12514
12519
|
"mode": "0000644",
|
|
@@ -13452,7 +13457,7 @@
|
|
|
13452
13457
|
{
|
|
13453
13458
|
"path": "tests/schema_lag.mjs",
|
|
13454
13459
|
"mode": "0000644",
|
|
13455
|
-
"sha256": "
|
|
13460
|
+
"sha256": "af0db545b71f9cc3b88ae0a9cd09e909d9956326dd0aba8bb02a330e2cb21c8b"
|
|
13456
13461
|
},
|
|
13457
13462
|
{
|
|
13458
13463
|
"path": "tests/schema_lag_db.mjs",
|
|
@@ -2356,5 +2356,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2356
2356
|
landed since 1.19.939 with no explicit bump. run 35647628385. (task 1002620)
|
|
2357
2357
|
1.19.941 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2358
2358
|
landed since 1.19.940 with no explicit bump. run 35652433730. (task 1002620)
|
|
2359
|
+
1.19.942 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2360
|
+
landed since 1.19.941 with no explicit bump. run 35659043986. (task 1002620)
|
|
2359
2361
|
---------------------------------------------------------------------------
|
|
2360
2362
|
```
|
|
@@ -167,7 +167,7 @@ running a go-live.
|
|
|
167
167
|
- **Survey co-tenant git state as `lars`, never as root.** `ssh cloudbongos` lands you as root, where `git config --get remote.origin.url` on a `lars`-owned repo returns **nothing** — which reads exactly like "this instance has no remote" and is wrong. They do: `git@github-instances:example-owner/<slug>.git`. Prefix every probe with `sudo -u lars`.
|
|
168
168
|
- **A scaffold's `migrate` script is not guaranteed.** 21 of the 22 co-tenants have `scripts.migrate`; `mercury` has **no `scripts` block at all** and is started directly by its systemd `ExecStart`, so the normal lane cannot complete on it. `--skip-migrate` gets the install through but silently skips every schema change in the window — check what that window carries before reaching for it, rather than after.
|
|
169
169
|
- **An instance's database moves with its code, on every path** (task 1002002). `bongos upgrade` migrates (step 4) before it restarts; the control-plane runner behind the Deploy door drives it with `PGDATABASE` set to the target instance's own database; provisioning migrates at stand-up. A pinned co-tenant needs nothing extra, because its code only moves through `bongos upgrade`. `--skip-migrate` is the one way out of lockstep. Pinned by `tests/instance_db_migrated_on_code_move.mjs`.
|
|
170
|
-
- **`/version` reports `schemaPending`** (task 1002002): how many migrations the running code ships — core, plus each module this process has enabled (DB overrides included, task 1004136) — that this instance's database has not recorded — `null` when unknown (database unreachable, or a core older than the field). Above 0 is the 2026-07-04 outage shape, where the first query touching those tables fails. Fix: `migrate` against that instance DB with `PGDATABASE` set
|
|
170
|
+
- **`/version` reports `schemaPending`** (task 1002002): how many migrations the running code ships — core, plus each module this process has enabled (DB overrides included, task 1004136) — that this instance's database has not recorded — `null` when unknown (database unreachable, or a core older than the field). Above 0 is the 2026-07-04 outage shape, where the first query touching those tables fails. Fix: `migrate` against that instance DB with `PGDATABASE` set — it reads the same DB overrides, so a module switched on by the hall's Modules toggle gets its migrations too (`npm run migrate -- --print-modules` shows the set it will apply). The SessionStart `deploy-divergence` line alarms on it for the instance a checkout talks to; `--skip-migrate` above is the usual way to cause one.
|
|
171
171
|
- **The health check polls the restart** (fixed in task [#1984](https://example.com/builders#/task/1984)). The service binds its port ~1s after `systemctl restart`, so `--health-url` now polls up to ~30s for a 2xx before reporting a warning — an immediate `fetch failed` no longer means a failed upgrade. (Pre-1984 cores fetched once and spuriously reported `fetch failed`; there, confirm with `is-active` + a manual `curl`.)
|
|
172
172
|
- **The ledger auto-inserts via `PGDATABASE` too** (fixed in task [#1984](https://example.com/builders#/task/1984)). A consumer on `PGDATABASE` + peer auth now gets its `core_upgrades` row written automatically — the channel delegates the insert to `psql -d "$PGDATABASE"`, exactly like `migrate.sh`, so no manual `psql INSERT` is needed. (`DATABASE_URL` still works, via the `pg` driver.) Pre-1984 cores only auto-wrote with `DATABASE_URL`; on those, record the row manually.
|
|
173
173
|
- **No deploy key on the droplet** → deploys/upgrades ride a `git bundle`, not `git pull` (idea 509).
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.942",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.942",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.942",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
|
@@ -184,6 +184,9 @@ const INTEGRATION = new Set([
|
|
|
184
184
|
// migrate.sh has just run can show the expected stems (core + enabled modules) equal the recorded ones,
|
|
185
185
|
// so a healthy instance reads zero rather than a permanent SCHEMA BEHIND.
|
|
186
186
|
'schema_lag_db',
|
|
187
|
+
// task 1004137: migrate.sh's module set reads the hall's DB overrides — needs the
|
|
188
|
+
// override table and a database the real migrate.sh can connect to.
|
|
189
|
+
'migrate_module_overrides_db',
|
|
187
190
|
'scouting_rollup_fanout', 'session_records',
|
|
188
191
|
// task 1003217: the cost-row RAISE against real SQL. Every claim in it IS the
|
|
189
192
|
// SQL — an ON CONFLICT DO UPDATE guarded to move a row only upward, and a
|
package/scripts/migrate.sh
CHANGED
|
@@ -117,6 +117,46 @@ if [ "${1:-}" = "--print-db" ]; then
|
|
|
117
117
|
exit 0
|
|
118
118
|
fi
|
|
119
119
|
|
|
120
|
+
# The modules whose migrations the module loop below applies: the SAME set the server mounts routes
|
|
121
|
+
# for, DB overrides included (task 1004137). The server awaits refreshOverrides() before building its
|
|
122
|
+
# app; this read used to skip it, so a module switched on only by the hall's Modules toggle was
|
|
123
|
+
# "disabled — skipping" on every deploy while the next restart mounted its routes against tables that
|
|
124
|
+
# did not exist (the 2026-07-04 outage shape, per module).
|
|
125
|
+
# The overrides are read from the database this run migrates: PGDATABASE is pinned to $DB and
|
|
126
|
+
# DATABASE_URL blanked, because pool.js prefers DATABASE_URL and psql never reads it. FAILS OPEN to the
|
|
127
|
+
# config packs — refreshOverrides() swallows a DB error, and a require that throws (no `pg`) is caught
|
|
128
|
+
# here — so an unreadable override never fails a deploy; stderr is left visible so the fallback is not
|
|
129
|
+
# silent. CORE_ROOT rides in as argv, not interpolated, for the backslash reason above.
|
|
130
|
+
enabled_module_set() {
|
|
131
|
+
DATABASE_URL='' PGDATABASE="$DB" node -e "
|
|
132
|
+
const path = require('path');
|
|
133
|
+
const core = process.argv[1];
|
|
134
|
+
(async () => {
|
|
135
|
+
const { enabledModules } = require(path.join(core, 'src/modules'));
|
|
136
|
+
let pool;
|
|
137
|
+
try {
|
|
138
|
+
({ pool } = require(path.join(core, 'src/bongos/pool')));
|
|
139
|
+
await require(path.join(core, 'src/bongos/module-overrides')).refreshOverrides();
|
|
140
|
+
} catch (e) {
|
|
141
|
+
process.stderr.write('migrate.sh: could not read DB module overrides, using the config packs: ' + e.message + '\n');
|
|
142
|
+
} finally {
|
|
143
|
+
if (pool) await pool.end().catch(() => {});
|
|
144
|
+
}
|
|
145
|
+
process.stdout.write(enabledModules().join(' '));
|
|
146
|
+
})().catch((e) => {
|
|
147
|
+
process.stderr.write('migrate.sh: could not read module config: ' + e.message + '\n');
|
|
148
|
+
});
|
|
149
|
+
" "$CORE_ROOT" || true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Test/ops seam (task 1004137): --print-modules reports the module set this run would migrate, after
|
|
153
|
+
# reading the DB overrides, and exits before any schema work. tests/migrate_module_overrides_db.mjs
|
|
154
|
+
# asserts through it that a hall toggle reaches the module loop.
|
|
155
|
+
if [ "${1:-}" = "--print-modules" ]; then
|
|
156
|
+
printf '%s\n' "$(enabled_module_set)"
|
|
157
|
+
exit 0
|
|
158
|
+
fi
|
|
159
|
+
|
|
120
160
|
# --- Instance-seed policy (task 1704 / ADR 0105) --------------------------
|
|
121
161
|
# OTB/product scope-truth (versions, goals, done_when_criteria) lives in seed
|
|
122
162
|
# migrations under migrations/instance/ (plus a few guarded blocks embedded in the
|
|
@@ -279,22 +319,15 @@ fi
|
|
|
279
319
|
[ "$SEED_INSTANCE" = "on" ] || echo "instance seeds skipped (migrations/instance/) — non-owning / vanilla instance"
|
|
280
320
|
|
|
281
321
|
# Module-owned migrations (modules/<key>/migrations/*.sql) — applied only when the module is
|
|
282
|
-
# enabled. The enablement is
|
|
283
|
-
#
|
|
284
|
-
# config is instance content (resolveInstanceRoot() falls back to
|
|
285
|
-
# above).
|
|
286
|
-
#
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const { enabledModules } = require('$CORE_ROOT/src/modules');
|
|
292
|
-
process.stdout.write(enabledModules().join(' '));
|
|
293
|
-
} catch(e) {
|
|
294
|
-
process.stderr.write('migrate.sh: could not read module config: ' + e.message + '\n');
|
|
295
|
-
process.stdout.write('');
|
|
296
|
-
}
|
|
297
|
-
" 2>/dev/null || true)
|
|
322
|
+
# enabled. The enablement is the instance's config/modules.json (or the neutral starter) plus the
|
|
323
|
+
# DB overrides (enabled_module_set above). The module CODE lives in the core package (require
|
|
324
|
+
# $CORE_ROOT/src/modules), but the config is instance content (resolveInstanceRoot() falls back to
|
|
325
|
+
# cwd == INSTANCE_ROOT, set above). Read HERE, after the core loop, so core_248's
|
|
326
|
+
# module_enablement_overrides table exists even on a from-scratch database. The stem-key guarantee
|
|
327
|
+
# means moving a migration from migrations/game/ to modules/game/migrations/ does NOT re-run it on
|
|
328
|
+
# prod — schema_migrations is keyed by filename stem alone (ADR 0083 / BV1.R49, task 1418). A
|
|
329
|
+
# vanilla instance leaves game disabled via config/modules.neutral.json.
|
|
330
|
+
NODE_ENABLED_MODULES=$(enabled_module_set)
|
|
298
331
|
|
|
299
332
|
# Modules can be shipped by the CORE package or by the INSTANCE repo, so scan modules/ under
|
|
300
333
|
# BOTH roots. Apply each module key ONCE — today the two roots coincide (so instance-root modules
|
package/src/bongos/schema-lag.js
CHANGED
|
@@ -16,9 +16,6 @@
|
|
|
16
16
|
// off is expected nothing, so it can never alarm. Instance seeds (migrations/instance/) are an
|
|
17
17
|
// opt-in no running code depends on, so they are never counted.
|
|
18
18
|
//
|
|
19
|
-
// KNOWN GAP: migrate.sh does not read DB overrides (task 1004137), so for a module on ONLY by
|
|
20
|
-
// override this reports a true gap that running migrate does not yet close.
|
|
21
|
-
//
|
|
22
19
|
// Surfaced as `schemaPending` on /version (a count, never the names) and logged at boot;
|
|
23
20
|
// scripts/gds/deploy-divergence.js turns a non-zero count into the SessionStart alarm.
|
|
24
21
|
|
package/src/module-api.js
CHANGED
|
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
71
71
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
72
72
|
// the entry to that file. Look for a version's history there, not here.
|
|
73
73
|
// ---------------------------------------------------------------------------
|
|
74
|
-
const CORE_VERSION = '1.19.
|
|
74
|
+
const CORE_VERSION = '1.19.942'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
75
75
|
|
|
76
76
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
77
77
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// tests/migrate_module_overrides_db.mjs — migrate.sh migrates a module the hall switched on (task 1004137).
|
|
2
|
+
//
|
|
3
|
+
// The hall's Modules toggle writes module_enablement_overrides, and the server reads that table
|
|
4
|
+
// before it mounts any routes. migrate.sh used to pick its module set in a fresh process that never
|
|
5
|
+
// read it, so a module on ONLY by override was skipped on every deploy while the next restart
|
|
6
|
+
// mounted its routes against tables that did not exist. This drives the real migrate.sh through its
|
|
7
|
+
// --print-modules seam (the same function its module loop calls) against a real database.
|
|
8
|
+
//
|
|
9
|
+
// Integration lane: needs Postgres plus the PG* env migrate.sh connects with (the lane sets both);
|
|
10
|
+
// self-skips when no Postgres is reachable. Leaves the override table as it found it.
|
|
11
|
+
//
|
|
12
|
+
// Run: DATABASE_URL=postgres://... node tests/migrate_module_overrides_db.mjs
|
|
13
|
+
|
|
14
|
+
import { strict as assert } from 'node:assert';
|
|
15
|
+
import { execFileSync } from 'node:child_process';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
const { pool } = require('../src/bongos/pool.js');
|
|
22
|
+
const { moduleScopeKey } = require('../src/modules.js');
|
|
23
|
+
|
|
24
|
+
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
25
|
+
const MIGRATE = path.join(REPO_ROOT, 'scripts', 'migrate.sh');
|
|
26
|
+
// Ships a migration, meters no spend and is off in the packs, so the override alone decides it.
|
|
27
|
+
const MODULE = 'discord';
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
await pool.query('SELECT 1');
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.log(`migrate_module_overrides_db.mjs SKIPPED — no reachable Postgres (${e.code || e.message}). Set DATABASE_URL to run.`);
|
|
33
|
+
await pool.end().catch(() => {});
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { rows: [{ db }] } = await pool.query('SELECT current_database() AS db');
|
|
38
|
+
const scope = moduleScopeKey();
|
|
39
|
+
|
|
40
|
+
function printModules(overrides = {}) {
|
|
41
|
+
const env = { ...process.env, PGDATABASE: db, ...overrides };
|
|
42
|
+
delete env.INIT_CWD;
|
|
43
|
+
const out = execFileSync('bash', [MIGRATE, '--print-modules'], {
|
|
44
|
+
cwd: REPO_ROOT, env, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
|
|
45
|
+
});
|
|
46
|
+
return out.trim().split(/\s+/).filter(Boolean);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const setOverride = (enabled) => pool.query(
|
|
50
|
+
`INSERT INTO module_enablement_overrides (scope, module_key, enabled) VALUES ($1, $2, $3)
|
|
51
|
+
ON CONFLICT (scope, module_key) DO UPDATE SET enabled = EXCLUDED.enabled`,
|
|
52
|
+
[scope, MODULE, enabled],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const { rows: prior } = await pool.query(
|
|
56
|
+
'SELECT enabled, set_by, set_at FROM module_enablement_overrides WHERE scope = $1 AND module_key = $2',
|
|
57
|
+
[scope, MODULE],
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
await pool.query('DELETE FROM module_enablement_overrides WHERE scope = $1 AND module_key = $2', [scope, MODULE]);
|
|
62
|
+
const packs = printModules();
|
|
63
|
+
assert.ok(packs.length > 0, 'with no override the pack set still resolves (not an empty read)');
|
|
64
|
+
assert.ok(!packs.includes(MODULE), `precondition: ${MODULE} is off in the packs, so only an override can turn it on`);
|
|
65
|
+
console.log(` ok no override: ${MODULE} is not migrated`);
|
|
66
|
+
|
|
67
|
+
await setOverride(true);
|
|
68
|
+
const toggled = printModules();
|
|
69
|
+
assert.ok(toggled.includes(MODULE), `a hall toggle ON must reach migrate's module set, got: ${toggled.join(' ')}`);
|
|
70
|
+
assert.deepEqual(toggled.filter((m) => m !== MODULE), packs, 'and changes nothing else');
|
|
71
|
+
console.log(` ok override on: ${MODULE} is migrated`);
|
|
72
|
+
|
|
73
|
+
// Fail-open: an override migrate cannot read falls back to the packs, never to "no modules".
|
|
74
|
+
// The override row is still ON here, so only the fallback can produce the pack set.
|
|
75
|
+
const unreadable = printModules({ PGHOST: '127.0.0.1', PGPORT: '1' });
|
|
76
|
+
assert.deepEqual(unreadable, packs, 'an unreachable override database resolves exactly the pack set');
|
|
77
|
+
console.log(' ok unreadable overrides fall back to the packs');
|
|
78
|
+
} finally {
|
|
79
|
+
if (prior.length) {
|
|
80
|
+
await pool.query(
|
|
81
|
+
`INSERT INTO module_enablement_overrides (scope, module_key, enabled, set_by, set_at)
|
|
82
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
83
|
+
ON CONFLICT (scope, module_key)
|
|
84
|
+
DO UPDATE SET enabled = EXCLUDED.enabled, set_by = EXCLUDED.set_by, set_at = EXCLUDED.set_at`,
|
|
85
|
+
[scope, MODULE, prior[0].enabled, prior[0].set_by, prior[0].set_at],
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
await pool.query('DELETE FROM module_enablement_overrides WHERE scope = $1 AND module_key = $2', [scope, MODULE]);
|
|
89
|
+
}
|
|
90
|
+
await pool.end().catch(() => {});
|
|
91
|
+
}
|
package/tests/schema_lag.mjs
CHANGED
|
@@ -84,8 +84,8 @@ test('an enabled module whose migrations never ran is counted beside the core ga
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
test('the default expectation follows the server\'s own enablement, DB overrides included', () => {
|
|
87
|
-
// `discord` ships a migration and meters no spend, so the override alone decides it.
|
|
88
|
-
//
|
|
87
|
+
// `discord` ships a migration and meters no spend, so the override alone decides it. migrate.sh
|
|
88
|
+
// reads the same override layer (tests/migrate_module_overrides_db.mjs, task 1004137).
|
|
89
89
|
const STEM = 'discord_001_board_messages';
|
|
90
90
|
try {
|
|
91
91
|
setModuleOverrides({ discord: true });
|