@bongos/core 1.19.218 → 1.19.219
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/modules/dev-box/box-access.js +47 -8
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +3 -1
- package/tests/box_access.mjs +57 -2
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.219",
|
|
6
|
+
"core_contract": "1.19.219",
|
|
7
|
+
"source_commit": "c74ac31eedb3ec3676f8517b51302df625298931",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-18T03:06:20.562Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 311,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 1634,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "4da1158ccf79b2a7a5253dad319cc74192493be9bda2e6a8874df8c60f581cc5",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -2697,7 +2697,7 @@
|
|
|
2697
2697
|
{
|
|
2698
2698
|
"path": "modules/dev-box/box-access.js",
|
|
2699
2699
|
"mode": "0000644",
|
|
2700
|
-
"sha256": "
|
|
2700
|
+
"sha256": "870976966de7c48be4172390dc8e4f7d2eb6ac53e20dfb3fd5d40b08cfcd7850"
|
|
2701
2701
|
},
|
|
2702
2702
|
{
|
|
2703
2703
|
"path": "modules/dev-box/box-credential.js",
|
|
@@ -4287,12 +4287,12 @@
|
|
|
4287
4287
|
{
|
|
4288
4288
|
"path": "package-lock.json",
|
|
4289
4289
|
"mode": "0000644",
|
|
4290
|
-
"sha256": "
|
|
4290
|
+
"sha256": "ac23681c5493a57f1faca551e4896e4a7a4e2dabb6246bf2a84c39ae6e571257"
|
|
4291
4291
|
},
|
|
4292
4292
|
{
|
|
4293
4293
|
"path": "package.json",
|
|
4294
4294
|
"mode": "0000644",
|
|
4295
|
-
"sha256": "
|
|
4295
|
+
"sha256": "7122e5cca352a5abc317d25267eba6c0bab955febf2179bf362a896be424d0bc"
|
|
4296
4296
|
},
|
|
4297
4297
|
{
|
|
4298
4298
|
"path": "public-docs/index.html",
|
|
@@ -5907,7 +5907,7 @@
|
|
|
5907
5907
|
{
|
|
5908
5908
|
"path": "src/module-api.js",
|
|
5909
5909
|
"mode": "0000644",
|
|
5910
|
-
"sha256": "
|
|
5910
|
+
"sha256": "d509a7e4f16027ccef999e8aadf1a2cef5368bce5cd0c3bda3b7eb61cbceaa5f"
|
|
5911
5911
|
},
|
|
5912
5912
|
{
|
|
5913
5913
|
"path": "src/module-loader/catalog.js",
|
|
@@ -6202,7 +6202,7 @@
|
|
|
6202
6202
|
{
|
|
6203
6203
|
"path": "tests/box_access.mjs",
|
|
6204
6204
|
"mode": "0000644",
|
|
6205
|
-
"sha256": "
|
|
6205
|
+
"sha256": "1e4db680c5925e473fff9ad6247e797bd9089fdf3696c3ffb161903bda41dcda"
|
|
6206
6206
|
},
|
|
6207
6207
|
{
|
|
6208
6208
|
"path": "tests/box_auth_check.mjs",
|
|
@@ -171,24 +171,63 @@ const BASE_SPARSE_PATHS = [
|
|
|
171
171
|
// globs come in two shapes: directory globs (trailing '/', e.g. 'modules/dev-box/')
|
|
172
172
|
// and file-list globs (exact paths, e.g. the kernel key's 'src/bongos/db.js'). We
|
|
173
173
|
// KEEP the directory globs (normalized to no trailing slash, matching the BASE
|
|
174
|
-
// style)
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
// BASE
|
|
174
|
+
// style). A FILE glob cannot be emitted as-is, so it contributes its PARENT
|
|
175
|
+
// DIRECTORY instead — unless BASE or another emitted dir already covers it.
|
|
176
|
+
//
|
|
177
|
+
// It used to be dropped outright, on the reasoning that "every file glob in the
|
|
178
|
+
// map sits under a BASE directory (src/bongos, scripts) or is a top-level file
|
|
179
|
+
// cone mode pulls automatically". That was true when written and **silently
|
|
180
|
+
// stopped being true**: ADR 0174 gave the `government` key the file globs
|
|
181
|
+
// `config/government.json` + `config/government.neutral.json`, and `config` is
|
|
182
|
+
// not in BASE. The result was a goal walled to `government` whose box could never
|
|
183
|
+
// see two files inside its own scope wall — which released task 1003018 (R05 of
|
|
184
|
+
// goal 1000069), whose entire deliverable was one of them. Rather than restore an
|
|
185
|
+
// invariant that expires again the next time a module claims a config file, the
|
|
186
|
+
// parent is emitted and the class is covered by construction.
|
|
187
|
+
//
|
|
188
|
+
// TRADE-OFF, stated rather than implied: the parent directory is a SUPERSET of
|
|
189
|
+
// the glob — asking for `config/government.json` materializes all of `config/`.
|
|
190
|
+
// The box's view is already a superset of the wall (BASE hands out `scripts`,
|
|
191
|
+
// `docs` and `tests` wholesale regardless of scope), so this is consistent with
|
|
192
|
+
// the existing posture, not a new concession. The WALL is unchanged: what a
|
|
193
|
+
// builder may author is still decided by goal-scope-check against the globs, not
|
|
194
|
+
// by what happens to be on disk.
|
|
195
|
+
//
|
|
196
|
+
// Top-level file globs (no '/') contribute nothing — cone mode includes root
|
|
197
|
+
// files automatically. Deterministic: BASE in declared order, then the module
|
|
198
|
+
// dirs sorted + deduped.
|
|
179
199
|
function sparsePathsForScopeKeys(scopeKeys, moduleScopeMap) {
|
|
180
200
|
const base = [...BASE_SPARSE_PATHS];
|
|
181
201
|
const seen = new Set(base);
|
|
182
202
|
const extra = [];
|
|
203
|
+
// Cone mode materializes a directory and everything under it, so a path is
|
|
204
|
+
// already covered when IT or any ancestor has been emitted. This is what keeps
|
|
205
|
+
// `scripts/gds/box.js` from adding `scripts/gds` — BASE's `scripts` covers it.
|
|
206
|
+
const covered = (dir) => {
|
|
207
|
+
let p = dir;
|
|
208
|
+
for (;;) {
|
|
209
|
+
if (seen.has(p)) return true;
|
|
210
|
+
const cut = p.lastIndexOf('/');
|
|
211
|
+
if (cut < 0) return false;
|
|
212
|
+
p = p.slice(0, cut);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const add = (dir) => {
|
|
216
|
+
if (!dir || covered(dir)) return;
|
|
217
|
+
seen.add(dir);
|
|
218
|
+
extra.push(dir);
|
|
219
|
+
};
|
|
183
220
|
for (const key of Array.isArray(scopeKeys) ? scopeKeys : []) {
|
|
184
221
|
const entry = moduleScopeMap && typeof moduleScopeMap.scopeForModule === 'function'
|
|
185
222
|
? moduleScopeMap.scopeForModule(key)
|
|
186
223
|
: null;
|
|
187
224
|
if (!entry || !Array.isArray(entry.globs)) continue;
|
|
188
225
|
for (const glob of entry.globs) {
|
|
189
|
-
if (typeof glob !== 'string' || !glob
|
|
190
|
-
|
|
191
|
-
|
|
226
|
+
if (typeof glob !== 'string' || !glob) continue;
|
|
227
|
+
if (glob.endsWith('/')) { add(glob.replace(/\/+$/, '')); continue; }
|
|
228
|
+
const cut = glob.lastIndexOf('/');
|
|
229
|
+
if (cut < 0) continue; // a root file — cone mode already includes it
|
|
230
|
+
add(glob.slice(0, cut));
|
|
192
231
|
}
|
|
193
232
|
}
|
|
194
233
|
extra.sort();
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.219",
|
|
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.219",
|
|
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.219",
|
|
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
|
@@ -863,8 +863,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
863
863
|
// landed since 1.19.216 with no explicit bump. run 32084927511. (task 1002620)
|
|
864
864
|
// 1.19.218 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
865
865
|
// landed since 1.19.217 with no explicit bump. run 32086598601. (task 1002620)
|
|
866
|
+
// 1.19.219 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
867
|
+
// landed since 1.19.218 with no explicit bump. run 32094215476. (task 1002620)
|
|
866
868
|
// ---------------------------------------------------------------------------
|
|
867
|
-
const CORE_VERSION = '1.19.
|
|
869
|
+
const CORE_VERSION = '1.19.219'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
868
870
|
|
|
869
871
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
870
872
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/box_access.mjs
CHANGED
|
@@ -221,14 +221,69 @@ t('cone-filter: dev-box keeps its DIRS, DROPS its file globs (scripts/gds/box.js
|
|
|
221
221
|
assert.ok(out.includes('devbox-app'), 'the app dir is kept');
|
|
222
222
|
assert.ok(!out.some((p) => p.endsWith('.js') || p.endsWith('.sh')), 'no file globs survive the cone filter');
|
|
223
223
|
assert.ok(!out.includes('scripts/gds/box.js'), 'the box CLI file is dropped (BASE scripts covers it)');
|
|
224
|
+
// …and its PARENT is not added either: BASE's `scripts` already covers it, so
|
|
225
|
+
// the ancestor check must stop `scripts/gds` from appearing. This is the half
|
|
226
|
+
// that keeps the file-glob rescue below from over-sharing.
|
|
227
|
+
assert.ok(!out.includes('scripts/gds'), 'a covered parent is not re-emitted');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// A file glob whose parent is NOT already covered must contribute that parent.
|
|
231
|
+
// Regression for the live failure that released task 1003018 (R05 of goal
|
|
232
|
+
// 1000069): the `government` key's config/government*.json globs were dropped on
|
|
233
|
+
// the reasoning that every file glob sits under a BASE directory — true when
|
|
234
|
+
// written, false once ADR 0174 added them, since `config` is not in BASE. The box
|
|
235
|
+
// could not see two files inside its own scope wall.
|
|
236
|
+
t('file-glob rescue: government contributes `config` for its config/*.json globs', () => {
|
|
237
|
+
const out = access.sparsePathsForScopeKeys(['government'], scopeMap);
|
|
238
|
+
assert.ok(out.includes('modules/government'), 'the module dir is kept');
|
|
239
|
+
assert.ok(out.includes('config'), 'config/government.neutral.json must reach the box via its parent');
|
|
240
|
+
assert.ok(!out.some((p) => p.endsWith('.json')), 'still no file paths — cone mode would reject one');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
t('file-glob rescue holds for EVERY key in the map — no module can silently lose one', () => {
|
|
244
|
+
// Enumerated, never sampled: a module that gains a file glob under a new parent
|
|
245
|
+
// is covered the day it lands, which is exactly how this bug escaped before.
|
|
246
|
+
for (const key of scopeMap.moduleKeys()) {
|
|
247
|
+
const out = access.sparsePathsForScopeKeys([key], scopeMap);
|
|
248
|
+
for (const glob of scopeMap.scopeForModule(key).globs) {
|
|
249
|
+
if (glob.endsWith('/')) continue;
|
|
250
|
+
const cut = glob.lastIndexOf('/');
|
|
251
|
+
if (cut < 0) continue; // a root file — cone mode includes it automatically
|
|
252
|
+
const parent = glob.slice(0, cut);
|
|
253
|
+
const reachable = out.some((p) => parent === p || parent.startsWith(`${p}/`));
|
|
254
|
+
assert.ok(reachable, `${key}: no cone path materializes ${glob} (parent ${parent})`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
t('the emitted set stays directories only, for every key', () => {
|
|
260
|
+
// A leading dot is a DIRECTORY here ('.devcontainer', '.claude'), so the
|
|
261
|
+
// extension test must require a non-dot character before the dot — otherwise
|
|
262
|
+
// every BASE dotfile-dir reads as a file and this assertion fires on healthy
|
|
263
|
+
// input. (It did, on first write.)
|
|
264
|
+
const looksLikeFile = (seg) => /[^.]\.[a-z0-9]+$/i.test(seg);
|
|
265
|
+
for (const key of scopeMap.moduleKeys()) {
|
|
266
|
+
for (const p of access.sparsePathsForScopeKeys([key], scopeMap)) {
|
|
267
|
+
assert.ok(!looksLikeFile(p.split('/').pop()),
|
|
268
|
+
`${key}: ${p} looks like a file — git sparse-checkout set would abort on it`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
224
271
|
});
|
|
225
272
|
|
|
226
|
-
t('cone-filter: the kernel key
|
|
273
|
+
t('cone-filter: the kernel key materializes its real DIR globs (config, src/module-loader)', () => {
|
|
227
274
|
const out = access.sparsePathsForScopeKeys(['kernel'], scopeMap);
|
|
228
275
|
// kernel is mostly individual src/bongos/*.js FILES (dropped — BASE src/bongos
|
|
229
276
|
// covers them via cone ancestor-inclusion) + a few genuine DIR globs.
|
|
230
277
|
assert.ok(out.includes('config'), 'config/ is a real dir the task needs, not in BASE');
|
|
231
|
-
|
|
278
|
+
// src/module-loader/ is a real dir not in BASE, but it is NOT emitted verbatim:
|
|
279
|
+
// kernel also carries the file globs src/instance-config.js, src/branding.js,
|
|
280
|
+
// src/modules.js and src/module-api.js, whose rescued parent is `src` — and once
|
|
281
|
+
// `src` is emitted the ancestor check absorbs every path beneath it, this one
|
|
282
|
+
// included. Asserting literal membership would be asserting emission ORDER, not
|
|
283
|
+
// reachability. What the box must actually get is the DIRECTORY's contents, so
|
|
284
|
+
// assert that, using the same idiom as the enumerated rescue test above.
|
|
285
|
+
const reaches = (dir) => out.some((p) => dir === p || dir.startsWith(`${p}/`));
|
|
286
|
+
assert.ok(reaches('src/module-loader'), 'src/module-loader must be materialized (here via the rescued `src`)');
|
|
232
287
|
assert.ok(!out.includes('src/bongos/db.js'), 'the kernel FILE globs are dropped');
|
|
233
288
|
assert.ok(!out.includes('server.js'), 'top-level files never enter the sparse set (cone auto-includes them)');
|
|
234
289
|
});
|