@bongos/core 1.25.13 → 1.25.14

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 (42) hide show
  1. package/.bongos-core.json +65 -45
  2. package/clients/bongos-client/index.d.ts +2 -2
  3. package/docs/adr/0328-a-hosted-projects-authority-is-its-membership-row-not-its-owner-column.md +1 -1
  4. package/docs/adr/0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md +124 -0
  5. package/docs/adr/README.md +1 -0
  6. package/docs/api/openapi.json +6 -0
  7. package/docs/api-reference.md +2 -2
  8. package/docs/copy-inventory.md +28 -34
  9. package/docs/copy-registry.json +41 -125
  10. package/docs/file-map.md +1 -1
  11. package/docs/module-api-changelog.md +2 -0
  12. package/docs/page-inventory.json +1 -0
  13. package/docs/page-readings.json +3 -3
  14. package/modules/front-door-guide/db.js +13 -5
  15. package/modules/front-door-guide/guide.js +8 -2
  16. package/modules/front-door-guide/migrations/front_door_guide_003_starting_point.sql +12 -0
  17. package/modules/front-door-guide/module.json +2 -2
  18. package/modules/front-door-guide/plan.js +15 -6
  19. package/modules/front-door-guide/routes/front-door-guide-plan.js +3 -2
  20. package/modules/front-door-guide/routes/front-door-guide.js +17 -4
  21. package/modules/front-door-guide/starting-point.js +55 -0
  22. package/modules/hall-ui/public/genesis-home.js +29 -2
  23. package/modules/hall-ui/public/goals-page.js +3 -29
  24. package/modules/hall-ui/public/index.html +2 -1
  25. package/modules/hall-ui/public/task-lib.js +45 -0
  26. package/modules/hall-ui/public/work.js +3 -47
  27. package/modules/lifecycle/kickoff-seed.js +9 -5
  28. package/modules/onboarding/genesis-home.js +1 -1
  29. package/package-lock.json +306 -3
  30. package/package.json +4 -2
  31. package/release-notes.json +18 -0
  32. package/scripts/bongos/package-core.js +4 -2
  33. package/src/bongos/module-scope-map.js +1 -0
  34. package/src/module-api.js +1 -1
  35. package/tests/cutover_codemod.mjs +1 -1
  36. package/tests/front_door_guide_db.mjs +6 -1
  37. package/tests/front_door_guide_existing.mjs +238 -0
  38. package/tests/genesis_home.mjs +80 -2
  39. package/tests/package_core.mjs +11 -7
  40. package/tests/pruned_lockfile_integrity.mjs +4 -2
  41. package/tests/status_page_no_dead_uptime.mjs +1 -1
  42. package/tests/task_lib.mjs +46 -0
package/.bongos-core.json CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/bongos/package-core.js",
5
- "core_version": "1.25.13",
6
- "core_contract": "1.25.13",
7
- "source_commit": "6144401eb07488528be2d4c98786f479a900c9d0",
5
+ "core_version": "1.25.14",
6
+ "core_contract": "1.25.14",
7
+ "source_commit": "c787ea767033e83cc2ef245450a292b99f23d077",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-11-13T19:37:53.952Z",
9
+ "built_at": "2026-11-13T20:00:44.555Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 656,
12
+ "docs_redacted": 657,
13
13
  "agent_docs_stubbed": 33,
14
- "functional_verbatim": 4016,
14
+ "functional_verbatim": 4019,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 4706,
20
- "tree_sha256": "fbec1349dacd426f02d295f9f37bf8e36691d86d3ba8c9d5df7f9c70123dc2e7",
19
+ "file_count": 4710,
20
+ "tree_sha256": "38ceaa985a20dd0efed34bfdebd5fb598d5ebe7c968a3178998e5ed96600bf6c",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -352,7 +352,7 @@
352
352
  {
353
353
  "path": "clients/bongos-client/index.d.ts",
354
354
  "mode": "0000644",
355
- "sha256": "72b35b37e40d677c4f0b3df0fbc69c7bc062daeac97fd71b67e9a463af24fadb"
355
+ "sha256": "3b5acc8f398f18e7144bd00d4072ec8ab13c049667f531262e97416050e26770"
356
356
  },
