@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
@@ -250,14 +250,22 @@ function makeCoreUpgradeHandler({ provisioning, pool, parseId, validateOrRespond
250
250
  * and not asking it is what keeps the one comparison in the system (the runner's channel
251
251
  * resolution) the only one that can be wrong.
252
252
  *
253
- * An unknown `recommended` — the registry could not be read — leaves a failure STANDING.
254
- * Not knowing what is on offer is not evidence that the box recovered, and the direction
255
- * to fail in is showing an old failure, never hiding a live one.
253
+ * An UNREAD registry — `registryRead` false, the snapshot's `available` empty — leaves a
254
+ * failure STANDING. Not knowing what is on offer is not evidence that the box recovered,
255
+ * and the direction to fail in is showing an old failure, never hiding a live one. A
256
+ * registry that answered with nothing on offer is different: the box is current, and a
257
+ * failure about some other version is history (task 1004534).
256
258
  */
257
- function lastMoveSuperseded(target, served, recommended) {
259
+ function lastMoveSuperseded(target, served, recommended, registryRead = false) {
258
260
  if (!target) return false;
259
261
  if (served && String(served) === String(target)) return true;
260
- return !!(recommended && String(recommended) !== String(target));
262
+ if (recommended) return String(recommended) !== String(target);
263
+ // NOTHING ON OFFER FROM A REGISTRY THAT ANSWERED is an up-to-date box, not an unknown
264
+ // (task 1004534). The snapshot stores an empty `available` when the registry could not
265
+ // be read, so only that case leaves the failure standing. On 2026-10-02 cloudbongos
266
+ // served 1.21.5 with nothing newer in its rule, and a day-old failure about 1.20.73
267
+ // still led its /deploy page because a null recommendation was read as "unknown".
268
+ return !!(registryRead && served);
261
269
  }
262
270
 
263
271
  /**
@@ -371,7 +379,7 @@ function previewFromSnapshot(inst, snap, openIntent, lastMove) {
371
379
  // already moved past (task 1004172 — lastMoveSuperseded says why at length). The
372
380
  // CLIENT must not work this out: the page's standing rule is that it compares no
373
381
  // versions, and this is a version question wearing a different hat.
374
- superseded: lastMoveSuperseded(lastMove.target_version, served, recommended),
382
+ superseded: lastMoveSuperseded(lastMove.target_version, served, recommended, available.length > 0),
375
383
  // Truncated because it reaches a DOM and upgrade.js's refusals can carry a whole
376
384
  // `git status` (the dirty-tree one lists every file). Never set on a DONE move:
377
385
  // a done row's last_error is the note below, and a move that worked is not an error.
@@ -468,6 +476,25 @@ function updateChannelOf(inst) {
468
476
  return UPDATE_CHANNELS.includes(c) ? c : DEFAULT_UPDATE_CHANNEL;
469
477
  }
470
478
 
479
+ /**
480
+ * THIS hall's own update rule — the control-plane row's — for the offers the core makes
481
+ * outside /deploy: Settings → Software update and the hall's update banner (task 1004535).
482
+ * Those live in the core, which cannot read a module's table, so this is handed to them
483
+ * through the `provisioning.selfUpdateChannel` seam. Before it they asked with the platform
484
+ * default (patch) while the runner and the sweep followed the stored rule (minor on
485
+ * cloudbongos), so a step-up release would have read "up to date" there as it installed.
486
+ * null — no row, an unknown value, a failed read — means "use the default"; never throws.
487
+ */
488
+ async function selfUpdateChannel(db) {
489
+ try {
490
+ const { rows } = await db.query("SELECT update_channel FROM provisioning_instances WHERE hosting_shape = 'control-plane' LIMIT 1");
491
+ const c = rows[0] && rows[0].update_channel;
492
+ return UPDATE_CHANNELS.includes(c) ? c : null;
493
+ } catch {
494
+ return null;
495
+ }
496
+ }
497
+
471
498
  /**
472
499
  * POST /provisioning/instances/:id/update-channel — set how far this project's core
473
500
  * may move (task 1004445). Body: { channel: 'pinned' | 'patch' | 'minor' }.
@@ -518,5 +545,5 @@ function makeUpdateChannelHandler({ provisioning, pool, parseId, validateOrRespo
518
545
  };
519
546
  }
520
547
 
521
- module.exports = { UPDATE_CHANNELS, DEFAULT_UPDATE_CHANNEL, updateChannelOf, makeUpdateChannelHandler, CORE_UPGRADE_FROM, lastCoreMove, lastMoveSuperseded, parseRepoNote, preflightForOffer, UPGRADE_SHAPES, VERSION_RE, isCoreVersion, coreUpgradeFault, enqueueCoreUpgrade, makeCoreUpgradeHandler, previewFromSnapshot, makeCoreUpgradePreviewHandler, makeControlPlaneHandler };
548
+ module.exports = { UPDATE_CHANNELS, DEFAULT_UPDATE_CHANNEL, updateChannelOf, selfUpdateChannel, makeUpdateChannelHandler, CORE_UPGRADE_FROM, lastCoreMove, lastMoveSuperseded, parseRepoNote, preflightForOffer, UPGRADE_SHAPES, VERSION_RE, isCoreVersion, coreUpgradeFault, enqueueCoreUpgrade, makeCoreUpgradeHandler, previewFromSnapshot, makeCoreUpgradePreviewHandler, makeControlPlaneHandler };
522
549
 
@@ -35,7 +35,8 @@
35
35
  "provisioning.instanceState",
36
36
  "provisioning.projectPlanets",
37
37
  "provisioning.projectOwnedBy",
38
- "provisioning.projectPublishIdentity"
38
+ "provisioning.projectPublishIdentity",
39
+ "provisioning.selfUpdateChannel"
39
40
  ],
40
41
  "consumes": []
41
42
  }
@@ -6,6 +6,7 @@
6
6
  const api = require('../../src/module-api');
7
7
  const { pool } = api;
8
8
  const provisioning = require('./provisioning');
9
+ const { selfUpdateChannel } = require('./core-upgrade');
9
10
 
10
11
  // The `provisioning.projectPublishIdentity` port (task 1003578, ADR 0247 D4): the name and
11
12
  // description the publish gate judges, for the control-plane project a hub catalog row was
@@ -49,6 +50,7 @@ function registerProvisioningSeams() {
49
50
  api.registerProvider('provisioning.projectPlanets', (hosts) => provisioning.planetChoicesForHosts(pool, hosts));
50
51
  api.registerProvider('provisioning.projectOwnedBy', (target) => provisioning.projectOwnedBy(pool, target));
51
52
  api.registerProvider('provisioning.projectPublishIdentity', (target) => projectPublishIdentity(pool, target));
53
+ api.registerProvider('provisioning.selfUpdateChannel', () => selfUpdateChannel(pool));
52
54
  }
53
55
 
54
56
  module.exports = { registerProvisioningSeams, projectPublishIdentity };
@@ -1232,27 +1232,7 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1232
1232
  .filters button:not([aria-pressed="true"]) .n{color:var(--ink-faint);}
1233
1233
  .mineEmpty{font-size:14.5px;font-weight:600;color:var(--ink-soft);padding:10px 0 22px;}
1234
1234
 
1235
- /* ── the create rail ── */
1236
- .steps{display:flex;align-items:flex-start;margin-bottom:26px;}
1237
- .steps li{flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;position:relative;list-style:none;}
1238
- .steps li:not(:first-child)::before{content:"";position:absolute;top:15px;right:50%;width:100%;height:3px;
1239
- background:var(--line);margin-right:15px;border-radius:2px;}
1240
- /* the rail's marks are NON-TEXT at WCAG 1.4.11's 3:1, and the chrome world's
1241
- --accent measures 2.10:1 on the card — so the ring and the connector take
1242
- --accent-deep (5.77:1 on the card, and the derived bright twin in dark). The
1243
- done step's FILL stays --accent with --accent-on ink on it (task 1003298). */
1244
- .steps li.done:not(:first-child)::before{background:var(--accent-deep);}
1245
- .steps .snum{width:32px;height:32px;border-radius:50%;border:3px solid var(--line);background:var(--bg-card);
1246
- display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-weight:700;
1247
- font-size:14px;color:var(--ink-faint);position:relative;z-index:1;}
1248
- .steps li.done .snum{border-color:var(--accent-deep);background:var(--accent);color:var(--accent-on);}
1249
- .steps li.now .snum{border-color:var(--accent-deep);color:var(--accent-deep);}
1250
- .steps .slbl{font-size:12.5px;font-weight:700;color:var(--ink-faint);}
1251
- .steps li.now .slbl,.steps li.done .slbl{color:var(--ink-soft);}
1252
- .steps li[role=button]{cursor:pointer;}
1253
- .steps li[role=button]:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:8px;}
1254
- .createSplit{display:grid;grid-template-columns:1fr 300px;gap:var(--pad-md);align-items:center;}
1255
- @media (max-width:840px){.createSplit{grid-template-columns:1fr;}.createSplit .bongoCell{display:none;}}
1235
+ .createSplit{display:block;}
1256
1236
 
1257
1237
  /* ── the honest empty / not-available-here state. A child instance does not
1258
1238
  provision, so it must SAY so rather than fall into the generic alert. ── */
@@ -1600,28 +1580,10 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1600
1580
  ═══════════════════════════════════════════════════════════════════════ */
1601
1581
  #view-new .wrap{max-width:1180px;}
1602
1582
  #view-new .card{background:none;border-radius:0;box-shadow:none;padding:34px 0 60px;margin:0;}
1603
- /* the six-step strip as the rail: six hairlines, a 7px dot, one lit step on the
1604
- accent with its halo, the number in the display voice, the name in the label
1605
- face; a step already answered (role=button) stays a way back */
1606
- #view-new .steps{display:grid;grid-template-columns:repeat(10,1fr);gap:0 10px;align-items:start;margin:0 0 40px;}
1607
- #view-new .steps li{display:block;position:relative;border-top:1px solid var(--rule);padding:12px 0 0;gap:0;}
1608
- #view-new .steps li::before{content:"";position:absolute;top:-4px;left:0;right:auto;width:7px;height:7px;margin:0;border-radius:50%;border:1px solid var(--rule);background:var(--bg);}
1609
- #view-new .steps .snum{display:block;width:auto;height:auto;border:0;border-radius:0;background:none;font-family:var(--font-display);font-weight:300;font-size:22px;letter-spacing:-.02em;line-height:1.1;color:var(--ink-faint);margin-bottom:2px;}
1610
- #view-new .steps .slbl{display:block;font-family:var(--label-face);font-size:var(--label-size);font-weight:400;letter-spacing:var(--label-space);text-transform:uppercase;line-height:1.3;color:var(--ink-faint);}
1611
- #view-new .steps li.done{border-top-color:var(--ink-soft);}
1612
- #view-new .steps li.done::before{background:var(--ink-soft);border-color:var(--ink-soft);}
1613
- #view-new .steps li.done .snum,#view-new .steps li.done .slbl{color:var(--ink-soft);background:none;}
1614
- #view-new .steps li.now{border-top-color:var(--accent);}
1615
- #view-new .steps li.now::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
1616
- #view-new .steps li.now .snum,#view-new .steps li.now .slbl{color:var(--ink);}
1617
- #view-new .steps li[role=button]:hover .slbl{color:var(--ink);}
1618
- /* the step: the title lowercase in the display voice, one clause, the fine
1619
- print in the body face; the bongo pair beside it (the owner's one mark on
1620
- every surface), its halo gone */
1621
- #view-new .createSplit{align-items:start;gap:48px;}
1622
- #view-new .bongoCell{padding-top:60px;}
1623
- #view-new .bongos .glow{display:none;}
1624
- #view-new .panel h1{font-weight:300;font-size:clamp(28px,3.4vw,44px);letter-spacing:-.035em;line-height:1.04;text-transform:lowercase;color:var(--ink);text-shadow:none;margin:0 0 10px;max-width:18ch;text-wrap:balance;}
1583
+ /* the screen: the title in the display voice at the design of record's light weight and
1584
+ sentence case (task 1004504), one clause, the fine print in the body face — over the
1585
+ night room the page draws behind it */
1586
+ #view-new .panel h1{font-weight:200;font-size:clamp(32px,3.8vw,52px);letter-spacing:-.035em;line-height:1.05;text-transform:none;color:var(--ink);text-shadow:none;margin:0 0 10px;max-width:18ch;text-wrap:balance;}
1625
1587
  #view-new .panel .lede{font-size:15.5px;font-weight:400;line-height:1.5;color:var(--ink-soft);margin:0 0 26px;max-width:62ch;}
1626
1588
  #view-new .panel .lede strong,#view-new .panel .lede em{color:var(--ink);font-weight:500;font-style:normal;}
1627
1589
  /* the done clause's link to Your projects clears the 24px hit floor as a box (an inline's rect is its content box) */
@@ -1640,7 +1602,7 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1640
1602
  #view-new .linklike:hover{color:var(--ink);}
1641
1603
  /* the doors: pills, lowercase, the accent only on the one that acts; back and
1642
1604
  skip as hairline pills; the GitHub sign-in inverted; no lift, no shadow */
1643
- #view-new .btn{min-height:44px;padding:0 22px;font-family:var(--font-body);font-weight:500;font-size:15px;text-transform:lowercase;white-space:nowrap;box-shadow:none;transition:border-color .15s ease,background .15s ease,color .15s ease;}
1605
+ #view-new .btn{min-height:44px;padding:0 22px;font-family:var(--font-body);font-weight:500;font-size:15px;text-transform:none;white-space:nowrap;box-shadow:none;transition:border-color .15s ease,background .15s ease,color .15s ease;}
1644
1606
  #view-new .btn:hover{transform:none;box-shadow:none;background:color-mix(in srgb,var(--accent) 88%,var(--ink));}
1645
1607
  #view-new .btn:active{transform:none;}
1646
1608
  #view-new .btn:disabled{background:none;border:1px solid var(--rule-soft);color:var(--ink-faint);}
@@ -1659,9 +1621,3 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1659
1621
  #view-new .inviteBox{margin-top:34px;}
1660
1622
  #view-new .inviteBox .finePrint{margin-top:10px;}
1661
1623
  #view-new #wizInviteLater{margin-top:14px;}
1662
- /* one fold for the whole wizard: 840 is where the page's bands and ledger stack
1663
- (cosmos's createSplit collapse), so the rail folds with them, not before them */
1664
- @media (max-width:840px){
1665
- #view-new .steps{grid-template-columns:repeat(3,1fr);gap:18px 10px;margin-bottom:30px;}
1666
- #view-new .steps .snum{font-size:18px;}
1667
- }