@bongos/core 1.25.11 → 1.25.13
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 +120 -30
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +16 -0
- package/clients/bongos-client/index.cjs +16 -0
- package/clients/bongos-client/index.d.ts +22 -0
- package/clients/bongos-client/index.mjs +16 -0
- package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +108 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +376 -3
- package/docs/api-reference.md +13 -1
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +4 -0
- package/modules/front-door-guide/CLAUDE.md +15 -0
- package/modules/front-door-guide/claude.js +55 -0
- package/modules/front-door-guide/context.js +54 -0
- package/modules/front-door-guide/db.js +137 -0
- package/modules/front-door-guide/guide.js +148 -0
- package/modules/front-door-guide/limits.js +87 -0
- package/modules/front-door-guide/migrations/front_door_guide_001_conversations.sql +48 -0
- package/modules/front-door-guide/migrations/front_door_guide_002_plan_and_account.sql +37 -0
- package/modules/front-door-guide/module.json +31 -0
- package/modules/front-door-guide/plan.js +93 -0
- package/modules/front-door-guide/pollers/retention-sweep.js +67 -0
- package/modules/front-door-guide/routes/front-door-guide-plan.js +144 -0
- package/modules/front-door-guide/routes/front-door-guide.js +196 -0
- package/modules/front-door-guide/settings.js +72 -0
- package/modules/provisioning/module.json +2 -1
- package/modules/provisioning/seams.js +10 -0
- package/modules/provisioning/starter-bundles.js +3 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/bongos/publish-manifest.js +1 -0
- package/scripts/bongos/run-unit-tests.js +4 -0
- package/src/bongos/module-scope-map.js +6 -0
- package/src/module-api.js +1 -1
- package/tests/front_door_guide.mjs +410 -0
- package/tests/front_door_guide_db.mjs +110 -0
- package/tests/front_door_guide_plan.mjs +344 -0
- package/tests/module_loader.mjs +1 -1
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.
|
|
6
|
-
"core_contract": "1.25.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.25.13",
|
|
6
|
+
"core_contract": "1.25.13",
|
|
7
|
+
"source_commit": "6144401eb07488528be2d4c98786f479a900c9d0",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-11-
|
|
9
|
+
"built_at": "2026-11-13T19:37:53.952Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
13
|
-
"agent_docs_stubbed":
|
|
14
|
-
"functional_verbatim":
|
|
12
|
+
"docs_redacted": 656,
|
|
13
|
+
"agent_docs_stubbed": 33,
|
|
14
|
+
"functional_verbatim": 4016,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 4706,
|
|
20
|
+
"tree_sha256": "fbec1349dacd426f02d295f9f37bf8e36691d86d3ba8c9d5df7f9c70123dc2e7",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -332,12 +332,12 @@
|
|
|
332
332
|
{
|
|
333
333
|
"path": "clients/bongos-client/README.md",
|
|
334
334
|
"mode": "0000644",
|
|
335
|
-
"sha256": "
|
|
335
|
+
"sha256": "443db1b62f84147c42bcbc1d2556e47f90925c2e1fe67107193101ae611d69f4"
|
|
336
336
|
},
|
|
337
337
|
{
|
|
338
338
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
339
339
|
"mode": "0000644",
|
|
340
|
-
"sha256": "
|
|
340
|
+
"sha256": "701b55ca742af38e1fd644a11fc550c992b4c243621a3a66b8b303d988f9bef5"
|
|
341
341
|
},
|
|
342
342
|
{
|
|
343
343
|
"path": "clients/bongos-client/examples/hello-world.mjs",
|
|
@@ -347,17 +347,17 @@
|
|
|
347
347
|
{
|
|
348
348
|
"path": "clients/bongos-client/index.cjs",
|
|
349
349
|
"mode": "0000644",
|
|
350
|
-
"sha256": "
|
|
350
|
+
"sha256": "01eec68e5292a12cb58ddc22e78893c0dd1ef374c4949d8f58486cd86ba3809c"
|
|
351
351
|
},
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/index.d.ts",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "72b35b37e40d677c4f0b3df0fbc69c7bc062daeac97fd71b67e9a463af24fadb"
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
"path": "clients/bongos-client/index.mjs",
|
|
359
359
|
"mode": "0000644",
|
|
360
|
-
"sha256": "
|
|
360
|
+
"sha256": "603986b89a0e4030b3ce590f47d2d2f99e994ca3b596c58a117cb2c08d37f558"
|
|
361
361
|
},
|
|
362
362
|
{
|
|
363
363
|
"path": "clients/bongos-client/package.json",
|
|
@@ -2489,20 +2489,25 @@
|
|
|
2489
2489
|
"mode": "0000644",
|
|
2490
2490
|
"sha256": "1d8b8c6782ca394e6f85072355140136eff97e1a26ace0fcf392f1206b7a77ec"
|
|
2491
2491
|
},
|
|
2492
|
+
{
|
|
2493
|
+
"path": "docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md",
|
|
2494
|
+
"mode": "0000644",
|
|
2495
|
+
"sha256": "aedd6b7dc8ba2955c48d44dd6d7ee24b42219b22ef034db1f1b27e23bc04f30c"
|
|
2496
|
+
},
|
|
2492
2497
|
{
|
|
2493
2498
|
"path": "docs/adr/README.md",
|
|
2494
2499
|
"mode": "0000644",
|
|
2495
|
-
"sha256": "
|
|
2500
|
+
"sha256": "50221b2eb63f103558dfce9e164cf2a25ea60cfbc4171d8f23d8db72ca08be97"
|
|
2496
2501
|
},
|
|
2497
2502
|
{
|
|
2498
2503
|
"path": "docs/api-reference.md",
|
|
2499
2504
|
"mode": "0000644",
|
|
2500
|
-
"sha256": "
|
|
2505
|
+
"sha256": "956db8f10f4503ccaedbfe94b50449bdffbb70fd8fdb1aae7397b9973e62c84f"
|
|
2501
2506
|
},
|
|
2502
2507
|
{
|
|
2503
2508
|
"path": "docs/api/openapi.json",
|
|
2504
2509
|
"mode": "0000644",
|
|
2505
|
-
"sha256": "
|
|
2510
|
+
"sha256": "b60a213d5657260a2e12a85eb83e364722e954cb2c39730c6a596433a7d73126"
|
|
2506
2511
|
},
|
|
2507
2512
|
{
|
|
2508
2513
|
"path": "docs/architecture.md",
|
|
@@ -3077,7 +3082,7 @@
|
|
|
3077
3082
|
{
|
|
3078
3083
|
"path": "docs/file-map.md",
|
|
3079
3084
|
"mode": "0000644",
|
|
3080
|
-
"sha256": "
|
|
3085
|
+
"sha256": "0d82688dbf0f4b2fb85eaabe58972e9fedc7579c933e83ce431624567099ff36"
|
|
3081
3086
|
},
|
|
3082
3087
|
{
|
|
3083
3088
|
"path": "docs/handoff-template.md",
|
|
@@ -3087,7 +3092,7 @@
|
|
|
3087
3092
|
{
|
|
3088
3093
|
"path": "docs/module-api-changelog.md",
|
|
3089
3094
|
"mode": "0000644",
|
|
3090
|
-
"sha256": "
|
|
3095
|
+
"sha256": "0ddc252d589300b4d36f14e8c24f5133e17da786060a2c7ae7b50c7caa77e86e"
|
|
3091
3096
|
},
|
|
3092
3097
|
{
|
|
3093
3098
|
"path": "docs/modules-contract.md",
|
|
@@ -5514,6 +5519,76 @@
|
|
|
5514
5519
|
"mode": "0000644",
|
|
5515
5520
|
"sha256": "065588e708b12864390aa4a3453f648556f3c2f9547952a9b0eb69be9cf37c2f"
|
|
5516
5521
|
},
|
|
5522
|
+
{
|
|
5523
|
+
"path": "modules/front-door-guide/CLAUDE.md",
|
|
5524
|
+
"mode": "0000644",
|
|
5525
|
+
"sha256": "7cb9dac9cb87b679e1ae50e4112b3a7928a38ebb9902c8947a74d17bec4d9009"
|
|
5526
|
+
},
|
|
5527
|
+
{
|
|
5528
|
+
"path": "modules/front-door-guide/claude.js",
|
|
5529
|
+
"mode": "0000644",
|
|
5530
|
+
"sha256": "789c754572ea1183ea276f66e202192d1ccf3032d4661d3d5e572de41ce5a3c9"
|
|
5531
|
+
},
|
|
5532
|
+
{
|
|
5533
|
+
"path": "modules/front-door-guide/context.js",
|
|
5534
|
+
"mode": "0000644",
|
|
5535
|
+
"sha256": "81c10bc4e96f603416cab0c8bb6af3c204b136d67ab7f01fede558de39c06c0c"
|
|
5536
|
+
},
|
|
5537
|
+
{
|
|
5538
|
+
"path": "modules/front-door-guide/db.js",
|
|
5539
|
+
"mode": "0000644",
|
|
5540
|
+
"sha256": "1bbe4f1605e1e8cc6daa6d32150e7cd32cb28df5f527f88b8d36a0d6b6dcc1fc"
|
|
5541
|
+
},
|
|
5542
|
+
{
|
|
5543
|
+
"path": "modules/front-door-guide/guide.js",
|
|
5544
|
+
"mode": "0000644",
|
|
5545
|
+
"sha256": "590a26cd79ce41f84fa29635da0e63fc682db3653fdebeb9ba0e834a6fa4062c"
|
|
5546
|
+
},
|
|
5547
|
+
{
|
|
5548
|
+
"path": "modules/front-door-guide/limits.js",
|
|
5549
|
+
"mode": "0000644",
|
|
5550
|
+
"sha256": "b8819228f1246bbeabb04612f1a6722ea29e63e12a371300f45e421a596b33c7"
|
|
5551
|
+
},
|
|
5552
|
+
{
|
|
5553
|
+
"path": "modules/front-door-guide/migrations/front_door_guide_001_conversations.sql",
|
|
5554
|
+
"mode": "0000644",
|
|
5555
|
+
"sha256": "aad5ccdcfcdc275e5f3448d9e90c4982d5f382fb1e4d015c4709ddb4354837a7"
|
|
5556
|
+
},
|
|
5557
|
+
{
|
|
5558
|
+
"path": "modules/front-door-guide/migrations/front_door_guide_002_plan_and_account.sql",
|
|
5559
|
+
"mode": "0000644",
|
|
5560
|
+
"sha256": "632ea54bd430c2d143da7323ad848f28a1c53ac0735850d04cd6177b10c9c857"
|
|
5561
|
+
},
|
|
5562
|
+
{
|
|
5563
|
+
"path": "modules/front-door-guide/module.json",
|
|
5564
|
+
"mode": "0000644",
|
|
5565
|
+
"sha256": "de486a674d919fed27a3356dade38e29c14dc2a0efa45eb4f9013fdeb17cd326"
|
|
5566
|
+
},
|
|
5567
|
+
{
|
|
5568
|
+
"path": "modules/front-door-guide/plan.js",
|
|
5569
|
+
"mode": "0000644",
|
|
5570
|
+
"sha256": "6da0d0b8c41c9a8b8fbffacbbc85cffe1e7c61853f847fb2ac72b0ec77ae0460"
|
|
5571
|
+
},
|
|
5572
|
+
{
|
|
5573
|
+
"path": "modules/front-door-guide/pollers/retention-sweep.js",
|
|
5574
|
+
"mode": "0000644",
|
|
5575
|
+
"sha256": "12c973f96f276c3552e6d4137fe29d39e1319286418f9f81231a2661da663209"
|
|
5576
|
+
},
|
|
5577
|
+
{
|
|
5578
|
+
"path": "modules/front-door-guide/routes/front-door-guide-plan.js",
|
|
5579
|
+
"mode": "0000644",
|
|
5580
|
+
"sha256": "58cee518fe51190f7d4105b82d199f5868b6a0fd8747c9212a0e83bed435ac06"
|
|
5581
|
+
},
|
|
5582
|
+
{
|
|
5583
|
+
"path": "modules/front-door-guide/routes/front-door-guide.js",
|
|
5584
|
+
"mode": "0000644",
|
|
5585
|
+
"sha256": "f53fd28640999a4ab2868010b7502712fb9b82d70a043d5f97aa916bd603b9e8"
|
|
5586
|
+
},
|
|
5587
|
+
{
|
|
5588
|
+
"path": "modules/front-door-guide/settings.js",
|
|
5589
|
+
"mode": "0000644",
|
|
5590
|
+
"sha256": "fc0726ff9e1e0f2be291d8af37ff2ac1f36735c7dcf376bf9c4c201e2db35e6e"
|
|
5591
|
+
},
|
|
5517
5592
|
{
|
|
5518
5593
|
"path": "modules/government/CLAUDE.md",
|
|
5519
5594
|
"mode": "0000644",
|
|
@@ -10152,7 +10227,7 @@
|
|
|
10152
10227
|
{
|
|
10153
10228
|
"path": "modules/provisioning/module.json",
|
|
10154
10229
|
"mode": "0000644",
|
|
10155
|
-
"sha256": "
|
|
10230
|
+
"sha256": "535232bcf3691956bd0e34386da934b23f25889334dcad16c3f2983e2104b6ad"
|
|
10156
10231
|
},
|
|
10157
10232
|
{
|
|
10158
10233
|
"path": "modules/provisioning/onboard-plan.js",
|
|
@@ -10307,7 +10382,7 @@
|
|
|
10307
10382
|
{
|
|
10308
10383
|
"path": "modules/provisioning/seams.js",
|
|
10309
10384
|
"mode": "0000644",
|
|
10310
|
-
"sha256": "
|
|
10385
|
+
"sha256": "26168956a1c30dcb6192d2c0f4865ab3bc02fe89eb4551b82a66069027e8f473"
|
|
10311
10386
|
},
|
|
10312
10387
|
{
|
|
10313
10388
|
"path": "modules/provisioning/settings-push.js",
|
|
@@ -10322,7 +10397,7 @@
|
|
|
10322
10397
|
{
|
|
10323
10398
|
"path": "modules/provisioning/starter-bundles.js",
|
|
10324
10399
|
"mode": "0000644",
|
|
10325
|
-
"sha256": "
|
|
10400
|
+
"sha256": "7b7f866a439b873f28f6ae6667964eb98c886d02ff1ffcc51067aaf2ef5a4cbb"
|
|
10326
10401
|
},
|
|
10327
10402
|
{
|
|
10328
10403
|
"path": "modules/provisioning/terms-ack.js",
|
|
@@ -12247,12 +12322,12 @@
|
|
|
12247
12322
|
{
|
|
12248
12323
|
"path": "package-lock.json",
|
|
12249
12324
|
"mode": "0000644",
|
|
12250
|
-
"sha256": "
|
|
12325
|
+
"sha256": "3e98540a12076778a81f41e055028f600bcbf94c0c2a555adf002c69d2b72734"
|
|
12251
12326
|
},
|
|
12252
12327
|
{
|
|
12253
12328
|
"path": "package.json",
|
|
12254
12329
|
"mode": "0000644",
|
|
12255
|
-
"sha256": "
|
|
12330
|
+
"sha256": "158a3afd6782e3f28c2a49dd85e5fe3a83bb8debb3464a5d851c685fb36f53ba"
|
|
12256
12331
|
},
|
|
12257
12332
|
{
|
|
12258
12333
|
"path": "public-docs/index.html",
|
|
@@ -12272,7 +12347,7 @@
|
|
|
12272
12347
|
{
|
|
12273
12348
|
"path": "release-notes.json",
|
|
12274
12349
|
"mode": "0000644",
|
|
12275
|
-
"sha256": "
|
|
12350
|
+
"sha256": "6010acbd56137643326e0ecc314d93c9b097dd4cbff4cf9d801e4ce7a51acc67"
|
|
12276
12351
|
},
|
|
12277
12352
|
{
|
|
12278
12353
|
"path": "scripts/bongos/CLAUDE.md",
|
|
@@ -13407,7 +13482,7 @@
|
|
|
13407
13482
|
{
|
|
13408
13483
|
"path": "scripts/bongos/publish-manifest.js",
|
|
13409
13484
|
"mode": "0000644",
|
|
13410
|
-
"sha256": "
|
|
13485
|
+
"sha256": "d7d803f0b61423ae35a2db5d06b2a04850f0055d2d0aba38c17ad78c463892e9"
|
|
13411
13486
|
},
|
|
13412
13487
|
{
|
|
13413
13488
|
"path": "scripts/bongos/publish-watch.js",
|
|
@@ -13542,7 +13617,7 @@
|
|
|
13542
13617
|
{
|
|
13543
13618
|
"path": "scripts/bongos/run-unit-tests.js",
|
|
13544
13619
|
"mode": "0000644",
|
|
13545
|
-
"sha256": "
|
|
13620
|
+
"sha256": "248d61074607a03eb23d6a23c009a8ed8f332128865c591d7481325943d2f61d"
|
|
13546
13621
|
},
|
|
13547
13622
|
{
|
|
13548
13623
|
"path": "scripts/bongos/runner-drift.js",
|
|
@@ -15927,7 +16002,7 @@
|
|
|
15927
16002
|
{
|
|
15928
16003
|
"path": "src/bongos/module-scope-map.js",
|
|
15929
16004
|
"mode": "0000644",
|
|
15930
|
-
"sha256": "
|
|
16005
|
+
"sha256": "92b6ac609252f96e73acab6a9171cda465d36d75975ede79c96f13176e0d54ef"
|
|
15931
16006
|
},
|
|
15932
16007
|
{
|
|
15933
16008
|
"path": "src/bongos/module-store.js",
|
|
@@ -16282,7 +16357,7 @@
|
|
|
16282
16357
|
{
|
|
16283
16358
|
"path": "src/module-api.js",
|
|
16284
16359
|
"mode": "0000644",
|
|
16285
|
-
"sha256": "
|
|
16360
|
+
"sha256": "012ede63ed757a41e42926e2d3b0516e703aede0515a5140614882f16607d470"
|
|
16286
16361
|
},
|
|
16287
16362
|
{
|
|
16288
16363
|
"path": "src/module-loader/catalog.js",
|
|
@@ -18279,6 +18354,21 @@
|
|
|
18279
18354
|
"mode": "0000644",
|
|
18280
18355
|
"sha256": "37e3cfc000f7ab17b04a5b145a8d209bfe911664bbb272340aabbe7152ad6c3a"
|
|
18281
18356
|
},
|
|
18357
|
+
{
|
|
18358
|
+
"path": "tests/front_door_guide.mjs",
|
|
18359
|
+
"mode": "0000644",
|
|
18360
|
+
"sha256": "d4f0af7817c3e0f031fc00d8b77d2b94ddb994a39d6a03e3ba9badabae362f7a"
|
|
18361
|
+
},
|
|
18362
|
+
{
|
|
18363
|
+
"path": "tests/front_door_guide_db.mjs",
|
|
18364
|
+
"mode": "0000644",
|
|
18365
|
+
"sha256": "e5f04555dd7bf89159afe0bef0ea1bc98f3218b9643dff122dd847f5730a923c"
|
|
18366
|
+
},
|
|
18367
|
+
{
|
|
18368
|
+
"path": "tests/front_door_guide_plan.mjs",
|
|
18369
|
+
"mode": "0000644",
|
|
18370
|
+
"sha256": "42bf945cfe325b0654f6ab621f0cc95b5a97e712641ae088ff577753ec042ad5"
|
|
18371
|
+
},
|
|
18282
18372
|
{
|
|
18283
18373
|
"path": "tests/funded_project_pays_proof_db.mjs",
|
|
18284
18374
|
"mode": "0000644",
|
|
@@ -20637,7 +20727,7 @@
|
|
|
20637
20727
|
{
|
|
20638
20728
|
"path": "tests/module_loader.mjs",
|
|
20639
20729
|
"mode": "0000644",
|
|
20640
|
-
"sha256": "
|
|
20730
|
+
"sha256": "5321c7c72df0c6901b78d6d099e30eeca3e9a7858e47c12c81edb647fa9cf515"
|
|
20641
20731
|
},
|
|
20642
20732
|
{
|
|
20643
20733
|
"path": "tests/module_manifest.mjs",
|
|
@@ -5,7 +5,7 @@ A **generated**, zero-dependency typed client for the Bongos API — produced fr
|
|
|
5
5
|
by hand; it regenerates when the spec changes, so it can never drift from the routes.
|
|
6
6
|
|
|
7
7
|
- API version: **v1** (served at `/api/bongos/v1`)
|
|
8
|
-
-
|
|
8
|
+
- 709 operations across 86 resource groups
|
|
9
9
|
|
|
10
10
|
## Use it from your project
|
|
11
11
|
|
|
@@ -486,6 +486,22 @@ function createClient(opts = {}) {
|
|
|
486
486
|
// POST /founding/start — rank: any-builder — POST /founding/start
|
|
487
487
|
postFoundingStart: (args) => request("POST", "/founding/start", { hasBody: true }, args),
|
|
488
488
|
},
|
|
489
|
+
"frontDoorGuide": {
|
|
490
|
+
// POST /front-door-guide/conversations — rank: public — POST /front-door-guide/conversations
|
|
491
|
+
postFrontDoorGuideConversations: (args) => request("POST", "/front-door-guide/conversations", { hasBody: true }, args),
|
|
492
|
+
// GET /front-door-guide/conversations/{id} — rank: public — GET /front-door-guide/conversations/:id
|
|
493
|
+
getFrontDoorGuideConversationsId: (args) => request("GET", "/front-door-guide/conversations/{id}", { hasBody: false }, args),
|
|
494
|
+
// POST /front-door-guide/conversations/{id}/attach — rank: any-builder — POST /front-door-guide/conversations/:id/attach
|
|
495
|
+
postFrontDoorGuideConversationsIdAttach: (args) => request("POST", "/front-door-guide/conversations/{id}/attach", { hasBody: true }, args),
|
|
496
|
+
// POST /front-door-guide/conversations/{id}/messages — rank: public — POST /front-door-guide/conversations/:id/messages
|
|
497
|
+
postFrontDoorGuideConversationsIdMessages: (args) => request("POST", "/front-door-guide/conversations/{id}/messages", { hasBody: true }, args),
|
|
498
|
+
// POST /front-door-guide/conversations/{id}/plan — rank: public — POST /front-door-guide/conversations/:id/plan
|
|
499
|
+
postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
|
|
500
|
+
// GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
|
|
501
|
+
getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
|
|
502
|
+
// GET /front-door-guide/status — rank: public — GET /front-door-guide/status
|
|
503
|
+
getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
|
|
504
|
+
},
|
|
489
505
|
"github": {
|
|
490
506
|
// GET /github/orgs — rank: any-builder — GET /github/orgs
|
|
491
507
|
getGithubOrgs: (args) => request("GET", "/github/orgs", { hasBody: false }, args),
|
|
@@ -485,6 +485,22 @@ function createClient(opts = {}) {
|
|
|
485
485
|
// POST /founding/start — rank: any-builder — POST /founding/start
|
|
486
486
|
postFoundingStart: (args) => request("POST", "/founding/start", { hasBody: true }, args),
|
|
487
487
|
},
|
|
488
|
+
"frontDoorGuide": {
|
|
489
|
+
// POST /front-door-guide/conversations — rank: public — POST /front-door-guide/conversations
|
|
490
|
+
postFrontDoorGuideConversations: (args) => request("POST", "/front-door-guide/conversations", { hasBody: true }, args),
|
|
491
|
+
// GET /front-door-guide/conversations/{id} — rank: public — GET /front-door-guide/conversations/:id
|
|
492
|
+
getFrontDoorGuideConversationsId: (args) => request("GET", "/front-door-guide/conversations/{id}", { hasBody: false }, args),
|
|
493
|
+
// POST /front-door-guide/conversations/{id}/attach — rank: any-builder — POST /front-door-guide/conversations/:id/attach
|
|
494
|
+
postFrontDoorGuideConversationsIdAttach: (args) => request("POST", "/front-door-guide/conversations/{id}/attach", { hasBody: true }, args),
|
|
495
|
+
// POST /front-door-guide/conversations/{id}/messages — rank: public — POST /front-door-guide/conversations/:id/messages
|
|
496
|
+
postFrontDoorGuideConversationsIdMessages: (args) => request("POST", "/front-door-guide/conversations/{id}/messages", { hasBody: true }, args),
|
|
497
|
+
// POST /front-door-guide/conversations/{id}/plan — rank: public — POST /front-door-guide/conversations/:id/plan
|
|
498
|
+
postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
|
|
499
|
+
// GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
|
|
500
|
+
getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
|
|
501
|
+
// GET /front-door-guide/status — rank: public — GET /front-door-guide/status
|
|
502
|
+
getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
|
|
503
|
+
},
|
|
488
504
|
"github": {
|
|
489
505
|
// GET /github/orgs — rank: any-builder — GET /github/orgs
|
|
490
506
|
getGithubOrgs: (args) => request("GET", "/github/orgs", { hasBody: false }, args),
|
|
@@ -75,6 +75,7 @@ export interface GetCoreUpgradesResponse { ok: boolean; running: unknown; limit:
|
|
|
75
75
|
export interface GetDiscordChannelsPlanResponse { ok: boolean; guild_id: unknown; op_count: unknown; ops: unknown; warnings: unknown }
|
|
76
76
|
export interface GetDiscordChannelsSnapshotResponse { ok: boolean; guild_id: unknown; config: unknown; warnings: unknown }
|
|
77
77
|
export interface GetDoneWhenPendingReviewResponse { criteria: unknown; count: unknown }
|
|
78
|
+
export interface GetFrontDoorGuideMineResponse { ok: boolean; conversation: unknown }
|
|
78
79
|
export interface GetGithubOrgsOrgResponse { org: unknown }
|
|
79
80
|
export interface GetGithubRepoResponse { ok: boolean; repo: unknown; private_deployable: boolean }
|
|
80
81
|
export interface GetGithubReposResponse { repos: unknown }
|
|
@@ -389,6 +390,11 @@ export interface PostDoneWhenCriterionIdUnsatisfyResponse { criterion: unknown }
|
|
|
389
390
|
export interface PostFeedbackReceiptRequest { sha256: string; kind?: "bug" | "idea" }
|
|
390
391
|
export interface PostFeedbackReceiptResponse { ok: boolean; receipt: unknown; hub: unknown }
|
|
391
392
|
export interface PostFoundingPlanRequest { days?: Record<string, unknown>; passes?: number; advisors?: string; government?: string; expected_builders?: number; existing?: boolean }
|
|
393
|
+
export interface PostFrontDoorGuideConversationsIdAttachRequest { token: string }
|
|
394
|
+
export interface PostFrontDoorGuideConversationsIdAttachResponse { ok: boolean; conversation: unknown }
|
|
395
|
+
export interface PostFrontDoorGuideConversationsIdMessagesRequest { token: string; text: string; website?: string }
|
|
396
|
+
export interface PostFrontDoorGuideConversationsIdPlanRequest { token: string; website?: string }
|
|
397
|
+
export interface PostFrontDoorGuideConversationsRequest { website?: string }
|
|
392
398
|
export interface PostGithubRepoInviteRequest { github_login: string; permission?: string }
|
|
393
399
|
export interface PostGithubRepoVisibilityRequest { repo: string; visibility: "public" | "private" }
|
|
394
400
|
export interface PostGithubRepoVisibilityResponse { ok: boolean; repo: unknown; private_deployable: boolean }
|
|
@@ -1158,6 +1164,22 @@ export interface BongosClient {
|
|
|
1158
1164
|
/** POST /founding/start — rank: any-builder */
|
|
1159
1165
|
postFoundingStart(args?: RequestArgs): Promise<ApiResponse>;
|
|
1160
1166
|
};
|
|
1167
|
+
"frontDoorGuide": {
|
|
1168
|
+
/** POST /front-door-guide/conversations — rank: public */
|
|
1169
|
+
postFrontDoorGuideConversations(args?: RequestArgs & { body?: PostFrontDoorGuideConversationsRequest }): Promise<ApiResponse>;
|
|
1170
|
+
/** GET /front-door-guide/conversations/{id} — rank: public */
|
|
1171
|
+
getFrontDoorGuideConversationsId(args?: RequestArgs): Promise<ApiResponse>;
|
|
1172
|
+
/** POST /front-door-guide/conversations/{id}/attach — rank: any-builder */
|
|
1173
|
+
postFrontDoorGuideConversationsIdAttach(args: RequestArgs & { body: PostFrontDoorGuideConversationsIdAttachRequest }): Promise<PostFrontDoorGuideConversationsIdAttachResponse>;
|
|
1174
|
+
/** POST /front-door-guide/conversations/{id}/messages — rank: public */
|
|
1175
|
+
postFrontDoorGuideConversationsIdMessages(args: RequestArgs & { body: PostFrontDoorGuideConversationsIdMessagesRequest }): Promise<ApiResponse>;
|
|
1176
|
+
/** POST /front-door-guide/conversations/{id}/plan — rank: public */
|
|
1177
|
+
postFrontDoorGuideConversationsIdPlan(args: RequestArgs & { body: PostFrontDoorGuideConversationsIdPlanRequest }): Promise<ApiResponse>;
|
|
1178
|
+
/** GET /front-door-guide/mine — rank: any-builder */
|
|
1179
|
+
getFrontDoorGuideMine(args?: RequestArgs): Promise<GetFrontDoorGuideMineResponse>;
|
|
1180
|
+
/** GET /front-door-guide/status — rank: public */
|
|
1181
|
+
getFrontDoorGuideStatus(args?: RequestArgs): Promise<ApiResponse>;
|
|
1182
|
+
};
|
|
1161
1183
|
"github": {
|
|
1162
1184
|
/** GET /github/orgs — rank: any-builder */
|
|
1163
1185
|
getGithubOrgs(args?: RequestArgs): Promise<ApiResponse>;
|
|
@@ -482,6 +482,22 @@ export function createClient(opts = {}) {
|
|
|
482
482
|
// POST /founding/start — rank: any-builder — POST /founding/start
|
|
483
483
|
postFoundingStart: (args) => request("POST", "/founding/start", { hasBody: true }, args),
|
|
484
484
|
},
|
|
485
|
+
"frontDoorGuide": {
|
|
486
|
+
// POST /front-door-guide/conversations — rank: public — POST /front-door-guide/conversations
|
|
487
|
+
postFrontDoorGuideConversations: (args) => request("POST", "/front-door-guide/conversations", { hasBody: true }, args),
|
|
488
|
+
// GET /front-door-guide/conversations/{id} — rank: public — GET /front-door-guide/conversations/:id
|
|
489
|
+
getFrontDoorGuideConversationsId: (args) => request("GET", "/front-door-guide/conversations/{id}", { hasBody: false }, args),
|
|
490
|
+
// POST /front-door-guide/conversations/{id}/attach — rank: any-builder — POST /front-door-guide/conversations/:id/attach
|
|
491
|
+
postFrontDoorGuideConversationsIdAttach: (args) => request("POST", "/front-door-guide/conversations/{id}/attach", { hasBody: true }, args),
|
|
492
|
+
// POST /front-door-guide/conversations/{id}/messages — rank: public — POST /front-door-guide/conversations/:id/messages
|
|
493
|
+
postFrontDoorGuideConversationsIdMessages: (args) => request("POST", "/front-door-guide/conversations/{id}/messages", { hasBody: true }, args),
|
|
494
|
+
// POST /front-door-guide/conversations/{id}/plan — rank: public — POST /front-door-guide/conversations/:id/plan
|
|
495
|
+
postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
|
|
496
|
+
// GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
|
|
497
|
+
getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
|
|
498
|
+
// GET /front-door-guide/status — rank: public — GET /front-door-guide/status
|
|
499
|
+
getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
|
|
500
|
+
},
|
|
485
501
|
"github": {
|
|
486
502
|
// GET /github/orgs — rank: any-builder — GET /github/orgs
|
|
487
503
|
getGithubOrgs: (args) => request("GET", "/github/orgs", { hasBody: false }, args),
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# 0406 — Every project gets a sandbox that follows main, and live moves only when a person promotes
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted. The model is settled; §6 lists two cost choices the gated tasks ask the owner when they reach them, and neither changes the model.
|
|
4
|
+
- **Date:** 2026-11-13
|
|
5
|
+
- **Task:** [task 1005288](https://cloudbongos.com/builders#/task/1005288) (goal 1000106 — working area 1, Project creation)
|
|
6
|
+
- **Decided by:** the owner's direction of 2026-11-13 (quoted in §1), with the shape checked against the code and Render's own docs by Claude, who wrote the record.
|
|
7
|
+
- **Builds on:** [ADR 0345](0345-we-host-every-projects-hall-and-its-app-deploys-where-the-owner-chooses.md) (we host the hall; the app runs on the owner's Render account) · [ADR 0327](0327-a-cloud-host-runs-on-the-owners-account-and-the-key-is-borrowed.md) (the Render key is borrowed, never stored) · [ADR 0161](0161-publish-on-merge.md) (for Cloud Bongos itself a merge is not live until a pin moves) · [ADR 0369](0369-ship-mode-decides-who-starts-a-ship-not-how-it-lands.md) (ship mode says who starts a ship, not where it lands)
|
|
8
|
+
- **Distinct from:** [ADR 0044](0044-per-box-live-game-preview.md) / [ADR 0046](0046-sandbox-first-review-gate.md) — the builder's private **local preview** (`scripts/bongos/sandbox-stage.js`, `scripts/bongos/local-preview.js`). That is one builder's look *before* shipping, on their own machine. This ADR is about the project's shared, hosted sandbox *after* work lands.
|
|
9
|
+
- **Gates:** [task 1005289](https://cloudbongos.com/builders#/task/1005289) (set it up) · [task 1005290](https://cloudbongos.com/builders#/task/1005290) (land on the sandbox, promote to live) · [task 1005291](https://cloudbongos.com/builders#/task/1005291) (safety) · [task 1005292](https://cloudbongos.com/builders#/task/1005292) (Cloud Bongos's own) · [task 1005293](https://cloudbongos.com/builders#/task/1005293) (the walk)
|
|
10
|
+
|
|
11
|
+
## 1. The owner's words
|
|
12
|
+
|
|
13
|
+
> "each project would have a sandbox, so yes cloudbongos would have one, but so would every site someone creates. maybe its a second github or just a different branch and we host it on the render free version... essentially a local host but has fake data or sandbox keys that dont actually change anything. maybe it uses the real keys for the data but is gated to not actually send anything back."
|
|
14
|
+
|
|
15
|
+
## 2. The decision
|
|
16
|
+
|
|
17
|
+
Every project whose app runs on Render has **two apps from one repository**:
|
|
18
|
+
|
|
19
|
+
| | **Sandbox** | **Live (the main site)** |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| What it runs | whatever has landed on `main`, automatically | the commit a person last promoted |
|
|
22
|
+
| Render service | a second web service on the owner's account, **free plan** | the owner's existing service, on the plan they chose |
|
|
23
|
+
| Updates when | every merge (Render auto-deploy from `main`) | only when a person presses **promote** (auto-deploy switched off) |
|
|
24
|
+
| Data | its own database with seeded fake data (§4) | the real data |
|
|
25
|
+
| Keys | each provider's sandbox/test keys; real keys only when lent, behind the gate (§5) | the real keys |
|
|
26
|
+
| Marked | every page carries a visible "sandbox" band | — |
|
|
27
|
+
|
|
28
|
+
**Promotion is a person's act.** The owner (or whoever the project's rules allow) sees which landed commits are on the sandbox and not on live, and presses promote. That asks Render to deploy that exact commit to the live service. It needs the owner's Render key typed in for that one request, as every Render action already does (`modules/render-deploy/render.js`, ADR 0327 §2) — so no stored credential can ever move live by itself. This is the project law *"Land only. Ask before going live"* made physical: agents land, and landing reaches only the sandbox.
|
|
29
|
+
|
|
30
|
+
**Ship mode is untouched.** Auto mode still ships hands-off and Manual still asks before each ship (ADR 0369). Both only ever land, and landing now reaches the sandbox; neither can promote.
|
|
31
|
+
|
|
32
|
+
## 3. Why "the sandbox follows main" and not a sandbox branch
|
|
33
|
+
|
|
34
|
+
The starting point offered a `sandbox` branch, promoted by merging it into `main`. Checked against the code, that is the costlier shape:
|
|
35
|
+
|
|
36
|
+
- **Everything already lands on `main`.** `ship.js`, the grader, the merge queue, the strand fixer and the release pipeline all key on `main`. A sandbox branch means every one of them learns a second target, and every promotion is a merge that can conflict.
|
|
37
|
+
- **Render can already deploy a chosen commit.** A service set to `autoDeploy: no` is deployed by an explicit request that names the commit. The client has `triggerDeploy`, `listDeploys` and `rollbackTo` today (`scripts/bongos/render-api.js`); promotion adds a commit id to the first.
|
|
38
|
+
- **It is the model Cloud Bongos already runs.** For the platform, a merge is not live until a published release carries it and the hub's pin moves (ADR 0161, [`docs/recipes/core-release-pipeline.md`](../recipes/core-release-pipeline.md)). "The sandbox follows what landed; live holds a pin a person moves" is the same rule, so the platform and every project now share one model (§7).
|
|
39
|
+
|
|
40
|
+
So: **one repository, no second repository, no sandbox branch.** The owner's "maybe a second github" is declined for the reason the brief gave — two copies drift and double the upkeep.
|
|
41
|
+
|
|
42
|
+
What changes in code (for [task 1005289](https://cloudbongos.com/builders#/task/1005289) and [task 1005290](https://cloudbongos.com/builders#/task/1005290)): today the one service is created with `branch: 'main'` and `autoDeploy: 'yes'` (`scripts/bongos/render-payload.js`), so every merge already goes straight to the main site. Under this ADR the sandbox service takes that payload, and the live service is switched to `autoDeploy: 'no'`.
|
|
43
|
+
|
|
44
|
+
## 4. The sandbox's database
|
|
45
|
+
|
|
46
|
+
Render's free database is **not** usable here (Render docs, read 2026-11-13: [render.com/docs/free](https://render.com/docs/free)):
|
|
47
|
+
|
|
48
|
+
- it **expires 30 days after creation**, with 14 days' grace before Render deletes it;
|
|
49
|
+
- a workspace may have **only one** free database;
|
|
50
|
+
- it has no backups.
|
|
51
|
+
|
|
52
|
+
The platform already refuses it for the same reasons (`modules/provisioning/render-standup.js`: "The database has no free plan here"). So:
|
|
53
|
+
|
|
54
|
+
- **The app has a paid database** → the sandbox gets **a second database inside that same database server**, filled with seeded fake data. No extra Render bill; it shares the server's capacity. ([task 1005289](https://cloudbongos.com/builders#/task/1005289) confirms on a real account that Render allows a second database in one server; if it does not, the fallback is the owner's choice in §6.)
|
|
55
|
+
- **The app has no database** → the sandbox has none either.
|
|
56
|
+
- The sandbox **never** points at the live database. Its writes would be real writes.
|
|
57
|
+
|
|
58
|
+
## 5. Safety: fake by default, and a gate when real keys are lent
|
|
59
|
+
|
|
60
|
+
1. **Default:** seeded fake data and each provider's sandbox/test keys (Stripe test mode, and so on). Nothing the sandbox does can reach a real customer.
|
|
61
|
+
2. **Real keys, only when the owner lends them** (so the sandbox can show real data), and then:
|
|
62
|
+
- **Prefer a read-only key.** Where the provider offers a restricted or read-only key, that is the key to lend. This is the only part of the gate that cannot be coded around, so it is the floor.
|
|
63
|
+
- **The outbound gate.** The project's app runs with `BONGOS_SANDBOX=1`, and the project's starter carries a small outbound wrapper that, for each known provider, lets reads through and refuses sends, charges and writes, logging each refusal where the owner can see it.
|
|
64
|
+
- **Said plainly:** the app is the owner's own code. The gate covers calls that go through the wrapper; code written to bypass it is not caught. That is why a read-only key comes first.
|
|
65
|
+
3. A side effect worth knowing: Render's free plan already blocks outgoing mail ports (25, 465, 587), so a sandbox on the free plan cannot send email over SMTP at all.
|
|
66
|
+
|
|
67
|
+
## 6. Cost, and what the owner chooses
|
|
68
|
+
|
|
69
|
+
**Cost to the owner** (Render's docs, read 2026-11-13):
|
|
70
|
+
|
|
71
|
+
- **Sandbox app: $0.** Free plan: 0.1 CPU, 512 MB memory. It **sleeps after 15 minutes with no visitors and takes about a minute to wake**, which is fine for a place to look at work before it goes live. Free apps share **750 running hours a month per Render workspace**; a sleeping app uses none. Past that, every free app on the workspace pauses until the next month. Local files are lost on every sleep and restart (no disks), which is why the sandbox's data lives in the database.
|
|
72
|
+
- **Sandbox database: $0** when it sits inside the app's existing paid database (§4).
|
|
73
|
+
- Free apps count against the workspace's shared bandwidth and build minutes; a busy sandbox could use some of them up.
|
|
74
|
+
|
|
75
|
+
**Cost to us: nothing in hosting** — the sandbox runs on the owner's account (ADR 0327, ADR 0345). Our cost is the runner's time setting it up and the work in the sibling tasks.
|
|
76
|
+
|
|
77
|
+
🔀 **Owner choices still open** (not blocking this ADR; each is asked in the task that needs it):
|
|
78
|
+
|
|
79
|
+
1. **If Render will not hold a second database in one server**, the sandbox's database is either (a) the cheapest paid Render database, a few dollars a month on the owner's bill, *(recommended)*, or (b) none — the sandbox shows the app with no data. Asked in [task 1005289](https://cloudbongos.com/builders#/task/1005289).
|
|
80
|
+
2. **Where Cloud Bongos's own sandbox runs** (§7): (a) on the box the hub already uses — no new spend, but it takes memory from the box every project hall shares — or (b) a small separate server, a few dollars a month. Asked in [task 1005292](https://cloudbongos.com/builders#/task/1005292). Recommended: (b), because the shared box is already near its memory wall ([task 1003875](https://cloudbongos.com/builders#/task/1003875)).
|
|
81
|
+
|
|
82
|
+
## 7. Cases
|
|
83
|
+
|
|
84
|
+
- **A project with no app yet** gets no hosted sandbox. There is nothing to run. Its builders keep the private local preview, and the sandbox is set up the moment the app is connected to Render, at creation or later from settings ([task 1005289](https://cloudbongos.com/builders#/task/1005289)).
|
|
85
|
+
- **An app that deploys somewhere other than Render** (ADR 0345 lets the owner choose) gets no automatic sandbox. The model is the same, but we only set it up on Render.
|
|
86
|
+
- **An app linked to an existing Render service** ("adopt") keeps that service as live; the sandbox is a new free service copying its build settings.
|
|
87
|
+
- **Tearing a project down** removes the sandbox service and the sandbox database only — never the owner's live service (ADR 0327 §3: we never destroy an owner's infrastructure without being asked).
|
|
88
|
+
- **Cloud Bongos itself** runs the same rule one level up. Its "main" is the published core release (ADR 0161). Its sandbox is a second Cloud Bongos instance that takes **every** release as it is published and carries a throwaway test project ([`modules/provisioning/test-project.js`](../../modules/provisioning/test-project.js)), so a full project-creation walk costs nothing real. The live hub moves its pin only when a person promotes. Today the hub's patch subscription moves its pin to each patch release by itself (task 1005020); once the sandbox exists, whether patches still go live hands-off is the owner's call in [task 1005292](https://cloudbongos.com/builders#/task/1005292).
|
|
89
|
+
|
|
90
|
+
## 8. Considered and not done
|
|
91
|
+
|
|
92
|
+
- **A second repository.** Doubles upkeep and drifts.
|
|
93
|
+
- **A `sandbox` branch, promoted by merge.** Every landing tool would need a second target, and promotions could conflict (§3).
|
|
94
|
+
- **Render's free database for the sandbox.** Expires in 30 days, one per workspace (§4).
|
|
95
|
+
- **The sandbox reading the live database.** Any write would be real.
|
|
96
|
+
- **An outbound gate with no read-only key behind it, sold as "safe".** It only covers code that goes through it; we say so instead (§5).
|
|
97
|
+
|
|
98
|
+
## 9. The sibling tasks, re-read against this record (2026-11-13)
|
|
99
|
+
|
|
100
|
+
Each sibling task's description now opens with a dated note, *"Re-read against ADR 0406 … What the decision changes here"*, written through `PATCH /api/bongos/tasks/<id>`; the owner's original words are kept below it.
|
|
101
|
+
|
|
102
|
+
| Task | What changed |
|
|
103
|
+
|---|---|
|
|
104
|
+
| [task 1005289](https://cloudbongos.com/builders#/task/1005289) | Retitled *"Give every project a sandbox: a free Render app that follows main, at creation or later"* (the sandbox branch is gone). Note: free service auto-deploys from `main`, live switched to `autoDeploy: 'no'`; never Render's free database, a second database in the paid server instead (confirm first, else owner choice 1); adopt, no-app and teardown cases. |
|
|
105
|
+
| [task 1005290](https://cloudbongos.com/builders#/task/1005290) | Landing stays on `main`; promote deploys one chosen commit to live, `triggerDeploy` gains a commit id, the owner types the Render key for that request, each promotion is recorded; ship mode untouched. |
|
|
106
|
+
| [task 1005291](https://cloudbongos.com/builders#/task/1005291) | A read-only key is the floor; the gate is an outbound wrapper in the starter active under `BONGOS_SANDBOX=1`, with its limit said plainly; free plan blocks mail ports. |
|
|
107
|
+
| [task 1005292](https://cloudbongos.com/builders#/task/1005292) | Same rule over the release pin; a second instance takes every release and carries a throwaway test project; owner choice 2 and the patch auto-move question are asked here. |
|
|
108
|
+
| [task 1005293](https://cloudbongos.com/builders#/task/1005293) | Added checks: no live deploy after a ship, promote refuses without the key, the sandbox band shows, sandbox data is fake, and the lent key is confirmed read-only. |
|
package/docs/adr/README.md
CHANGED
|
@@ -521,3 +521,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
|
|
|
521
521
|
| 0403 | [**In game mode the visor is the control and the scene is the view** ([task 1005203](https://cloudbongos.com/builders#/task/1005203), goal 1000142; owner 2026-11-11). Every main call to action you can see in game mode lives on the visor (the accent button, the key hints, the Actions sheet); the city, the sky and Home only show the project and can be moved through, never carry buttons of their own. A scene offers its actions to the visor through `OTBVisor.scene`. Found not yet keeping it: the city's decide button and door, the sky's top row and composer, Home's gallery links, the Artist's feedback tab.](0403-in-game-mode-the-visor-is-the-control-and-the-scene-is-the-view.md) | hall / game frame |
|
|
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
|
+
| 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 |
|