@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 +9 -9
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +3 -1
- package/tests/lib_sh_resolution.mjs +142 -0
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
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:
|
|
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": "
|
|
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": "
|
|
4725
|
+
"sha256": "c3a2cfd45a78396f4f7186492cf625a2351f4dfd78c0d82dbffc4217db97a68d"
|
|
4726
4726
|
},
|
|
4727
4727
|
{
|
|
4728
4728
|
"path": "package.json",
|
|
4729
4729
|
"mode": "0000644",
|
|
4730
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
+
});
|