@bongos/core 1.21.4 → 1.21.6

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.
Files changed (126) hide show
  1. package/.bongos-core.json +233 -108
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +2 -0
  4. package/clients/bongos-client/index.cjs +2 -0
  5. package/clients/bongos-client/index.d.ts +3 -1
  6. package/clients/bongos-client/index.mjs +2 -0
  7. package/docs/adr/0361-merges-publish-as-candidates-release-decides-what-others-are-offered.md +1 -0
  8. package/docs/adr/0362-the-governor-docket-is-collected-from-contributed-sources.md +34 -0
  9. package/docs/adr/README.md +1 -0
  10. package/docs/api/openapi.json +37 -2
  11. package/docs/api-reference.md +4 -3
  12. package/docs/copy-inventory.md +541 -658
  13. package/docs/copy-registry.json +1205 -2340
  14. package/docs/module-api-changelog.md +4 -0
  15. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +1 -1
  16. package/docs/onboarding/diagrams/assertions.json +1 -1
  17. package/docs/page-inventory.json +47 -28
  18. package/docs/page-readings.json +1128 -1339
  19. package/modules/autonomy/config-idle.js +192 -0
  20. package/modules/autonomy/governor-docket.js +101 -0
  21. package/modules/autonomy/routes/autonomy.js +27 -0
  22. package/modules/autonomy/runner-health.js +22 -1
  23. package/modules/discord/board-broadcast.js +3 -1
  24. package/modules/discord/craft-broadcast.js +107 -0
  25. package/modules/discord/routes/discord.js +10 -0
  26. package/modules/discord/ship-broadcast.js +30 -2
  27. package/modules/economy/reward.js +3 -0
  28. package/modules/government/board.js +20 -5
  29. package/modules/government/docket-vocab.js +82 -0
  30. package/modules/government/docket.js +458 -0
  31. package/modules/government/routes/government.js +34 -0
  32. package/modules/hall-ui/public/city-draw.js +438 -0
  33. package/modules/hall-ui/public/city.css +110 -0
  34. package/modules/hall-ui/public/city.html +71 -0
  35. package/modules/hall-ui/public/city.js +177 -0
  36. package/modules/hall-ui/public/city.states.json +30 -0
  37. package/modules/hall-ui/public/gate.js +11 -4
  38. package/modules/hall-ui/public/genesis-home.js +9 -10
  39. package/modules/hall-ui/public/profile.css +4 -0
  40. package/modules/hall-ui/public/profile.js +25 -1
  41. package/modules/hall-ui/public/settings-autobongos.js +19 -1
  42. package/modules/hall-ui/public/settings.css +26 -0
  43. package/modules/hall-ui/public/settings.html +8 -0
  44. package/modules/hall-ui/public/settings.js +43 -3
  45. package/modules/ideas/governor-docket.js +93 -0
  46. package/modules/ideas/routes/blockers.js +5 -0
  47. package/modules/lifecycle/governor-docket.js +192 -0
  48. package/modules/lifecycle/routes/gate-approvals.js +78 -33
  49. package/modules/lifecycle/routes/lifecycle.js +3 -0
  50. package/modules/onboarding/routes/access-requests.js +68 -27
  51. package/modules/platform-identity/craft-rollup.js +72 -0
  52. package/modules/platform-identity/migrations/platform_identity_029_activity_crafts.sql +23 -0
  53. package/modules/platform-identity/platform-identity.js +12 -6
  54. package/modules/platform-identity/routes/sso.js +4 -0
  55. package/modules/platform-identity/tests/platform-identity.mjs +1 -1
  56. package/modules/provisioning/core-upgrade.js +34 -7
  57. package/modules/provisioning/module.json +2 -1
  58. package/modules/provisioning/seams.js +2 -0
  59. package/modules/public-landing/public/assets/cosmos.css +6 -50
  60. package/modules/public-landing/public/projects.html +1170 -1659
  61. package/modules/public-landing/public/projects.probes.json +18 -18
  62. package/modules/public-landing/public/projects.states.json +24 -31
  63. package/modules/security/routes/reports.js +39 -0
  64. package/package-lock.json +2 -2
  65. package/package.json +1 -1
  66. package/release-notes.json +72 -0
  67. package/scripts/gds/autobongos-grade-cap.js +187 -0
  68. package/scripts/gds/autobongos-loop.js +4 -0
  69. package/scripts/gds/autobongos-run.js +154 -13
  70. package/scripts/gds/autobongos-verify.js +211 -14
  71. package/scripts/gds/provision-core-upgrade.js +14 -2
  72. package/scripts/gds/provision-repo.js +77 -13
  73. package/scripts/gds/ship-flow.js +5 -0
  74. package/scripts/gds/ship-preflight-steps.js +2 -1
  75. package/scripts/gds/ship.js +10 -0
  76. package/scripts/gds/update-sweep.js +24 -8
  77. package/scripts/gds/upgrade-outcome.js +1 -0
  78. package/src/bongos/auth-admission.js +95 -13
  79. package/src/bongos/db-kernel.js +1 -1
  80. package/src/bongos/module-rechecks.js +77 -0
  81. package/src/bongos/route-rank-check.js +3 -0
  82. package/src/bongos/routes/core-update.js +68 -2
  83. package/src/bongos/routes/modules.js +17 -0
  84. package/src/bongos/serve-internal.js +14 -0
  85. package/src/bongos/software-update.js +3 -2
  86. package/src/module-api.js +1 -1
  87. package/tests/activity_rollup_order_db.mjs +3 -1
  88. package/tests/activity_snapshots_db.mjs +2 -0
  89. package/tests/autobongos_grade_cap.mjs +125 -0
  90. package/tests/autobongos_loop.mjs +230 -1
  91. package/tests/autobongos_verify.mjs +239 -3
  92. package/tests/autonomy_config_idle.mjs +272 -0
  93. package/tests/core_update_banner.mjs +29 -0
  94. package/tests/core_upgrade_door.mjs +31 -1
  95. package/tests/core_upgrade_runner.mjs +20 -0
  96. package/tests/discord_craft_broadcast.mjs +162 -0
  97. package/tests/genesis_home.mjs +1 -1
  98. package/tests/government_routes.mjs +3 -1
  99. package/tests/governor_docket.mjs +552 -0
  100. package/tests/hall_audit.mjs +10 -1
  101. package/tests/hall_city.mjs +369 -0
  102. package/tests/hall_page_gate_map.mjs +5 -0
  103. package/tests/hub_craft_rollup.mjs +350 -0
  104. package/tests/onboard.mjs +10 -4
  105. package/tests/platform_boot.mjs +1 -1
  106. package/tests/profile_rollup_consent.mjs +2 -0
  107. package/tests/profile_route.mjs +16 -2
  108. package/tests/projects_hub.mjs +196 -89
  109. package/tests/projects_hub_app_status.mjs +3 -1
  110. package/tests/projects_hub_app_step.mjs +72 -48
  111. package/tests/projects_hub_dns_ready.mjs +10 -2
  112. package/tests/projects_hub_look.mjs +32 -22
  113. package/tests/projects_hub_module_picker.mjs +112 -62
  114. package/tests/projects_hub_pre_uat.mjs +48 -41
  115. package/tests/provision.mjs +78 -0
  116. package/tests/public_landing_projects.mjs +12 -6
  117. package/tests/settings_main_role.mjs +190 -0
  118. package/tests/software_update.mjs +56 -1
  119. package/tests/update_subscription_engine.mjs +55 -3
  120. package/tests/wizard_demo.mjs +37 -11
  121. package/tests/wizard_draft_resume.mjs +34 -22
  122. package/tests/wizard_front_door.mjs +173 -103
  123. package/tests/wizard_intent_resume.mjs +28 -25
  124. package/tests/wizard_physics.mjs +94 -76
  125. package/tests/wizard_physics_more.mjs +428 -277
  126. package/tests/wizard_six_screens.mjs +126 -0
