@bongos/core 1.19.863 → 1.19.864

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,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.863",
6
- "core_contract": "1.19.863",
7
- "source_commit": "f7ba964fecdad465711447780224d81c6d161651",
5
+ "core_version": "1.19.864",
6
+ "core_contract": "1.19.864",
7
+ "source_commit": "c073f3cd57b680341105e1e2f06e3a5c0ebb3358",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-18T00:51:13.074Z",
9
+ "built_at": "2026-09-18T01:11:02.555Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 500,
13
13
  "agent_docs_stubbed": 26,
14
- "functional_verbatim": 2280,
14
+ "functional_verbatim": 2281,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2806,
20
- "tree_sha256": "a6156c439f3369569a8f4a35b905f401d800592b85c16f01f948bb1eac6126b9",
19
+ "file_count": 2807,
20
+ "tree_sha256": "605295e9a15f1948dd81353eab191ae7c28bbf4c6859146311c02ffc16a3e235",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2592,7 +2592,7 @@
2592
2592
  {
2593
2593
  "path": "docs/file-map.md",
2594
2594
  "mode": "0000644",
2595
- "sha256": "eaa7dca723187a394a3b6ee252bbb81b13b76cc384a4651b6ee74a859af9d611"
2595
+ "sha256": "38c851145d7b4066a378b1af75747b6cc28529b7f824bd6b7e30e0502bc6346c"
2596
2596
  },
