@bongos/core 1.19.785 → 1.19.786

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.785",
6
- "core_contract": "1.19.785",
7
- "source_commit": "022d941502640ca75c63a0fb7d13ae42233b583f",
5
+ "core_version": "1.19.786",
6
+ "core_contract": "1.19.786",
7
+ "source_commit": "785c921afb48af049814782f27929cc27885667c",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-16T22:11:28.177Z",
9
+ "built_at": "2026-09-16T22:20:27.767Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 483,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2668,
20
- "tree_sha256": "e71aafdc39bbf2b01c233a16c86515be287220faecbb7afaa6f874ffb6dbd9fa",
20
+ "tree_sha256": "3d454ef4a876f5368603708cbe4f13b53dc57a854dc03e217285b327b6dd0bf9",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2512,7 +2512,7 @@
2512
2512
  {
2513
2513
  "path": "docs/module-api-changelog.md",
2514
2514
  "mode": "0000644",
2515
- "sha256": "37d573a87561b4c12d3b3d1d416ad720fa4286a57fd2e30f906f0262cb70ad4d"
2515
+ "sha256": "580f9ae0d3677bc11fe335f73027c314edd8633f2397cd71400e07725a8f4a03"
2516
2516
  },
2517
2517
  {
2518
2518
  "path": "docs/modules-contract.md",
@@ -7062,7 +7062,7 @@
7062
7062
  {
7063
7063
  "path": "modules/security/secret-scrub.js",
7064
7064
  "mode": "0000644",
7065
- "sha256": "26e920133f0ad40de27a0b20e97492d8d42e656561e2e331e8b6ecce3de2ccf3"
7065
+ "sha256": "c28b9a47e3d01d206cb2a13e71844865a95cc2a9dc5e0237e1153ccf8f292286"
7066
7066
  },
7067
7067
  {
7068
7068
  "path": "modules/security/security.js",
@@ -7622,12 +7622,12 @@
7622
7622
  {
7623
7623
  "path": "package-lock.json",
7624
7624
  "mode": "0000644",
7625
- "sha256": "39247eaf1ee78994bb9f1be1d50c320bbf7a1184efe408bec6458a8450638036"
7625
+ "sha256": "a08e66b825d352b3b0c128f3b5b71d4665183bf734d69d0e837adf8946a28f19"
7626
7626
  },
7627
7627
  {
7628
7628
  "path": "package.json",
7629
7629
  "mode": "0000644",
7630
- "sha256": "6ce05e6b15c23da646d860f0c9d2c5a84cbee1fac61af6c807cefe7e2b743eae"
7630
+ "sha256": "9f9dfe9f5f8cc3d3ebc1cd46909eb73ac9ef03046933478f391cb6c23680cfa6"
7631
7631
  },
7632
7632
  {
7633
7633
  "path": "public-docs/index.html",
@@ -9492,7 +9492,7 @@
9492
9492
  {
9493
9493
  "path": "src/module-api.js",
9494
9494
  "mode": "0000644",
9495
- "sha256": "0f2dbf8705fbe60f6a38db6c2e40c5b671576645a092902706e5251d78758784"
9495
+ "sha256": "0eb65d596ccf4f9af9cb2ec8769e373c18f3148b93e785157895d4dbb94299c7"
9496
9496
  },
9497
9497
  {
9498
9498
  "path": "src/module-loader/catalog.js",
@@ -12557,7 +12557,7 @@
12557
12557
  {
12558
12558
  "path": "tests/scrubber_corpus.mjs",
12559
12559
  "mode": "0000644",
12560
- "sha256": "cb05f1824487124163f7b8dac0a8c589a1a02cbb1130f06ac716701fea6bf59c"
12560
+ "sha256": "d1f80894bd96f866359d3d1997e36e8843fe3dba141ac621874cdc1d530b9282"
12561
12561
  },
12562
12562
  {
12563
12563
  "path": "tests/seam_wiring_guard.mjs",
@@ -2044,5 +2044,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2044
2044
  landed since 1.19.783 with no explicit bump. run 35155326585. (task 1002620)
2045
2045
  1.19.785 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2046
2046
  landed since 1.19.784 with no explicit bump. run 35156349018. (task 1002620)
2047
+ 1.19.786 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2048
+ landed since 1.19.785 with no explicit bump. run 35157132070. (task 1002620)
2047
2049
  ---------------------------------------------------------------------------
2048
2050
  ```
@@ -190,12 +190,34 @@ const ENV_SECRET_PREFIX_RE = /^(?:gds_|pms_|mac_|apple|anthropic|stripe|cf_|clou
190
190
  // last `cd` (task 2130). Exact-match only, so real password vars (MYSQL_PWD, DB_PWD, …)
191
191
  // still match below.
192
192
  const ENV_BENIGN_KEY_RE = /^(?:PWD|OLDPWD)$/;
193
+ // CONFIG-IDENTIFIER NAMES under a provider prefix (task 1003512). ENV_SECRET_PREFIX_RE
194
+ // matches ^anthropic, so the Claude Code harness's own ANTHROPIC_DEFAULT_OPUS_MODEL —
195
+ // whose value is a MODEL ID like claude-opus-5, not a credential — was collected as a
196
+ // live secret. package-core's fail-closed leak gate then flagged every functional file
197
+ // containing that string verbatim and refused to build, on ANY machine where Claude
198
+ // Code had set its model vars, i.e. every builder machine. Hit live packaging
199
+ // 1.19.209; the workaround was `env -u ANTHROPIC_DEFAULT_OPUS_MODEL`.
200
+ //
201
+ // AN ALLOWLIST ON THE NAME, NOT A SHAPE TEST ON THE VALUE. The entropy/prefix check on
202
+ // the VALUE is the other obvious fix and this file already records why that direction
203
+ // loses: see the doc-path exemption above, where three shape rules were tried and each
204
+ // one leaked, because a predicate built on what a secret LOOKS like also admits a
205
+ // secret dressed the other way. These literals feed the PUBLIC mirror and session
206
+ // uploads, so a shape hole here is a smuggling channel. That a _MODEL or _BASE_URL var
207
+ // holds a configuration identifier is a fact about the NAME, which cannot be dressed.
208
+ //
209
+ // NARROW BY CONSTRUCTION: this exempts only names matched by the provider PREFIX. A
210
+ // name carrying an actual secret word (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN) matches
211
+ // ENV_SECRET_KEY_RE first and is still collected, whatever it ends with.
212
+ const ENV_CONFIG_NAME_RE = /(?:_MODEL|_BASE_URL)$/i;
193
213
  function collectEnvSecrets(env = process.env) {
194
214
  const out = [];
195
215
  for (const [k, v] of Object.entries(env || {})) {
196
216
  if (typeof v !== 'string' || v.length < 8) continue;
197
217
  if (ENV_BENIGN_KEY_RE.test(k)) continue;
198
- if (ENV_SECRET_KEY_RE.test(k) || ENV_SECRET_PREFIX_RE.test(k)) out.push(v);
218
+ // A secret WORD in the name always wins — it is never exempted below.
219
+ if (ENV_SECRET_KEY_RE.test(k)) { out.push(v); continue; }
220
+ if (ENV_SECRET_PREFIX_RE.test(k) && !ENV_CONFIG_NAME_RE.test(k)) out.push(v);
199
221
  }
200
222
  return out;
201
223
  }
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.785",
3
+ "version": "1.19.786",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.785",
9
+ "version": "1.19.786",
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.785",
3
+ "version": "1.19.786",
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
@@ -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.785'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.786'; // 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');
@@ -327,6 +327,65 @@ test('collectEnvSecrets: benign shell PWD/OLDPWD are skipped, real *_PWD passwor
327
327
  assert.ok(got.includes(env.MYSQL_PWD), 'MYSQL_PWD (a real password var) must still be collected');
328
328
  });
329
329
 
330
+ test('collectEnvSecrets: Claude Code harness config vars are skipped, real anthropic credentials still collected (task 1003512)', () => {
331
+ // Regression: ENV_SECRET_PREFIX_RE matches ^anthropic, so the harness's own
332
+ // ANTHROPIC_DEFAULT_OPUS_MODEL — value = a MODEL ID, not a credential — was collected
333
+ // as a live secret. package-core's fail-closed leak gate then flagged every functional
334
+ // file containing that string verbatim (the grader, llm-pricing and their tests) and
335
+ // refused to build on ANY machine where Claude Code had set its model vars. Hit live
336
+ // packaging 1.19.209; the workaround was `env -u ANTHROPIC_DEFAULT_OPUS_MODEL`.
337
+ const env = {
338
+ ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-5',
339
+ ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-sonnet-5',
340
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-haiku-4-5-20251001',
341
+ ANTHROPIC_MODEL: 'claude-opus-5-20260101',
342
+ ANTHROPIC_SMALL_FAST_MODEL: 'claude-haiku-4-5-20251001',
343
+ ANTHROPIC_BASE_URL: 'https://api.anthropic.com',
344
+ // ...and the ones that really are credentials, under the SAME provider prefix.
345
+ ANTHROPIC_API_KEY: 'sk-' + 'ant-' + randStr(31, 30, B64URL),
346
+ ANTHROPIC_AUTH_TOKEN: randStr(32, 40, B64URL),
347
+ };
348
+ const got = collectEnvSecrets(env);
349
+
350
+ for (const k of ['ANTHROPIC_DEFAULT_OPUS_MODEL', 'ANTHROPIC_DEFAULT_SONNET_MODEL',
351
+ 'ANTHROPIC_DEFAULT_HAIKU_MODEL', 'ANTHROPIC_MODEL', 'ANTHROPIC_SMALL_FAST_MODEL',
352
+ 'ANTHROPIC_BASE_URL']) {
353
+ assert.ok(!got.includes(env[k]), `${k} is a config identifier and must not be collected`);
354
+ }
355
+ // The exemption is on the NAME and must never reach a name carrying a secret word.
356
+ assert.ok(got.includes(env.ANTHROPIC_API_KEY), 'ANTHROPIC_API_KEY must still be collected');
357
+ assert.ok(got.includes(env.ANTHROPIC_AUTH_TOKEN), 'ANTHROPIC_AUTH_TOKEN must still be collected');
358
+ assert.equal(got.length, 2, 'exactly the two real credentials, nothing else');
359
+ });
360
+
361
+ test('the *_MODEL exemption cannot be used to smuggle a credential (task 1003512)', () => {
362
+ // A name that carries a secret WORD is collected whatever it ends with — the
363
+ // exemption applies only to names matched by the provider PREFIX alone. Without this,
364
+ // the fix would be a hole: these literals feed the PUBLIC mirror and session uploads.
365
+ const env = {
366
+ ANTHROPIC_SECRET_MODEL: randStr(33, 40, B64URL),
367
+ ANTHROPIC_API_KEY_MODEL: randStr(34, 40, B64URL),
368
+ OPENAI_TOKEN_BASE_URL: randStr(35, 40, B64URL),
369
+ };
370
+ const got = collectEnvSecrets(env);
371
+ for (const k of Object.keys(env)) {
372
+ assert.ok(got.includes(env[k]), `${k} carries a secret word and must still be collected`);
373
+ }
374
+ });
375
+
376
+ test('a model id survives a transcript scrub while a real key does not (task 1003512)', () => {
377
+ // The end-to-end shape of the bug: the model id is what package-core found verbatim
378
+ // in modules/grading and failed the build on. RECALL IS UNCHANGED for the credential.
379
+ const env = {
380
+ ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-5',
381
+ ANTHROPIC_API_KEY: 'sk-' + 'ant-' + randStr(36, 30, B64URL),
382
+ };
383
+ const text = `the grader ran on ${env.ANTHROPIC_DEFAULT_OPUS_MODEL} using ${env.ANTHROPIC_API_KEY}`;
384
+ const out = scrubSecrets(text, collectEnvSecrets(env));
385
+ assert.ok(out.includes('claude-opus-5'), 'a model id is not a secret and must survive');
386
+ assert.ok(!out.includes(env.ANTHROPIC_API_KEY), 'the key must still be scrubbed');
387
+ });
388
+
330
389
  test('self-reference `key = key` (SQL SET col = col) survives — zero recall loss', () => {
331
390
  // task 1688: the core packager redacts live SQL, so a `_token` COLUMN self-increment
332
391
  // must NOT be corrupted — while a real `key = <secret>` assignment is STILL redacted.