@bongos/core 1.19.624 → 1.19.625
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 +10 -10
- package/docs/module-api-changelog.md +2 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +1 -1
- package/tests/cli_sessions.mjs +109 -4
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.625",
|
|
6
|
+
"core_contract": "1.19.625",
|
|
7
|
+
"source_commit": "19a2b295b0d1a0755168ec39b249dc1a5f9b961e",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-09T08:21:23.081Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 464,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 2582,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "c6d6c5f0e0b67618fd3d94d6beb816506c9d15c480cc0dc0de0768b4b27cce23",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/backlog-review/SKILL.md",
|
|
@@ -2757,7 +2757,7 @@
|
|
|
2757
2757
|
{
|
|
2758
2758
|
"path": "docs/module-api-changelog.md",
|
|
2759
2759
|
"mode": "0000644",
|
|
2760
|
-
"sha256": "
|
|
2760
|
+
"sha256": "6979862e5d574d45a8cf53196775cb2f3c53e601e4f812e3bd69c3b3a9c7cc15"
|
|
2761
2761
|
},
|
|
2762
2762
|
{
|
|
2763
2763
|
"path": "docs/modules-contract.md",
|
|
@@ -7682,12 +7682,12 @@
|
|
|
7682
7682
|
{
|
|
7683
7683
|
"path": "package-lock.json",
|
|
7684
7684
|
"mode": "0000644",
|
|
7685
|
-
"sha256": "
|
|
7685
|
+
"sha256": "b1bf1316b6bf58eede860ae199233be76e1beb440d2cf7f4c96171e8f6347f05"
|
|
7686
7686
|
},
|
|
7687
7687
|
{
|
|
7688
7688
|
"path": "package.json",
|
|
7689
7689
|
"mode": "0000644",
|
|
7690
|
-
"sha256": "
|
|
7690
|
+
"sha256": "1e54c8559b66bcda15cbfb24e216bb5d3421a9e0c9d07f240c2414019288fe9a"
|
|
7691
7691
|
},
|
|
7692
7692
|
{
|
|
7693
7693
|
"path": "public-docs/index.html",
|
|
@@ -9422,7 +9422,7 @@
|
|
|
9422
9422
|
{
|
|
9423
9423
|
"path": "src/module-api.js",
|
|
9424
9424
|
"mode": "0000644",
|
|
9425
|
-
"sha256": "
|
|
9425
|
+
"sha256": "7a6f5a46c866658041e6299fe46188834184f510dd496edef5cb2f7b0c414088"
|
|
9426
9426
|
},
|
|
9427
9427
|
{
|
|
9428
9428
|
"path": "src/module-loader/catalog.js",
|
|
@@ -10032,7 +10032,7 @@
|
|
|
10032
10032
|
{
|
|
10033
10033
|
"path": "tests/cli_sessions.mjs",
|
|
10034
10034
|
"mode": "0000644",
|
|
10035
|
-
"sha256": "
|
|
10035
|
+
"sha256": "ab1ee394c03eccadee0958ea38595e1f4e221146b593559e3474c9573d81ecf7"
|
|
10036
10036
|
},
|
|
10037
10037
|
{
|
|
10038
10038
|
"path": "tests/cli_surface.mjs",
|
|
@@ -1697,5 +1697,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1697
1697
|
landed since 1.19.622 with no explicit bump. run 34323141703. (task 1002620)
|
|
1698
1698
|
1.19.624 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1699
1699
|
landed since 1.19.623 with no explicit bump. run 34326009063. (task 1002620)
|
|
1700
|
+
1.19.625 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1701
|
+
landed since 1.19.624 with no explicit bump. run 34328603214. (task 1002620)
|
|
1700
1702
|
---------------------------------------------------------------------------
|
|
1701
1703
|
```
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.625",
|
|
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.625",
|
|
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.625",
|
|
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
|
@@ -55,7 +55,7 @@ const { buildInfo } = require('./build-info');
|
|
|
55
55
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
56
56
|
// the entry to that file. Look for a version's history there, not here.
|
|
57
57
|
// ---------------------------------------------------------------------------
|
|
58
|
-
const CORE_VERSION = '1.19.
|
|
58
|
+
const CORE_VERSION = '1.19.625'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
59
59
|
|
|
60
60
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
61
61
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/cli_sessions.mjs
CHANGED
|
@@ -28,16 +28,79 @@ const ic = require(path.join(REPO_ROOT, 'src', 'instance-config.js'));
|
|
|
28
28
|
const lib = require(path.join(REPO_ROOT, 'scripts', 'gds', 'cli-lib.js'));
|
|
29
29
|
|
|
30
30
|
// SESSION_PATH is frozen at module load from os.homedir(), so anything touching the real save path
|
|
31
|
-
// runs in a child with its own
|
|
31
|
+
// runs in a child with its own home directory.
|
|
32
|
+
//
|
|
33
|
+
// SETTING `HOME` ALONE IS NOT ISOLATION, AND THE MISS COST REAL CREDENTIALS (task 1003760).
|
|
34
|
+
// On Windows os.homedir() reads USERPROFILE and never consults HOME, so the original
|
|
35
|
+
// `env: { ...process.env, HOME: home }` isolated nothing there: every child below wrote
|
|
36
|
+
// its fixtures into the developer's ACTUAL ~/.config/<instance>/, overwriting the live
|
|
37
|
+
// CLI session with `token:'TOKEN-A', api_base:'https://a.example.com'` and leaving
|
|
38
|
+
// a.example.com.json / b.example.com.json / broken.json in the real session store. The
|
|
39
|
+
// owner had to re-issue a CLI token to recover, and because a claim is bound to the
|
|
40
|
+
// session that created it, the re-auth then orphaned an in-flight claim too.
|
|
41
|
+
//
|
|
42
|
+
// CI is Linux, where HOME *is* honoured — so this can never go red there. Two layers,
|
|
43
|
+
// because the platform list is not knowable in advance:
|
|
44
|
+
// 1. Override every variable a platform might read (USERPROFILE is the Windows one;
|
|
45
|
+
// HOMEDRIVE/HOMEPATH are the legacy fallback os.homedir() tries next).
|
|
46
|
+
// 2. FAIL CLOSED IN THE CHILD: prove os.homedir() actually landed in the sandbox
|
|
47
|
+
// BEFORE running any body, and abort if it did not. A future platform that reads
|
|
48
|
+
// some third variable then fails this test loudly instead of silently eating the
|
|
49
|
+
// developer's credentials — which is the only outcome that is acceptable for a
|
|
50
|
+
// test whose whole job is writing to a session store.
|
|
51
|
+
// THE AUDIT THIS FIX OWED, RECORDED HERE RATHER THAN IN A SHIP NOTE. `grep -rn "HOME:"
|
|
52
|
+
// tests/ scripts/` at the time of the fix (task 1003760) found the pattern in ten files.
|
|
53
|
+
// Three already override the Windows variable and are correct: tests/memory_pull.mjs:438,
|
|
54
|
+
// tests/redteam_patrol.mjs:123, tests/setup_device_flow_fallback.mjs:130 — so the
|
|
55
|
+
// convention existed and THIS file simply missed it. Two still set HOME alone and can go
|
|
56
|
+
// FALSE-GREEN on Windows, tracked as task 1003763: tests/cli_package.mjs:140+149 (whose own
|
|
57
|
+
// comment says the temp HOME exists "so a real session file on this machine cannot make a
|
|
58
|
+
// verb look healthier than it is" — on Windows it can) and tests/cli_surface.mjs:174 (which
|
|
59
|
+
// points HOME at a nonexistent dir to simulate "no session", and on Windows sees the real
|
|
60
|
+
// one). Neither DESTROYS anything — this file was the only one writing a session store — so
|
|
61
|
+
// they were filed rather than folded in. Two uses are legitimately HOME-only and must stay:
|
|
62
|
+
// tests/scrubber_corpus.mjs:228 uses HOME:'/root' as corpus DATA, and
|
|
63
|
+
// tests/lib_sh_resolution.mjs exercises POSIX shell resolution where HOME is the subject.
|
|
64
|
+
// They are why closing this class needs an allowlist, not a blanket rule (1003763).
|
|
65
|
+
//
|
|
66
|
+
// Also done off-repo when this landed, and unverifiable from a diff, so stated plainly: the
|
|
67
|
+
// three fixture files this bug left in the REAL session store — a.example.com.json,
|
|
68
|
+
// b.example.com.json, broken.json under ~/.config/<instance>/instances/ — were deleted, and
|
|
69
|
+
// the live session + auth were re-verified afterwards.
|
|
70
|
+
//
|
|
71
|
+
// KNOWN GAP, deliberately left: on Windows this suite now asserts no permission-tightness
|
|
72
|
+
// property at all (see the owner-only test below). NTFS has no POSIX triad, so the real
|
|
73
|
+
// property is the per-user profile ACL; an icacls-style assertion would restore the signal
|
|
74
|
+
// and does not exist here.
|
|
75
|
+
function sandboxEnv(home) {
|
|
76
|
+
const { root } = path.parse(home);
|
|
77
|
+
return {
|
|
78
|
+
...process.env,
|
|
79
|
+
HOME: home,
|
|
80
|
+
USERPROFILE: home, // Windows: what os.homedir() actually reads
|
|
81
|
+
HOMEDRIVE: root.replace(/[\\/]+$/, ''), // legacy Windows fallback pair
|
|
82
|
+
HOMEPATH: home.slice(root.length - 1) || '\\',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
32
86
|
function inSandbox(body) {
|
|
33
87
|
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'bongos-sess-'));
|
|
34
88
|
try {
|
|
35
89
|
const code = `const R=${JSON.stringify(REPO_ROOT)};
|
|
90
|
+
const SANDBOX=${JSON.stringify(home)};
|
|
91
|
+
const os=require('node:os');
|
|
92
|
+
// Layer 2: refuse to touch a session store outside the sandbox. Runs before the
|
|
93
|
+
// requires below so not even a module-load side effect can reach the real home.
|
|
94
|
+
if (os.homedir() !== SANDBOX) {
|
|
95
|
+
console.error('ERR sandbox-escape: os.homedir()=' + os.homedir() + ' but the sandbox is ' + SANDBOX
|
|
96
|
+
+ ' — this platform does not take the home override, and writing here would clobber the real session store.');
|
|
97
|
+
process.exit(2);
|
|
98
|
+
}
|
|
36
99
|
const lib=require(R+'/scripts/gds/cli-lib.js');
|
|
37
100
|
const ic=require(R+'/src/instance-config.js');
|
|
38
101
|
const fs=require('node:fs'), path=require('node:path');
|
|
39
102
|
(async()=>{ ${body} })().catch((e)=>{ console.error('ERR '+e.message); process.exit(1); });`;
|
|
40
|
-
const r = spawnSync(process.execPath, ['-e', code], { encoding: 'utf8', env:
|
|
103
|
+
const r = spawnSync(process.execPath, ['-e', code], { encoding: 'utf8', env: sandboxEnv(home) });
|
|
41
104
|
return { home, out: `${r.stdout || ''}${r.stderr || ''}`, status: r.status };
|
|
42
105
|
} finally {
|
|
43
106
|
fs.rmSync(home, { recursive: true, force: true });
|
|
@@ -78,6 +141,36 @@ test('the store anchor is FIXED, not brand-derived — that is the whole fix', (
|
|
|
78
141
|
assert.ok(!/configHome|configDirName|safeBrand/.test(fn), `sessionStoreDir must not read the brand:\n${fn}`);
|
|
79
142
|
});
|
|
80
143
|
|
|
144
|
+
// ── 1b. The sandbox is really a sandbox ─────────────────────────────────────────────────────
|
|
145
|
+
//
|
|
146
|
+
// These guard the guard (task 1003760). Every test below writes to a session store, so if
|
|
147
|
+
// the isolation is a no-op they write to the DEVELOPER'S store — which is exactly what
|
|
148
|
+
// happened on Windows, where os.homedir() reads USERPROFILE and the original helper set
|
|
149
|
+
// only HOME. A test suite that can delete credentials must prove it cannot before it runs.
|
|
150
|
+
|
|
151
|
+
test('the sandbox actually relocates os.homedir() — on THIS platform', () => {
|
|
152
|
+
const { out, status, home } = inSandbox(`console.log(JSON.stringify({ h: require('node:os').homedir() }));`);
|
|
153
|
+
assert.equal(status, 0, `sandbox child failed: ${out}`);
|
|
154
|
+
const { h } = JSON.parse(out.trim().split('\n').pop());
|
|
155
|
+
assert.equal(h, home,
|
|
156
|
+
'os.homedir() inside the sandbox must BE the sandbox — otherwise every test here writes to the real session store');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('a session store path resolved inside the sandbox stays inside it', () => {
|
|
160
|
+
const { out, status, home } = inSandbox(`console.log(JSON.stringify({ p: ic.configPath('gds-session.json'), d: lib.sessionStoreDir() }));`);
|
|
161
|
+
assert.equal(status, 0, `sandbox child failed: ${out}`);
|
|
162
|
+
const { p, d } = JSON.parse(out.trim().split('\n').pop());
|
|
163
|
+
assert.ok(p.startsWith(home), `the active session pointer resolved OUTSIDE the sandbox: ${p}`);
|
|
164
|
+
assert.ok(d.startsWith(home), `the session store dir resolved OUTSIDE the sandbox: ${d}`);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('sandboxEnv overrides every home variable a platform might read', () => {
|
|
168
|
+
const env = sandboxEnv(path.join(os.tmpdir(), 'probe-home'));
|
|
169
|
+
assert.equal(env.HOME, path.join(os.tmpdir(), 'probe-home'));
|
|
170
|
+
assert.equal(env.USERPROFILE, env.HOME, 'USERPROFILE is the one Windows reads — the original miss');
|
|
171
|
+
assert.ok('HOMEDRIVE' in env && 'HOMEPATH' in env, 'the legacy Windows fallback pair must be set too');
|
|
172
|
+
});
|
|
173
|
+
|
|
81
174
|
// ── 2. A login never destroys another instance's session ────────────────────────────────────
|
|
82
175
|
|
|
83
176
|
test('signing into a second instance PRESERVES the first — including one written before the store existed', () => {
|
|
@@ -127,13 +220,25 @@ test('re-saving the SAME instance is idempotent and files nothing extra', () =>
|
|
|
127
220
|
assert.equal(r.token, 'T2');
|
|
128
221
|
});
|
|
129
222
|
|
|
223
|
+
// POSIX MODE BITS DO NOT EXIST ON WINDOWS, so this assertion could never pass there
|
|
224
|
+
// (task 1003760). NTFS has no owner/group/other triad: Node reports 0666 for any
|
|
225
|
+
// writable file and 0444 for a read-only one, and chmod(0o600) is silently a no-op —
|
|
226
|
+
// measured on win32, both before and after an explicit chmod. Asserting '600' there
|
|
227
|
+
// made the unit suite permanently red on every Windows checkout, which is the exact
|
|
228
|
+
// harm task 1003754 names: a test that always fails is how a genuinely failing suite
|
|
229
|
+
// stops being read. So the mode claim is asserted where the platform can express it,
|
|
230
|
+
// and on Windows the file's EXISTENCE is still asserted — the security property has
|
|
231
|
+
// to be met by NTFS ACLs (the per-user profile directory), not by a mode integer.
|
|
130
232
|
test('session files are owner-only', () => {
|
|
131
233
|
const { out } = inSandbox(`
|
|
132
234
|
await lib.saveSession({ token:'T', api_base:'https://a.example.com', builder:{github_login:'x'} });
|
|
133
|
-
const
|
|
235
|
+
const p = lib.sessionStorePath('https://a.example.com');
|
|
236
|
+
const f = fs.statSync(p).mode & 0o777;
|
|
134
237
|
const d = fs.statSync(lib.sessionStoreDir()).mode & 0o777;
|
|
135
|
-
console.log(JSON.stringify({ file: f.toString(8), dir: d.toString(8) }));`);
|
|
238
|
+
console.log(JSON.stringify({ file: f.toString(8), dir: d.toString(8), exists: fs.existsSync(p) }));`);
|
|
136
239
|
const r = JSON.parse(out.trim().split('\n').pop());
|
|
240
|
+
assert.equal(r.exists, true, 'the session file must be written wherever we run');
|
|
241
|
+
if (process.platform === 'win32') return; // no POSIX triad to assert — see above
|
|
137
242
|
assert.equal(r.file, '600', 'a session file holds a bearer token');
|
|
138
243
|
assert.equal(r.dir, '700');
|
|
139
244
|
});
|