@bongos/core 1.19.334 → 1.19.335

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.334",
6
- "core_contract": "1.19.334",
7
- "source_commit": "17d7b23f872fb3f64737ae5ffe270b91ace779a0",
5
+ "core_version": "1.19.335",
6
+ "core_contract": "1.19.335",
7
+ "source_commit": "b5f2b884a9011be30bffe5bbd62c272a7497314a",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-25T00:36:48.394Z",
9
+ "built_at": "2026-08-25T00:51:04.860Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 325,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 1837,
20
- "tree_sha256": "15089adb0fd9a51245746cbd141dd57dceadee53a5e640beb0d7059c7f219610",
20
+ "tree_sha256": "9792847e3608bc598acfe751efe68d1e8cbb5b0ab10a19490cf2f325db36a44c",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -4722,12 +4722,12 @@
4722
4722
  {
4723
4723
  "path": "package-lock.json",
4724
4724
  "mode": "0000644",
4725
- "sha256": "27cc593724db16a7e292e6f8287d3fadfbda3a6eaff49c1c97a08fe5bf175ce5"
4725
+ "sha256": "c3a2cfd45a78396f4f7186492cf625a2351f4dfd78c0d82dbffc4217db97a68d"
4726
4726
  },
4727
4727
  {
4728
4728
  "path": "package.json",
4729
4729
  "mode": "0000644",
4730
- "sha256": "5d2f06a29143a871ca7dd2f20d46ba2b05389a57aafddc6891147baa2a00e124"
4730
+ "sha256": "9896b1417474da8bf8b09e8dd188455d6d75b5e95602c7409a81ea17ee6e4cc3"
4731
4731
  },