@@ -0,0 +1,126 @@
1
+ // tests/wizard_six_screens.mjs — the blended create wizard (task 1004504, BV2.PS16; goal 1000121).
2
+ //
3
+ // The design of record is docs/design/mocks/combined-onboarding/index.html (the owner approved it
4
+ // as drawn, 2026-10-01): six screens and the done panel, in this order — sign in, demo or real
5
+ // (the terms as its one tick), what are you making, a few quick checks, check what we set up,
6
+ // give it a look → Create, done — with the mockup's own words, no progress rail, and a review
7
+ // that cannot be skipped: every prefilled answer is a row the founder confirms or changes, and
8
+ // Continue stays locked until all of them are confirmed.
9
+ //
10
+ // This file pins the shape and the words statically. The rows' behaviour is executed by
11
+ // tests/wizard_physics_more.mjs (the controller under a DOM stub) and walked end to end by the
12
+ // kit probes in projects.probes.json; the night room's tokens and motion by tests/projects_hub.mjs.
13
+ //
14
+ // Run: node --test tests/wizard_six_screens.mjs
15
+
16
+ import assert from 'node:assert/strict';
17
+ import { test } from 'node:test';
18
+ import fs from 'node:fs';
19
+ import path from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+
22
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
23
+ const HUB = fs.readFileSync(path.join(ROOT, 'modules', 'public-landing', 'public', 'projects.html'), 'utf8').replace(/\r\n/g, '\n');
24
+ const SCRIPT = HUB.slice(HUB.lastIndexOf('<script>'), HUB.lastIndexOf('</script>'));
25
+ const VIEW = (HUB.match(/<section id="view-new" hidden>[\s\S]*?\n<\/section>/) || [''])[0];
26
+ const MOCK = fs.readFileSync(path.join(ROOT, 'docs', 'design', 'mocks', 'combined-onboarding', 'index.html'), 'utf8').replace(/\r\n/g, '\n');
27
+ const panel = (id) => (VIEW.match(new RegExp(`<section class="panel[^"]*" id="${id}"[\\s\\S]*?\\n {10}</section>`)) || [''])[0];
28
+
29
+ const ORDER = ['panel-gate', 'panel-fork', 'panel-what', 'panel-checks', 'panel-review', 'panel-look', 'panel-done'];
30
+
31
+ test('six screens and the done panel, in the design of record\'s order, in the markup and in the controller\'s map', () => {
32
+ assert.ok(VIEW, 'the ?view=new section is found');
33
+ const inMarkup = [...VIEW.matchAll(/<section class="panel[^"]*" id="(panel-[a-z]+)"/g)].map((m) => m[1]);
34
+ assert.deepEqual(inMarkup, ORDER, 'the panels appear in this order and there are no others');
35
+ const map = (SCRIPT.match(/var panels = \{([^}]*)\}/) || [, ''])[1];
36
+ const fromMap = [...map.matchAll(/(\d+):\s*'(panel-[a-z]+)'/g)].map((m) => [Number(m[1]), m[2]]);
37
+ assert.deepEqual(fromMap, ORDER.map((id, i) => [i, id]), 'the controller numbers them 0–6 in the same order');
38
+ assert.match(SCRIPT, /var DRAFT_KEY = 'cb-create-draft-v9';/, 'a renumbering bumps the draft key, so an older draft is ignored rather than replayed onto the wrong screen');
39
+ });
40
+
41
+ test('the old screens and the progress rails are gone', () => {
42
+ for (const id of ['panel-terms', 'panel-physics', 'panel-name', 'panel-type', 'panel-detail', 'panel-modules', 'panel-home', 'panel-address', 'panel-app']) {
43
+ assert.doesNotMatch(HUB, new RegExp(`id="${id}"`), `${id} folded into the six screens`);
44
+ }
45
+ assert.doesNotMatch(VIEW, /class="steps"|id="physRail"|data-step=/, 'no progress rail, outer or inner');
46
+ assert.doesNotMatch(SCRIPT, /function paintRail\(|function physNextQ\(|function physPaintStage\(/, 'nor the code that painted them');
47
+ assert.doesNotMatch(VIEW, /id="physStage"|id="forkStage"|class="bongoCell"|class="bongos"/, 'the forming planet, the plate and the drums give way to the night room');
48
+ assert.match(VIEW, /<div class="wizTop">\s*<span class="wizEyebrow" id="wizEyebrow">New project<\/span>\s*<button type="button" class="wizBack" id="wizBack" hidden>← Back<\/button>/,
49
+ 'one eyebrow names the screen and one Back walks backwards');
50
+ });
51
+
52
+ test('each screen opens with the mockup\'s own words', () => {
53
+ const pairs = [
54
+ ['panel-gate', 'Make something.', 'Sign in with GitHub to start your project.'],
55
+ ['panel-fork', 'You’re about to start a digital planet.', 'Try a small demo first, or start your real project.'],
56
+ ['panel-what', 'What are you making?', null],
57
+ ['panel-checks', 'A few quick checks.', 'These decide which legal and payout options we can offer.'],
58
+ ['panel-review', 'Check what we set up.', 'We filled these in from your answers. Confirm each one, or change it.'],
59
+ ['panel-look', 'Give it a look.', 'So builders always know which project they’re in.'],
60
+ ];
61
+ for (const [id, h, lede] of pairs) {
62
+ const p = panel(id);
63
+ assert.ok(p, `${id} is found`);
64
+ const mockLine = h.replace(/’/g, '(’|\'|&rsquo;)');
65
+ assert.match(MOCK, new RegExp(mockLine.replace(/[.?]/g, '\\$&')), `"${h}" is the mockup's own headline`);
66
+ assert.match(p, new RegExp(`<h1 id="[a-z-]+h[0-9]?"?[^>]*>${h.replace(/[.?]/g, '\\$&')}`), `${id} opens "${h}"`);
67
+ if (lede) assert.match(p, new RegExp(`<p class="lede">${lede.replace(/[.?]/g, '\\$&')}</p>`), `${id}'s one line`);
68
+ }
69
+ assert.match(panel('panel-gate'), /Continue with GitHub/, 'the gate\'s door');
70
+ assert.match(panel('panel-fork'), /<button type="submit" class="btn big" id="wizStart" disabled>Start my project<\/button>/);
71
+ assert.match(panel('panel-fork'), /id="wizDemo"[^>]*disabled>Try the demo<\/button>/, 'both doors wait for the terms tick');
72
+ assert.match(panel('panel-fork'), /I can sign for this project, and I accept the <a class="termsRead" href="\/terms"/, 'the terms are one tick on the fork, with the terms one click away');
73
+ assert.match(panel('panel-what'), /<span>Name<\/span>[\s\S]*<span id="typeLbl">Kind<\/span>[\s\S]*In a sentence <small>\(optional — puts it on the public map\)<\/small>/, 'name, kind, one optional sentence');
74
+ });
75
+
76
+ test('planet words survive only as the light touch: the fork and the alive moment', () => {
77
+ const words = VIEW.replace(/<!--[\s\S]*?-->/g, '').replace(/<[^>]+>/g, ' ');
78
+ const planets = words.match(/planet/gi) || [];
79
+ assert.equal(planets.length, 1, 'one planet in the whole view: the fork\'s headline');
80
+ assert.match(SCRIPT, /\(state\.name \|\| state\.slug \|\| 'Your project'\) \+ ' is alive\.'/, 'the alive moment');
81
+ assert.match(SCRIPT, /if \(inst\.last_verified_up\) \{\n\s*\/\*[^*]*\*\/\n\s*\$\('done-h'\)\.textContent =/, 'said only once the project has answered (Live is a verified claim)');
82
+ });
83
+
84
+ test('the review cannot be skipped: seven rows, each confirmed or changed, and a locked Continue', () => {
85
+ const p = panel('panel-review');
86
+ const rows = [...p.matchAll(/<div class="setRow" data-row="([a-z]+)">/g)].map((m) => m[1]);
87
+ assert.deepEqual(rows, ['code', 'address', 'app', 'extras', 'team', 'rewards', 'run']);
88
+ for (const key of rows) {
89
+ const r = (p.match(new RegExp(`<div class="setRow" data-row="${key}">[\\s\\S]*?<span class="acts">[^\\n]*\\n`)) || [''])[0];
90
+ assert.match(r, /<button type="button" class="rowOk" data-row-ok>Looks right<\/button><button type="button" class="rowChg" data-row-chg aria-expanded="false">Change<\/button>/, `${key}: Looks right and Change`);
91
+ assert.match(r, /<div class="opts" hidden>[\s\S]*<button type="button" class="btn small rowUse" data-row-use>Use this<\/button>/, `${key}: Change opens the row's own controls with Use this`);
92
+ }
93
+ assert.match(p, /<button type="submit" class="btn" id="reviewGo" disabled>Confirm 7 more<\/button>/, 'Continue is baked locked');
94
+ assert.match(SCRIPT, /go\.textContent = left \? 'Confirm ' \+ left \+ ' more' : 'Continue';/, 'and says how many rows are left');
95
+ assert.match(SCRIPT, /if \(step === 4\) \{\n\s*var open = unconfirmedRows\(\);\n\s*if \(open\.length\) \{ openRow\(open\[0\]\); return false; \}/, 'Continue with a row left opens that row');
96
+ assert.match(SCRIPT, /if \(unconfirmedRows\(\)\.length\) \{ show\(4, true\); validateStep\(4\); return; \}/, 'and Create refuses until every row is confirmed');
97
+ });
98
+
99
+ test('nothing the old steps could do is lost: their controls are moved whole into the rows', () => {
100
+ const p = panel('panel-review');
101
+ const has = (row, ids) => {
102
+ const r = (p.match(new RegExp(`<div class="setRow" data-row="${row}">[\\s\\S]*?\\n {16}</div>\\n`)) || [''])[0];
103
+ for (const id of ids) assert.match(r, new RegExp(`id="${id}"`), `${row} row hosts #${id}`);
104
+ };
105
+ has('code', ['physExisting', 'c-green', 'c-adopt', 'adoptNote', 'ghConnect', 'ghAdopt', 'ghFresh', 'manualHome', 'h-home']);
106
+ has('address', ['f-slug', 'addrConfirm', 'addrCustom', 'f-domain', 'f-noaddr']);
107
+ has('app', ['appOpts', 'renderLater', 'renderSetup', 'f-renderKey', 'renderWs', 'renderSvc', 'renderNew']);
108
+ has('extras', ['modQ', 'modCards', 'modWhy', 'modCoreNote']);
109
+ has('team', ['physTeam', 'physStartN', 'physExpected', 'teamCards']);
110
+ has('run', ['physSuite']);
111
+ for (const id of ['physCountry', 'physRegion', 'physAges', 'physIntent', 'physForms', 'physHaveEntity', 'checksStop', 'physStopMsg', 'physFromAccount']) {
112
+ assert.match(panel('panel-checks'), new RegExp(`id="${id}"`), `the quick checks host #${id}`);
113
+ }
114
+ for (const id of ['demoSetup', 'demoIdea', 'demoInvites', 'demoStart', 'wizResume']) {
115
+ assert.match(panel('panel-fork'), new RegExp(`id="${id}"`), `the fork hosts #${id}`);
116
+ }
117
+ for (const id of ['wizLook', 'wizRecap', 'createAlert', 'doCreate']) {
118
+ assert.match(panel('panel-look'), new RegExp(`id="${id}"`), `the look screen hosts #${id}`);
119
+ }
120
+ /* two answers moved across screens, so two old guarantees are re-pinned where they live now */
121
+ assert.match(SCRIPT, /function renderNow\(\) \{ return !appSkipped\(\) && /, 'a framing on the founder\'s own machines rules Render out at Create, whatever was picked before');
122
+ assert.match(SCRIPT, /function renderLater\(\) \{ return !appSkipped\(\) && /);
123
+ assert.match(SCRIPT, /if \(key === 'extras' && starterBundles\) state\.modules = pickedModules\(\);/, 'confirming the extras before the catalog lands files no answer, never an empty list');
124
+ const ids = [...VIEW.matchAll(/\sid="([^"]+)"/g)].map((m) => m[1]);
125
+ assert.deepEqual(ids.filter((id, i) => ids.indexOf(id) !== i), [], 'moved, never copied: every id in the view is unique');
126
+ });