@bongos/core 1.19.707 → 1.19.708
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 +11 -11
- package/docs/module-api-changelog.md +2 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/box-infra.js +33 -0
- package/src/module-api.js +1 -1
- package/tests/box_infra_resolve.mjs +89 -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.708",
|
|
6
|
+
"core_contract": "1.19.708",
|
|
7
|
+
"source_commit": "42f201a980e11b8b417c2afa527230ed1ab05775",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-13T06:
|
|
9
|
+
"built_at": "2026-09-13T06:14:54.451Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 477,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 2639,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "369223629e32da5858cc92a00ab2643eaa169ca59d1d89d6ab77ab8c50e3fd57",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2802,7 +2802,7 @@
|
|
|
2802
2802
|
{
|
|
2803
2803
|
"path": "docs/module-api-changelog.md",
|
|
2804
2804
|
"mode": "0000644",
|
|
2805
|
-
"sha256": "
|
|
2805
|
+
"sha256": "fd622c24f29995f2c8ebdd272cf5784f05285bbafc6c3da490308ed5e1730ba7"
|
|
2806
2806
|
},
|
|
2807
2807
|
{
|
|
2808
2808
|
"path": "docs/modules-contract.md",
|
|
@@ -7782,12 +7782,12 @@
|
|
|
7782
7782
|
{
|
|
7783
7783
|
"path": "package-lock.json",
|
|
7784
7784
|
"mode": "0000644",
|
|
7785
|
-
"sha256": "
|
|
7785
|
+
"sha256": "4f9b97401aebd998dd23bf3ec95a333fd6c596c0ea5551dc02dc6e863ad92742"
|
|
7786
7786
|
},
|
|
7787
7787
|
{
|
|
7788
7788
|
"path": "package.json",
|
|
7789
7789
|
"mode": "0000644",
|
|
7790
|
-
"sha256": "
|
|
7790
|
+
"sha256": "9002e7fc0a70168d56042d71c7905aa045b541dbc36d61e88180a8dfb1e0f559"
|
|
7791
7791
|
},
|
|
7792
7792
|
{
|
|
7793
7793
|
"path": "public-docs/index.html",
|
|
@@ -7982,7 +7982,7 @@
|
|
|
7982
7982
|
{
|
|
7983
7983
|
"path": "scripts/gds/box-infra.js",
|
|
7984
7984
|
"mode": "0000644",
|
|
7985
|
-
"sha256": "
|
|
7985
|
+
"sha256": "431691aed02a415c619dc0ba33106ac1e832e539260eff5f526debebe2d8ffff"
|
|
7986
7986
|
},
|
|
7987
7987
|
{
|
|
7988
7988
|
"path": "scripts/gds/box-sync.js",
|
|
@@ -9567,7 +9567,7 @@
|
|
|
9567
9567
|
{
|
|
9568
9568
|
"path": "src/module-api.js",
|
|
9569
9569
|
"mode": "0000644",
|
|
9570
|
-
"sha256": "
|
|
9570
|
+
"sha256": "98205e89563b71f2e6ddbe44a9639464bdc589c20f3f0a8de12a2b968ac06569"
|
|
9571
9571
|
},
|
|
9572
9572
|
{
|
|
9573
9573
|
"path": "src/module-loader/catalog.js",
|
|
@@ -10012,7 +10012,7 @@
|
|
|
10012
10012
|
{
|
|
10013
10013
|
"path": "tests/box_infra_resolve.mjs",
|
|
10014
10014
|
"mode": "0000644",
|
|
10015
|
-
"sha256": "
|
|
10015
|
+
"sha256": "fde24a8c273a098c89bbbce6c006fa4400448c9522b93707f5cd3f4fb358c515"
|
|
10016
10016
|
},
|
|
10017
10017
|
{
|
|
10018
10018
|
"path": "tests/box_onboard.mjs",
|
|
@@ -1873,5 +1873,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1873
1873
|
landed since 1.19.705 with no explicit bump. run 34740247460. (task 1002620)
|
|
1874
1874
|
1.19.707 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1875
1875
|
landed since 1.19.706 with no explicit bump. run 34741980536. (task 1002620)
|
|
1876
|
+
1.19.708 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1877
|
+
landed since 1.19.707 with no explicit bump. run 34742245823. (task 1002620)
|
|
1876
1878
|
---------------------------------------------------------------------------
|
|
1877
1879
|
```
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.708",
|
|
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.708",
|
|
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.708",
|
|
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/scripts/gds/box-infra.js
CHANGED
|
@@ -216,6 +216,9 @@ function readCloudInit({ authorizedKeysBlock = '', boxEnv = '', gdsSession = '',
|
|
|
216
216
|
// below — they are minted per-provision, not read from infra/. A missing inlined
|
|
217
217
|
// file is COLLECTED and fails loud after the render (ADR 0150) — a half-wired box
|
|
218
218
|
// (that component silently never boots) is a bug, not something to warn past.
|
|
219
|
+
//
|
|
220
|
+
// Every name passed to fileGzB64 below is INSTANCE-owned and deliberately absent
|
|
221
|
+
// from the neutral core's own infra/ — see infra/README.md (ADR 0150).
|
|
219
222
|
const missingInfra = [];
|
|
220
223
|
const fileGzB64 = (name) => {
|
|
221
224
|
try {
|
|
@@ -267,6 +270,36 @@ function readCloudInit({ authorizedKeysBlock = '', boxEnv = '', gdsSession = '',
|
|
|
267
270
|
+ `— a box would boot half-wired (ADR 0150). Fix the instance infra/ before provisioning.`,
|
|
268
271
|
);
|
|
269
272
|
}
|
|
273
|
+
// ADR 0150 prong B named this escalation and never implemented it: "assert no
|
|
274
|
+
// __…_B64__ placeholders survive the render, so a *partial* infra/ also surfaces
|
|
275
|
+
// rather than half-wiring". The missingInfra check above only catches files THIS
|
|
276
|
+
// file knows to ask for. It cannot catch the other direction — an instance
|
|
277
|
+
// template carrying a token box-infra.js does not substitute. That renders a
|
|
278
|
+
// cloud-init with the literal token in it, and cloud-init happily writes the
|
|
279
|
+
// garbage as a file: the box boots half-wired, silently, which is the one
|
|
280
|
+
// outcome ADR 0150 exists to prevent.
|
|
281
|
+
//
|
|
282
|
+
// The stakes are not hypothetical for one of them. __BUILDER_AUTHORIZED_KEYS_B64__
|
|
283
|
+
// is the baked SSH key block; if a template misspells it, the substitution never
|
|
284
|
+
// happens and the box comes up with a garbage authorized_keys — permanently
|
|
285
|
+
// unreachable over SSH, exactly the failure task 1003635 was filed about (it
|
|
286
|
+
// guessed the wrong mechanism, but the outcome it named was reachable this way).
|
|
287
|
+
//
|
|
288
|
+
// Same pattern the happy-path test has always asserted, now enforced in the code
|
|
289
|
+
// rather than only in the test.
|
|
290
|
+
// The pattern is the placeholder CONVENTION, so this assumes a template never
|
|
291
|
+
// carries a literal __UPPER_SNAKE__ it means to keep. Nothing in this tree does,
|
|
292
|
+
// and a false positive fails loud and legibly (it names the token) rather than
|
|
293
|
+
// shipping a bad box — the safe direction to be wrong in. An instance that ever
|
|
294
|
+
// needs a literal one should escape it in the template, not weaken this check.
|
|
295
|
+
const survivors = [...new Set(rendered.match(/__[A-Z0-9_]+__/g) || [])];
|
|
296
|
+
if (survivors.length) {
|
|
297
|
+
throw new Error(
|
|
298
|
+
`box cloud-init under ${infraDir} left ${survivors.length} placeholder(s) unsubstituted: `
|
|
299
|
+
+ `${survivors.join(', ')} — box-infra.js does not know these tokens, so the box would `
|
|
300
|
+
+ `boot half-wired (ADR 0150). Reconcile the instance template with this renderer.`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
270
303
|
return rendered;
|
|
271
304
|
}
|
|
272
305
|
|
package/src/module-api.js
CHANGED
|
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
71
71
|
// there. scripts/gds/bump-version.js still rewrites the literal below; it appends
|
|
72
72
|
// the entry to that file. Look for a version's history there, not here.
|
|
73
73
|
// ---------------------------------------------------------------------------
|
|
74
|
-
const CORE_VERSION = '1.19.
|
|
74
|
+
const CORE_VERSION = '1.19.708'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
75
75
|
|
|
76
76
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
77
77
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
|
@@ -17,8 +17,12 @@ import { createRequire } from 'node:module';
|
|
|
17
17
|
import fs from 'node:fs';
|
|
18
18
|
import os from 'node:os';
|
|
19
19
|
import path from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
20
21
|
import { makeRunner } from './helpers.mjs';
|
|
21
22
|
|
|
23
|
+
// This repo's root — the boundary tests at the bottom read the REAL tree.
|
|
24
|
+
const REPO_ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
25
|
+
|
|
22
26
|
const require = createRequire(import.meta.url);
|
|
23
27
|
const box = require('../scripts/gds/box.js');
|
|
24
28
|
|
|
@@ -153,5 +157,90 @@ await test('readCloudInit renders a non-empty cloud-init with no leftover __PLAC
|
|
|
153
157
|
assert.ok(!/__[A-Z0-9_]+__/.test(out), 'no unsubstituted __PLACEHOLDER__ tokens remain');
|
|
154
158
|
});
|
|
155
159
|
|
|
160
|
+
// ===========================================================================
|
|
161
|
+
// An UNKNOWN placeholder half-wires the box (task 1003635, ADR 0150 prong B)
|
|
162
|
+
//
|
|
163
|
+
// missingInfra only catches files this renderer knows to ask for. The other
|
|
164
|
+
// direction — an instance template carrying a token box-infra.js never
|
|
165
|
+
// substitutes — used to render straight through, leaving the literal token in
|
|
166
|
+
// the cloud-init for cloud-init to write out as a file. ADR 0150 named the
|
|
167
|
+
// assertion as an escalation and it was never implemented.
|
|
168
|
+
// ===========================================================================
|
|
169
|
+
|
|
170
|
+
await test('an UNKNOWN __TOKEN__ in the instance template is refused, not rendered through', () => {
|
|
171
|
+
const { infra } = makeInfra();
|
|
172
|
+
fs.appendFileSync(path.join(infra, TEMPLATE), '\n# __SOME_FUTURE_THING_B64__\n');
|
|
173
|
+
assert.throws(
|
|
174
|
+
() => box.readCloudInit({ infraDir: infra }),
|
|
175
|
+
(err) => /__SOME_FUTURE_THING_B64__/.test(err.message) && /placeholder|half-wired|ADR 0150/i.test(err.message),
|
|
176
|
+
'an unsubstituted placeholder must fail loud — rendering it through writes garbage onto the box',
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
await test('a misspelled AUTHORIZED_KEYS token cannot ship a permanently SSH-unreachable box', () => {
|
|
181
|
+
// The stakes case. A template that spells the key block even slightly wrong
|
|
182
|
+
// gets no substitution, so the box boots with a garbage authorized_keys and
|
|
183
|
+
// nobody can SSH in — the outcome task 1003635 reported, by the mechanism it
|
|
184
|
+
// did not find. It must be refused before DigitalOcean is touched.
|
|
185
|
+
const { infra } = makeInfra();
|
|
186
|
+
fs.appendFileSync(path.join(infra, TEMPLATE), '\n# __BUILDER_AUTHORIZED_KEY_B64__\n');
|
|
187
|
+
assert.throws(
|
|
188
|
+
() => box.readCloudInit({ infraDir: infra, authorizedKeysBlock: 'ssh-ed25519 AAAA' }),
|
|
189
|
+
/__BUILDER_AUTHORIZED_KEY_B64__/,
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
await test('the happy path still renders — the assertion does not fire on a correct template', () => {
|
|
194
|
+
const { infra } = makeInfra();
|
|
195
|
+
const out = box.readCloudInit({
|
|
196
|
+
infraDir: infra, authorizedKeysBlock: 'ssh-ed25519 AAAA', boxEnv: 'X=1', gdsSession: '{"t":1}',
|
|
197
|
+
});
|
|
198
|
+
assert.ok(out && out.length > 0, 'a correct template must still render');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// ===========================================================================
|
|
202
|
+
// The core / instance boundary (task 1003635)
|
|
203
|
+
//
|
|
204
|
+
// The absence of the cloud-init set from the core's own infra/ was filed once as
|
|
205
|
+
// a P1 outage ("a dev box becomes permanently SSH-unreachable"). It is not one —
|
|
206
|
+
// ADR 0150 says the neutral core ships no box cloud-init, and the two throws
|
|
207
|
+
// above are what make a missing one legible instead of dangerous. These pin that
|
|
208
|
+
// boundary against the REAL tree so the next reader gets a test telling them so.
|
|
209
|
+
// ===========================================================================
|
|
210
|
+
|
|
211
|
+
await test('the INLINED list is exactly what box-infra.js actually asks fileGzB64 for', () => {
|
|
212
|
+
// The list above says "kept in sync with box.js's fileGzB64 calls" — by hand.
|
|
213
|
+
// Derive it instead, so adding a 10th inlined file cannot leave these tests
|
|
214
|
+
// silently proving less than they claim.
|
|
215
|
+
const SRC = fs.readFileSync(path.join(REPO_ROOT, 'scripts/gds/box-infra.js'), 'utf8');
|
|
216
|
+
const called = [...SRC.matchAll(/fileGzB64\('([^']+)'\)/g)].map((m) => m[1]);
|
|
217
|
+
assert.ok(called.length > 0, 'found no fileGzB64 calls — did box-infra.js move or get renamed?');
|
|
218
|
+
assert.deepEqual([...new Set(called)].sort(), [...INLINED].sort(),
|
|
219
|
+
'the INLINED fixture list has drifted from box-infra.js — the happy-path test would stop covering every inlined file');
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await test('the neutral core ships NO box cloud-init — that is ADR 0150, not a missing file', () => {
|
|
223
|
+
const coreInfra = path.join(REPO_ROOT, 'infra');
|
|
224
|
+
assert.ok(!fs.existsSync(path.join(coreInfra, TEMPLATE)),
|
|
225
|
+
`the core now ships infra/${TEMPLATE}. ADR 0150 says it must not ("The neutral core still ships no infra/") — the cloud-init is instance-owned. If that decision changed, amend ADR 0150 and this test together.`);
|
|
226
|
+
for (const name of INLINED) {
|
|
227
|
+
assert.ok(!fs.existsSync(path.join(coreInfra, name)),
|
|
228
|
+
`infra/${name} is a cloud-init asset and belongs to the host instance, not the core (ADR 0150)`);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
await test("core infra/ carries only the CLONE-RIDE scripts, which is why it looks half-empty", () => {
|
|
233
|
+
// The other population: these run on the box out of /workspace/infra/, arriving
|
|
234
|
+
// with the cloned source rather than through cloud-init. Their presence beside
|
|
235
|
+
// nine absences is the thing that reads as "files are missing" — infra/README.md
|
|
236
|
+
// exists to answer that, so it is required to stay.
|
|
237
|
+
const coreInfra = path.join(REPO_ROOT, 'infra');
|
|
238
|
+
for (const name of ['box-heartbeat.sh', 'box-report-host-keys.sh', 'box-report-terminal.sh', 'box-report-version.sh']) {
|
|
239
|
+
assert.ok(fs.existsSync(path.join(coreInfra, name)), `infra/${name} rides the clone and must stay in the core`);
|
|
240
|
+
}
|
|
241
|
+
assert.ok(fs.existsSync(path.join(coreInfra, 'README.md')),
|
|
242
|
+
'infra/README.md explains the two populations — without it the nine absences read as breakage again (task 1003635)');
|
|
243
|
+
});
|
|
244
|
+
|
|
156
245
|
for (const d of tmps) { try { fs.rmSync(d, { recursive: true, force: true }); } catch { /* best-effort */ } }
|
|
157
246
|
summary();
|