@bongos/core 1.19.311 → 1.19.312

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 CHANGED
@@ -2,11 +2,11 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.311",
6
- "core_contract": "1.19.311",
7
- "source_commit": "e1c43e441e7fc621f31480ab2306aa29cf6fabfa",
5
+ "core_version": "1.19.312",
6
+ "core_contract": "1.19.312",
7
+ "source_commit": "1115918f0f231eb592993c52535bccf7459ba201",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-23T20:49:01.750Z",
9
+ "built_at": "2026-08-23T20:51:36.647Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 323,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 1766,
20
- "tree_sha256": "52b0f6698975b1156c233e14471c23249226712403aaad8498402f78a7a3c5d4",
20
+ "tree_sha256": "8fa5a70e1592609c53386120743ab236e02cd64aaf8c3911891bd79d6a8da6ea",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -3057,7 +3057,7 @@
3057
3057
  {
3058
3058
  "path": "modules/government/db.js",
3059
3059
  "mode": "0000644",
3060
- "sha256": "6d85422869793382fc372a43b6a2b745bcb0e8a62c4fec06b780e812ae5066b9"
3060
+ "sha256": "e48b8e01738969ca589496ee0bea94b5a31995e853a1347f63ca83895d4d28fd"
3061
3061
  },
3062
3062
  {
3063
3063
  "path": "modules/government/membership-predicate.js",
@@ -4582,12 +4582,12 @@
4582
4582
  {
4583
4583
  "path": "package-lock.json",
4584
4584
  "mode": "0000644",
4585
- "sha256": "ac29f684d093a69db95b7e41ff40c70dccf70ea5a9bce2e78bf2a5b02ec302e7"
4585
+ "sha256": "57b834edcb83e8b41bb7535bbacc1740537b0f3551726295884ea35615a88686"
4586
4586
  },
4587
4587
  {
4588
4588
  "path": "package.json",
4589
4589
  "mode": "0000644",
4590
- "sha256": "118f6dad272f412617ba4f4693317498f42580f7bb84cdca272705b3a696fe22"
4590
+ "sha256": "7e8d9420573b8eabbe2ad7f96f0317d4b454fcf5788b68bfc6afdf6fb45b3cb4"
4591
4591
  },
4592
4592
  {
4593
4593
  "path": "public-docs/index.html",
@@ -6257,7 +6257,7 @@
6257
6257
  {
6258
6258
  "path": "src/module-api.js",
6259
6259
  "mode": "0000644",
6260
- "sha256": "c936d7dda32ef492b30f7b1230157e27d088606066056188794b0fd1b42f34f7"
6260
+ "sha256": "a35a7a2ca59f77d06b12aaaec28b4d82bbe5a4713289c072d4e9cc45d0d467e5"
6261
6261
  },
6262
6262
  {
6263
6263
  "path": "src/module-loader/catalog.js",
@@ -7387,7 +7387,7 @@
7387
7387
  {
7388
7388
  "path": "tests/government_rank_sync.mjs",
7389
7389
  "mode": "0000644",
7390
- "sha256": "83462482dff692a3587edecd0e57e0d7638fa08076329a7591c0cb2222d50e47"
7390
+ "sha256": "8e430f7286ec798eceaba7db962bb3725c1de2e9cbaeee70739aae6287695d7e"
7391
7391
  },
7392
7392
  {
7393
7393
  "path": "tests/government_require_permission.mjs",
@@ -94,9 +94,9 @@ async function syncRank(client, { builderId, rank } = {}) {
94
94
  return { target: null, added: [], removed: [] };
95
95
  }
96
96
  const q = client || pool;
97
- const seededRoles = await getSeededRanks(q);
98
- const currentRoles = await getRankAssignmentsForBuilder(q, builderId);
99
- const plan = planRankSync({ rank, currentRoles, seededRoles });
97
+ const seededRanks = await getSeededRanks(q);
98
+ const currentRanks = await getRankAssignmentsForBuilder(q, builderId);
99
+ const plan = planRankSync({ rank, currentRanks, seededRanks });
100
100
 
101
101
  if (plan.remove.length > 0) {
102
102
  await q.query(
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.311",
3
+ "version": "1.19.312",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.311",
9
+ "version": "1.19.312",
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.311",
3
+ "version": "1.19.312",
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",
package/src/module-api.js CHANGED
@@ -1049,8 +1049,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
1049
1049
  // landed since 1.19.309 with no explicit bump. run 32665109518. (task 1002620)
1050
1050
  // 1.19.311 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1051
1051
  // landed since 1.19.310 with no explicit bump. run 32665535518. (task 1002620)
1052
+ // 1.19.312 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1053
+ // landed since 1.19.311 with no explicit bump. run 32665664699. (task 1002620)
1052
1054
  // ---------------------------------------------------------------------------
1053
- const CORE_VERSION = '1.19.311'; // CI auto-patch carrier (ADR 0161); see changelog above
1055
+ const CORE_VERSION = '1.19.312'; // CI auto-patch carrier (ADR 0161); see changelog above
1054
1056
 
1055
1057
  // A namespaced logger so a module's log lines are attributable + consistent.
1056
1058
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -229,3 +229,93 @@ test('every governance migration keeps its objects namespaced and additive', ()
229
229
  assert.ok(m[1].startsWith('governance_'), `object ${m[1]} is not governance_-namespaced`);
230
230
  }
231
231
  });
232
+
233
+ // ---------------------------------------------------------------------------
234
+ // the writer, EXECUTED (task 1003213)
235
+ // ---------------------------------------------------------------------------
236
+ //
237
+ // Everything above this line proves the DECISION (planRankSync, called directly
238
+ // with the right argument names) and the SQL TEXT (regex over db.js source). That
239
+ // pair has a hole exactly the width of the call site: nothing asserted that
240
+ // db.syncRank passes planRankSync the parameters it actually destructures.
241
+ //
242
+ // It did not, for a week. The ADR 0174 governance→government rename landed the
243
+ // call site as `planRankSync({ rank, currentRoles, seededRoles })` (14dcedd) and
244
+ // then renamed the planner's parameters to `currentRanks`/`seededRanks` (f7cdcce).
245
+ // The planner therefore read an EMPTY seed list, returned target:null / add:[],
246
+ // and syncRank silently wrote NOTHING — no throw, so safeSyncRankRole logged
247
+ // nothing either. Every builder whose first sign-in came after their instance's
248
+ // run-once governance_002 backfill held ZERO permissions (getPermissionKeysForBuilder
249
+ // resolves only through government_builder_ranks), including a freshly seated
250
+ // Archon owner locked out of their own hall.
251
+ //
252
+ // So these RUN the writer against a recording client. A rename that desynchronises
253
+ // the call site from the planner fails here, where source-text assertions cannot see it.
254
+
255
+ const govDb = require(path.join(GOV, 'db.js'));
256
+
257
+ // A stand-in for the caller's transaction client that records every statement and
258
+ // answers the writer's two reads. Order matters: the assignments read also names
259
+ // `government_ranks` (it joins it), so match the more specific table first.
260
+ function recordingClient({ seeded = SEEDED, held = [] } = {}) {
261
+ const calls = [];
262
+ return {
263
+ calls,
264
+ find: (re) => calls.find((c) => re.test(c.sql)),
265
+ async query(sql, params) {
266
+ calls.push({ sql, params });
267
+ if (/INSERT INTO|DELETE FROM/.test(sql)) return { rows: [] };
268
+ if (/FROM government_builder_ranks br/.test(sql)) return { rows: held };
269
+ if (/FROM government_ranks/.test(sql)) return { rows: seeded };
270
+ return { rows: [] };
271
+ },
272
+ };
273
+ }
274
+
275
+ test('the writer EXECUTES its plan: a rank-less builder really gets the INSERT', async () => {
276
+ const c = recordingClient({ held: [] });
277
+ const res = await govDb.syncRank(c, { builderId: 42, rank: 'archon' });
278
+
279
+ // The verdict must survive the call site — target:null here is the regression.
280
+ assert.equal(res.target, 'archon',
281
+ 'syncRank must pass planRankSync the parameter names it destructures (currentRanks/seededRanks)');
282
+ assert.deepEqual([...res.added], ['archon']);
283
+
284
+ const insert = c.find(/INSERT INTO government_builder_ranks/);
285
+ assert.ok(insert, 'the assignment INSERT must actually be issued, not merely present in the source');
286
+ assert.deepEqual(insert.params, [42, ['archon']],
287
+ 'the INSERT must name the builder and the seeded rank the plan chose');
288
+ });
289
+
290
+ test('the writer EXECUTES its plan: a demotion really issues the DELETE', async () => {
291
+ // The trust-boundary half: a demoted Archon must lose `archon` on the next request.
292
+ const c = recordingClient({ held: [seededRank_('archon')] });
293
+ const res = await govDb.syncRank(c, { builderId: 7, rank: 'thetes' });
294
+
295
+ assert.equal(res.target, 'thetes');
296
+ assert.deepEqual([...res.removed], ['archon']);
297
+
298
+ const del = c.find(/DELETE FROM government_builder_ranks/);
299
+ assert.ok(del, 'the superseded assignment DELETE must actually be issued');
300
+ assert.deepEqual(del.params, [7, ['archon']]);
301
+ });
302
+
303
+ test('the writer EXECUTES its plan: an unchanged rank writes nothing (idempotence)', async () => {
304
+ const c = recordingClient({ held: [seededRank_('metic')] });
305
+ const res = await govDb.syncRank(c, { builderId: 9, rank: 'metic' });
306
+
307
+ assert.deepEqual([...res.added], []);
308
+ assert.deepEqual([...res.removed], []);
309
+ assert.ok(!c.find(/INSERT INTO|DELETE FROM/),
310
+ 'a builder already holding the right rank must cost reads only — no write');
311
+ });
312
+
313
+ test('the writer EXECUTES its plan: a custom rank survives a rank change', async () => {
314
+ const c = recordingClient({ held: [seededRank_('archon'), customRank('release-manager')] });
315
+ const res = await govDb.syncRank(c, { builderId: 11, rank: 'metic' });
316
+
317
+ assert.deepEqual([...res.removed], ['archon'],
318
+ 'only seeded ranks rotate — an Archon-assigned custom rank must never be revoked');
319
+ const del = c.find(/DELETE FROM government_builder_ranks/);
320
+ assert.deepEqual(del.params, [11, ['archon']]);
321
+ });