@bongos/core 1.19.957 → 1.19.959
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 +27 -22
- package/docs/copy-inventory.md +13 -11
- package/docs/copy-registry.json +31 -13
- package/docs/module-api-changelog.md +4 -0
- package/modules/government/protected-surfaces.json +35 -0
- package/modules/hall-ui/public/deploy.js +12 -0
- package/modules/provisioning/core-upgrade.js +3 -0
- package/modules/provisioning/migrations/provisioning_024_snapshot_schema_pending.sql +17 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/provision-core-upgrade.js +24 -6
- package/src/bongos/module-scope-map.js +12 -0
- package/src/module-api.js +1 -1
- package/tests/core_upgrade_door.mjs +9 -0
- package/tests/core_upgrade_runner.mjs +33 -0
- package/tests/deploy_page_projects.mjs +14 -0
- package/tests/government_protected_surfaces.mjs +81 -0
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.959",
|
|
6
|
+
"core_contract": "1.19.959",
|
|
7
|
+
"source_commit": "762c63db2672a1dac87eb25a78bd3a93717b6d1a",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-22T14:26:09.898Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 514,
|
|
13
13
|
"agent_docs_stubbed": 26,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2358,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2898,
|
|
20
|
+
"tree_sha256": "f587a606503aa60197f7ffbed71f7a3df76cfafda2da9b932090732dfc2cc512",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2157,12 +2157,12 @@
|
|
|
2157
2157
|
{
|
|
2158
2158
|
"path": "docs/copy-inventory.md",
|
|
2159
2159
|
"mode": "0000644",
|
|
2160
|
-
"sha256": "
|
|
2160
|
+
"sha256": "77cb83609d2a80e2c7520746181ef858839d37e8c0997b5dce42127d0c4c119c"
|
|
2161
2161
|
},
|
|
2162
2162
|
{
|
|
2163
2163
|
"path": "docs/copy-registry.json",
|
|
2164
2164
|
"mode": "0000644",
|
|
2165
|
-
"sha256": "
|
|
2165
|
+
"sha256": "8d83ca0d16a1f9d0efc89f0331f6940592ce34e0dd6f92c448575497bce96548"
|
|
2166
2166
|
},
|
|
2167
2167
|
{
|
|
2168
2168
|
"path": "docs/design/apex-pass-2-direction.md",
|
|
@@ -2692,7 +2692,7 @@
|
|
|
2692
2692
|
{
|
|
2693
2693
|
"path": "docs/module-api-changelog.md",
|
|
2694
2694
|
"mode": "0000644",
|
|
2695
|
-
"sha256": "
|
|
2695
|
+
"sha256": "164da9dadc56356e91897f78786de7c42b32e37534971b6743985abeba81d718"
|
|
2696
2696
|
},
|
|
2697
2697
|
{
|
|
2698
2698
|
"path": "docs/modules-contract.md",
|
|
@@ -4497,7 +4497,7 @@
|
|
|
4497
4497
|
{
|
|
4498
4498
|
"path": "modules/government/protected-surfaces.json",
|
|
4499
4499
|
"mode": "0000644",
|
|
4500
|
-
"sha256": "
|
|
4500
|
+
"sha256": "ad15115c455dc9eb8b7786ce704beb94b5c40fabe17806e88b5edffb20b164cf"
|
|
4501
4501
|
},
|
|
4502
4502
|
{
|
|
4503
4503
|
"path": "modules/government/ranks.js",
|
|
@@ -4822,7 +4822,7 @@
|
|
|
4822
4822
|
{
|
|
4823
4823
|
"path": "modules/hall-ui/public/deploy.js",
|
|
4824
4824
|
"mode": "0000644",
|
|
4825
|
-
"sha256": "
|
|
4825
|
+
"sha256": "e3a4fa62e761dddfb54a1f13680eb64ff87c4d37e83fa41a846ebfe1f41d44c8"
|
|
4826
4826
|
},
|
|
4827
4827
|
{
|
|
4828
4828
|
"path": "modules/hall-ui/public/diagram-viewer.css",
|
|
@@ -6542,7 +6542,7 @@
|
|
|
6542
6542
|
{
|
|
6543
6543
|
"path": "modules/provisioning/core-upgrade.js",
|
|
6544
6544
|
"mode": "0000644",
|
|
6545
|
-
"sha256": "
|
|
6545
|
+
"sha256": "96c6b73411a489e5c41fd567123fa8ef35f7a757db0e1df0c0cafd720674b05f"
|
|
6546
6546
|
},
|
|
6547
6547
|
{
|
|
6548
6548
|
"path": "modules/provisioning/credential-preflight.js",
|
|
@@ -6674,6 +6674,11 @@
|
|
|
6674
6674
|
"mode": "0000644",
|
|
6675
6675
|
"sha256": "1fb60b17c411d9529f4c0ecd0b3d1efc9b2061567a1b31bf74fa706e2e83b3d7"
|
|
6676
6676
|
},
|
|
6677
|
+
{
|
|
6678
|
+
"path": "modules/provisioning/migrations/provisioning_024_snapshot_schema_pending.sql",
|
|
6679
|
+
"mode": "0000644",
|
|
6680
|
+
"sha256": "1287440b0088a6451dd4df234e578e06fc6f3e892915e64cd6c6e1f09dadd9d5"
|
|
6681
|
+
},
|
|
6677
6682
|
{
|
|
6678
6683
|
"path": "modules/provisioning/module.json",
|
|
6679
6684
|
"mode": "0000644",
|
|
@@ -8077,12 +8082,12 @@
|
|
|
8077
8082
|
{
|
|
8078
8083
|
"path": "package-lock.json",
|
|
8079
8084
|
"mode": "0000644",
|
|
8080
|
-
"sha256": "
|
|
8085
|
+
"sha256": "e0d9870134171629f6021c929775456f72729ad7131249f17c5e99cd64d2405f"
|
|
8081
8086
|
},
|
|
8082
8087
|
{
|
|
8083
8088
|
"path": "package.json",
|
|
8084
8089
|
"mode": "0000644",
|
|
8085
|
-
"sha256": "
|
|
8090
|
+
"sha256": "830c6340ff774389b6a391c8045116ccabc871a23ba09688e03380892f340a2a"
|
|
8086
8091
|
},
|
|
8087
8092
|
{
|
|
8088
8093
|
"path": "public-docs/index.html",
|
|
@@ -9027,7 +9032,7 @@
|
|
|
9027
9032
|
{
|
|
9028
9033
|
"path": "scripts/gds/provision-core-upgrade.js",
|
|
9029
9034
|
"mode": "0000644",
|
|
9030
|
-
"sha256": "
|
|
9035
|
+
"sha256": "f22c31d00a50a312d7228922cbe70fedc503e704cc7f2cb33a8686a4954c1c1e"
|
|
9031
9036
|
},
|
|
9032
9037
|
{
|
|
9033
9038
|
"path": "scripts/gds/provision-disconnect.js",
|
|
@@ -9892,7 +9897,7 @@
|
|
|
9892
9897
|
{
|
|
9893
9898
|
"path": "src/bongos/module-scope-map.js",
|
|
9894
9899
|
"mode": "0000644",
|
|
9895
|
-
"sha256": "
|
|
9900
|
+
"sha256": "70b35812cbf26b9ce8c25663bbc4fcce40272b4877b89baf70cd64a5fe90b3b3"
|
|
9896
9901
|
},
|
|
9897
9902
|
{
|
|
9898
9903
|
"path": "src/bongos/module-submissions.js",
|
|
@@ -10087,7 +10092,7 @@
|
|
|
10087
10092
|
{
|
|
10088
10093
|
"path": "src/module-api.js",
|
|
10089
10094
|
"mode": "0000644",
|
|
10090
|
-
"sha256": "
|
|
10095
|
+
"sha256": "73781b940ba631e4642209a973a119375f7ff12f23027033030b1c95f0cc45f7"
|
|
10091
10096
|
},
|
|
10092
10097
|
{
|
|
10093
10098
|
"path": "src/module-loader/catalog.js",
|
|
@@ -10992,12 +10997,12 @@
|
|
|
10992
10997
|
{
|
|
10993
10998
|
"path": "tests/core_upgrade_door.mjs",
|
|
10994
10999
|
"mode": "0000644",
|
|
10995
|
-
"sha256": "
|
|
11000
|
+
"sha256": "c4238e2f2e2c52f23fb6948f5e6545bc4880efe75eb9af229a455db6017db05c"
|
|
10996
11001
|
},
|
|
10997
11002
|
{
|
|
10998
11003
|
"path": "tests/core_upgrade_runner.mjs",
|
|
10999
11004
|
"mode": "0000644",
|
|
11000
|
-
"sha256": "
|
|
11005
|
+
"sha256": "85bc665f5d80ff1c7e8134e6be7dd8fa336b4fb50344164b034b0e72a963f04d"
|
|
11001
11006
|
},
|
|
11002
11007
|
{
|
|
11003
11008
|
"path": "tests/cosmos_token_contrast.mjs",
|
|
@@ -11142,7 +11147,7 @@
|
|
|
11142
11147
|
{
|
|
11143
11148
|
"path": "tests/deploy_page_projects.mjs",
|
|
11144
11149
|
"mode": "0000644",
|
|
11145
|
-
"sha256": "
|
|
11150
|
+
"sha256": "5c582192ddd83ef289be692b12d898c8837b54312348751082478d036987a647"
|
|
11146
11151
|
},
|
|
11147
11152
|
{
|
|
11148
11153
|
"path": "tests/design_tokens_sync.mjs",
|
|
@@ -11772,7 +11777,7 @@
|
|
|
11772
11777
|
{
|
|
11773
11778
|
"path": "tests/government_protected_surfaces.mjs",
|
|
11774
11779
|
"mode": "0000644",
|
|
11775
|
-
"sha256": "
|
|
11780
|
+
"sha256": "4299e738542cd8951ec9846c4add158e902cb2ad29deba6c4afbfdb2b94877bf"
|
|
11776
11781
|
},
|
|
11777
11782
|
{
|
|
11778
11783
|
"path": "tests/government_rank_sync.mjs",
|
package/docs/copy-inventory.md
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
> Deterministic on a given tree — regenerate and commit rather than hand-editing.
|
|
5
5
|
> Machine-readable twin: [`copy-registry.json`](copy-registry.json).
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**1924 strings** across 3 surfaces · 1663 distinct pieces of copy · 1924 certain, 0 heuristic · 179 shown in more than one place.
|
|
8
8
|
|
|
9
9
|
## Surfaces
|
|
10
10
|
|
|
11
11
|
| surface | lives at | files | strings |
|
|
12
12
|
|---|---|---|---|
|
|
13
|
-
| `builders-hall` | `modules/hall-ui/public` | 92 |
|
|
13
|
+
| `builders-hall` | `modules/hall-ui/public` | 92 | 1429 |
|
|
14
14
|
| `status-dashboard` | `modules/status-ui/public` | 4 | 100 |
|
|
15
15
|
| `landing` | `modules/public-landing/public` | 5 | 395 |
|
|
16
16
|
|
|
@@ -78,7 +78,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
78
78
|
| `07f422cbdb7e` | 2x | ) and capture-resistant by design. | modules/public-landing/public/projects.html:1030, modules/public-landing/public/projects.html:1057 |
|
|
79
79
|
| … | | _139 more in the JSON registry_ | |
|
|
80
80
|
|
|
81
|
-
## `builders-hall` —
|
|
81
|
+
## `builders-hall` — 1429 strings
|
|
82
82
|
|
|
83
83
|
| id | conf | text | where |
|
|
84
84
|
|---|---|---|---|
|
|
@@ -327,7 +327,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
327
327
|
| `2366356926b4` | certain | Could not mark the primer just now. Try again. | `modules/hall-ui/public/primer.js:259` |
|
|
328
328
|
| `753987b5da13` | certain | Could not reach the submit endpoint. | `modules/hall-ui/public/modules.js:297` |
|
|
329
329
|
| `6f500726f0ac` | certain | Could not read the report: {…} | `modules/hall-ui/public/watch.js:640` |
|
|
330
|
-
| `21c2f33168a3` | certain | Could not read this project's deploy state: {…} | `modules/hall-ui/public/deploy.js:
|
|
330
|
+
| `21c2f33168a3` | certain | Could not read this project's deploy state: {…} | `modules/hall-ui/public/deploy.js:322` |
|
|
331
331
|
| `8b470cebf53d` | certain | Could not remove your key. Try again. | `modules/hall-ui/public/settings.js:1133` |
|
|
332
332
|
| `4cf6bc8b377b` | certain | Could not remove. Try again. | `modules/hall-ui/public/settings.js:1132` |
|
|
333
333
|
| `7a778d188e87` | certain | Could not remove: {…} | `modules/hall-ui/public/government.js:369` |
|
|
@@ -376,6 +376,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
376
376
|
| `a55e423263f0` | certain | Cross-project record | `modules/hall-ui/public/profile.html:94` |
|
|
377
377
|
| `a55e423263f0` | certain | Cross-project record | `modules/hall-ui/public/settings.html:95` |
|
|
378
378
|
| `24013a074724` | certain | Custom rank | `modules/hall-ui/public/government.html:113` |
|
|
379
|
+
| `cf7d7d5d5e83` | certain | Database behind. | `modules/hall-ui/public/deploy.js:286` |
|
|
379
380
|
| `6744aed3d15e` | certain | Dated exploit-detail engagement reports — kept out of the repo (threat-model §6.3) and served only to Archons. | `modules/hall-ui/public/watch.html:131` |
|
|
380
381
|
| `7c6891813679` | certain | Default ({…}) | `modules/hall-ui/public/settings.js:63` |
|
|
381
382
|
| `7ec7dc1adaa6` | certain | Deploy — {{worldName}} | `modules/hall-ui/public/deploy.html:6` |
|
|
@@ -639,7 +640,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
639
640
|
| `f14a91b3f625` | certain | Most recent first. Each row is one recorded work session; every id on it opens its record. | `modules/hall-ui/public/sessions.html:56` |
|
|
640
641
|
| `e52ae74f0052` | certain | Move to goal | `modules/hall-ui/public/task.js:581` |
|
|
641
642
|
| `e77d5f3beaef` | certain | Move to {…} | `modules/hall-ui/public/deploy.js:269` |
|
|
642
|
-
| `e77d5f3beaef` | certain | Move to {…} | `modules/hall-ui/public/deploy.js:
|
|
643
|
+
| `e77d5f3beaef` | certain | Move to {…} | `modules/hall-ui/public/deploy.js:383` |
|
|
643
644
|
| `393139f648b8` | certain | Moving to core | `modules/hall-ui/public/deploy.js:140` |
|
|
644
645
|
| `ae84ebe1d735` | certain | Name cannot be blank. | `modules/hall-ui/public/settings.js:761` |
|
|
645
646
|
| `31e91ee6ce03` | certain | Name must be {…} characters or fewer. | `modules/hall-ui/public/settings.js:766` |
|
|
@@ -676,7 +677,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
676
677
|
| `2a6d7552e21f` | certain | No other sessions. | `modules/hall-ui/public/settings-sessions.js:64` |
|
|
677
678
|
| `9f73b3f3dad0` | certain | No rank floor — any builder can claim this task | `modules/hall-ui/public/task-lib.js:62` |
|
|
678
679
|
| `3fd0c6fcb92e` | certain | No request and no invite needed. Sign in with GitHub, and a step-by-step guide takes you the rest of the way. | `modules/hall-ui/public/hall-render.js:277` |
|
|
679
|
-
| `2947c1ddea9a` | certain | No running box to deploy. | `modules/hall-ui/public/deploy.js:
|
|
680
|
+
| `2947c1ddea9a` | certain | No running box to deploy. | `modules/hall-ui/public/deploy.js:360` |
|
|
680
681
|
| `9fb9f766450d` | certain | No sections yet | `modules/hall-ui/public/primer.js:130` |
|
|
681
682
|
| `bef9fe43ba84` | certain | No sessions recorded yet. They land here as builders ship and end sessions. | `modules/hall-ui/public/sessions.js:146` |
|
|
682
683
|
| `4485497d87bb` | certain | No specialities yet. Create one below — it takes a name and a craft, and you can train it afterwards. | `modules/hall-ui/public/settings-specialities.js:169` |
|
|
@@ -708,7 +709,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
708
709
|
| `fec5d78497e8` | certain | Nothing in the backlog right now. | `modules/hall-ui/public/work.js:1107` |
|
|
709
710
|
| `905e99f158c2` | certain | Nothing is discarded by omission: every task needs a decision before this can be submitted. Abandoning stamps | `modules/hall-ui/public/goals-render.js:1012` |
|
|
710
711
|
| `2ec0fbb20a42` | certain | Nothing is waiting. A spark appears here when its author offers a quick idea up for development. | `modules/hall-ui/public/ideas.js:843` |
|
|
711
|
-
| `9ac63d97239a` | certain | Nothing newer is published that this box can take. There is nothing to deploy. | `modules/hall-ui/public/deploy.js:
|
|
712
|
+
| `9ac63d97239a` | certain | Nothing newer is published that this box can take. There is nothing to deploy. | `modules/hall-ui/public/deploy.js:303` |
|
|
712
713
|
| `073d7fb013ae` | certain | Nothing of yours is {…} right now. | `modules/hall-ui/public/thinking.js:311` |
|
|
713
714
|
| `ad9a17a8a5eb` | certain | Nothing shipped yet. | `modules/hall-ui/public/profile.js:242` |
|
|
714
715
|
| `ad9a17a8a5eb` | certain | Nothing shipped yet. | `modules/hall-ui/public/work.js:1068` |
|
|
@@ -899,7 +900,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
899
900
|
| `7e1d54119e08` | certain | Select task {…} for bulk release | `modules/hall-ui/public/work.js:242` |
|
|
900
901
|
| `ae43a132699b` | certain | Selectable today | `modules/hall-ui/public/government.js:799` |
|
|
901
902
|
| `53cc6d8dd23c` | certain | Send invitation | `modules/hall-ui/public/goals-render.js:1211` |
|
|
902
|
-
| `a39b0f9d86e5` | certain | Serving {…} — read from the box itself, {…}. | `modules/hall-ui/public/deploy.js:
|
|
903
|
+
| `a39b0f9d86e5` | certain | Serving {…} — read from the box itself, {…}. | `modules/hall-ui/public/deploy.js:306` |
|
|
903
904
|
| `64a1f055129e` | certain | Session card richness | `modules/hall-ui/public/settings-render.js:83` |
|
|
904
905
|
| `d14e8e9acaff` | certain | Session ended. | `modules/hall-ui/public/settings-sessions.js:81` |
|
|
905
906
|
| `55e0a34bafed` | certain | Session log{…} | `modules/hall-ui/public/task.js:487` |
|
|
@@ -954,7 +955,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
954
955
|
| `ec1c2dae4a90` | certain | Standing there | `modules/hall-ui/public/profile.js:314` |
|
|
955
956
|
| `eaad12cacb9d` | certain | Start over | `modules/hall-ui/public/studio.js:235` |
|
|
956
957
|
| `efe530c0e3a7` | certain | Still open | `modules/hall-ui/public/profile.js:494` |
|
|
957
|
-
| `490a3cbb8c1c` | certain | Still working on core {…}. It keeps going without this page — reload to see where it got to. | `modules/hall-ui/public/deploy.js:
|
|
958
|
+
| `490a3cbb8c1c` | certain | Still working on core {…}. It keeps going without this page — reload to see where it got to. | `modules/hall-ui/public/deploy.js:419` |
|
|
958
959
|
| `9a4ced1afb6c` | certain | Stop waiting on task {…} | `modules/hall-ui/public/task.js:278` |
|
|
959
960
|
| `b0861c874a2f` | certain | Stopped using it. | `modules/hall-ui/public/settings-specialities.js:200` |
|
|
960
961
|
| `6c6544f5c011` | certain | Stored encrypted; never shown again after saving — only its last four digits. | `modules/hall-ui/public/settings.html:193` |
|
|
@@ -1082,7 +1083,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1082
1083
|
| `9a685b01e2c6` | certain | This page opens at a higher rank. | `modules/hall-ui/public/government.html:37` |
|
|
1083
1084
|
| `9a685b01e2c6` | certain | This page opens at a higher rank. | `modules/hall-ui/public/project-settings.html:36` |
|
|
1084
1085
|
| `9a685b01e2c6` | certain | This page opens at a higher rank. | `modules/hall-ui/public/watch.html:40` |
|
|
1085
|
-
| `f93fcb24c6ba` | certain | This platform | `modules/hall-ui/public/deploy.js:
|
|
1086
|
+
| `f93fcb24c6ba` | certain | This platform | `modules/hall-ui/public/deploy.js:352` |
|
|
1087
|
+
| `3c8aaec39c40` | certain | This project's code expects {…} database change{…} that its database has not applied yet. Anything that relies | `modules/hall-ui/public/deploy.js:286` |
|
|
1086
1088
|
| `6e9dfe1fb903` | certain | This restarts {…} onto core | `modules/hall-ui/public/deploy.js:269` |
|
|
1087
1089
|
| `69e8beced2ff` | certain | This sends the idea back to its author. Say why, and which section. | `modules/hall-ui/public/board-room.js:363` |
|
|
1088
1090
|
| `09256febc32d` | certain | This sentence has {…} {…} where a value is dropped in when it is shown. | `modules/hall-ui/public/copy-desk.js:422` |
|
|
@@ -1348,7 +1350,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
|
|
|
1348
1350
|
| `2fb1dad96280` | certain | pending, on the People tab | `modules/hall-ui/public/watch.html:46` |
|
|
1349
1351
|
| `3b22c5af029b` | certain | rank or above, or that it is your own. | `modules/hall-ui/public/copy-desk.html:47` |
|
|
1350
1352
|
| `80ddf28baee7` | certain | rank-key (kebab-case) | `modules/hall-ui/public/government.html:82` |
|
|
1351
|
-
| `41a4b66c21e5` | certain | reads the control plane's own observation · ADR 0293 · every move is recorded with who asked | `modules/hall-ui/public/deploy.js:
|
|
1353
|
+
| `41a4b66c21e5` | certain | reads the control plane's own observation · ADR 0293 · every move is recorded with who asked | `modules/hall-ui/public/deploy.js:364` |
|
|
1352
1354
|
| `f83f0a9d6b6a` | certain | recorded, on the Operations tab | `modules/hall-ui/public/watch.html:49` |
|
|
1353
1355
|
| `26da1df6fd4a` | certain | reflects it. | `modules/hall-ui/public/settings.html:136` |
|
|
1354
1356
|
| `d4bb81532896` | certain | repro steps, context, anything that helps… | `modules/hall-ui/public/ideas.html:84` |
|
package/docs/copy-registry.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"generator": "scripts/gds/copy-inventory.js",
|
|
4
4
|
"goal": 1000074,
|
|
5
5
|
"counts": {
|
|
6
|
-
"strings":
|
|
7
|
-
"unique_ids":
|
|
8
|
-
"certain":
|
|
6
|
+
"strings": 1924,
|
|
7
|
+
"unique_ids": 1663,
|
|
8
|
+
"certain": 1924,
|
|
9
9
|
"heuristic": 0,
|
|
10
10
|
"duplicate_ids": 179
|
|
11
11
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"builders-hall": {
|
|
14
14
|
"at": "modules/hall-ui/public",
|
|
15
15
|
"files": 92,
|
|
16
|
-
"strings":
|
|
16
|
+
"strings": 1429
|
|
17
17
|
},
|
|
18
18
|
"status-dashboard": {
|
|
19
19
|
"at": "modules/status-ui/public",
|
|
@@ -1067,7 +1067,7 @@
|
|
|
1067
1067
|
"occurrences": 2,
|
|
1068
1068
|
"at": [
|
|
1069
1069
|
"modules/hall-ui/public/deploy.js:269",
|
|
1070
|
-
"modules/hall-ui/public/deploy.js:
|
|
1070
|
+
"modules/hall-ui/public/deploy.js:383"
|
|
1071
1071
|
]
|
|
1072
1072
|
},
|
|
1073
1073
|
{
|
|
@@ -4122,7 +4122,7 @@
|
|
|
4122
4122
|
"surface": "builders-hall",
|
|
4123
4123
|
"text": "Could not read this project's deploy state: {…}",
|
|
4124
4124
|
"file": "modules/hall-ui/public/deploy.js",
|
|
4125
|
-
"line":
|
|
4125
|
+
"line": 322,
|
|
4126
4126
|
"origin": "js-markup",
|
|
4127
4127
|
"confidence": "certain"
|
|
4128
4128
|
},
|
|
@@ -4558,6 +4558,15 @@
|
|
|
4558
4558
|
"origin": "html-text",
|
|
4559
4559
|
"confidence": "certain"
|
|
4560
4560
|
},
|
|
4561
|
+
{
|
|
4562
|
+
"id": "cf7d7d5d5e83",
|
|
4563
|
+
"surface": "builders-hall",
|
|
4564
|
+
"text": "Database behind.",
|
|
4565
|
+
"file": "modules/hall-ui/public/deploy.js",
|
|
4566
|
+
"line": 286,
|
|
4567
|
+
"origin": "js-markup",
|
|
4568
|
+
"confidence": "certain"
|
|
4569
|
+
},
|
|
4561
4570
|
{
|
|
4562
4571
|
"id": "6744aed3d15e",
|
|
4563
4572
|
"surface": "builders-hall",
|
|
@@ -6930,7 +6939,7 @@
|
|
|
6930
6939
|
"surface": "builders-hall",
|
|
6931
6940
|
"text": "Move to {…}",
|
|
6932
6941
|
"file": "modules/hall-ui/public/deploy.js",
|
|
6933
|
-
"line":
|
|
6942
|
+
"line": 383,
|
|
6934
6943
|
"origin": "js-text-assign",
|
|
6935
6944
|
"confidence": "certain"
|
|
6936
6945
|
},
|
|
@@ -7263,7 +7272,7 @@
|
|
|
7263
7272
|
"surface": "builders-hall",
|
|
7264
7273
|
"text": "No running box to deploy.",
|
|
7265
7274
|
"file": "modules/hall-ui/public/deploy.js",
|
|
7266
|
-
"line":
|
|
7275
|
+
"line": 360,
|
|
7267
7276
|
"origin": "js-markup",
|
|
7268
7277
|
"confidence": "certain"
|
|
7269
7278
|
},
|
|
@@ -7551,7 +7560,7 @@
|
|
|
7551
7560
|
"surface": "builders-hall",
|
|
7552
7561
|
"text": "Nothing newer is published that this box can take. There is nothing to deploy.",
|
|
7553
7562
|
"file": "modules/hall-ui/public/deploy.js",
|
|
7554
|
-
"line":
|
|
7563
|
+
"line": 303,
|
|
7555
7564
|
"origin": "js-markup",
|
|
7556
7565
|
"confidence": "certain"
|
|
7557
7566
|
},
|
|
@@ -9270,7 +9279,7 @@
|
|
|
9270
9279
|
"surface": "builders-hall",
|
|
9271
9280
|
"text": "Serving {…} — read from the box itself, {…}.",
|
|
9272
9281
|
"file": "modules/hall-ui/public/deploy.js",
|
|
9273
|
-
"line":
|
|
9282
|
+
"line": 306,
|
|
9274
9283
|
"origin": "js-markup",
|
|
9275
9284
|
"confidence": "certain"
|
|
9276
9285
|
},
|
|
@@ -9765,7 +9774,7 @@
|
|
|
9765
9774
|
"surface": "builders-hall",
|
|
9766
9775
|
"text": "Still working on core {…}. It keeps going without this page — reload to see where it got to.",
|
|
9767
9776
|
"file": "modules/hall-ui/public/deploy.js",
|
|
9768
|
-
"line":
|
|
9777
|
+
"line": 419,
|
|
9769
9778
|
"origin": "js-notice",
|
|
9770
9779
|
"confidence": "certain"
|
|
9771
9780
|
},
|
|
@@ -10917,7 +10926,16 @@
|
|
|
10917
10926
|
"surface": "builders-hall",
|
|
10918
10927
|
"text": "This platform",
|
|
10919
10928
|
"file": "modules/hall-ui/public/deploy.js",
|
|
10920
|
-
"line":
|
|
10929
|
+
"line": 352,
|
|
10930
|
+
"origin": "js-markup",
|
|
10931
|
+
"confidence": "certain"
|
|
10932
|
+
},
|
|
10933
|
+
{
|
|
10934
|
+
"id": "3c8aaec39c40",
|
|
10935
|
+
"surface": "builders-hall",
|
|
10936
|
+
"text": "This project's code expects {…} database change{…} that its database has not applied yet. Anything that relies on {…} may fail until the migrations run.",
|
|
10937
|
+
"file": "modules/hall-ui/public/deploy.js",
|
|
10938
|
+
"line": 286,
|
|
10921
10939
|
"origin": "js-markup",
|
|
10922
10940
|
"confidence": "certain"
|
|
10923
10941
|
},
|
|
@@ -13311,7 +13329,7 @@
|
|
|
13311
13329
|
"surface": "builders-hall",
|
|
13312
13330
|
"text": "reads the control plane's own observation · ADR 0293 · every move is recorded with who asked",
|
|
13313
13331
|
"file": "modules/hall-ui/public/deploy.js",
|
|
13314
|
-
"line":
|
|
13332
|
+
"line": 364,
|
|
13315
13333
|
"origin": "js-markup",
|
|
13316
13334
|
"confidence": "certain"
|
|
13317
13335
|
},
|
|
@@ -2388,5 +2388,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2388
2388
|
landed since 1.19.955 with no explicit bump. run 35691908420. (task 1002620)
|
|
2389
2389
|
1.19.957 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2390
2390
|
landed since 1.19.956 with no explicit bump. run 35692861666. (task 1002620)
|
|
2391
|
+
1.19.958 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2392
|
+
landed since 1.19.957 with no explicit bump. run 35735231183. (task 1002620)
|
|
2393
|
+
1.19.959 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2394
|
+
landed since 1.19.958 with no explicit bump. run 35740227000. (task 1002620)
|
|
2391
2395
|
---------------------------------------------------------------------------
|
|
2392
2396
|
```
|
|
@@ -26,7 +26,13 @@
|
|
|
26
26
|
"permission": "path.protected.modify",
|
|
27
27
|
"surfaces": [
|
|
28
28
|
{ "glob": "src/bongos/auth.js", "group": "authz", "why": "requireBuilder / requireRank definitions" },
|
|
29
|
+
{ "glob": "src/bongos/auth-admission.js", "group": "authz", "why": "task 1004024. Carved out of auth.js (task 1003206): the OAuth flows, session-token minting, admission and IdP checks auth.js now delegates to. Registering auth.js alone protected the facade and none of them." },
|
|
30
|
+
{ "glob": "src/bongos/auth-config.js", "group": "authz", "why": "task 1004024. Carved out of auth.js (task 1003206): the OAuth flows, session-token minting, admission and IdP checks auth.js now delegates to. Registering auth.js alone protected the facade and none of them." },
|
|
31
|
+
{ "glob": "src/bongos/auth-discord.js", "group": "authz", "why": "task 1004024. Carved out of auth.js (task 1003206): the OAuth flows, session-token minting, admission and IdP checks auth.js now delegates to. Registering auth.js alone protected the facade and none of them." },
|
|
32
|
+
{ "glob": "src/bongos/auth-github.js", "group": "authz", "why": "task 1004024. Carved out of auth.js (task 1003206): the OAuth flows, session-token minting, admission and IdP checks auth.js now delegates to. Registering auth.js alone protected the facade and none of them." },
|
|
33
|
+
{ "glob": "src/bongos/auth-idp.js", "group": "authz", "why": "task 1004024. Carved out of auth.js (task 1003206): the OAuth flows, session-token minting, admission and IdP checks auth.js now delegates to. Registering auth.js alone protected the facade and none of them." },
|
|
29
34
|
{ "glob": "src/bongos/db.js", "group": "authz", "why": "rank tiers, REQUIRES_RANK_TIER — the CASE edited in the SEC #863 incident" },
|
|
35
|
+
{ "glob": "src/bongos/db-kernel.js", "group": "authz", "why": "task 1004024. The kernel db slice carved out of db.js (BV1.R69 / ADR 0091): builder identity and the rank reads the SEC #863 entry above exists for." },
|
|
30
36
|
{ "glob": "src/bongos/route-rank-check.js", "group": "authz", "why": "the route-gate auditor" },
|
|
31
37
|
{ "glob": "src/bongos/permission-path-check.js", "group": "authz", "why": "the matcher that reads this registry (self-protect)" },
|
|
32
38
|
{ "glob": "src/bongos/middleware/", "group": "authz", "why": "audit + any auth middleware" },
|
|
@@ -43,11 +49,40 @@
|
|
|
43
49
|
{ "glob": "scripts/gds/box-infra.js", "group": "box-access", "why": "task 1002891. CREDENTIAL READER: reads process.env.CLOUDFLARE_API_TOKEN and process.env.CLOUDFLARE_ACCOUNT_ID into the CF config the box plane provisions against." },
|
|
44
50
|
{ "glob": "scripts/gds/cf-tunnel.js", "group": "box-access", "why": "task 1002891. CREDENTIAL READER: defaults its token parameter to process.env.CLOUDFLARE_API_TOKEN, so it reads the credential whenever a caller omits one. Not named by the recorded decision — the recomputation found it, which is the whole argument for computing the set instead of transcribing it." },
|
|
45
51
|
{ "glob": "scripts/gds/box.js", "group": "box-access", "why": "task 1002891. CREDENTIAL READER: reads process.env.DO_API_TOKEN — the DigitalOcean control plane for the box fleet. Also not named by the recorded decision. Registering it does NOT widen any module wall: the dev-box module key already lists this file and already derives protected:true from the modules/dev-box/ entries above, so the derived protected-module set is unchanged (verified before and after against src/bongos/module-scope-map.js)." },
|
|
52
|
+
{ "glob": "scripts/gds/box-auth-check.js", "group": "box-access", "why": "task 1004024. Split out of the box.js family and never registered; box-infra.js was already listed by name above." },
|
|
53
|
+
{ "glob": "scripts/gds/box-sync.js", "group": "box-access", "why": "task 1004024. Split out of the box.js family and never registered; box-infra.js was already listed by name above." },
|
|
46
54
|
{ "glob": "scripts/gds/do-api.js", "group": "box-access", "why": "task 1002891. The DigitalOcean API client the token is handed TO. Unlike the five above it reads no process.env value — it takes the token as a parameter and throws when a live call has none — so the drift tripwire does not demand it and its absence from that computed set is expected, not a bug. It is registered because the recorded decision named it and because it is the code that puts the credential on the wire." },
|
|
47
55
|
{ "glob": "modules/grading/grader.js", "group": "pipeline", "why": "BV1.R73: grading carved to modules/grading/ — the glob follows the file" },
|
|
56
|
+
{ "glob": "modules/grading/grader-config.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
57
|
+
{ "glob": "modules/grading/grader-model.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
58
|
+
{ "glob": "modules/grading/grader-no-artifact.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
59
|
+
{ "glob": "modules/grading/grader-prompt.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
60
|
+
{ "glob": "modules/grading/grader-score.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
61
|
+
{ "glob": "modules/grading/grader-subagent.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
48
62
|
{ "glob": "modules/grading/grader-workers/", "group": "pipeline", "why": "the adversarial panel (Narc/Hacker/Quality/Efficiency) — blunting these blunts the gate" },
|
|
49
63
|
{ "glob": "modules/grading/grader-rubric.json", "group": "pipeline", "why": "the grader's scoring rubric (ADR 0058)" },
|
|
50
64
|
{ "glob": "scripts/gds/ship.js", "group": "pipeline", "why": "the ship lifecycle driver" },
|
|
65
|
+
{ "glob": "scripts/gds/ship-check.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
66
|
+
{ "glob": "scripts/gds/ship-deploy-target.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
67
|
+
{ "glob": "scripts/gds/ship-escalation.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
68
|
+
{ "glob": "scripts/gds/ship-finish.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
69
|
+
{ "glob": "scripts/gds/ship-flow.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
70
|
+
{ "glob": "scripts/gds/ship-git.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
71
|
+
{ "glob": "scripts/gds/ship-grade-steps.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
72
|
+
{ "glob": "scripts/gds/ship-grade.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
73
|
+
{ "glob": "scripts/gds/ship-honesty.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
74
|
+
{ "glob": "scripts/gds/ship-io.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
75
|
+
{ "glob": "scripts/gds/ship-land.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
76
|
+
{ "glob": "scripts/gds/ship-memory-sync.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
77
|
+
{ "glob": "scripts/gds/ship-merge-gate.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
78
|
+
{ "glob": "scripts/gds/ship-merge.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
79
|
+
{ "glob": "scripts/gds/ship-preflight-steps.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
80
|
+
{ "glob": "scripts/gds/ship-regen.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
81
|
+
{ "glob": "scripts/gds/ship-resume.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
82
|
+
{ "glob": "scripts/gds/ship-session-upload.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
83
|
+
{ "glob": "scripts/gds/ship-state.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
84
|
+
{ "glob": "scripts/gds/ship-surprise.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
85
|
+
{ "glob": "scripts/gds/ship-visual.js", "group": "pipeline", "why": "task 1004024. The 2026-08-23 carve of ship.js (task 1003205): the land path, the ship state machine, the grade gate steps, the merge and pushVia, about 6,200 lines behind a 373-line protected entry point." },
|
|
51
86
|
{ "glob": "scripts/gds/confirm.js", "group": "pipeline", "why": "the confirm step" },
|
|
52
87
|
{ "glob": "scripts/gds/merge-mode.js", "group": "pipeline", "why": "the manual land fallback" },
|
|
53
88
|
{ "glob": "scripts/gds/ci-grade.js", "group": "pipeline", "why": "CI grade-gate driver — steers the grade check (ADR 0058)" },
|
|
@@ -277,6 +277,17 @@
|
|
|
277
277
|
</div>`;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
+
// "Database behind" (task 1004153): the box's code ships migrations its database has not
|
|
281
|
+
// applied, e.g. after an upgrade with --skip-migrate. Silent at 0 AND at null — null is an
|
|
282
|
+
// unknown reading, and the no-answer note above already speaks for a box that did not answer.
|
|
283
|
+
function schemaBehindHtml(p) {
|
|
284
|
+
const n = p.schema_pending;
|
|
285
|
+
if (!Number.isInteger(n) || n <= 0) return '';
|
|
286
|
+
return `<p class="ps-invalid"><strong>Database behind.</strong> This project's code expects
|
|
287
|
+
${escapeHtml(String(n))} database change${n === 1 ? '' : 's'} that its database has not applied yet.
|
|
288
|
+
Anything that relies on ${n === 1 ? 'it' : 'them'} may fail until the migrations run.</p>`;
|
|
289
|
+
}
|
|
290
|
+
|
|
280
291
|
// One box's card. `isSelf` only changes the words, never what is offered: the runner
|
|
281
292
|
// treats the platform's own row and a tenant's identically, and a page that implied
|
|
282
293
|
// otherwise would be describing a rule that does not exist.
|
|
@@ -299,6 +310,7 @@
|
|
|
299
310
|
${p.reading === 'no_answer'
|
|
300
311
|
? `<p class="ps-invalid">The box did not answer when the control plane last looked, so this version is unknown rather than unchanged. A move is not offered while that is true.</p>`
|
|
301
312
|
: ''}
|
|
313
|
+
${schemaBehindHtml(p)}
|
|
302
314
|
${action}
|
|
303
315
|
</div></li>`;
|
|
304
316
|
}
|
|
@@ -259,6 +259,9 @@ function previewFromSnapshot(inst, snap, openIntent, lastMove) {
|
|
|
259
259
|
// Named so the UI cannot accidentally render "up to date" over a missing reading.
|
|
260
260
|
reading: served ? 'ok' : 'no_answer',
|
|
261
261
|
observed_at: (snap && snap.observed_at) || null,
|
|
262
|
+
// Migrations the box's code ships that its database has not applied (task 1004153).
|
|
263
|
+
// null is UNKNOWN, not zero — an old core, or a box that did not answer.
|
|
264
|
+
schema_pending: snap && Number.isInteger(snap.schema_pending) ? snap.schema_pending : null,
|
|
262
265
|
// What the upgrade SAYS it would do, from the runner's dry run (task 1004121).
|
|
263
266
|
// Withheld unless it was taken against the move now on offer: a verdict about
|
|
264
267
|
// 1.19.920 tells the owner nothing true about pressing a button that says 1.19.921,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- provisioning_024 — each box's schemaPending in the core-version snapshot (task 1004153,
|
|
2
|
+
-- from idea 1001088).
|
|
3
|
+
--
|
|
4
|
+
-- /version reports `schemaPending`: core + enabled-module migrations the running code ships
|
|
5
|
+
-- that the instance's own database has not recorded. Only the instance a checkout talks to
|
|
6
|
+
-- was ever watched for it (the SessionStart divergence line); co-tenants were not. A
|
|
7
|
+
-- co-tenant upgraded with --skip-migrate (mercury has no scripts.migrate) serves new code
|
|
8
|
+
-- over an old schema and nothing said so. The runner already reads each box's loopback
|
|
9
|
+
-- /version on every tick for served_version; this stores the other half of that answer.
|
|
10
|
+
--
|
|
11
|
+
-- NULL means UNKNOWN — the box did not answer, or runs a core older than the field — and
|
|
12
|
+
-- is a different state from 0. The control must not render one as the other.
|
|
13
|
+
--
|
|
14
|
+
-- Additive, idempotent, no down-migration.
|
|
15
|
+
|
|
16
|
+
ALTER TABLE provisioning_core_version_snapshot
|
|
17
|
+
ADD COLUMN IF NOT EXISTS schema_pending integer;
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.959",
|
|
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.959",
|
|
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.959",
|
|
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",
|
|
@@ -72,6 +72,21 @@ function parseServedVersion(stdout) {
|
|
|
72
72
|
return m ? m[0] : null;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* The `schemaPending` count from a /version body — migrations the box's code ships that its
|
|
77
|
+
* own database has not recorded (task 1004153). PURE.
|
|
78
|
+
*
|
|
79
|
+
* null means UNKNOWN (no answer, not JSON, or a core older than the field), never 0: a
|
|
80
|
+
* co-tenant that cannot say must not read as one whose database is current. Bounded the
|
|
81
|
+
* same way scripts/gds/deploy-divergence.js bounds it, since the body is a network answer.
|
|
82
|
+
*/
|
|
83
|
+
function parseSchemaPending(stdout) {
|
|
84
|
+
if (!stdout || typeof stdout !== 'string') return null;
|
|
85
|
+
let n;
|
|
86
|
+
try { n = JSON.parse(stdout).schemaPending; } catch { return null; }
|
|
87
|
+
return Number.isInteger(n) && n >= 0 && n <= 100000 ? n : null;
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
/**
|
|
76
91
|
* Is this target a version the instance may actually be moved to? PURE.
|
|
77
92
|
*
|
|
@@ -466,7 +481,9 @@ async function snapshotCoreVersions(inst, deps) {
|
|
|
466
481
|
const instanceDir = inst.hosting_shape === 'standalone' ? standaloneRoot(inst) : selfRoot();
|
|
467
482
|
try {
|
|
468
483
|
const probe = boxExec(versionCmd(inst), { allowFail: true });
|
|
469
|
-
const
|
|
484
|
+
const body = probe && !probe.softFailed ? (probe.stdout || '') : null;
|
|
485
|
+
const served = parseServedVersion(body);
|
|
486
|
+
const schemaPending = parseSchemaPending(body);
|
|
470
487
|
const listed = channelMod.listAvailableVersions({ cwd: instanceDir });
|
|
471
488
|
const available = (listed && listed.versions) || [];
|
|
472
489
|
// What the channel would take FROM the version the box is actually on. Resolving it
|
|
@@ -486,18 +503,19 @@ async function snapshotCoreVersions(inst, deps) {
|
|
|
486
503
|
const preflight = null;
|
|
487
504
|
await db.query(
|
|
488
505
|
`INSERT INTO provisioning_core_version_snapshot
|
|
489
|
-
(instance_id, served_version, available, recommended, observed_at, preflight, preflight_at)
|
|
490
|
-
VALUES ($1, $2, $3::jsonb, $4, now(), $5::jsonb, $6)
|
|
506
|
+
(instance_id, served_version, available, recommended, observed_at, preflight, preflight_at, schema_pending)
|
|
507
|
+
VALUES ($1, $2, $3::jsonb, $4, now(), $5::jsonb, $6, $7)
|
|
491
508
|
ON CONFLICT (instance_id) DO UPDATE
|
|
492
509
|
SET served_version = EXCLUDED.served_version, available = EXCLUDED.available,
|
|
493
510
|
recommended = EXCLUDED.recommended, observed_at = now(),
|
|
511
|
+
schema_pending = EXCLUDED.schema_pending,
|
|
494
512
|
-- A tick with nothing to preview must not ERASE the last verdict; it simply
|
|
495
513
|
-- has nothing newer to say. Only a real dry run overwrites one.
|
|
496
514
|
preflight = COALESCE(EXCLUDED.preflight, provisioning_core_version_snapshot.preflight),
|
|
497
515
|
preflight_at = COALESCE(EXCLUDED.preflight_at, provisioning_core_version_snapshot.preflight_at)`,
|
|
498
516
|
[inst.id, served, JSON.stringify(available), recommended || null,
|
|
499
|
-
preflight ? JSON.stringify(preflight) : null, preflight ? new Date() : null]);
|
|
500
|
-
return { ok: true, served, available: available.length, preflight };
|
|
517
|
+
preflight ? JSON.stringify(preflight) : null, preflight ? new Date() : null, schemaPending]);
|
|
518
|
+
return { ok: true, served, available: available.length, preflight, schemaPending };
|
|
501
519
|
} catch (e) {
|
|
502
520
|
log(` ~ core-version snapshot for ${inst.slug} skipped (${(e && e.message) || e})`);
|
|
503
521
|
return { ok: true, skipped: true };
|
|
@@ -519,4 +537,4 @@ async function snapshotAllCoreVersions(deps) {
|
|
|
519
537
|
return { seen };
|
|
520
538
|
}
|
|
521
539
|
|
|
522
|
-
module.exports = { UPGRADE_SHAPES, resolveRunAs, versionCmd, parseServedVersion, targetFault, parsePreflight, upgradeInvocation, preflightUpgrade, preflightCoreUpgrade, coreUpgradeInstance, snapshotCoreVersions, snapshotAllCoreVersions };
|
|
540
|
+
module.exports = { UPGRADE_SHAPES, resolveRunAs, versionCmd, parseServedVersion, parseSchemaPending, targetFault, parsePreflight, upgradeInvocation, preflightUpgrade, preflightCoreUpgrade, coreUpgradeInstance, snapshotCoreVersions, snapshotAllCoreVersions };
|
|
@@ -48,6 +48,9 @@ const MODULE_GLOBS = {
|
|
|
48
48
|
'src/bongos/auth.js', 'src/bongos/db.js', 'src/bongos/db-kernel.js', 'src/bongos/pool.js',
|
|
49
49
|
'src/bongos/routes.js', 'src/bongos/route-rank-check.js',
|
|
50
50
|
'src/bongos/permission-path-check.js', 'src/bongos/sensitive-surfaces.js',
|
|
51
|
+
// task 1004024: the auth.js carve (db-kernel.js, above, is db.js's), now protected.
|
|
52
|
+
'src/bongos/auth-admission.js', 'src/bongos/auth-config.js', 'src/bongos/auth-discord.js',
|
|
53
|
+
'src/bongos/auth-github.js', 'src/bongos/auth-idp.js',
|
|
51
54
|
'src/bongos/middleware/', 'src/bongos/live-channel.js', 'src/bongos/secret-box.js',
|
|
52
55
|
'src/bongos/repo-info.js', 'src/bongos/api-path-404.js', 'src/bongos/serve-internal.js',
|
|
53
56
|
'src/bongos/module-scope-map.js', 'src/bongos/hierarchy-config.js',
|
|
@@ -91,6 +94,14 @@ const MODULE_GLOBS = {
|
|
|
91
94
|
lifecycle: [
|
|
92
95
|
'modules/lifecycle/',
|
|
93
96
|
'scripts/gds/ship.js', 'scripts/gds/claim.js', 'scripts/gds/release.js',
|
|
97
|
+
// task 1004024: the 2026-08-23 ship.js carve, now protected (by name: no '*' here).
|
|
98
|
+
'scripts/gds/ship-check.js', 'scripts/gds/ship-deploy-target.js', 'scripts/gds/ship-escalation.js',
|
|
99
|
+
'scripts/gds/ship-finish.js', 'scripts/gds/ship-flow.js', 'scripts/gds/ship-git.js',
|
|
100
|
+
'scripts/gds/ship-grade-steps.js', 'scripts/gds/ship-grade.js', 'scripts/gds/ship-honesty.js',
|
|
101
|
+
'scripts/gds/ship-io.js', 'scripts/gds/ship-land.js', 'scripts/gds/ship-memory-sync.js',
|
|
102
|
+
'scripts/gds/ship-merge-gate.js', 'scripts/gds/ship-merge.js', 'scripts/gds/ship-preflight-steps.js',
|
|
103
|
+
'scripts/gds/ship-regen.js', 'scripts/gds/ship-resume.js', 'scripts/gds/ship-session-upload.js',
|
|
104
|
+
'scripts/gds/ship-state.js', 'scripts/gds/ship-surprise.js', 'scripts/gds/ship-visual.js',
|
|
94
105
|
'scripts/gds/merge-mode.js', 'scripts/gds/confirm.js', 'scripts/gds/main-audit.js',
|
|
95
106
|
'scripts/gds/gate-review.js', 'scripts/gds/push-main.js', 'scripts/gds/ci-grade.js',
|
|
96
107
|
'scripts/gds/merge-lock.js', 'scripts/gds/version-close.js',
|
|
@@ -355,6 +366,7 @@ const MODULE_GLOBS = {
|
|
|
355
366
|
'modules/dev-box/', 'devbox-app/',
|
|
356
367
|
'scripts/gds/box.js', 'scripts/gds/box-auth-check.js', 'scripts/gds/box-connect-lib.js',
|
|
357
368
|
'scripts/gds/smoke-box.sh',
|
|
369
|
+
'scripts/gds/box-sync.js', // task 1004024: split out of box.js, now protected
|
|
358
370
|
|
|
359
371
|
// ADOPTED (task 1004111): the box BRING-UP surface. box.js (already here)
|
|
360
372
|
// orchestrates these five provisioning CLIs, and infra/ is the shell-script
|
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.959'; // 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');
|
|
@@ -404,6 +404,15 @@ await t('no snapshot at all reports observed_at:null rather than a confident-loo
|
|
|
404
404
|
assert.equal(p.available_count, 0);
|
|
405
405
|
});
|
|
406
406
|
|
|
407
|
+
await t('schema_pending passes through as a count, and UNKNOWN stays null rather than reading as 0 (task 1004153)', () => {
|
|
408
|
+
const snap = { served_version: '1.19.758', available: [], recommended: null, observed_at: 'x' };
|
|
409
|
+
assert.equal(CU.previewFromSnapshot(previewInst, { ...snap, schema_pending: 3 }, null).schema_pending, 3);
|
|
410
|
+
assert.equal(CU.previewFromSnapshot(previewInst, { ...snap, schema_pending: 0 }, null).schema_pending, 0);
|
|
411
|
+
assert.equal(CU.previewFromSnapshot(previewInst, { ...snap, schema_pending: null }, null).schema_pending, null);
|
|
412
|
+
assert.equal(CU.previewFromSnapshot(previewInst, snap, null).schema_pending, null, 'a row written before provisioning_024');
|
|
413
|
+
assert.equal(CU.previewFromSnapshot(previewInst, undefined, null).schema_pending, null, 'no snapshot at all');
|
|
414
|
+
});
|
|
415
|
+
|
|
407
416
|
await t('an open intent is surfaced with its target, so the page can say what is already running', () => {
|
|
408
417
|
const p = CU.previewFromSnapshot(previewInst, { served_version: '1.19.758', available: [], recommended: null },
|
|
409
418
|
{ action: 'core-upgrade', state: 'running', target_version: '1.19.762' });
|
|
@@ -30,6 +30,8 @@ import { strict as assert } from 'node:assert';
|
|
|
30
30
|
import { createRequire } from 'node:module';
|
|
31
31
|
import fs from 'node:fs';
|
|
32
32
|
import path from 'node:path';
|
|
33
|
+
// An ESM named import, not R.parseSchemaPending: knip credits a CJS export only when a test imports it this way.
|
|
34
|
+
import { parseSchemaPending } from '../scripts/gds/provision-core-upgrade.js';
|
|
33
35
|
|
|
34
36
|
const require = createRequire(import.meta.url);
|
|
35
37
|
const R = require('../scripts/gds/provision-core-upgrade.js');
|
|
@@ -404,6 +406,37 @@ await t('a box that does not answer still writes a snapshot — a NULL reading i
|
|
|
404
406
|
assert.equal(w.params[3], null, 'and nothing is recommended against a version we could not read');
|
|
405
407
|
});
|
|
406
408
|
|
|
409
|
+
await t('parseSchemaPending reads the count, and anything it cannot trust is null — never 0 (task 1004153)', () => {
|
|
410
|
+
assert.equal(parseSchemaPending(JSON.stringify({ coreVersion: '1.19.953', schemaPending: 3 })), 3);
|
|
411
|
+
assert.equal(parseSchemaPending(JSON.stringify({ coreVersion: '1.19.953', schemaPending: 0 })), 0);
|
|
412
|
+
assert.equal(parseSchemaPending(JSON.stringify({ coreVersion: '1.19.700' })), null, 'a core older than the field');
|
|
413
|
+
assert.equal(parseSchemaPending(JSON.stringify({ schemaPending: null })), null, 'the box itself does not know');
|
|
414
|
+
for (const bad of [-1, 1.5, '3', 100001]) {
|
|
415
|
+
assert.equal(parseSchemaPending(JSON.stringify({ schemaPending: bad })), null, `schemaPending=${JSON.stringify(bad)}`);
|
|
416
|
+
}
|
|
417
|
+
assert.equal(parseSchemaPending('cloudbongos 1.19.762 (ok)'), null, 'not JSON');
|
|
418
|
+
assert.equal(parseSchemaPending(''), null);
|
|
419
|
+
assert.equal(parseSchemaPending(null), null);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await t('the snapshot stores the box\'s schemaPending next to its served version (task 1004153)', async () => {
|
|
423
|
+
const queries = [];
|
|
424
|
+
const d = makeDeps({ queries });
|
|
425
|
+
d.exec = (cmd) => ({ ok: true, stdout: /\/version/.test(cmd) ? JSON.stringify({ coreVersion: '1.19.760', schemaPending: 4 }) : '' });
|
|
426
|
+
const r = await R.snapshotCoreVersions(inst(), d);
|
|
427
|
+
const w = queries.find((q) => /provisioning_core_version_snapshot/.test(q.sql));
|
|
428
|
+
assert.match(w.sql, /schema_pending = EXCLUDED\.schema_pending/, 'a re-read replaces the old count');
|
|
429
|
+
assert.equal(w.params[6], 4);
|
|
430
|
+
assert.equal(r.schemaPending, 4);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
await t('a box that does not answer stores schema_pending NULL, not a clean 0', async () => {
|
|
434
|
+
const queries = [];
|
|
435
|
+
await R.snapshotCoreVersions(inst(), makeDeps({ served: null, queries }));
|
|
436
|
+
const w = queries.find((q) => /provisioning_core_version_snapshot/.test(q.sql));
|
|
437
|
+
assert.equal(w.params[6], null);
|
|
438
|
+
});
|
|
439
|
+
|
|
407
440
|
await t('a shape the runner cannot reach is skipped entirely — no snapshot, no claim about it', async () => {
|
|
408
441
|
const queries = [];
|
|
409
442
|
const r = await R.snapshotCoreVersions(inst({ hosting_shape: 'dedicated' }), makeDeps({ queries }));
|
|
@@ -181,6 +181,20 @@ test('a box that did not answer is never rendered as up to date', async () => {
|
|
|
181
181
|
assert.doesNotMatch(html, /id="dp-preview-1"/, 'and is offered no move');
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
test('a box whose database is behind its code says so (task 1004153)', async () => {
|
|
185
|
+
const b = boot({ controlPlane: preview('1', 'cloudbongos', { schema_pending: 2 }) });
|
|
186
|
+
await b.settle();
|
|
187
|
+
assert.match(b.panel(), /Database behind\.<\/strong> This project's code expects\s+2 database changes/);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('a database that is current, or whose state is unknown, gets no "behind" flag', async () => {
|
|
191
|
+
for (const schema_pending of [0, null, undefined]) {
|
|
192
|
+
const b = boot({ controlPlane: preview('1', 'cloudbongos', { schema_pending }) });
|
|
193
|
+
await b.settle();
|
|
194
|
+
assert.doesNotMatch(b.panel(), /Database behind/, `schema_pending=${schema_pending}`);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
184
198
|
test('an unenrolled control plane still lets the projects through', async () => {
|
|
185
199
|
// The regression this pins: the platform's own missing row used to be the whole
|
|
186
200
|
// page, so one un-run setup command would hide every project too.
|
|
@@ -116,6 +116,14 @@ const EXPECTED_GLOBS_BEFORE_R101 = [
|
|
|
116
116
|
// If the owner does want the agents module rank-walled, it needs the entry here,
|
|
117
117
|
// a publish-manifest carve-out, and the module-scope-map roster test updated —
|
|
118
118
|
// three deliberate edits, not a side effect of a scope fix.
|
|
119
|
+
// One ADDED_SINCE_R101 entry per file carved out of `parent`, chained so each sits directly
|
|
120
|
+
// below the previous one — the order the registry lists them in.
|
|
121
|
+
function carve(parent, names, why) {
|
|
122
|
+
const dir = path.posix.dirname(parent);
|
|
123
|
+
const globs = names.map((n) => `${dir}/${n}.js`);
|
|
124
|
+
return globs.map((glob, i) => ({ after: i ? globs[i - 1] : parent, glob, why }));
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
const ADDED_SINCE_R101 = [
|
|
120
128
|
// task 1003366, audit ref MIT1 (2026-08-29 security audit, goal 1000084). The EIGHT
|
|
121
129
|
// execution roots the merge resolver runs out of a cloned branch. The audit named four
|
|
@@ -263,6 +271,30 @@ const ADDED_SINCE_R101 = [
|
|
|
263
271
|
+ 'sub-Metic builders out of in spirit, so the real cost of this entry is three '
|
|
264
272
|
+ 'tasks that arguably should not have been open.',
|
|
265
273
|
},
|
|
274
|
+
// task 1004024, owner decision 2026-09-22 (all five families). Each protected FILE below
|
|
275
|
+
// had been carved into `<name>-*.js` siblings and only the facade stayed registered. The
|
|
276
|
+
// carve tripwire further down is what found the four beyond the one the task named.
|
|
277
|
+
// Listed BY NAME, not as `<name>-*.js`: path-match (the goal scope wall) reads no '*'.
|
|
278
|
+
...carve('src/bongos/auth.js', ['auth-admission', 'auth-config', 'auth-discord', 'auth-github', 'auth-idp'],
|
|
279
|
+
'the auth.js carve: session-token minting and the OAuth exchange, admission and '
|
|
280
|
+
+ 'first-admin seating, IdP assertion checks.'),
|
|
281
|
+
...carve('src/bongos/db.js', ['db-kernel'],
|
|
282
|
+
'the kernel slice carved out of db.js: builder identity and the rank reads the '
|
|
283
|
+
+ 'SEC #863 entry exists for.'),
|
|
284
|
+
...carve('scripts/gds/box.js', ['box-auth-check', 'box-sync'],
|
|
285
|
+
'the box.js family: the dev-box session-start auth gate and the box sync; box-infra.js '
|
|
286
|
+
+ 'was already listed by name.'),
|
|
287
|
+
...carve('modules/grading/grader.js', ['grader-config', 'grader-model', 'grader-no-artifact',
|
|
288
|
+
'grader-prompt', 'grader-score', 'grader-subagent'],
|
|
289
|
+
'the grader.js carve: the deterministic permission-path pre-pass and the server-side '
|
|
290
|
+
+ 'score guards a model cannot talk past.'),
|
|
291
|
+
...carve('scripts/gds/ship.js', ['ship-check', 'ship-deploy-target', 'ship-escalation',
|
|
292
|
+
'ship-finish', 'ship-flow', 'ship-git', 'ship-grade-steps', 'ship-grade', 'ship-honesty',
|
|
293
|
+
'ship-io', 'ship-land', 'ship-memory-sync', 'ship-merge-gate', 'ship-merge',
|
|
294
|
+
'ship-preflight-steps', 'ship-regen', 'ship-resume', 'ship-session-upload', 'ship-state',
|
|
295
|
+
'ship-surprise', 'ship-visual'],
|
|
296
|
+
'the 2026-08-23 ship.js carve: the land path, the ship state machine, the grade gate '
|
|
297
|
+
+ 'steps and pushVia, ~6,200 lines behind a 373-line protected entry point.'),
|
|
266
298
|
];
|
|
267
299
|
|
|
268
300
|
// Surfaces RENAMED since R101 — still protected, under a new path. Distinct from
|
|
@@ -392,6 +424,55 @@ test('every execution root in the closure is a protected surface (MIT1 drift tri
|
|
|
392
424
|
}
|
|
393
425
|
});
|
|
394
426
|
|
|
427
|
+
// ---------- the carve tripwire: a protected FILE's `<name>-*.js` siblings are protected ----------
|
|
428
|
+
//
|
|
429
|
+
// task 1004024. Splitting a protected file into `<name>-<phase>.js` siblings is this repo's
|
|
430
|
+
// carve convention, and every carve so far left only the facade registered: ship.js (21
|
|
431
|
+
// files), grader.js (6), auth.js (5), db.js, box.js. A require()-graph rule was measured and
|
|
432
|
+
// rejected — from the protected scripts it reaches 52 unprotected files (upgrade.js, login.js,
|
|
433
|
+
// package-core.js…), floor-gating ordinary work. The name rule is the shape a carve leaves.
|
|
434
|
+
function stemSiblings(entry, tracked) {
|
|
435
|
+
const dir = path.posix.dirname(entry);
|
|
436
|
+
const prefix = `${path.posix.basename(entry, '.js')}-`;
|
|
437
|
+
return tracked.filter((f) => path.posix.dirname(f) === dir
|
|
438
|
+
&& path.posix.basename(f).startsWith(prefix) && f.endsWith('.js'));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
test('no protected glob uses a wildcard — the goal scope wall could not read it', () => {
|
|
442
|
+
// permission-path-check reads '*', but module-scope-map derives ownership and the
|
|
443
|
+
// protected module set through path-match, which knows only an exact path or a '/'
|
|
444
|
+
// prefix. A wildcard here would protect files no module can own (task 1004024).
|
|
445
|
+
assert.deepEqual(ppc.PROTECTED_GLOBS.filter((g) => g.includes('*')), []);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test('stemSiblings finds a split-out file and nothing that merely resembles one', () => {
|
|
449
|
+
const tree = ['scripts/gds/ship.js', 'scripts/gds/ship-land.js', 'scripts/gds/shipper.js',
|
|
450
|
+
'scripts/gds/ship_x.js', 'scripts/gds/sub/ship-x.js', 'scripts/gds/ship-notes.md', 'src/ship-y.js'];
|
|
451
|
+
assert.deepEqual(stemSiblings('scripts/gds/ship.js', tree), ['scripts/gds/ship-land.js']);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
test('every file split out of a protected file is itself protected (1004024 carve tripwire)', () => {
|
|
455
|
+
const tracked = execFileSync('git', ['ls-files', '*.js'], { cwd: ROOT, encoding: 'utf8' })
|
|
456
|
+
.split('\n').map((s) => s.trim()).filter(Boolean);
|
|
457
|
+
const entries = ppc.PROTECTED_GLOBS.filter((g) => g.endsWith('.js') && !g.includes('*'));
|
|
458
|
+
let checked = 0;
|
|
459
|
+
for (const entry of entries) {
|
|
460
|
+
const floor = ppc.RANK_TIER[ppc.surfaceFor(entry).floor];
|
|
461
|
+
for (const rel of stemSiblings(entry, tracked)) {
|
|
462
|
+
checked += 1;
|
|
463
|
+
const surface = ppc.surfaceFor(rel);
|
|
464
|
+
assert.ok(surface,
|
|
465
|
+
`${rel} sits beside the protected ${entry} under its name — the shape a carve leaves — `
|
|
466
|
+
+ 'but no protected surface covers it. Register it by name in '
|
|
467
|
+
+ 'modules/government/protected-surfaces.json, declare it in ADDED_SINCE_R101, and '
|
|
468
|
+
+ 'give it the parent\'s owning module in src/bongos/module-scope-map.js.');
|
|
469
|
+
assert.ok(ppc.RANK_TIER[surface.floor] >= floor,
|
|
470
|
+
`${rel} is floored at '${surface.floor}', below the ${entry} it was carved from.`);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
assert.ok(checked >= 35, `fixture sanity: expected the five known carves (35 files), saw ${checked}`);
|
|
474
|
+
});
|
|
475
|
+
|
|
395
476
|
// ---------- the credential tripwire: every credential READER is a protected surface ----------
|
|
396
477
|
//
|
|
397
478
|
// task 1002891, from idea 1000692 (the grader's hacker worker, on the 1002690 re-grade).
|