357
357
  {
358
358
  "path": "clients/bongos-client/index.mjs",
@@ -2117,7 +2117,7 @@
2117
2117
  {
2118
2118
  "path": "docs/adr/0328-a-hosted-projects-authority-is-its-membership-row-not-its-owner-column.md",
2119
2119
  "mode": "0000644",
2120
- "sha256": "0a40681d78739b99df16e4207e71283d15d4b3895bf24c757c9894060254a03f"
2120
+ "sha256": "0aa065ddef149060b4f4ebf774a74d25239eb3efa8d9a2a80bd0e3ae60eb6c35"
2121
2121
  },
2122
2122
  {
2123
2123
  "path": "docs/adr/0329-the-rendered-fit-check-is-a-kit-floor-and-an-advisory-ship-check-row.md",
@@ -2494,20 +2494,25 @@
2494
2494
  "mode": "0000644",
2495
2495
  "sha256": "aedd6b7dc8ba2955c48d44dd6d7ee24b42219b22ef034db1f1b27e23bc04f30c"
2496
2496
  },
2497
+ {
2498
+ "path": "docs/adr/0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md",
2499
+ "mode": "0000644",
2500
+ "sha256": "0af8295774d6c056587f2d96d83e44d0cab496bc1e034ca9807419665723f994"
2501
+ },
2497
2502
  {
2498
2503
  "path": "docs/adr/README.md",
2499
2504
  "mode": "0000644",
2500
- "sha256": "50221b2eb63f103558dfce9e164cf2a25ea60cfbc4171d8f23d8db72ca08be97"
2505
+ "sha256": "64486d3e734bce60b0a215ce5bc97b6219958a730f033aa73af10281fd7ff5f9"
2501
2506
  },
2502
2507
  {
2503
2508
  "path": "docs/api-reference.md",
2504
2509
  "mode": "0000644",
2505
- "sha256": "956db8f10f4503ccaedbfe94b50449bdffbb70fd8fdb1aae7397b9973e62c84f"
2510
+ "sha256": "6222bc04e7b134403b1867df8bef9f6c645717bacc4a23f8273a16f50b7e0878"
2506
2511
  },
2507
2512
  {
2508
2513
  "path": "docs/api/openapi.json",
2509
2514
  "mode": "0000644",
2510
- "sha256": "b60a213d5657260a2e12a85eb83e364722e954cb2c39730c6a596433a7d73126"
2515
+ "sha256": "1b95f85a807b76f6d5bbf422e392a24f104c45c87445d24b9225023f47945415"
2511
2516
  },
2512
2517
  {
2513
2518
  "path": "docs/architecture.md",
@@ -2532,12 +2537,12 @@
2532
2537
  {
2533
2538
  "path": "docs/copy-inventory.md",
2534
2539
  "mode": "0000644",
2535
- "sha256": "77bdd4ba391686810218092ce41a3beffa96c1bb64b9468adbd6cad5b42ed788"
2540
+ "sha256": "1c2ebe0efec2386493e84c8fbfbbf066a7dbe0e5b33f67a12345c5ecd501c785"
2536
2541
  },
2537
2542
  {
2538
2543
  "path": "docs/copy-registry.json",
2539
2544
  "mode": "0000644",
2540
- "sha256": "b523b08e1350f6714d19d598d49749cbf5d767b8cf323fc89a11c8b5a9198ff2"
2545
+ "sha256": "d1900ea8456a9fd633d8ca10b22137cce2c781ff8b01f0a9f02745c63a994269"
2541
2546
  },
2542
2547
  {
2543
2548
  "path": "docs/design/apex-pass-2-direction.md",
@@ -3082,7 +3087,7 @@
3082
3087
  {
3083
3088
  "path": "docs/file-map.md",
3084
3089
  "mode": "0000644",
3085
- "sha256": "0d82688dbf0f4b2fb85eaabe58972e9fedc7579c933e83ce431624567099ff36"
3090
+ "sha256": "14d2cd161653eec8b9478b8552e1bf39b93f60a608da0a72099734be16e5053e"
3086
3091
  },
3087
3092
  {
3088
3093
  "path": "docs/handoff-template.md",
@@ -3092,7 +3097,7 @@
3092
3097
  {
3093
3098
  "path": "docs/module-api-changelog.md",
3094
3099
  "mode": "0000644",
3095
- "sha256": "0ddc252d589300b4d36f14e8c24f5133e17da786060a2c7ae7b50c7caa77e86e"
3100
+ "sha256": "88acc962bf4ec0ff97a231925d1f09932a1273b292febb9acce60d6d2b4dddc4"
3096
3101
  },
3097
3102
  {
3098
3103
  "path": "docs/modules-contract.md",
@@ -3172,12 +3177,12 @@
3172
3177
  {
3173
3178
  "path": "docs/page-inventory.json",
3174
3179
  "mode": "0000644",
3175
- "sha256": "db4c5144737b8fa016950d6febc43b7d0b1913bc8a79fba3149ebbad0d206346"
3180
+ "sha256": "000de9b745ac238dd88d2ead1cca85a33971d51670c180bed2d362d38ead1543"
3176
3181
  },
3177
3182
  {
3178
3183
  "path": "docs/page-readings.json",
3179
3184
  "mode": "0000644",
3180
- "sha256": "b4d16b777b6193169be5ea13ce4f076e4878a507a0ed9d247678d4b2a48d4d48"
3185
+ "sha256": "dce87c59b19831ab2a52a7bd66c1677d4866d2bb4c205d6c95e061a55a4cb50a"
3181
3186
  },
3182
3187
  {
3183
3188
  "path": "docs/project-context.template.md",
@@ -5537,12 +5542,12 @@
5537
5542
  {
5538
5543
  "path": "modules/front-door-guide/db.js",
5539
5544
  "mode": "0000644",
5540
- "sha256": "1bbe4f1605e1e8cc6daa6d32150e7cd32cb28df5f527f88b8d36a0d6b6dcc1fc"
5545
+ "sha256": "104aa56aa103975af48440fa46409b0b5f7ee5b609b60adcc2aa7fb398523b31"
5541
5546
  },
5542
5547
  {
5543
5548
  "path": "modules/front-door-guide/guide.js",
5544
5549
  "mode": "0000644",
5545
- "sha256": "590a26cd79ce41f84fa29635da0e63fc682db3653fdebeb9ba0e834a6fa4062c"
5550
+ "sha256": "6e1a0d6cb2cb7eac8ce3fe71f0c54b732eb2ab92450a014724cecadd1f7f7fc9"
5546
5551
  },
5547
5552
  {
5548
5553
  "path": "modules/front-door-guide/limits.js",
@@ -5559,15 +5564,20 @@
5559
5564
  "mode": "0000644",
5560
5565
  "sha256": "632ea54bd430c2d143da7323ad848f28a1c53ac0735850d04cd6177b10c9c857"
5561
5566
  },
5567
+ {
5568
+ "path": "modules/front-door-guide/migrations/front_door_guide_003_starting_point.sql",
5569
+ "mode": "0000644",
5570
+ "sha256": "b23fd7ddc84a4d5a972e6f2ff3598d5551e8d837944d3d07bd225cee08dfa166"
5571
+ },
5562
5572
  {
5563
5573
  "path": "modules/front-door-guide/module.json",
5564
5574
  "mode": "0000644",
5565
- "sha256": "de486a674d919fed27a3356dade38e29c14dc2a0efa45eb4f9013fdeb17cd326"
5575
+ "sha256": "d59d73e45dbfdfacfe1885ec3a1a3ac09c03d992fac658c004161a7b34e93a90"
5566
5576
  },
5567
5577
  {
5568
5578
  "path": "modules/front-door-guide/plan.js",
5569
5579
  "mode": "0000644",
5570
- "sha256": "6da0d0b8c41c9a8b8fbffacbbc85cffe1e7c61853f847fb2ac72b0ec77ae0460"
5580
+ "sha256": "2f5b226fa26e7c0e35b26a9f55119e987dba3650c673b44645b33aec3bca72e4"
5571
5581
  },
5572
5582
  {
5573
5583
  "path": "modules/front-door-guide/pollers/retention-sweep.js",
@@ -5577,18 +5587,23 @@
5577
5587
  {
5578
5588
  "path": "modules/front-door-guide/routes/front-door-guide-plan.js",
5579
5589
  "mode": "0000644",
5580
- "sha256": "58cee518fe51190f7d4105b82d199f5868b6a0fd8747c9212a0e83bed435ac06"
5590
+ "sha256": "ec20b0acd7892d1cc6c5b6edaa2449bcfd25d675235c6f1ff1747962da76a0d7"
5581
5591
  },
5582
5592
  {
5583
5593
  "path": "modules/front-door-guide/routes/front-door-guide.js",
5584
5594
  "mode": "0000644",
5585
- "sha256": "f53fd28640999a4ab2868010b7502712fb9b82d70a043d5f97aa916bd603b9e8"
5595
+ "sha256": "86ed13db9fc81da0003f25066ba57784a814ebfa17bf05ca5e9b9a3e48983c55"
5586
5596
  },
5587
5597
  {
5588
5598
  "path": "modules/front-door-guide/settings.js",
5589
5599
  "mode": "0000644",
5590
5600
  "sha256": "fc0726ff9e1e0f2be291d8af37ff2ac1f36735c7dcf376bf9c4c201e2db35e6e"
5591
5601
  },
5602
+ {
5603
+ "path": "modules/front-door-guide/starting-point.js",
5604
+ "mode": "0000644",
5605
+ "sha256": "4278c8c321eff277dc0d84f37d4092b704760bb70d4929490091e766060bdd3e"
5606
+ },
5592
5607
  {
5593
5608
  "path": "modules/government/CLAUDE.md",
5594
5609
  "mode": "0000644",
@@ -6602,7 +6617,7 @@
6602
6617
  {
6603
6618
  "path": "modules/hall-ui/public/genesis-home.js",
6604
6619
  "mode": "0000644",
6605
- "sha256": "8dd86aab78586f87ad32e1e4e1c6e135e5d0664498f8dc559290e13f1f5c7d35"
6620
+ "sha256": "e4e71303e1d615d7457a3b0f7a900d26ca27ad8fb6035890354bcd26dc111b16"
6606
6621
  },
6607
6622
  {
6608
6623
  "path": "modules/hall-ui/public/genesis/r5-life-1-primordial-sea-cut.webp",
@@ -6702,7 +6717,7 @@
6702
6717
  {
6703
6718
  "path": "modules/hall-ui/public/goals-page.js",
6704
6719
  "mode": "0000644",
6705
- "sha256": "b38559f290c5ab2516c11cb171d0d520e33766ea84e8ee4ab43cfca3b5089a6c"
6720
+ "sha256": "26d4711006f13057d020a9de79062b0243f58d295579ccb7ac77dacfdd74e387"
6706
6721
  },
6707
6722
  {
6708
6723
  "path": "modules/hall-ui/public/goals-render.js",
@@ -6927,7 +6942,7 @@
6927
6942
  {
6928
6943
  "path": "modules/hall-ui/public/index.html",
6929
6944
  "mode": "0000644",
6930
- "sha256": "74e0c0c9ec6929b33ef006f3e2895ded3e87d33a69eb01f473586560f19316f4"
6945
+ "sha256": "172530c5eadd7b8791c978a9a1953dc852800618940a2b99d966c78b0b0d7ce7"
6931
6946
  },
6932
6947
  {
6933
6948
  "path": "modules/hall-ui/public/index.states.json",
@@ -7542,7 +7557,7 @@
7542
7557
  {
7543
7558
  "path": "modules/hall-ui/public/task-lib.js",
7544
7559
  "mode": "0000644",
7545
- "sha256": "40e4fe7b718b69d6484802a08f54525824f496410c3c3f63410a5e6bca678ace"
7560
+ "sha256": "0320fc00e377a32c44b3f1e38220307bf59d2bc433352f78409e4111719e7540"
7546
7561
  },
7547
7562
  {
7548
7563
  "path": "modules/hall-ui/public/task.css",
@@ -7702,7 +7717,7 @@
7702
7717
  {
7703
7718
  "path": "modules/hall-ui/public/work.js",
7704
7719
  "mode": "0000644",
7705
- "sha256": "fd8d67541dada082c4348b423996b556f446ce2550810b4d52211e852ebceeb1"
7720
+ "sha256": "ae37df94bcf24cee34e5d89e71a5947a6535eca0d73642c4b2bbd128315f279d"
7706
7721
  },
7707
7722
  {
7708
7723
  "path": "modules/hall-ui/public/work.states.json",
@@ -8517,7 +8532,7 @@
8517
8532
  {
8518
8533
  "path": "modules/lifecycle/kickoff-seed.js",
8519
8534
  "mode": "0000644",
8520
- "sha256": "99388ead53a583fcf239f4ea833046825903fab1efbcfc62440de9db720fae11"
8535
+ "sha256": "c06a5c11f54b01c2cf2f492dff0ee929ff8bf44d75eaa6e7d974f7d128d8000b"
8521
8536
  },
8522
8537
  {
8523
8538
  "path": "modules/lifecycle/lifecycle.js",
@@ -9347,7 +9362,7 @@
9347
9362
  {
9348
9363
  "path": "modules/onboarding/genesis-home.js",
9349
9364
  "mode": "0000644",
9350
- "sha256": "a3ae0fb919c2ae4e081419cf5448fc731c553d28daf2d4847185016c9406e06c"
9365
+ "sha256": "77f9b217824e7cee4c652f08212cdd27e5d497dffd8cc0141f7e78b2337cb87d"
9351
9366
  },
9352
9367
  {
9353
9368
  "path": "modules/onboarding/howto-guide.js",
@@ -12322,12 +12337,12 @@
12322
12337
  {
12323
12338
  "path": "package-lock.json",
12324
12339
  "mode": "0000644",
12325
- "sha256": "3e98540a12076778a81f41e055028f600bcbf94c0c2a555adf002c69d2b72734"
12340
+ "sha256": "7e52b55eec543f27f482307f29f9cf49874ce77137f5a29eff3705f737147efd"
12326
12341
  },
12327
12342
  {
12328
12343
  "path": "package.json",
12329
12344
  "mode": "0000644",
12330
- "sha256": "158a3afd6782e3f28c2a49dd85e5fe3a83bb8debb3464a5d851c685fb36f53ba"
12345
+ "sha256": "13af5e2d8b0f4682ad0688f525c6d3c1cfe7c8962966c0bb8c4cc5df51118760"
12331
12346
  },
12332
12347
  {
12333
12348
  "path": "public-docs/index.html",
@@ -12347,7 +12362,7 @@
12347
12362
  {
12348
12363
  "path": "release-notes.json",
12349
12364
  "mode": "0000644",
12350
- "sha256": "6010acbd56137643326e0ecc314d93c9b097dd4cbff4cf9d801e4ce7a51acc67"
12365
+ "sha256": "e6698238d2808b5f90c1360c9e495538a7412ca4c97fd177b9d1ad33d6fed335"
12351
12366
  },
12352
12367
  {
12353
12368
  "path": "scripts/bongos/CLAUDE.md",
@@ -13327,7 +13342,7 @@
13327
13342
  {
13328
13343
  "path": "scripts/bongos/package-core.js",
13329
13344
  "mode": "0000644",
13330
- "sha256": "0a7dbbf17c298e491f118624636fa2fbd6e17562b740c311ce54e047086bf07a"
13345
+ "sha256": "a4b7f10de4674acfbcd6fb310c39b0e30d8ea4b4cdb81b4eeb0c5be05708ed1b"
13331
13346
  },
13332
13347
  {
13333
13348
  "path": "scripts/bongos/page-inventory.js",
@@ -16002,7 +16017,7 @@
16002
16017
  {
16003
16018
  "path": "src/bongos/module-scope-map.js",
16004
16019
  "mode": "0000644",
16005
- "sha256": "92b6ac609252f96e73acab6a9171cda465d36d75975ede79c96f13176e0d54ef"
16020
+ "sha256": "029f171c9fc25360996cdb397f61d3585642321faf0323d32954cbe22e496c76"
16006
16021
  },
16007
16022
  {
16008
16023
  "path": "src/bongos/module-store.js",
@@ -16357,7 +16372,7 @@
16357
16372
  {
16358
16373
  "path": "src/module-api.js",
16359
16374
  "mode": "0000644",
16360
- "sha256": "012ede63ed757a41e42926e2d3b0516e703aede0515a5140614882f16607d470"
16375
+ "sha256": "95f60fdf2c30bdf5576aecd5ebe3e05c0602447f74de995f7a5d520061c95d4a"
16361
16376
  },
16362
16377
  {
16363
16378
  "path": "src/module-loader/catalog.js",
@@ -17857,7 +17872,7 @@
17857
17872
  {
17858
17873
  "path": "tests/cutover_codemod.mjs",
17859
17874
  "mode": "0000644",
17860
- "sha256": "399bbfc621ea6bf6d2ace5010c0ef1993f95190faaf46d82a18827e1710758c2"
17875
+ "sha256": "a4a2e3307fb51ad7d7985b7304137f2005804152fb866e417fa365e91daf7ee3"
17861
17876
  },
17862
17877
  {
17863
17878
  "path": "tests/db_backup_nightly.mjs",
@@ -18362,7 +18377,12 @@
18362
18377
  {
18363
18378
  "path": "tests/front_door_guide_db.mjs",
18364
18379
  "mode": "0000644",
18365
- "sha256": "e5f04555dd7bf89159afe0bef0ea1bc98f3218b9643dff122dd847f5730a923c"
18380
+ "sha256": "2bb8fbda29cc530e19cb613df43fce3e566cb2e74f10978747dafe628a7b3278"
18381
+ },
18382
+ {
18383
+ "path": "tests/front_door_guide_existing.mjs",
18384
+ "mode": "0000644",
18385
+ "sha256": "efcc99771db5f09f487d305c12cedb3f1b572a9b7b11922a330c0a8c8b6e1f7f"
18366
18386
  },
18367
18387
  {
18368
18388
  "path": "tests/front_door_guide_plan.mjs",
@@ -18402,7 +18422,7 @@
18402
18422
  {
18403
18423
  "path": "tests/genesis_home.mjs",
18404
18424
  "mode": "0000644",
18405
- "sha256": "b09fc950add6cc7b919dbfe2bee8038d97cfeda64ca62972fbf7155978f2f4c4"
18425
+ "sha256": "d9061795648e5580618c33971f8dcba2c59d609c947fba87ef7a099e092f712e"
18406
18426
  },
18407
18427
  {
18408
18428
  "path": "tests/genesis_life_plates.mjs",
@@ -21087,7 +21107,7 @@
21087
21107
  {
21088
21108
  "path": "tests/package_core.mjs",
21089
21109
  "mode": "0000644",
21090
- "sha256": "4ce3ca6ee427db35708719d045042209c68d153301e2e61ab0ba46d4dba10f84"
21110
+ "sha256": "3195b78bb67142b698c55edaf7116e54136749c4d4cd583ae154abfcfb7896bd"
21091
21111
  },
21092
21112
  {
21093
21113
  "path": "tests/page_gate_second_door.mjs",
@@ -21852,7 +21872,7 @@
21852
21872
  {
21853
21873
  "path": "tests/pruned_lockfile_integrity.mjs",
21854
21874
  "mode": "0000644",
21855
- "sha256": "e6585a21c00446071682b7549087ddcff236b189f158d5e3129072806c5df5a0"
21875
+ "sha256": "773448a71918301361fbe62492bde091db05098c5db007991ea11a8a5628930a"
21856
21876
  },
21857
21877
  {
21858
21878
  "path": "tests/public_landing_projects.mjs",
@@ -22917,7 +22937,7 @@
22917
22937
  {
22918
22938
  "path": "tests/status_page_no_dead_uptime.mjs",
22919
22939
  "mode": "0000644",
22920
- "sha256": "3621920afeb31f3fbf0b9502d046c78ee3a88c73c6140975f13564565729a7ef"
22940
+ "sha256": "12fc7c212db47dc5481b30340c619dbd17f8719176068a503949318dd46444a1"
22921
22941
  },
22922
22942
  {
22923
22943
  "path": "tests/status_page_wording.mjs",
@@ -23032,7 +23052,7 @@
23032
23052
  {
23033
23053
  "path": "tests/task_lib.mjs",
23034
23054
  "mode": "0000644",
23035
- "sha256": "b375c05ab47e72ff1e59590f71214b33c455a7412b288a953be36a727d60e60f"
23055
+ "sha256": "fd8b046bd7a70e23ef902799bbf2f612ce9d26baebd1a6aa0bdf6c3fa2de26ec"
23036
23056
  },
23037
23057
  {
23038
23058
  "path": "tests/task_list_paging.mjs",
@@ -392,9 +392,9 @@ export interface PostFeedbackReceiptResponse { ok: boolean; receipt: unknown; hu
392
392
  export interface PostFoundingPlanRequest { days?: Record<string, unknown>; passes?: number; advisors?: string; government?: string; expected_builders?: number; existing?: boolean }
393
393
  export interface PostFrontDoorGuideConversationsIdAttachRequest { token: string }
394
394
  export interface PostFrontDoorGuideConversationsIdAttachResponse { ok: boolean; conversation: unknown }
395
- export interface PostFrontDoorGuideConversationsIdMessagesRequest { token: string; text: string; website?: string }
395
+ export interface PostFrontDoorGuideConversationsIdMessagesRequest { token: string; text: string; website?: string; starting_point?: string }
396
396
  export interface PostFrontDoorGuideConversationsIdPlanRequest { token: string; website?: string }
397
- export interface PostFrontDoorGuideConversationsRequest { website?: string }
397
+ export interface PostFrontDoorGuideConversationsRequest { website?: string; starting_point?: string }
398
398
  export interface PostGithubRepoInviteRequest { github_login: string; permission?: string }
399
399
  export interface PostGithubRepoVisibilityRequest { repo: string; visibility: "public" | "private" }
400
400
  export interface PostGithubRepoVisibilityResponse { ok: boolean; repo: unknown; private_deployable: boolean }
@@ -1,6 +1,6 @@
1
1
  # ADR 0328 — A hosted project's authority is its membership row, not its owner column
2
2
 
3
- - **Status:** accepted. **Amended 2026-10-16:** Phase 2 (admitting `member`) is suspended because a `member` row is written at every hub sign-in and is not a grant from the project. The gate stays owner-or-archon. See the *Amendment* at the end ([task 1004754](https://cloudbongos.com/builders#/task/1004754)).
3
+ - **Status:** accepted. **Amended 2026-10-16:** Phase 2 (admitting `member`) is suspended because a `member` row is written at every hub sign-in and is not a grant from the project. The gate stays owner-or-archon. See the *Amendment* at the end ([task 1004754](https://cloudbongos.com/builders#/task/1004754)). **Phase 2 is replaced by [ADR 0407](0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md)** (accepted by the owner 2026-11-13): an owner-made grant row in provisioning, never a membership row.
4
4
  - **Date:** 2026-09-22
5
5
  - **Task:** [task 1003882](https://cloudbongos.com/builders#/task/1003882) (goal 1000094 — BONGOS-V2)
6
6
  - **Deciders:** the scoping call — "every API action must name its project; a non-member may only apply" — is the owner's, recorded 2026-09-13 on the task. This ADR is the mechanism that carries it out: where the underlying membership data already lives, what a route must call to consult it, and what a non-member is told.
@@ -0,0 +1,124 @@
1
+ # ADR 0407 — A hosted project's grant is made by its owner, not witnessed at sign-in
2
+
3
+ - **Status:** accepted — the owner accepted this design as written on 2026-11-13, including its three answers below (no archon-made grants; `operate` = reads, the variable-name list and restart; the sign-in default stays `member`). Design only: nothing here widens a gate. The gate stays owner-or-archon until [task 1004161](https://cloudbongos.com/builders#/task/1004161) builds what is written here.
4
+ - **Date:** 2026-11-13
5
+ - **Task:** [task 1004753](https://cloudbongos.com/builders#/task/1004753) (goal 1000106, check `wa1-members-owner-granted`)
6
+ - **Amends:** [ADR 0328](0328-a-hosted-projects-authority-is-its-membership-row-not-its-owner-column.md) — replaces its suspended Phase 2 and re-states its Decision 3 (what a refused caller is told).
7
+ - **Follow-on tasks (updated 2026-11-13, in the task records):** [task 1004161](https://cloudbongos.com/builders#/task/1004161) is rewritten to build §§1–4 and the attack tests, and is taken off hold with an explicit promote the moment this task lands (promote refuses while this task is unshipped, and nothing else clears a park); [task 1004162](https://cloudbongos.com/builders#/task/1004162) is re-checked against §6 (a third refusal, and it now owns the membership port).
8
+ - **Related:** [ADR 0016](0016-trust-boundary-server-enforced-permissions.md) (authority is read live from the database on every request), [ADR 0083](0083-modular-architecture-strangler-build-plan.md) (modules cooperate through ports), [ADR 0141](<redacted>.md) / [0205](0205-federated-checkin-needs-the-hubs-own-signin-witness.md) (the sign-in witness), [ADR 0151](0151-governance-permissions-as-atom-ranks-as-roles.md) §3 (the ownership axis), [ADR 0176](0176-private-repo-deploy-keys.md) / task 1004194 (repo-private stays owner-only because it uses the owner's GitHub token).
9
+
10
+ ## Context
11
+
12
+ ADR 0328 Phase 2 would have admitted a `member` row of `<redacted>` onto the hosted-project routes. Its 2026-10-16 amendment suspended that, and every fact behind the suspension was re-checked against the code for this ADR (2026-11-13):
13
+
14
+ - `recordFederatedSignin` (`modules/platform-identity/platform-identity.js`) inserts `membership_kind = 'member'` with `signin_verified_at = now()` on every completed hub sign-in, and turns a `pending` row into `member`. Its own comment calls it "the only way a membership row is born".
15
+ - It is called from `POST /sso/token` and `POST /sso/device/poll` (`modules/platform-identity/routes/sso.js`). `POST /sso/device/start` takes only a typed `origin` and no session; it refuses only an unknown, inactive or secretless client. So any GitHub user can get a witnessed `member` row on any credentialed project, and the project's own server is never asked.
16
+ - `POST /sso/membership/check-in` (`touchMembership`) lets the **project's server** set any kind, `owner` included, on a row that already has a sign-in witness. On the instance side, `membershipKind` (`src/bongos/auth-admission.js`) reports `owner` for the first admin and `member` for everyone else, and with `admission.policy: open` that is every GitHub sign-up.
17
+
18
+ So no value of `membership_kind` means "the owner trusts this person with the hosting". `member` means "has signed in here"; `owner` means "this project's server says so". Neither is a fact the hub itself decided.
19
+
20
+ **What the gate guards today.** `requireProjectOwner` (`modules/provisioning/route-helpers.js`, task 1004159) admits the row's `owner_builder_id`, or a caller whose live rank is `archon`; everyone else gets `404 instance_not_found`. It is mounted on 14 routes. The task's "14 routes" is accurate for that helper, but **28 routes** take a hosted project's `:id`. The other 14 check inline or by permission:
21
+
22
+ | Gate today | Routes |
23
+ |---|---|
24
+ | `requireProjectOwner` (owner or archon) — 14 | `GET …/:id`; `PATCH …/:id/detail`; `GET …/:id/invite-suggestions`; `GET`/`PATCH …/:id/settings`; `POST …/:id/teardown`; `POST …/:id/restart`; `POST …/:id/domain`; `POST …/:id/github-app` (all `routes/provisioning.js`); `POST …/:id/disconnect` (`routes/disconnect.js`); `GET`/`POST …/:id/env-manifest`, `PATCH`/`DELETE …/:id/env-manifest/:varId` (`routes/env-manifest.js`) |
25
+ | inline, owner or archon — 4 | `GET`/`PATCH …/:id/look`, `PUT`/`DELETE …/:id/logo` (`routes/look.js`) |
26
+ | inline, owner only — 6 | `POST …/:id/demo` (`routes/demo.js`); `POST …/:id/github-app/pick-up` (`routes/github-setup.js`); `GET`/`POST …/:id/render` (`routes/render-standup.js`); `POST …/:id/repo-private` (`routes/repo-private.js`) |
27
+ | owner or `core.pin.move` — 3 | `GET`/`POST …/:id/core-upgrade`, `POST …/:id/update-channel` (`routes/core-upgrade.js`) |
28
+ | `provisioning.fleet.manage` only — 2 | `POST …/:id/force-teardown`; `POST …/:id/update-subscription` |
29
+
30
+ ## Decision
31
+
32
+ ### 1. The grant is its own row, in the provisioning module, with one writer
33
+
34
+ A new table, `provisioning_project_grants` (migration `<redacted>.sql`, additive, in the module's own namespace):
35
+
36
+ | Column | Meaning |
37
+ |---|---|
38
+ | `id` | bigint identity |
39
+ | `instance_id` | `provisioning_instances.id`, `ON DELETE CASCADE` (disconnect deletes the row, so its grants go with it) |
40
+ | `grantee_builder_id` | the hub `builders.id` of the person granted — the same key as `owner_builder_id`, so the gate compares like with like |
41
+ | `level` | `text NOT NULL CHECK (level IN ('operate'))` — one level today (§3); a second level is an ADR amendment, never a free string |
42
+ | `granted_by_builder_id`, `granted_at` | who made it, when |
43
+ | `revoked_at`, `revoked_by_builder_id` | null while live; a revoke is a stamp, never a delete, so the record survives |
44
+
45
+ A partial unique index on `(instance_id, grantee_builder_id) WHERE revoked_at IS NULL` allows one live grant per person per project; re-granting after a revoke makes a new row.
46
+
47
+ **The single writer** is a new file `modules/provisioning/grants.js` (`grantProjectAccess`, `revokeProjectAccess`, `liveGrant`), called only by the grant routes in §2. Nothing else may insert or update the table; a test greps for any other `INSERT INTO provisioning_project_grants` / `UPDATE provisioning_project_grants`.
48
+
49
+ **Why here and not in `<redacted>`.** ADR 0328 rejected a separate provisioning table because a second copy of membership would drift. That reason is gone: the membership table does not hold grants, and its writers (sign-in, check-in, invites) are exactly the paths that must never create one. Keeping the grant beside `owner_builder_id` also means the gate reads both facts in one query in the module that owns them, with no cross-module port in the admission path, so "the port is down" can never decide who gets in.
50
+
51
+ ### 2. Who may make and remove a grant
52
+
53
+ - **Create — the project's owner only, from their own hub session.** `POST /provisioning/instances/:id/grants { github_login }`, gated `requireBuilder` + `requireProjectOwner(loadInstance, { archonOverride: false })`. The login is resolved **server-side** to an existing, active hub builder; no such builder → `404 grantee_not_found` ("they need to sign in to the hub once first"). The reply names the person found (display name and picture), because a GitHub login can change hands. The owner cannot grant themselves. At most 25 live grants per project (`409 grant_limit`).
54
+ - **An archon cannot create a grant** on someone else's project. An archon already has fleet-support reach through the override; a grant would let them hand an owner's project to a third person without the owner, and in doubt we refuse. (Owner choice — see *Open questions*.)
55
+ - **Revoke** — `DELETE /provisioning/instances/:id/grants/:grantId`: the owner; the grantee themselves (leaving); or an archon. A revoke only ever removes access, so the archon door is a safety lever, not a widening.
56
+ - **List** — `GET /provisioning/instances/:id/grants`: owner or archon (the existing gate). A grantee sees their own grant on the project read, not the list.
57
+
58
+ **How the hub learns of the grant without trusting the visitor:** it does not learn it from anyone. The row is born on the hub from the owner's authenticated session, checked against `owner_builder_id` on the hub's own database. Nothing the visitor sends, nothing a project's server reports at check-in, and no sign-in can create, change or extend it. The gate never reads `<redacted>` to admit anyone.
59
+
60
+ ### 3. What a grantee may do — a short allow-list, opt-in per route
61
+
62
+ The one level, `operate`, is "help keep it running": look at the project and restart it, and maintain the list of environment variable names. Everything that changes what the project *is*, who can see it, where it lives, or that acts with the owner's own accounts stays owner-only.
63
+
64
+ | Route | Grantee (`operate`) |
65
+ |---|---|
66
+ | `GET …/:id` | ✅ read — the projection drops `owner_monthly_usd` (the owner's own bill) and `github_install` (an action on the owner's GitHub) |
67
+ | `GET …/:id/settings` | ✅ read |
68
+ | `GET …/:id/env-manifest` | ✅ read — names and purposes only; the platform holds no values (ADR 0323 §6) |
69
+ | `POST …/:id/env-manifest`, `PATCH`/`DELETE …/:id/env-manifest/:varId` | ✅ write — declaring a variable name changes no running behaviour; the manifest exists for builder sessions to read and keep current |
70
+ | `POST …/:id/restart` | ✅ write — recovers a stuck project; changes no data, costs nothing |
71
+ | `teardown`, `disconnect`, `domain`, `github-app`, `github-app/pick-up`, `repo-private`, `render` (GET and POST), `demo` | ❌ owner only (plus the archon override where it exists today). Teardown and disconnect destroy; domain moves the address; github-app, pick-up, repo-private and render act with the owner's own GitHub or Render account |
72
+ | `PATCH …/:id/settings`, `PATCH …/:id/detail`, look and logo (4) | ❌ owner only — who can see and join the project, and how it presents itself, is the owner's call |
73
+ | `GET …/:id/invite-suggestions` | ❌ owner only — inviting is the owner's lever |
74
+ | `core-upgrade` (2), `update-channel` | ❌ unchanged (owner or `core.pin.move`) |
75
+ | `force-teardown`, `update-subscription` | ❌ unchanged (fleet permission) |
76
+ | the grant routes (§2) | ❌ except a grantee revoking their own grant |
77
+
78
+ **Mechanism — opt-in, never default.** `requireProjectOwner` gains one option, `{ grantee: 'operate' }`. Without it (every route today, and every route added later) a grant admits nothing. With it, the gate admits the owner, then a live `operate` grant for `req.builder.id`, then the archon override, in that order, and sets `req.projectDoor` to `owner` · `grantee` · `archon`. The grant is read inside the gate on every request (no caching, ADR 0016), so a revoke takes effect on the grantee's next request. A failed grant read **denies** — the gate's existing `failFrom(res, err, 'instance_read_failed')`, never a fall-through to "admit". The inline-gated routes are not converted by this design; they stay owner-only by not having the option.
79
+
80
+ ### 4. The audit actor
81
+
82
+ `projectActor(req)` reads `req.projectDoor`: `api:self` (owner), `api:grantee:<builderId>` (grantee), `api:archon:<builderId>` (archon override). A grantee who is also an archon is recorded as `grantee`, because the owner's grant is what let them in. The grant routes write `provisioning_events` rows `grant-made` and `grant-revoked`, whose `detail` names the grantee's builder id and level; their actor is the same three-way label (a grantee leaving is `api:grantee:<id>`).
83
+
84
+ ### 5. The hub's sign-in default stays `member`
85
+
86
+ The task asked whether sign-in should stop writing `member`. **This design keeps it**, because once nothing grants on it, the word carries no authority, and changing it reaches three working features for no security gain:
87
+
88
+ - *My Projects* (`listMembershipsForAccount`) lists every non-`pending` row; a `visitor` default would still list them, but would make the existing project list say "visitor" for people who genuinely build there.
89
+ - The activity-rollup precheck (`membershipBacksRollup`) accepts any witnessed non-`pending` row; unchanged either way.
90
+ - Invites turn `pending` into `member` at sign-in; a `visitor` default would need its own rule for accepted invites.
91
+
92
+ The word is documented as "has signed in here" (ADR 0328's amendment already says so). If the owner later wants the label changed for clarity, that is its own task, not a security fix.
93
+
94
+ ### 6. What a refused caller is told (replaces ADR 0328 Decision 3; task 1004162)
95
+
96
+ - **No grant and no membership row** → `404 instance_not_found`, as today. A stranger learns nothing.
97
+ - **Not yet a member of the project** (a `visitor` or `pending` row, no grant) → `403 project_membership_required` with the apply path, as task 1004162 already specifies: a `visitor` is pointed to `POST /my-projects/join` (the shipped ADR 0141 / 0201 / 0247 join flow); a `pending` row is told their request is already on file and the owner decides. The message also says that managing the hosting is something the owner gives separately, so joining is not mistaken for that.
98
+ - **A member of the project (a `member` or `owner` kind row) without a grant** → `403 project_access_required`: "Only the project's owner, and people the owner has given access, can manage its hosting. Ask the owner to give you access." There is no self-serve request for hosting access.
99
+ - **How the row is read.** Through a port, `platform-identity.projectMembershipKind` as ADR 0328 named it, and only after the gate has already refused. If the port is unregistered, throws, or answers an unknown value, the answer is the `404`: on doubt, say less. This read only picks the wording of a refusal and can never admit anyone.
100
+ - **A grantee on a route without the opt-in** → `403 owner_only`, "Only the project's owner can do this." They already know the project exists.
101
+
102
+ ## Consequences
103
+
104
+ - A team can share one hosted project's day-to-day running, once task 1004161 lands, without the owner handing over teardown, the address or their own accounts.
105
+ - The device-flow attack in the task is closed by construction: running the device flow writes a membership row, and nothing reads that row to admit. Task 1004161's tests must show a GitHub user who only ran the device flow is refused on **all 28** routes, with a member row present.
106
+ - One new table, one new file, three routes, and one gate option. One extra indexed read per request on the 7 opt-in routes, only when the caller is not the owner.
107
+ - An owner can lock themselves out of nothing: a grantee can never revoke the owner, change the owner, or make grants.
108
+ - **Ownership transfer** has no route today. Whatever adds one must decide what happens to live grants; this ADR does not.
109
+ - The owner needs a place to give access. Task 1004161 builds the API and gate; the manage page's "People with access" card may be split into its own task at claim time, but the grant is not usable by a non-technical owner until it exists.
110
+
111
+ ## Alternatives considered
112
+
113
+ - **Admit `member` rows that a project's check-in reported** (ADR 0328 Phase 2). Rejected: the sign-in default is `member`, and check-in is the project's own word, which on an open project is every sign-up.
114
+ - **A `granted` kind inside `<redacted>`.** Rejected: that table's writers include check-in, which can set any kind; a grant must have one writer and no outside reporter.
115
+ - **Let an archon make grants.** Rejected for now (doubt → refuse); the owner can ask for it.
116
+ - **One grant level that admits every route the archon override admits.** Rejected: it would hand teardown and disconnect to anyone the owner added for a restart.
117
+ - **A self-serve "request hosting access" queue.** Not built: it adds a new inbox and a new notification for a request a person can simply make to the owner.
118
+
119
+ ## Owner decisions (2026-11-13)
120
+
121
+ 1. The design is accepted as written.
122
+ 2. An archon may not give access on someone else's project (§2).
123
+ 3. A grantee's level, `operate`, is the project read, the settings read, the variable-name list and restart (§3).
124
+ 4. Separately, the owner ruled that who may open a project's pages at all is chosen by its founders during genesis, not fixed by a platform default. That is outside this ADR (it is the project's page door, not its hosting) and is filed as an idea for the genesis work.
@@ -522,3 +522,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
522
522
  | 0404 | [**A party is a room, and rooms register as kinds** ([task 1005220](https://cloudbongos.com/builders#/task/1005220), goal 1000148). Any group that talks together is a room: a free-form party (cap 8), a chain party (ADR 0400), a scoping session (cap 40, owned by `lifecycle`) or a decision room (cap 40, `government`). Each owner contributes its kind to the `room.kinds` contribution point (a port is single-provider, so four owners would fail the boot) with `members`/`isMember`/optional `invite`/`accept`, and fires `room.opened`/`room.member.joined`/`room.member.left`/`room.closed`; consumers never read an owner's tables and reconcile against `members()`. Free-form party: one per builder, leader handover to the longest-standing member, disband on last leave. A chain room follows an open `chain_party` row. Unlinked players get everything but voice. V3 polls (3 s, cursor + 304, paused when hidden, per-builder limiter) rather than pushing through `/live`. With discord off, no voice key or voice state; chat still works. A room is never authority. Rejected: one port, a port per kind, a rooms module reading other modules' tables, a second party roster, push via `/live`, speaking indicators.](0404-a-party-is-a-room-and-rooms-register-as-kinds.md) | game frame / modules / Discord |
523
523
  | 0405 | [**Each character has one colour, and the visor wears it** ([task 1005218](https://cloudbongos.com/builders#/task/1005218), goal 1000142; owner 2026-11-12). The Artisan is ember (the accent), the Artist violet, the Patron gold, each mixed from the hall’s tokens and none typed in. In game mode the visor’s lines, name, picture rim and accent are the held character’s colour, and your picture on the glass is your character wearing the visor. The characters are redrawn at 64 by 64 as two-animal aliens, drawn by a script.](0405-each-character-has-one-colour-and-the-visor-wears-it.md) | hall / game frame |
524
524
  | 0406 | [**Every project gets a sandbox that follows main, and live moves only when a person promotes** ([task 1005288](https://cloudbongos.com/builders#/task/1005288), goal 1000106; owner 2026-11-13). One repository, no sandbox branch: a second Render web service on the free plan auto-deploys every landing on `main`, and the live service stops auto-deploying and takes only the commit a person promotes (with the Render key typed in for that request). Fake data and test keys by default; lent real keys should be read-only, behind an outbound gate that refuses sends, charges and writes. Render's free database expires in 30 days, so the sandbox gets a second database in the app's paid one. A project with no app gets no hosted sandbox; Cloud Bongos runs the same rule over its release pin.](0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md) | provisioning / hosting |
525
+ | 0407 | [**A hosted project's grant is made by its owner, not witnessed at sign-in** ([task 1004753](https://cloudbongos.com/builders#/task/1004753), goal 1000106; accepted by the owner 2026-11-13). Replaces ADR 0328's suspended Phase 2: no `membership_kind` admits anyone, because sign-in writes `member` for any GitHub user (the device flow included) and check-in is the project's own word. A new `provisioning_project_grants` row, one writer (`grants.js`), created only by the project's owner from their hub session (no archon create; owner, grantee or archon may revoke), read live in `requireProjectOwner` on routes that opt in with `{ grantee: 'operate' }`: the project read, settings read, env-manifest (names only) and restart. Teardown, disconnect, domain, the GitHub/Render/repo-private actions, settings and look writes stay owner-only. Audit actor `api:grantee:<id>`. The sign-in default stays `member`. A visitor or pending applicant gets 403 `project_membership_required` with the join path; a member without a grant gets 403 `project_access_required` (ask the owner); a stranger keeps the 404.](0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md) | provisioning / permissions |
@@ -38424,6 +38424,9 @@
38424
38424
  "website": {
38425
38425
  "type": "string",
38426
38426
  "maxLength": 500
38427
+ },
38428
+ "starting_point": {
38429
+ "type": "string"
38427
38430
  }
38428
38431
  },
38429
38432
  "required": [
@@ -38455,6 +38458,9 @@
38455
38458
  "website": {
38456
38459
  "type": "string",
38457
38460
  "maxLength": 500
38461
+ },
38462
+ "starting_point": {
38463
+ "type": "string"
38458
38464
  }
38459
38465
  },
38460
38466
  "additionalProperties": false
@@ -332,10 +332,10 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
332
332
 
333
333
  | Method | Path | Rank | Body | Description |
334
334
  |---|---|---|---|---|
335
- | POST | `/api/bongos/front-door-guide/conversations` | `public` | `website` | start a chat. |
335
+ | POST | `/api/bongos/front-door-guide/conversations` | `public` | `website`, `starting_point` | start a chat. |
336
336
  | GET | `/api/bongos/front-door-guide/conversations/:id` | `public` | — | the transcript, for the plan and the sign-up hand-off. |
337
337
  | POST | `/api/bongos/front-door-guide/conversations/:id/attach` | `any-builder` | `token` | the visitor has just signed in; the chat moves onto their account. |
338
- | POST | `/api/bongos/front-door-guide/conversations/:id/messages` | `public` | `token`, `text`, `website` | one visitor message, one guide reply. |
338
+ | POST | `/api/bongos/front-door-guide/conversations/:id/messages` | `public` | `token`, `text`, `website`, `starting_point` | one visitor message, one guide reply. |
339
339
  | POST | `/api/bongos/front-door-guide/conversations/:id/plan` | `public` | `token`, `website` | the visitor has no account yet. |
340
340
  | GET | `/api/bongos/front-door-guide/mine` | `any-builder` | — | my newest chat and plan (the creation wizard's pre-fill reads it). |
341
341
  | GET | `/api/bongos/front-door-guide/status` | `public` | — | the landing asks before it offers the chat. |