4732
4732
  {
4733
4733
  "path": "public-docs/index.html",
@@ -6577,7 +6577,7 @@
6577
6577
  {
6578
6578
  "path": "src/module-api.js",
6579
6579
  "mode": "0000644",
6580
- "sha256": "717fc58e2725b43ec1bc0a0e995172992ed0b42cba603c68482292b70da67c57"
6580
+ "sha256": "490504c9d10309b811026a035d5999360cbe00b8eb912bb8c4d0873c8271cff2"
6581
6581
  },
6582
6582
  {
6583
6583
  "path": "src/module-loader/catalog.js",
@@ -8072,7 +8072,7 @@
8072
8072
  {
8073
8073
  "path": "tests/lib_sh_resolution.mjs",
8074
8074
  "mode": "0000644",
8075
- "sha256": "4ec5ac626d9f8a72fe0e0066b266feb1f87b38c0dd8ac52f107c23e37a6a2e97"
8075
+ "sha256": "97630ec5029469ec99c6a87160822f319833857f12a79e42b4a465e362836ef0"
8076
8076
  },
8077
8077
  {
8078
8078
  "path": "tests/lifecycle-card.mjs",
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.334",
3
+ "version": "1.19.335",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.334",
9
+ "version": "1.19.335",
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.334",
3
+ "version": "1.19.335",
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
@@ -1095,8 +1095,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
1095
1095
  // landed since 1.19.332 with no explicit bump. run 32793666555. (task 1002620)
1096
1096
  // 1.19.334 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1097
1097
  // landed since 1.19.333 with no explicit bump. run 32794305277. (task 1002620)
1098
+ // 1.19.335 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1099
+ // landed since 1.19.334 with no explicit bump. run 32795232997. (task 1002620)
1098
1100
  // ---------------------------------------------------------------------------
1099
- const CORE_VERSION = '1.19.334'; // CI auto-patch carrier (ADR 0161); see changelog above
1101
+ const CORE_VERSION = '1.19.335'; // CI auto-patch carrier (ADR 0161); see changelog above
1100
1102
 
1101
1103
  // A namespaced logger so a module's log lines are attributable + consistent.
1102
1104
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -26,6 +26,7 @@ import { test } from 'node:test';
26
26
  import { createRequire } from 'node:module';
27
27
  import { spawnSync } from 'node:child_process';
28
28
  import fs from 'node:fs';
29
+ import os from 'node:os';
29
30
  import path from 'node:path';
30
31
  import { fileURLToPath } from 'node:url';
31
32
  import { fitnessSource } from './helpers.mjs';
@@ -152,3 +153,144 @@ test('the whole host-identity check is green on this tree', () => {
152
153
  const r = fitness.checkKernelPromptsNoHardcodedIdentity();
153
154
  assert.equal(r.ok, true, `violations:\n${r.violations.join('\n')}`);
154
155
  });
156
+
157
+ // ---- 4. the SAME rule applies to the baked box scripts (task 1003252) ------
158
+ //
159
+ // THE SECOND BUG, same class, different file group. The sweep above fixed
160
+ // scripts/gds/*.sh but never looked at infra/box-*.sh — the scripts baked onto a
161
+ // dev box. Those kept reading a hardcoded ~/.config/otb/gds-session.json while
162
+ // paste-token.js writes to ~/.config/<branding.configDir>/. On this instance
163
+ // (configDir "cloudbongos") that meant every /builder-reauth silently stranded the
164
+ // box: the 5-min heartbeat, the terminal/host-key/version reporters and the
165
+ // GDS-backed git credential helper all kept presenting a DEAD token and failing
166
+ // with a misleading "session expired — re-auth on the box", which is exactly what
167
+ // the builder had just done. Observed live: four reporters 401ing every tick and a
168
+ // checkout 311 commits behind origin/main.
169
+ //
170
+ // The fix mirrors instance-config.js's read-side fallback in bash: prefer the most
171
+ // recently written gds-session.json across ~/.config/*/, since branding is not
172
+ // readable from a script that must also run before any clone exists.
173
+
174
+ const BOX_SCRIPTS = [
175
+ 'box-heartbeat.sh',
176
+ 'box-report-terminal.sh',
177
+ 'box-report-host-keys.sh',
178
+ 'box-report-version.sh',
179
+ ];
180
+
181
+ const INFRA = path.join(ROOT, 'infra');
182
+ const boxCode = (f) => fitness.stripCommentsForIdentity(fs.readFileSync(path.join(INFRA, f), 'utf8'), '.sh');
183
+
184
+ test('every baked box script resolves the session across config dirs, not just the legacy one', () => {
185
+ for (const f of BOX_SCRIPTS) {
186
+ const src = boxCode(f);
187
+ assert.match(src, /\.config\/\*\/gds-session\.json/,
188
+ `${f} must fall back across ~/.config/*/ — without it a /builder-reauth into a `
189
+ + 'non-"otb" configDir strands the box on a dead token');
190
+ // The legacy literal may survive ONLY as the last-resort default, never as the
191
+ // sole source — i.e. it must be preceded by the glob scan.
192
+ // The scan widens what these scripts will read, so each candidate must be owned
193
+ // by the box user -- otherwise a file dropped by another local account could win
194
+ // simply by being newest.
195
+ assert.match(src, /\[ -O "\$_sess" \]/,
196
+ `${f} must require candidate session files to be owned by the current user`);
197
+ const globAt = src.indexOf('.config/*/gds-session.json');
198
+ const legacyAt = src.indexOf('.config/otb/gds-session.json');
199
+ if (legacyAt !== -1) {
200
+ assert.ok(globAt < legacyAt,
201
+ `${f} reaches the legacy path before scanning ~/.config/*/ — the fallback must come first`);
202
+ }
203
+ }
204
+ });
205
+
206
+ test('every baked box script passes bash -n', (t) => {
207
+ const probe = bash(['-n', 'infra/box-heartbeat.sh']);
208
+ if (!probe) return t.skip('bash not available on this machine');
209
+ for (const f of BOX_SCRIPTS) {
210
+ const r = bash(['-n', `infra/${f}`]);
211
+ assert.equal(r.status, 0, `bash -n infra/${f} failed:\n${r.stderr}`);
212
+ }
213
+ });
214
+
215
+ // Pull the resolver straight out of the committed file so this exercises the real
216
+ // code, not a copy that could drift away from it.
217
+ function resolverBlock(f) {
218
+ const src = fs.readFileSync(path.join(INFRA, f), 'utf8');
219
+ const start = src.indexOf('if [ -z "${GDS_SESSION:-}" ]; then');
220
+ const endMark = 'GDS_SESSION="${GDS_SESSION:-$HOME/.config/otb/gds-session.json}"';
221
+ const end = src.indexOf(endMark, start);
222
+ assert.ok(start !== -1 && end !== -1, `could not locate the resolver block in ${f}`);
223
+ return src.slice(start, end + endMark.length);
224
+ }
225
+
226
+ test('the resolver prefers the most recently written session across config dirs', (t) => {
227
+ const probe = bash(['-n', 'infra/box-report-version.sh']);
228
+ if (!probe) return t.skip('bash not available on this machine');
229
+
230
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'boxsess-'));
231
+ const legacy = path.join(home, '.config', 'otb');
232
+ const configured = path.join(home, '.config', 'cloudbongos');
233
+ fs.mkdirSync(legacy, { recursive: true });
234
+ fs.mkdirSync(configured, { recursive: true });
235
+ fs.writeFileSync(path.join(legacy, 'gds-session.json'), '{"token":"stale"}');
236
+ fs.writeFileSync(path.join(configured, 'gds-session.json'), '{"token":"fresh"}');
237
+ // Make the legacy copy unambiguously older than the freshly re-authed one.
238
+ const old = new Date(Date.now() - 60_000);
239
+ fs.utimesSync(path.join(legacy, 'gds-session.json'), old, old);
240
+
241
+ const block = resolverBlock('box-report-version.sh');
242
+ const run = (env) => spawnSync('bash', ['-c', `set -uo pipefail\n${block}\nprintf '%s' "$GDS_SESSION"`],
243
+ { encoding: 'utf8', env: { PATH: process.env.PATH, HOME: home, ...env } });
244
+
245
+ // 1. the freshly written session wins over the stale legacy one
246
+ assert.equal(run({}).stdout, path.join(configured, 'gds-session.json'));
247
+
248
+ // 2. an explicit override still beats the scan
249
+ assert.equal(run({ GDS_SESSION: '/explicit/path.json' }).stdout, '/explicit/path.json');
250
+
251
+ // 3. with nothing on disk it falls back to the historical path, so the caller's
252
+ // "no session at ..." message still names somewhere sensible
253
+ const empty = fs.mkdtempSync(path.join(os.tmpdir(), 'boxsess-empty-'));
254
+ const r3 = spawnSync('bash', ['-c', `set -uo pipefail\n${block}\nprintf '%s' "$GDS_SESSION"`],
255
+ { encoding: 'utf8', env: { PATH: process.env.PATH, HOME: empty } });
256
+ assert.equal(r3.stdout, path.join(empty, '.config', 'otb', 'gds-session.json'));
257
+
258
+ fs.rmSync(home, { recursive: true, force: true });
259
+ fs.rmSync(empty, { recursive: true, force: true });
260
+ });
261
+
262
+ // box-heartbeat.sh is the odd one out: its override variable (OTB_GDS_SESSION) is
263
+ // NOT the variable it resolves into (SF). A first cut of the fix guarded on the
264
+ // override but assigned to SF, so a caller that SET the override had it silently
265
+ // dropped and fell through to the legacy default — the exact bug being fixed,
266
+ // reintroduced through the back door. Pin all three branches.
267
+ test('box-heartbeat.sh honors OTB_GDS_SESSION, scans, then falls back', (t) => {
268
+ const probe = bash(['-n', 'infra/box-heartbeat.sh']);
269
+ if (!probe) return t.skip('bash not available on this machine');
270
+
271
+ const src = fs.readFileSync(path.join(INFRA, 'box-heartbeat.sh'), 'utf8');
272
+ const start = src.indexOf('SF="${OTB_GDS_SESSION:-}"');
273
+ const endMark = 'SF="${SF:-$HOME/.config/otb/gds-session.json}"';
274
+ const end = src.indexOf(endMark, start);
275
+ assert.ok(start !== -1 && end !== -1, 'could not locate the SF resolver in box-heartbeat.sh');
276
+ const block = src.slice(start, end + endMark.length);
277
+
278
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'hbsess-'));
279
+ const configured = path.join(home, '.config', 'cloudbongos');
280
+ fs.mkdirSync(configured, { recursive: true });
281
+ fs.writeFileSync(path.join(configured, 'gds-session.json'), '{"token":"fresh"}');
282
+
283
+ const run = (env, h = home) => spawnSync('bash',
284
+ ['-c', `set -euo pipefail\n${block}\nprintf '%s' "$SF"`],
285
+ { encoding: 'utf8', env: { PATH: process.env.PATH, HOME: h, ...env } }).stdout;
286
+
287
+ assert.equal(run({ OTB_GDS_SESSION: '/explicit/override.json' }), '/explicit/override.json',
288
+ 'the OTB_GDS_SESSION override must win — guarding on it but assigning elsewhere drops it');
289
+ assert.equal(run({}), path.join(configured, 'gds-session.json'));
290
+
291
+ const empty = fs.mkdtempSync(path.join(os.tmpdir(), 'hbsess-empty-'));
292
+ assert.equal(run({}, empty), path.join(empty, '.config', 'otb', 'gds-session.json'));
293
+
294
+ fs.rmSync(home, { recursive: true, force: true });
295
+ fs.rmSync(empty, { recursive: true, force: true });
296
+ });