@bongos/core 1.19.666 → 1.19.667
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 +38 -33
- package/docs/module-api-changelog.md +2 -0
- package/modules/dev-box/app/src/session-store.js +33 -9
- package/modules/hall-ui/public/shell.js +1 -1
- package/modules/public-landing/public/index.html +1 -1
- package/modules/public-landing/public/projects.html +1 -1
- package/modules/security/artifact-scan/detectors/credentials.js +8 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/box-infra.js +1 -1
- package/scripts/gds/cli-lib.js +55 -16
- package/scripts/gds/fetch-art-key.js +1 -1
- package/scripts/gds/init.js +1 -1
- package/scripts/gds/paste-token.js +10 -5
- package/scripts/gds/portability-smoke-memory.sh +1 -1
- package/scripts/gds/setup.js +4 -4
- package/scripts/gds/smoke-write.sh +2 -1
- package/scripts/hall-preview/refresh-fixtures.js +1 -1
- package/src/bongos/auth.js +27 -5
- package/src/bongos/middleware/rate-limit.js +17 -2
- package/src/bongos/routes/auth.js +46 -15
- package/src/instance-config.js +28 -2
- package/src/module-api.js +1 -1
- package/tests/cli_sessions.mjs +6 -5
- package/tests/landing_page.mjs +5 -1
- package/tests/lib_sh_resolution.mjs +84 -17
- package/tests/session_rename_fallback.mjs +383 -0
- package/tests/setup_device_flow_fallback.mjs +4 -1
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.667",
|
|
6
|
+
"core_contract": "1.19.667",
|
|
7
|
+
"source_commit": "fde10b200283c5047be40d5fc05a7489f3d5b73c",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-11T07:58:55.399Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 473,
|
|
13
13
|
"agent_docs_stubbed": 24,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2117,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2614,
|
|
20
|
+
"tree_sha256": "cbb2d92ddbc241d615a5a7b105b021310b739c85b8709fd9479d256ceba573e5",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2787,7 +2787,7 @@
|
|
|
2787
2787
|
{
|
|
2788
2788
|
"path": "docs/module-api-changelog.md",
|
|
2789
2789
|
"mode": "0000644",
|
|
2790
|
-
"sha256": "
|
|
2790
|
+
"sha256": "65505f4ffa0193c1827059d16ce364257fdfdc076f5585544e1d037f2bda40a8"
|
|
2791
2791
|
},
|
|
2792
2792
|
{
|
|
2793
2793
|
"path": "docs/modules-contract.md",
|
|
@@ -4212,7 +4212,7 @@
|
|
|
4212
4212
|
{
|
|
4213
4213
|
"path": "modules/dev-box/app/src/session-store.js",
|
|
4214
4214
|
"mode": "0000644",
|
|
4215
|
-
"sha256": "
|
|
4215
|
+
"sha256": "9fefb99a647184879d2960eda360b475f5ea14d6f7c78d46c4de67f2b9909baa"
|
|
4216
4216
|
},
|
|
4217
4217
|
{
|
|
4218
4218
|
"path": "modules/dev-box/app/src/ssh-setup.js",
|
|
@@ -5402,7 +5402,7 @@
|
|
|
5402
5402
|
{
|
|
5403
5403
|
"path": "modules/hall-ui/public/shell.js",
|
|
5404
5404
|
"mode": "0000644",
|
|
5405
|
-
"sha256": "
|
|
5405
|
+
"sha256": "f0f6462bd7e536b73162c758db37d30ceec6b5e4ec74815df778d85978d7eb5e"
|
|
5406
5406
|
},
|
|
5407
5407
|
{
|
|
5408
5408
|
"path": "modules/hall-ui/public/ship.wav",
|
|
@@ -6982,7 +6982,7 @@
|
|
|
6982
6982
|
{
|
|
6983
6983
|
"path": "modules/public-landing/public/index.html",
|
|
6984
6984
|
"mode": "0000644",
|
|
6985
|
-
"sha256": "
|
|
6985
|
+
"sha256": "ea0c3be6fcddc0e93414ee3ce247c0aee57d74c285b0ecd2dc13095118447d81"
|
|
6986
6986
|
},
|
|
6987
6987
|
{
|
|
6988
6988
|
"path": "modules/public-landing/public/index.probes.json",
|
|
@@ -7012,7 +7012,7 @@
|
|
|
7012
7012
|
{
|
|
7013
7013
|
"path": "modules/public-landing/public/projects.html",
|
|
7014
7014
|
"mode": "0000644",
|
|
7015
|
-
"sha256": "
|
|
7015
|
+
"sha256": "864b6ee7a8b1866196d6595914f614e388a51c2a160fd86f454ab4a32a4740d5"
|
|
7016
7016
|
},
|
|
7017
7017
|
{
|
|
7018
7018
|
"path": "modules/public-landing/public/projects.probes.json",
|
|
@@ -7082,7 +7082,7 @@
|
|
|
7082
7082
|
{
|
|
7083
7083
|
"path": "modules/security/artifact-scan/detectors/credentials.js",
|
|
7084
7084
|
"mode": "0000644",
|
|
7085
|
-
"sha256": "
|
|
7085
|
+
"sha256": "6ef164669b8947143ecc7095443ae2500b43ce61dd240d480598850c787920ef"
|
|
7086
7086
|
},
|
|
7087
7087
|
{
|
|
7088
7088
|
"path": "modules/security/artifact-scan/detectors/dependencies.js",
|
|
@@ -7757,12 +7757,12 @@
|
|
|
7757
7757
|
{
|
|
7758
7758
|
"path": "package-lock.json",
|
|
7759
7759
|
"mode": "0000644",
|
|
7760
|
-
"sha256": "
|
|
7760
|
+
"sha256": "e6a26c726108246ac30f4250a93e1fd7965dba6bd5dfcd950b849357634ddb02"
|
|
7761
7761
|
},
|
|
7762
7762
|
{
|
|
7763
7763
|
"path": "package.json",
|
|
7764
7764
|
"mode": "0000644",
|
|
7765
|
-
"sha256": "
|
|
7765
|
+
"sha256": "30fa12bd80546328d075b3d2b251c528c59ec033b486a6084bcca3b3d5c6f703"
|
|
7766
7766
|
},
|
|
7767
7767
|
{
|
|
7768
7768
|
"path": "public-docs/index.html",
|
|
@@ -7947,7 +7947,7 @@
|
|
|
7947
7947
|
{
|
|
7948
7948
|
"path": "scripts/gds/box-infra.js",
|
|
7949
7949
|
"mode": "0000644",
|
|
7950
|
-
"sha256": "
|
|
7950
|
+
"sha256": "7890dee972f792b633a86d5ac9e6195bafdfc6c197195b8ac3f00c4a0f80d5c0"
|
|
7951
7951
|
},
|
|
7952
7952
|
{
|
|
7953
7953
|
"path": "scripts/gds/box-sync.js",
|
|
@@ -8032,7 +8032,7 @@
|
|
|
8032
8032
|
{
|
|
8033
8033
|
"path": "scripts/gds/cli-lib.js",
|
|
8034
8034
|
"mode": "0000644",
|
|
8035
|
-
"sha256": "
|
|
8035
|
+
"sha256": "24b6e3f2f99f7e584692d58fdd50d94e2b9e58905213307d71e3590858fafd22"
|
|
8036
8036
|
},
|
|
8037
8037
|
{
|
|
8038
8038
|
"path": "scripts/gds/client-baseurl-guard.js",
|
|
@@ -8177,7 +8177,7 @@
|
|
|
8177
8177
|
{
|
|
8178
8178
|
"path": "scripts/gds/fetch-art-key.js",
|
|
8179
8179
|
"mode": "0000644",
|
|
8180
|
-
"sha256": "
|
|
8180
|
+
"sha256": "9fb05213e80f27ac02cb40c6ceb95a7c92ca81b0a531d9cd67ba09b497017d6d"
|
|
8181
8181
|
},
|
|
8182
8182
|
{
|
|
8183
8183
|
"path": "scripts/gds/fetch-sound-prefs.js",
|
|
@@ -8352,7 +8352,7 @@
|
|
|
8352
8352
|
{
|
|
8353
8353
|
"path": "scripts/gds/init.js",
|
|
8354
8354
|
"mode": "0000644",
|
|
8355
|
-
"sha256": "
|
|
8355
|
+
"sha256": "390df0043001a825bbd4709df767e8ef21089743b799fc9c638a5509e8222ae8"
|
|
8356
8356
|
},
|
|
8357
8357
|
{
|
|
8358
8358
|
"path": "scripts/gds/install-git-hooks.js",
|
|
@@ -8527,7 +8527,7 @@
|
|
|
8527
8527
|
{
|
|
8528
8528
|
"path": "scripts/gds/paste-token.js",
|
|
8529
8529
|
"mode": "0000644",
|
|
8530
|
-
"sha256": "
|
|
8530
|
+
"sha256": "9036bdd526ed13d1518b0f12289a68d86e0078a093d22607f7f5377b6759969c"
|
|
8531
8531
|
},
|
|
8532
8532
|
{
|
|
8533
8533
|
"path": "scripts/gds/portability-smoke-art.sh",
|
|
@@ -8537,7 +8537,7 @@
|
|
|
8537
8537
|
{
|
|
8538
8538
|
"path": "scripts/gds/portability-smoke-memory.sh",
|
|
8539
8539
|
"mode": "0000644",
|
|
8540
|
-
"sha256": "
|
|
8540
|
+
"sha256": "6822594619d66509430fa42f51abb4a53a612274e232ec227502d2b2d51f3417"
|
|
8541
8541
|
},
|
|
8542
8542
|
{
|
|
8543
8543
|
"path": "scripts/gds/preflight.js",
|
|
@@ -8872,7 +8872,7 @@
|
|
|
8872
8872
|
{
|
|
8873
8873
|
"path": "scripts/gds/setup.js",
|
|
8874
8874
|
"mode": "0000644",
|
|
8875
|
-
"sha256": "
|
|
8875
|
+
"sha256": "15243de5b4bde57313c601bf96bd2a10bb86dedceb18cb0a31495b998d1ca835"
|
|
8876
8876
|
},
|
|
8877
8877
|
{
|
|
8878
8878
|
"path": "scripts/gds/shell.js",
|
|
@@ -9022,7 +9022,7 @@
|
|
|
9022
9022
|
{
|
|
9023
9023
|
"path": "scripts/gds/smoke-write.sh",
|
|
9024
9024
|
"mode": "0000644",
|
|
9025
|
-
"sha256": "
|
|
9025
|
+
"sha256": "cfa2f05cd72aad3975a683e334e32341c4cc10e34802091e693fe26f2e49781f"
|
|
9026
9026
|
},
|
|
9027
9027
|
{
|
|
9028
9028
|
"path": "scripts/gds/spark.js",
|
|
@@ -9137,7 +9137,7 @@
|
|
|
9137
9137
|
{
|
|
9138
9138
|
"path": "scripts/hall-preview/refresh-fixtures.js",
|
|
9139
9139
|
"mode": "0000644",
|
|
9140
|
-
"sha256": "
|
|
9140
|
+
"sha256": "3faeb959f81f32e23b11c9ab623df7899bae647c07837bca54c946e7807ef0f6"
|
|
9141
9141
|
},
|
|
9142
9142
|
{
|
|
9143
9143
|
"path": "scripts/hall-preview/server.js",
|
|
@@ -9257,7 +9257,7 @@
|
|
|
9257
9257
|
{
|
|
9258
9258
|
"path": "src/bongos/auth.js",
|
|
9259
9259
|
"mode": "0000644",
|
|
9260
|
-
"sha256": "
|
|
9260
|
+
"sha256": "4ba2511e982a50e82cc7e600ad16905dc1765b89a6b11eedcec2a67cd86a19da"
|
|
9261
9261
|
},
|
|
9262
9262
|
{
|
|
9263
9263
|
"path": "src/bongos/cascade-dispatch.js",
|
|
@@ -9327,7 +9327,7 @@
|
|
|
9327
9327
|
{
|
|
9328
9328
|
"path": "src/bongos/middleware/rate-limit.js",
|
|
9329
9329
|
"mode": "0000644",
|
|
9330
|
-
"sha256": "
|
|
9330
|
+
"sha256": "16a4ec3664e0ae3ff2c38e75a04dacd1011d19b7a53631739ac39147578e5534"
|
|
9331
9331
|
},
|
|
9332
9332
|
{
|
|
9333
9333
|
"path": "src/bongos/module-scope-map.js",
|
|
@@ -9412,7 +9412,7 @@
|
|
|
9412
9412
|
{
|
|
9413
9413
|
"path": "src/bongos/routes/auth.js",
|
|
9414
9414
|
"mode": "0000644",
|
|
9415
|
-
"sha256": "
|
|
9415
|
+
"sha256": "511383c09afd0a89b568b071303a41f57dc20c5bd6284624230bf9e23056b8f5"
|
|
9416
9416
|
},
|
|
9417
9417
|
{
|
|
9418
9418
|
"path": "src/bongos/routes/backup.js",
|
|
@@ -9517,12 +9517,12 @@
|
|
|
9517
9517
|
{
|
|
9518
9518
|
"path": "src/instance-config.js",
|
|
9519
9519
|
"mode": "0000644",
|
|
9520
|
-
"sha256": "
|
|
9520
|
+
"sha256": "9338dde4ceeae35c208f2d434422642ce6851b3a2196c420463b85a3b23d2dc7"
|
|
9521
9521
|
},
|
|
9522
9522
|
{
|
|
9523
9523
|
"path": "src/module-api.js",
|
|
9524
9524
|
"mode": "0000644",
|
|
9525
|
-
"sha256": "
|
|
9525
|
+
"sha256": "c0e7feb5829d3c421b86a6a9a6465b05f495e66679c91688a41d0eb23d1c3207"
|
|
9526
9526
|
},
|
|
9527
9527
|
{
|
|
9528
9528
|
"path": "src/module-loader/catalog.js",
|
|
@@ -10142,7 +10142,7 @@
|
|
|
10142
10142
|
{
|
|
10143
10143
|
"path": "tests/cli_sessions.mjs",
|
|
10144
10144
|
"mode": "0000644",
|
|
10145
|
-
"sha256": "
|
|
10145
|
+
"sha256": "060821b27429a98d7120525efd8b40cdeb2f845c579db0f01b4b5f604b0122ca"
|
|
10146
10146
|
},
|
|
10147
10147
|
{
|
|
10148
10148
|
"path": "tests/cli_surface.mjs",
|
|
@@ -11452,12 +11452,12 @@
|
|
|
11452
11452
|
{
|
|
11453
11453
|
"path": "tests/landing_page.mjs",
|
|
11454
11454
|
"mode": "0000644",
|
|
11455
|
-
"sha256": "
|
|
11455
|
+
"sha256": "1e37768b7408632f83f0e118da0226d09324999909e7962fc7f27268d4290f20"
|
|
11456
11456
|
},
|
|
11457
11457
|
{
|
|
11458
11458
|
"path": "tests/lib_sh_resolution.mjs",
|
|
11459
11459
|
"mode": "0000644",
|
|
11460
|
-
"sha256": "
|
|
11460
|
+
"sha256": "fdefb4971d75dcf6ab1000323211a9fbe732508ae1a0a28c36b8087383ae797e"
|
|
11461
11461
|
},
|
|
11462
11462
|
{
|
|
11463
11463
|
"path": "tests/lifecycle-card.mjs",
|
|
@@ -12499,6 +12499,11 @@
|
|
|
12499
12499
|
"mode": "0000644",
|
|
12500
12500
|
"sha256": "1beb0554d1e29b853d54d17e4345ca7c62f1cd34c72fe6a20b9e2d712e7f2dce"
|
|
12501
12501
|
},
|
|
12502
|
+
{
|
|
12503
|
+
"path": "tests/session_rename_fallback.mjs",
|
|
12504
|
+
"mode": "0000644",
|
|
12505
|
+
"sha256": "02a61cc6a9949276e88e25d65e75a752cea36fccc1f0e7cec8bf7e44c1dfc93f"
|
|
12506
|
+
},
|
|
12502
12507
|
{
|
|
12503
12508
|
"path": "tests/session_reward_on_land.mjs",
|
|
12504
12509
|
"mode": "0000644",
|
|
@@ -12527,7 +12532,7 @@
|
|
|
12527
12532
|
{
|
|
12528
12533
|
"path": "tests/setup_device_flow_fallback.mjs",
|
|
12529
12534
|
"mode": "0000644",
|
|
12530
|
-
"sha256": "
|
|
12535
|
+
"sha256": "f047b209ec3b0ea2fcffbee7c3b36d8cf01bb18e19cfcfa9d32267db672d834d"
|
|
12531
12536
|
},
|
|
12532
12537
|
{
|
|
12533
12538
|
"path": "tests/setup_smoke.mjs",
|
|
@@ -1791,5 +1791,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1791
1791
|
landed since 1.19.664 with no explicit bump. run 34560552542. (task 1002620)
|
|
1792
1792
|
1.19.666 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1793
1793
|
landed since 1.19.665 with no explicit bump. run 34567142386. (task 1002620)
|
|
1794
|
+
1.19.667 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1795
|
+
landed since 1.19.666 with no explicit bump. run 34576878372. (task 1002620)
|
|
1794
1796
|
---------------------------------------------------------------------------
|
|
1795
1797
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// devbox-app/src/session-store.js — the app shares the GDS CLI's session file.
|
|
2
2
|
//
|
|
3
|
-
// ~/.config/<instance>/
|
|
3
|
+
// ~/.config/<instance>/bongos-session.json is the same file scripts/gds/cli-lib.js and
|
|
4
4
|
// paste-token.js read/write: { token, builder, api_base, ... }. Sharing it is
|
|
5
5
|
// a deliberate UX decision (ADR 0045): pairing the app also signs in every
|
|
6
6
|
// /builder-* skill on this machine, and a builder who already ran
|
|
@@ -16,12 +16,21 @@ const brand = require('./brand');
|
|
|
16
16
|
// The instance's CLI config dir (branding configDir) — so the app shares the
|
|
17
17
|
// exact session file the /builder-* CLI uses on this machine.
|
|
18
18
|
const DIR = path.join(os.homedir(), '.config', brand.CONFIG_DIR);
|
|
19
|
-
const FILE = path.join(DIR, '
|
|
20
|
-
// Read-side legacy
|
|
21
|
-
|
|
19
|
+
const FILE = path.join(DIR, 'bongos-session.json');
|
|
20
|
+
// Read-side legacy names only — accepted on read, never written to, so the app
|
|
21
|
+
// keeps working on a machine whose CLI has not yet re-authenticated. Newest
|
|
22
|
+
// first, mirroring SESSION_FILENAMES in src/instance-config.js; this app ships as
|
|
23
|
+
// its own bundle (own brand module, no core imports), so the list is duplicated
|
|
24
|
+
// rather than imported, and pinned against the real one by
|
|
25
|
+
// tests/session_rename_fallback.mjs (task 1003704).
|
|
26
|
+
const FILES_LEGACY = [
|
|
27
|
+
path.join(DIR, 'gds-session.json'),
|
|
28
|
+
path.join(DIR, 'pms-session.json'),
|
|
29
|
+
];
|
|
30
|
+
const FILES_READ = [FILE, ...FILES_LEGACY];
|
|
22
31
|
|
|
23
32
|
function read() {
|
|
24
|
-
for (const f of
|
|
33
|
+
for (const f of FILES_READ) {
|
|
25
34
|
try {
|
|
26
35
|
const data = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
27
36
|
if (data && typeof data.token === 'string' && data.token) return data;
|
|
@@ -48,11 +57,26 @@ function write({ token, builder, apiBase }) {
|
|
|
48
57
|
|
|
49
58
|
// Sign-out: drop ONLY our credential fields; preserve everything else
|
|
50
59
|
// (gemini_api_key etc.) so the app never destroys CLI-adjacent config.
|
|
60
|
+
//
|
|
61
|
+
// Strips EVERY accepted filename, not just the current one. read() falls through
|
|
62
|
+
// to an older name when the current file carries no token, so clearing FILE alone
|
|
63
|
+
// would leave a live token in a superseded file and the very next read would sign
|
|
64
|
+
// the builder straight back in. That was survivable while the only legacy name was
|
|
65
|
+
// the long-dead `pms-session.json`; with `gds-session.json` now on the read list
|
|
66
|
+
// it is the common case on every machine that has not re-authenticated yet
|
|
67
|
+
// (task 1003704).
|
|
51
68
|
function clear() {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
for (const target of FILES_READ) {
|
|
70
|
+
let existing = null;
|
|
71
|
+
try {
|
|
72
|
+
existing = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
73
|
+
} catch {
|
|
74
|
+
continue; // missing or unparsable → nothing to strip
|
|
75
|
+
}
|
|
76
|
+
if (!existing || typeof existing !== 'object') continue;
|
|
77
|
+
const { token: _t, builder: _b, ...rest } = existing;
|
|
78
|
+
fs.writeFileSync(target, `${JSON.stringify(rest, null, 2)}\n`, { mode: 0o600 });
|
|
79
|
+
}
|
|
56
80
|
}
|
|
57
81
|
|
|
58
82
|
module.exports = { read, write, clear, FILE };
|
|
@@ -867,7 +867,7 @@
|
|
|
867
867
|
// subdomains; a Max-Age=0 only matches the cookie whose Domain attribute
|
|
868
868
|
// it names, so the host-only expire alone leaves the apex cookie live).
|
|
869
869
|
var apex = location.hostname.split('.').slice(-2).join('.');
|
|
870
|
-
['gds_session', 'pms_session'].forEach(function (name) {
|
|
870
|
+
['bongos_session', 'gds_session', 'pms_session'].forEach(function (name) {
|
|
871
871
|
document.cookie = name + '=; Max-Age=0; path=/';
|
|
872
872
|
document.cookie = name + '=; Max-Age=0; path=/; Domain=.' + apex;
|
|
873
873
|
});
|
|
@@ -946,7 +946,7 @@ composition A; landing composition v3, picked by the owner 2026-08-27. No roll,
|
|
|
946
946
|
function doLogout() {
|
|
947
947
|
var finish = function () {
|
|
948
948
|
var apex = location.hostname.split('.').slice(-2).join('.');
|
|
949
|
-
['gds_session', 'pms_session'].forEach(function (name) {
|
|
949
|
+
['bongos_session', 'gds_session', 'pms_session'].forEach(function (name) {
|
|
950
950
|
document.cookie = name + '=; Max-Age=0; path=/';
|
|
951
951
|
document.cookie = name + '=; Max-Age=0; path=/; Domain=.' + apex;
|
|
952
952
|
});
|
|
@@ -7215,7 +7215,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
7215
7215
|
function doLogout() {
|
|
7216
7216
|
var finish = function () {
|
|
7217
7217
|
var apex = location.hostname.split('.').slice(-2).join('.');
|
|
7218
|
-
['gds_session', 'pms_session'].forEach(function (name) {
|
|
7218
|
+
['bongos_session', 'gds_session', 'pms_session'].forEach(function (name) {
|
|
7219
7219
|
document.cookie = name + '=; Max-Age=0; path=/';
|
|
7220
7220
|
document.cookie = name + '=; Max-Age=0; path=/; Domain=.' + apex;
|
|
7221
7221
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// credential stores (task 1002544).
|
|
3
3
|
//
|
|
4
4
|
// The pattern list is CURATED AND NAMED, not clever: each entry is a specific
|
|
5
|
-
// place secrets live — including our own ~/.config/otb/
|
|
5
|
+
// place secrets live — including our own ~/.config/otb/bongos-session.json and
|
|
6
6
|
// the Windows stores — spelled the way code spells it. A hit means "this
|
|
7
7
|
// artifact's text names a credential store", nothing more; whether it READS it
|
|
8
8
|
// is runtime behavior a static floor cannot see, and the finding says so.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// Patterns are tiered by SIGNAL, because the co-occurrence critical (floor.js)
|
|
11
11
|
// must not cry wolf:
|
|
12
12
|
// FILE — a concrete on-disk secret store path (.aws/credentials, id_rsa,
|
|
13
|
-
//
|
|
13
|
+
// bongos-session.json). Co-located with a network sink this is the
|
|
14
14
|
// strong read-then-send shape, so ONLY file-class hits arm the
|
|
15
15
|
// co-occurrence critical.
|
|
16
16
|
// ENV — an environment-variable NAME (GITHUB_TOKEN, NPM_TOKEN). Ordinary
|
|
@@ -29,7 +29,12 @@ const SEP = String.raw`[\\/]+`;
|
|
|
29
29
|
// line (ReDoS) and would hang the floor before any report is persisted; a
|
|
30
30
|
// bounded `[^\\/\n]*` cannot.
|
|
31
31
|
const CREDENTIAL_PATTERNS = Object.freeze([
|
|
32
|
-
|
|
32
|
+
// EVERY session filename, not just the current one: the file is renamed forward
|
|
33
|
+
// (task 1003704) while the old names stay readable, so an artifact reading ANY of
|
|
34
|
+
// them is reaching for a live credential. Matching only the newest name would have
|
|
35
|
+
// let a reader of gds-session.json through; matching only the oldest, a reader of
|
|
36
|
+
// bongos-session.json. Keep this list in step with SESSION_FILENAMES.
|
|
37
|
+
['our own Bongos CLI session token', new RegExp(String.raw`(?:bongos|gds|pms)-session\.json|\.config${SEP}otb`, 'i'), 'file'],
|
|
33
38
|
['SSH private key', new RegExp(String.raw`\.ssh${SEP}[^\\/\n]*(?:_rsa|_ed25519|_ecdsa)|\bid_rsa\b|\bid_ed25519\b|\bid_ecdsa\b`, 'i'), 'file'],
|
|
34
39
|
['AWS credentials file', new RegExp(String.raw`\.aws${SEP}credentials`, 'i'), 'file'],
|
|
35
40
|
['netrc', new RegExp(String.raw`(?:^|[^\w.])\.?_?netrc\b`, 'i'), 'file'],
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.667",
|
|
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.667",
|
|
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.667",
|
|
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
|
@@ -238,7 +238,7 @@ function readCloudInit({ authorizedKeysBlock = '', boxEnv = '', gdsSession = '',
|
|
|
238
238
|
// /etc/otb/box.env — empty by default (quick tunnel); the named-tunnel
|
|
239
239
|
// connector token + stable hostname when BOX_NAMED_TUNNEL is on (#771).
|
|
240
240
|
.replace(/__BOX_ENV_B64__/g, Buffer.from(boxEnv || '', 'utf8').toString('base64'))
|
|
241
|
-
// /root/.config/otb/
|
|
241
|
+
// /root/.config/otb/bongos-session.json — the builder's Bongos session, minted at
|
|
242
242
|
// provision so box-source-fetch (#600) can authenticate on FIRST boot and
|
|
243
243
|
// clone the rank-scoped repo. Without it the box never clones (the #818
|
|
244
244
|
// chicken-and-egg: the session normally comes from /builder-setup, which
|
package/scripts/gds/cli-lib.js
CHANGED
|
@@ -17,17 +17,32 @@ const os = require('node:os');
|
|
|
17
17
|
const { execSync } = require('node:child_process');
|
|
18
18
|
const ic = require('../../src/instance-config');
|
|
19
19
|
|
|
20
|
-
// Session token
|
|
21
|
-
// (~/.config/<configDir>/
|
|
22
|
-
// READ we try
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
// Session token filenames, NEWEST FIRST. The WRITE target is the configured
|
|
21
|
+
// instance dir (~/.config/<configDir>/bongos-session.json; OTB → ~/.config/otb,
|
|
22
|
+
// unchanged). On READ we try each name across every config read dir (configured +
|
|
23
|
+
// legacy otb) — so a pre-rename session, or one written by a differently-
|
|
24
|
+
// namespaced instance, still resolves (R61 / task 1200). os.homedir() keeps it
|
|
25
|
+
// per-user on any machine.
|
|
26
|
+
//
|
|
27
|
+
// WHY THE OLD NAMES STAY READABLE. This file is on disk on every builder machine
|
|
28
|
+
// and every live dev box. Renaming it with no fallback signs all of them out at
|
|
29
|
+
// once and every /builder-* command dies with 'no Bongos session'. So a read that
|
|
30
|
+
// resolves through a superseded name MIGRATES forward (see loadSession), and the
|
|
31
|
+
// old file is deliberately LEFT IN PLACE — a builder may roll back to an older
|
|
32
|
+
// CLI, which can only see the old name. Part 4 (task 1003706) deletes it behind a
|
|
33
|
+
// test of its absence. (task 1003704)
|
|
34
|
+
//
|
|
35
|
+
// Order is FILENAME-major, not directory-major: the newest name found in ANY read
|
|
36
|
+
// dir beats an older name in the configured dir. That is the precedence a rename
|
|
37
|
+
// wants, and it is the order the two-name version of this list already used.
|
|
38
|
+
// The list itself lives in instance-config (the lowest module that reads the
|
|
39
|
+
// file, and the only one cli-lib and paste-token.js can both import).
|
|
40
|
+
// Destructured, not read off `ic` as a member: knip cannot trace a namespace-only
|
|
41
|
+
// property access on this module and reports the export dead (the same blind spot
|
|
42
|
+
// task 1003703 closed for two other instance-config exports).
|
|
43
|
+
const { SESSION_FILENAMES } = require('../../src/instance-config');
|
|
44
|
+
const SESSION_PATH = ic.configPath(SESSION_FILENAMES[0]);
|
|
45
|
+
const SESSION_READ_PATHS = SESSION_FILENAMES.flatMap((n) => ic.configReadPaths(n));
|
|
31
46
|
// The API base every CLI call targets, resolved ONCE through the single source of
|
|
32
47
|
// truth in instance-config: <PREFIX>_API_BASE (then legacy GDS_/OTB_/PMS_) → the
|
|
33
48
|
// persisted session's api_base → THIS instance's publicOrigin from the branding
|
|
@@ -218,14 +233,36 @@ async function readSessionFile(p) {
|
|
|
218
233
|
}
|
|
219
234
|
}
|
|
220
235
|
|
|
236
|
+
// Copy a session that resolved through a SUPERSEDED path forward to SESSION_PATH,
|
|
237
|
+
// so the next command reads the new name directly instead of walking the fallback
|
|
238
|
+
// list forever. The old file is left in place on purpose (see SESSION_FILENAMES).
|
|
239
|
+
//
|
|
240
|
+
// BEST-EFFORT BY DESIGN: a read-only home, a full disk, or a permissions problem
|
|
241
|
+
// must never turn a working loadSession() into a failing command. The caller
|
|
242
|
+
// already holds a valid session; failing to write the copy changes nothing about
|
|
243
|
+
// this invocation. So every error is swallowed and the session is still returned.
|
|
244
|
+
async function migrateSessionFile(session) {
|
|
245
|
+
try {
|
|
246
|
+
await fsp.mkdir(path.dirname(SESSION_PATH), { recursive: true });
|
|
247
|
+
await fsp.writeFile(SESSION_PATH, JSON.stringify(session, null, 2), { mode: 0o600 });
|
|
248
|
+
return true;
|
|
249
|
+
} catch (_) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
221
254
|
async function loadSession() {
|
|
222
|
-
// Try each read path in priority order (configured dir's
|
|
223
|
-
// legacy otb dir, then the
|
|
224
|
-
//
|
|
225
|
-
//
|
|
255
|
+
// Try each read path in priority order (configured dir's bongos-session.json,
|
|
256
|
+
// legacy otb dir, then each superseded filename across the same dirs). A hit on
|
|
257
|
+
// anything OTHER than SESSION_PATH is migrated forward — SESSION_READ_PATHS[0]
|
|
258
|
+
// IS SESSION_PATH (configReadDirs puts the configured dir first), so the common
|
|
259
|
+
// case writes nothing.
|
|
226
260
|
for (const p of SESSION_READ_PATHS) {
|
|
227
261
|
const s = await readSessionFile(p);
|
|
228
|
-
if (s)
|
|
262
|
+
if (s) {
|
|
263
|
+
if (p !== SESSION_PATH) await migrateSessionFile(s);
|
|
264
|
+
return s;
|
|
265
|
+
}
|
|
229
266
|
}
|
|
230
267
|
return null;
|
|
231
268
|
}
|
|
@@ -1137,6 +1174,8 @@ module.exports = {
|
|
|
1137
1174
|
rewardPolicy,
|
|
1138
1175
|
costPlusOnlyNote,
|
|
1139
1176
|
SESSION_PATH,
|
|
1177
|
+
SESSION_FILENAMES,
|
|
1178
|
+
SESSION_READ_PATHS,
|
|
1140
1179
|
loadSession,
|
|
1141
1180
|
loadSessionSync,
|
|
1142
1181
|
saveSession,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// The art pipeline (modules/art-pipeline/pipeline/gen_api.py) runs LOCALLY and can't call the API
|
|
6
6
|
// per generation, so SessionStart runs this once: GET /api/gds/me/art-key and,
|
|
7
7
|
// based on the builder's live rank, write or remove the `shared_gemini_api_key`
|
|
8
|
-
// field in ~/.config/otb/
|
|
8
|
+
// field in ~/.config/otb/bongos-session.json. gen_api.py reads that field as a
|
|
9
9
|
// fallback BELOW the builder's own key — so own key always wins, and a newcomer
|
|
10
10
|
// with no own key falls back to the shared one we pay for.
|
|
11
11
|
//
|
package/scripts/gds/init.js
CHANGED
|
@@ -254,7 +254,7 @@ function buildBrandingConfig(spec) {
|
|
|
254
254
|
// Every instance gets its OWN session/config dir (task 1002626). Without
|
|
255
255
|
// this, instance-config.js falls back to the shared 'cloudbongos' dir, so
|
|
256
256
|
// every un-branded instance on a machine reads/writes the SAME
|
|
257
|
-
// ~/.config/cloudbongos/
|
|
257
|
+
// ~/.config/cloudbongos/bongos-session.json — signing in to one silently
|
|
258
258
|
// evicts the CLI session of every other, including the hub. Same slug
|
|
259
259
|
// family as the package name + provisioning slug.
|
|
260
260
|
configDir: spec.configDir ? String(spec.configDir).trim() : slugify(productName, 'instance'),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// scripts/gds/paste-token.js — V3.R91 / #401.
|
|
3
3
|
//
|
|
4
4
|
// Accept a CLI bearer minted by the builders' hall (POST /api/gds/auth/cli-token/issue)
|
|
5
|
-
// and write it into ~/.config/otb/
|
|
5
|
+
// and write it into ~/.config/otb/bongos-session.json. Preserves any existing
|
|
6
6
|
// fields (notably gemini_api_key registered via /builder-setup) so a token
|
|
7
7
|
// paste never silently un-registers a builder's Gemini key.
|
|
8
8
|
//
|
|
@@ -24,10 +24,13 @@
|
|
|
24
24
|
const fs = require('node:fs');
|
|
25
25
|
const path = require('node:path');
|
|
26
26
|
const ic = require('../../src/instance-config');
|
|
27
|
+
// Destructured for the same reason as cli-lib: a namespace-only `ic.X` read is
|
|
28
|
+
// invisible to knip, which then calls the export dead code.
|
|
29
|
+
const { SESSION_FILENAMES, readSessionConfigSync } = require('../../src/instance-config');
|
|
27
30
|
|
|
28
31
|
// WRITE the session to the configured instance dir (OTB → ~/.config/otb,
|
|
29
32
|
// unchanged; a fresh instance → its neutral dir). R61 / task 1200.
|
|
30
|
-
const SESSION_PATH = ic.configPath(
|
|
33
|
+
const SESSION_PATH = ic.configPath(SESSION_FILENAMES[0]);
|
|
31
34
|
// env → the EXISTING session's api_base → this instance's branding default.
|
|
32
35
|
// On a RE-auth a session file already exists, and its api_base is the best signal
|
|
33
36
|
// of which instance the builder is on — this file used to hardcode the founder
|
|
@@ -91,9 +94,11 @@ async function main() {
|
|
|
91
94
|
// way, treat as a fresh write.
|
|
92
95
|
let existing = {};
|
|
93
96
|
try {
|
|
94
|
-
// Read across config dirs (configured + legacy otb)
|
|
95
|
-
// old way still has its fields preserved on
|
|
96
|
-
|
|
97
|
+
// Read across config dirs (configured + legacy otb) AND across every accepted
|
|
98
|
+
// filename, so a session written the old way still has its fields preserved on
|
|
99
|
+
// the next paste. This is the re-auth path: a miss here does not fail loudly,
|
|
100
|
+
// it silently drops the builder's gemini_api_key (task 1003704).
|
|
101
|
+
const raw = readSessionConfigSync();
|
|
97
102
|
if (raw) existing = JSON.parse(raw);
|
|
98
103
|
} catch (_) {
|
|
99
104
|
/* fresh session; nothing to merge */
|
|
@@ -95,7 +95,7 @@ if [ -z "$REMOTE" ]; then bad "could not resolve origin remote for fresh-clone t
|
|
|
95
95
|
# --- 2. the fresh clone leaks NO secrets / NO builder memory ------------
|
|
96
96
|
LEAKS=0
|
|
97
97
|
CFG_DIR=$(gds_node "process.stdout.write(require('../../src/instance-config').configDirName())" 2>/dev/null) || CFG_DIR=""
|
|
98
|
-
for p in ".env.local" "spaces.env" ".config/${CFG_DIR:-otb}/gds-session.json" "etc/${CFG_DIR:-otb}"; do
|
|
98
|
+
for p in ".env.local" "spaces.env" ".config/${CFG_DIR:-otb}/bongos-session.json" ".config/${CFG_DIR:-otb}/gds-session.json" "etc/${CFG_DIR:-otb}"; do
|
|
99
99
|
if [ -e "$TMP/clone/$p" ]; then echo " leak: $p present in clone"; LEAKS=$((LEAKS+1)); fi
|
|
100
100
|
done
|
|
101
101
|
# builder_memory is server-side only — no memory dir should ship in-repo
|
package/scripts/gds/setup.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// Prints the user_code and verification_uri, then polls until the user
|
|
16
16
|
// completes auth (or expires/denies). On success, writes
|
|
17
|
-
// ~/.config/otb/
|
|
17
|
+
// ~/.config/otb/bongos-session.json (resolved from os.homedir(), so this works for
|
|
18
18
|
// any user on any machine; no path is hardcoded to a particular developer's
|
|
19
19
|
// home directory) and prints the builder profile.
|
|
20
20
|
|
|
@@ -49,7 +49,7 @@ function dryRunStep(msg) {
|
|
|
49
49
|
// pixel-art pipeline (gen_api.py). V3.R11 (#91): each builder pays their own
|
|
50
50
|
// Gemini bill, so spend is attributable per-builder on the public dashboard.
|
|
51
51
|
//
|
|
52
|
-
// Stored as gemini_api_key in ~/.config/otb/
|
|
52
|
+
// Stored as gemini_api_key in ~/.config/otb/bongos-session.json (mode 600, same
|
|
53
53
|
// file as the GitHub session token). gen_api.py reads this location before
|
|
54
54
|
// falling back to ~/.config/otb/env or .env.local.
|
|
55
55
|
//
|
|
@@ -476,7 +476,7 @@ async function main() {
|
|
|
476
476
|
|
|
477
477
|
// A valid session already exists on this machine. Don't silently adopt
|
|
478
478
|
// it. The session file is a single global path
|
|
479
|
-
// (~/.config/otb/
|
|
479
|
+
// (~/.config/otb/bongos-session.json), so a second person setting up on a
|
|
480
480
|
// shared device — or the same person onboarding a different account,
|
|
481
481
|
// e.g. for testing — would otherwise be invisibly bound to whoever set
|
|
482
482
|
// up first. On an interactive shell, confirm before continuing; the gate
|
|
@@ -513,7 +513,7 @@ async function main() {
|
|
|
513
513
|
console.log('');
|
|
514
514
|
console.log('Setting up as a different builder — the saved session will be replaced once you finish signing in...');
|
|
515
515
|
// Fall through to the Device Flow below, which calls saveSession() and
|
|
516
|
-
// overwrites ~/.config/otb/
|
|
516
|
+
// overwrites ~/.config/otb/bongos-session.json with the new identity.
|
|
517
517
|
} else {
|
|
518
518
|
console.log(`Continuing as ${who}.`);
|
|
519
519
|
process.exit(0);
|