2597
2597
  {
2598
2598
  "path": "docs/handoff-template.md",
@@ -2602,7 +2602,7 @@
2602
2602
  {
2603
2603
  "path": "docs/module-api-changelog.md",
2604
2604
  "mode": "0000644",
2605
- "sha256": "b67a7da05a53b1e15567815a30dae32036c4dc4a6fa094c63e28b7cdc349e129"
2605
+ "sha256": "efb0a55093a321e95fbbbe4d5a0d074ef2cd3bd0148dc820fe338027465d2aed"
2606
2606
  },
2607
2607
  {
2608
2608
  "path": "docs/modules-contract.md",
@@ -7927,12 +7927,12 @@
7927
7927
  {
7928
7928
  "path": "package-lock.json",
7929
7929
  "mode": "0000644",
7930
- "sha256": "d8d576d927a64fc4345b815d0f09cd76c4a0f81291fe6c9566627d040aeb4209"
7930
+ "sha256": "ea96e5b57ed6cd9e4a043090b7ab48ac78b8f058b2c9767d77633a20e528ff6b"
7931
7931
  },
7932
7932
  {
7933
7933
  "path": "package.json",
7934
7934
  "mode": "0000644",
7935
- "sha256": "8fe2a5bdbd9f52067911cfab21a28e6246d474022499d731d176e5624e25d2bb"
7935
+ "sha256": "feed56a36e8348a1790db370c1ea4a6896a6e120a490116212625d8317ff4cf6"
7936
7936
  },
7937
7937
  {
7938
7938
  "path": "public-docs/index.html",
@@ -9877,7 +9877,7 @@
9877
9877
  {
9878
9878
  "path": "src/module-api.js",
9879
9879
  "mode": "0000644",
9880
- "sha256": "c550b9efb0a77a548f269c52952abe1e92a9d4d9f9c85cceb697e32d08a8f96b"
9880
+ "sha256": "3ee60c835967094a7b5c983e651e0ada54b2127b2b38a329ecf8d6a9237cb0d2"
9881
9881
  },
9882
9882
  {
9883
9883
  "path": "src/module-loader/catalog.js",
@@ -11034,6 +11034,11 @@
11034
11034
  "mode": "0000644",
11035
11035
  "sha256": "acc6c86bfb9edaee192e9c363f4b578a01e1bba69422d618987d8ff75e883a63"
11036
11036
  },
11037
+ {
11038
+ "path": "tests/docs_scrubber_damage.mjs",
11039
+ "mode": "0000644",
11040
+ "sha256": "2d815aa719c9b83af094405b02dcb50c031267fd38cdd9306c81d592597966dd"
11041
+ },
11037
11042
  {
11038
11043
  "path": "tests/doctor_hooks.mjs",
11039
11044
  "mode": "0000644",
package/docs/file-map.md CHANGED
@@ -366,6 +366,7 @@ tests/
366
366
  ├── session_506_regression.mjs ← (6D.5): the #506 regression gate — runs the engine over tests/fixtures/session-506-digest.json, asserts the hand-labelled findings (→#513/#514/#468) reproduce.
367
367
  ├── grade_attempts.mjs ← (6D.6): logGradeAttempt swallow-safety + param coercion via an injected queryFn (no DB).
368
368
  ├── linkify_refs.mjs ← (#604): the doc-linkifier classifier — pins which `#NNN` rewrite (tasks) vs stay bare (heading anchors, link targets, idea/blocker/session/PR ids, code spans), incl. comma-list entity inheritance + idempotency.
369
+ ├── docs_scrubber_damage.mjs ← (task 1004027, part 4 of the scrubber-damage family after 1004021/1004022): docs/recipes/managed-settings-remote-control.md had TWO pieces of real prose replaced by the literal `<redacted>` — an in-page anchor target and an `infra/*.sh` script name — while FOUR other `<redacted>` in the same file are deliberate stand-ins for real secrets. Pins both halves: every in-page anchor resolves through docs-entropy's own parseFile (so the slug asserted is the slug the lint computes), the key-sync cron names the script `scripts/gds/box-infra.js` actually bakes into the cloud-init, and the placeholder count stays at EXACTLY four, matched by context rather than line number. The last assertion is the point — the anchor lint only reads link targets, so a global sweep of the literal would leave doc_broken_anchors at 0 while destroying four correct lines.
369
370
  ├── sandbox_stage.mjs ← (#927, ADR 0046): sandbox-first review gate — box detection, BOX_PREVIEW_HOSTNAME parsing, previewable-surface matching, decideShipGate table, tree-stamp freshness (temp git repo), runShipGate composition with injected fs/exec/prompt.
370
371
  ├── session_start_freshness.mjs ← (#1277, ADR 0067): the SessionStart freshness decision (decideFreshness) — pull ONLY on a clean `main` full clone strictly behind origin/main; warn in every other behind case; skip when up to date.
371
372
  ├── own_scope_guard.mjs ← (task 1003343, goal 1000045 criterion own-scope-held-by-a-test): the OWN-SCOPE structural guard, generalised out of memory_isolation.mjs. An explicit inventory of own-scoped route files; inside them the route's declared PATH decides — a path naming no builder must never read a subject from the request (direct, optional-chained, destructured, aliased, computed-key or header), a path that DOES name one needs a per-route exemption whose gate the guard verifies is present. Repo-wide backstop: any file mounting a `/me` route must be in the inventory. Source-grepping, so it runs in the DB-free `unit` lane.
@@ -2200,5 +2200,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2200
2200
  landed since 1.19.861 with no explicit bump. run 35292190396. (task 1002620)
2201
2201
  1.19.863 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2202
2202
  landed since 1.19.862 with no explicit bump. run 35292877780. (task 1002620)
2203
+ 1.19.864 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2204
+ landed since 1.19.863 with no explicit bump. run 35294233113. (task 1002620)
2203
2205
  ---------------------------------------------------------------------------
2204
2206
  ```
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.863",
3
+ "version": "1.19.864",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.863",
9
+ "version": "1.19.864",
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.863",
3
+ "version": "1.19.864",
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.863'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.864'; // 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');
@@ -0,0 +1,111 @@
1
+ // tests/docs_scrubber_damage.mjs — the secret-scrubber ate real prose in
2
+ // docs/recipes/managed-settings-remote-control.md (task 1004027, part 4 of the
3
+ // damage family after 1004021 / 1004022).
4
+ //
5
+ // Two distinct repairs, and the SECOND is the trap. A scrubber pass replaced
6
+ // two pieces of ordinary content with the literal `<redacted>`:
7
+ // - an in-page anchor target, so the link went nowhere;
8
+ // - an `infra/*.sh` script name, so the doc pointed at no script at all.
9
+ // But four OTHER `<redacted>` occurrences in the same file are DELIBERATE — they
10
+ // stand in for real secrets (a tunnel credential, two tokens, a trust seed).
11
+ // A global sweep "fixes" the two and destroys the four, and nothing in the repo
12
+ // would notice, because the anchor lint only ever looks at link targets.
13
+ //
14
+ // So this file pins BOTH halves: the anchor and the script path resolve, AND the
15
+ // placeholder count stays at exactly four. The second assertion is the one that
16
+ // makes a future sweep fail loudly instead of quietly.
17
+ import assert from 'node:assert/strict';
18
+ import { test } from 'node:test';
19
+ import { createRequire } from 'node:module';
20
+ import { fileURLToPath } from 'node:url';
21
+ import fs from 'node:fs';
22
+ import path from 'node:path';
23
+
24
+ const require = createRequire(import.meta.url);
25
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
26
+ const { parseFile } = require(path.join(ROOT, 'scripts', 'gds', 'docs-entropy.js'));
27
+
28
+ const REL = 'docs/recipes/managed-settings-remote-control.md';
29
+ const ABS = path.join(ROOT, REL);
30
+ const raw = () => fs.readFileSync(ABS, 'utf8');
31
+
32
+ // The doc is only worth asserting against while it exists at this path.
33
+ test('the recipe under repair is still tracked at its documented path', () => {
34
+ assert.ok(fs.existsSync(ABS), `${REL} is missing — move this test with it`);
35
+ });
36
+
37
+ test('every in-page anchor in the recipe resolves to a heading it actually has', () => {
38
+ // The damaged link read `[named-tunnel automation](#<redacted>)`. Resolve
39
+ // through the SAME parser docs-entropy.js uses, so the slug this asserts is
40
+ // the slug the lint computes — a test with its own slug rule would let the
41
+ // doc pass here and still red the ratchet.
42
+ const { headings, links } = parseFile(ABS);
43
+ const slugs = new Set(headings.map((h) => h.slug));
44
+ const inPage = links.filter((l) => l.href.startsWith('#'));
45
+
46
+ assert.ok(inPage.length > 0, 'fixture sanity: the recipe does link to its own sections');
47
+ const broken = inPage.filter((l) => !slugs.has(l.href.slice(1)));
48
+ assert.deepEqual(
49
+ broken.map((l) => `${l.line}: ${l.href}`), [],
50
+ 'an in-page anchor points at no heading in this file — this is what doc_broken_anchors counts',
51
+ );
52
+ });
53
+
54
+ test('the key-sync cron names a script the cloud-init renderer actually installs', () => {
55
+ // The damaged line read `infra/<redacted>.sh`. The authority for the real name
56
+ // is not prose anywhere: it is the renderer that bakes the script into the
57
+ // cloud-init, so assert the doc against THAT rather than against a literal.
58
+ const line = raw().split(/\r?\n/).find((l) => l.includes('GET /box/authorized-keys'))
59
+ ?? raw().split(/\r?\n/).find((l) => l.includes('keeps `authorized_keys` in sync'));
60
+ assert.ok(line, 'fixture sanity: the recipe still describes the authorized_keys sync cron');
61
+
62
+ const named = [...raw().matchAll(/`infra\/([a-z0-9-]+\.sh)`/g)].map((m) => m[1]);
63
+ assert.ok(
64
+ named.includes('box-authorized-keys-fetch.sh'),
65
+ `the recipe names no authorized-keys script; found ${JSON.stringify(named)}`,
66
+ );
67
+
68
+ // Scoped to the repaired name on purpose. Other `infra/*.sh` the recipe cites
69
+ // (box-connect.sh) are builder-side scripts absent from this checkout for an
70
+ // unrelated, pre-existing reason (idea 1000895) — asserting over all of them
71
+ // would red this test on a gap it is not about.
72
+ const renderer = fs.readFileSync(path.join(ROOT, 'scripts', 'gds', 'box-infra.js'), 'utf8');
73
+ assert.ok(
74
+ renderer.includes('box-authorized-keys-fetch.sh'),
75
+ 'box-infra.js no longer bakes box-authorized-keys-fetch.sh into the cloud-init — '
76
+ + 'the recipe now names a script nothing installs, so fix the doc to match the renderer',
77
+ );
78
+ });
79
+
80
+ test('the four deliberate <redacted> secret placeholders survive — a global sweep must fail here', () => {
81
+ // This is the anti-fix assertion. Each of these stands in for a real secret and
82
+ // is correct as written; "repairing" them is the damage, not the cure.
83
+ const lines = raw().split(/\r?\n/);
84
+ const placeholders = lines
85
+ .map((text, i) => ({ line: i + 1, text }))
86
+ .filter((l) => l.text.includes('<redacted>'));
87
+
88
+ assert.equal(
89
+ placeholders.length, 4,
90
+ 'expected exactly the four secret placeholders, got:\n'
91
+ + placeholders.map((p) => ` ${p.line}: ${p.text.trim().slice(0, 110)}`).join('\n'),
92
+ );
93
+
94
+ // Named by CONTEXT, not by line number, so ordinary edits above them don't red this.
95
+ const contexts = ['"credential"', 'BOX_TUNNEL_TOKEN', 'BOX_SOURCE_FULL_TOKEN', '/root/.claude.json'];
96
+ for (const ctx of contexts) {
97
+ assert.ok(
98
+ placeholders.some((p) => p.text.includes(ctx)),
99
+ `the deliberate placeholder for ${ctx} is gone — a <redacted> sweep took a real secret stand-in with it`,
100
+ );
101
+ }
102
+
103
+ // And no placeholder may sit in a link target or a path again: those two shapes
104
+ // are exactly what the scrubber damaged.
105
+ for (const p of placeholders) {
106
+ assert.ok(
107
+ !/\(#<redacted>\)/.test(p.text) && !/infra\/<redacted>/.test(p.text),
108
+ `line ${p.line} carries scrubber damage, not a secret placeholder: ${p.text.trim().slice(0, 110)}`,
109
+ );
110
+ }
111
+ });