@bongos/core 1.19.401 → 1.19.403
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 +50 -40
- package/clients/bongos-client/index.d.ts +1 -1
- package/docs/adr/0200-re-point-a-bring-your-own-domain.md +105 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +3 -2
- package/docs/copy-inventory.md +141 -138
- package/docs/copy-registry.json +205 -176
- package/docs/design/projects-hub-direction-v2.md +16 -0
- package/modules/platform-identity/project-stats.js +123 -38
- package/modules/platform-identity/routes/my-projects.js +13 -0
- package/modules/platform-identity/routes/projects.js +7 -4
- package/modules/provisioning/migrations/provisioning_012_domain_repoint.sql +35 -0
- package/modules/provisioning/provisioning.js +68 -8
- package/modules/provisioning/routes/provisioning.js +50 -23
- package/modules/ui-design/kit/fixtures/featured.json +1 -1
- package/modules/ui-design/kit/fixtures/my-projects.json +1 -1
- package/modules/ui-design/kit/serve.js +14 -3
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +126 -25
- package/public-landing/projects.html +155 -27
- package/public-landing/projects.probes.json +28 -0
- package/public-landing/projects.states.json +6 -3
- package/scripts/gds/provision-net.js +33 -0
- package/scripts/gds/provision-units.js +18 -0
- package/scripts/gds/provision.js +97 -5
- package/src/module-api.js +5 -1
- package/tests/cosmos_token_contrast.mjs +5 -2
- package/tests/project_stats.mjs +128 -2
- package/tests/projects_hub.mjs +106 -5
- package/tests/projects_hub_pre_uat.mjs +28 -2
- package/tests/provision.mjs +185 -12
- package/tests/provisioning_default_domain.mjs +5 -3
- package/tests/provisioning_domain_attach.mjs +166 -17
- package/tests/public_landing_projects.mjs +5 -1
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.403",
|
|
6
|
+
"core_contract": "1.19.403",
|
|
7
|
+
"source_commit": "59efd083f3bfbf52a8da49727c16d3487acd0717",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-28T20:35:12.999Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 350,
|
|
13
13
|
"agent_docs_stubbed": 23,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1662,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2035,
|
|
20
|
+
"tree_sha256": "ff41a19b163222f7501bcc6e1b9f9a8fa612c43aff15a0af618ac8527f19cdaa",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -372,7 +372,7 @@
|
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.d.ts",
|
|
374
374
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
375
|
+
"sha256": "cbe0ba674f055e30fea6c74dd1fd9eaed2333219610b76d3dcada33bce3939b6"
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
378
|
"path": "clients/bongos-client/index.mjs",
|
|
@@ -1499,10 +1499,15 @@
|
|
|
1499
1499
|
"mode": "0000644",
|
|
1500
1500
|
"sha256": "999c2eb382b51317a4f1fbf7a615855be7baeded04cf03c4e1a411b2f98386cd"
|
|
1501
1501
|
},
|
|
1502
|
+
{
|
|
1503
|
+
"path": "docs/adr/0200-re-point-a-bring-your-own-domain.md",
|
|
1504
|
+
"mode": "0000644",
|
|
1505
|
+
"sha256": "d73c7f4ebaf18bf81e461532144422b8d343698c50964687c52b13301af42c66"
|
|
1506
|
+
},
|
|
1502
1507
|
{
|
|
1503
1508
|
"path": "docs/adr/README.md",
|
|
1504
1509
|
"mode": "0000644",
|
|
1505
|
-
"sha256": "
|
|
1510
|
+
"sha256": "870abce88d6282c54c7818ba9d643639c866704a8f7e982afb0717c39c6dc9a0"
|
|
1506
1511
|
},
|
|
1507
1512
|
{
|
|
1508
1513
|
"path": "docs/api-reference.md",
|
|
@@ -1512,7 +1517,7 @@
|
|
|
1512
1517
|
{
|
|
1513
1518
|
"path": "docs/api/openapi.json",
|
|
1514
1519
|
"mode": "0000644",
|
|
1515
|
-
"sha256": "
|
|
1520
|
+
"sha256": "be970356181398e6f11fc8cad05c2190091aeb06cf5ceaf577a8a6bb86f0b375"
|
|
1516
1521
|
},
|
|
1517
1522
|
{
|
|
1518
1523
|
"path": "docs/architecture.md",
|
|
@@ -1537,12 +1542,12 @@
|
|
|
1537
1542
|
{
|
|
1538
1543
|
"path": "docs/copy-inventory.md",
|
|
1539
1544
|
"mode": "0000644",
|
|
1540
|
-
"sha256": "
|
|
1545
|
+
"sha256": "c8ffa819bae7285b8586ae031b6589b24e64584a262cf26df8b346a30333f05d"
|
|
1541
1546
|
},
|
|
1542
1547
|
{
|
|
1543
1548
|
"path": "docs/copy-registry.json",
|
|
1544
1549
|
"mode": "0000644",
|
|
1545
|
-
"sha256": "
|
|
1550
|
+
"sha256": "b0734640552c625d24ad070a830fe6bd36021830ed474cd739ab9b5fbb2eea56"
|
|
1546
1551
|
},
|
|
1547
1552
|
{
|
|
1548
1553
|
"path": "docs/design/apex-pass-2-direction.md",
|
|
@@ -1782,7 +1787,7 @@
|
|
|
1782
1787
|
{
|
|
1783
1788
|
"path": "docs/design/projects-hub-direction-v2.md",
|
|
1784
1789
|
"mode": "0000644",
|
|
1785
|
-
"sha256": "
|
|
1790
|
+
"sha256": "a6867fcaf7663cd308cc82abae779c96f7d67b1eb0011d96d31ced0e17c64c18"
|
|
1786
1791
|
},
|
|
1787
1792
|
{
|
|
1788
1793
|
"path": "docs/design/projects-hub-direction.md",
|
|
@@ -4752,12 +4757,12 @@
|
|
|
4752
4757
|
{
|
|
4753
4758
|
"path": "modules/platform-identity/project-stats.js",
|
|
4754
4759
|
"mode": "0000644",
|
|
4755
|
-
"sha256": "
|
|
4760
|
+
"sha256": "2e898799632a2b5c2ead9cb44fa0b8029fcb6d217f7d5f26c8a39b34c75bbea7"
|
|
4756
4761
|
},
|
|
4757
4762
|
{
|
|
4758
4763
|
"path": "modules/platform-identity/routes/my-projects.js",
|
|
4759
4764
|
"mode": "0000644",
|
|
4760
|
-
"sha256": "
|
|
4765
|
+
"sha256": "7e8c7b272f273719329ba5755dc88fe2a1359c1281150162ed9396512db33b3b"
|
|
4761
4766
|
},
|
|
4762
4767
|
{
|
|
4763
4768
|
"path": "modules/platform-identity/routes/profile.js",
|
|
@@ -4767,7 +4772,7 @@
|
|
|
4767
4772
|
{
|
|
4768
4773
|
"path": "modules/platform-identity/routes/projects.js",
|
|
4769
4774
|
"mode": "0000644",
|
|
4770
|
-
"sha256": "
|
|
4775
|
+
"sha256": "0e1aa7209b6442e1cc363b9a661da28c48776efd4c100f0b8e701cb96925be22"
|
|
4771
4776
|
},
|
|
4772
4777
|
{
|
|
4773
4778
|
"path": "modules/platform-identity/routes/public-profile.js",
|
|
@@ -4854,6 +4859,11 @@
|
|
|
4854
4859
|
"mode": "0000644",
|
|
4855
4860
|
"sha256": "99b0e59f165255643ba4d2a9e9c200985a7d4b162d93c1d169b0f738e9e09c77"
|
|
4856
4861
|
},
|
|
4862
|
+
{
|
|
4863
|
+
"path": "modules/provisioning/migrations/provisioning_012_domain_repoint.sql",
|
|
4864
|
+
"mode": "0000644",
|
|
4865
|
+
"sha256": "74c46df38eab2b8c0f59b2da423691b170e3e85a7ec9857fad239b912bca99f4"
|
|
4866
|
+
},
|
|
4857
4867
|
{
|
|
4858
4868
|
"path": "modules/provisioning/module.json",
|
|
4859
4869
|
"mode": "0000644",
|
|
@@ -4872,7 +4882,7 @@
|
|
|
4872
4882
|
{
|
|
4873
4883
|
"path": "modules/provisioning/provisioning.js",
|
|
4874
4884
|
"mode": "0000644",
|
|
4875
|
-
"sha256": "
|
|
4885
|
+
"sha256": "82c2502ad0c535a1faa43b167735d988527b54149778e5e796c1306139e760f9"
|
|
4876
4886
|
},
|
|
4877
4887
|
{
|
|
4878
4888
|
"path": "modules/provisioning/rate-limit.js",
|
|
@@ -4882,7 +4892,7 @@
|
|
|
4882
4892
|
{
|
|
4883
4893
|
"path": "modules/provisioning/routes/provisioning.js",
|
|
4884
4894
|
"mode": "0000644",
|
|
4885
|
-
"sha256": "
|
|
4895
|
+
"sha256": "bdf000da67e09dfa3bc394d7c3d7dbbd9e65fe4a653cc558291c5806f2ca46ca"
|
|
4886
4896
|
},
|
|
4887
4897
|
{
|
|
4888
4898
|
"path": "modules/provisioning/tests/liveness.mjs",
|
|
@@ -5222,7 +5232,7 @@
|
|
|
5222
5232
|
{
|
|
5223
5233
|
"path": "modules/ui-design/kit/fixtures/featured.json",
|
|
5224
5234
|
"mode": "0000644",
|
|
5225
|
-
"sha256": "
|
|
5235
|
+
"sha256": "f5d843cd881778afa835686ddc2adac253e705b37be063ce96892517436b6413"
|
|
5226
5236
|
},
|
|
5227
5237
|
{
|
|
5228
5238
|
"path": "modules/ui-design/kit/fixtures/leaderboard.json",
|
|
@@ -5237,7 +5247,7 @@
|
|
|
5237
5247
|
{
|
|
5238
5248
|
"path": "modules/ui-design/kit/fixtures/my-projects.json",
|
|
5239
5249
|
"mode": "0000644",
|
|
5240
|
-
"sha256": "
|
|
5250
|
+
"sha256": "05655ce99323e2174446477a4b3fbb8611f9e1a2a34a7f7b5bd947e9e661c593"
|
|
5241
5251
|
},
|
|
5242
5252
|
{
|
|
5243
5253
|
"path": "modules/ui-design/kit/fixtures/progress.json",
|
|
@@ -5272,7 +5282,7 @@
|
|
|
5272
5282
|
{
|
|
5273
5283
|
"path": "modules/ui-design/kit/serve.js",
|
|
5274
5284
|
"mode": "0000644",
|
|
5275
|
-
"sha256": "
|
|
5285
|
+
"sha256": "de42b4d4f908ebdf9b3a181b54d09d8541124a0d35a05d29ddea24233ecca641"
|
|
5276
5286
|
},
|
|
5277
5287
|
{
|
|
5278
5288
|
"path": "modules/ui-design/module.json",
|
|
@@ -5317,12 +5327,12 @@
|
|
|
5317
5327
|
{
|
|
5318
5328
|
"path": "package-lock.json",
|
|
5319
5329
|
"mode": "0000644",
|
|
5320
|
-
"sha256": "
|
|
5330
|
+
"sha256": "05858abe161f6ca2a6b106547449d3848028e58d99061ea02680cfa68acdea9f"
|
|
5321
5331
|
},
|
|
5322
5332
|
{
|
|
5323
5333
|
"path": "package.json",
|
|
5324
5334
|
"mode": "0000644",
|
|
5325
|
-
"sha256": "
|
|
5335
|
+
"sha256": "699f703451266b17963d5de5f9e4106f3f2fe21afc59019cb8f05f09abd4d118"
|
|
5326
5336
|
},
|
|
5327
5337
|
{
|
|
5328
5338
|
"path": "public-docs/index.html",
|
|
@@ -5562,7 +5572,7 @@
|
|
|
5562
5572
|
{
|
|
5563
5573
|
"path": "public-landing/assets/cosmos.css",
|
|
5564
5574
|
"mode": "0000644",
|
|
5565
|
-
"sha256": "
|
|
5575
|
+
"sha256": "d6eb8b2d965d528f1c0af9366ff93902afae3edacf2207526a074827a8913cfd"
|
|
5566
5576
|
},
|
|
5567
5577
|
{
|
|
5568
5578
|
"path": "public-landing/assets/verro-medallion.png",
|
|
@@ -5672,17 +5682,17 @@
|
|
|
5672
5682
|
{
|
|
5673
5683
|
"path": "public-landing/projects.html",
|
|
5674
5684
|
"mode": "0000644",
|
|
5675
|
-
"sha256": "
|
|
5685
|
+
"sha256": "2ddf92250375f1a9c2c15328feb0d3e7eeb95670f329eb08d0e6b3a8a1c6b0e0"
|
|
5676
5686
|
},
|
|
5677
5687
|
{
|
|
5678
5688
|
"path": "public-landing/projects.probes.json",
|
|
5679
5689
|
"mode": "0000644",
|
|
5680
|
-
"sha256": "
|
|
5690
|
+
"sha256": "87dfa686a4c794e1dcdee05829c07a6849df91f1fbc6b0cd2ca9b3cdaa548235"
|
|
5681
5691
|
},
|
|
5682
5692
|
{
|
|
5683
5693
|
"path": "public-landing/projects.states.json",
|
|
5684
5694
|
"mode": "0000644",
|
|
5685
|
-
"sha256": "
|
|
5695
|
+
"sha256": "a4b418dc93d4f24c6a6f5312801b414beef576eae6eb070a4371507a2a876f26"
|
|
5686
5696
|
},
|
|
5687
5697
|
{
|
|
5688
5698
|
"path": "public-landing/terms.html",
|
|
@@ -6447,7 +6457,7 @@
|
|
|
6447
6457
|
{
|
|
6448
6458
|
"path": "scripts/gds/provision-net.js",
|
|
6449
6459
|
"mode": "0000644",
|
|
6450
|
-
"sha256": "
|
|
6460
|
+
"sha256": "18c03ffa9cb4ec417ca527928a2146fa72630eada173c7e207dbad513af70acc"
|
|
6451
6461
|
},
|
|
6452
6462
|
{
|
|
6453
6463
|
"path": "scripts/gds/provision-repo.js",
|
|
@@ -6457,12 +6467,12 @@
|
|
|
6457
6467
|
{
|
|
6458
6468
|
"path": "scripts/gds/provision-units.js",
|
|
6459
6469
|
"mode": "0000644",
|
|
6460
|
-
"sha256": "
|
|
6470
|
+
"sha256": "14ef8b2a3581c93b27983d0e566b5cc317d1a5d3b6367ff8eb7ffef7e0b3f54d"
|
|
6461
6471
|
},
|
|
6462
6472
|
{
|
|
6463
6473
|
"path": "scripts/gds/provision.js",
|
|
6464
6474
|
"mode": "0000644",
|
|
6465
|
-
"sha256": "
|
|
6475
|
+
"sha256": "2fdb42802ae0bbefe79427d7e9a5d5967a89cb2ce757b2df5f49e9da25e60703"
|
|
6466
6476
|
},
|
|
6467
6477
|
{
|
|
6468
6478
|
"path": "scripts/gds/publish-credential-check.js",
|
|
@@ -7337,7 +7347,7 @@
|
|
|
7337
7347
|
{
|
|
7338
7348
|
"path": "src/module-api.js",
|
|
7339
7349
|
"mode": "0000644",
|
|
7340
|
-
"sha256": "
|
|
7350
|
+
"sha256": "711b77fdf5d91c9b90985f8693765776cb5acfe022bd3d70e4b2ca440c5a70ed"
|
|
7341
7351
|
},
|
|
7342
7352
|
{
|
|
7343
7353
|
"path": "src/module-loader/catalog.js",
|
|
@@ -7922,7 +7932,7 @@
|
|
|
7922
7932
|
{
|
|
7923
7933
|
"path": "tests/cosmos_token_contrast.mjs",
|
|
7924
7934
|
"mode": "0000644",
|
|
7925
|
-
"sha256": "
|
|
7935
|
+
"sha256": "6e13a6d5a059684d98e350075f59b7180544bf72509dd82cc0d89b5963fe7014"
|
|
7926
7936
|
},
|
|
7927
7937
|
{
|
|
7928
7938
|
"path": "tests/cost.mjs",
|
|
@@ -9337,7 +9347,7 @@
|
|
|
9337
9347
|
{
|
|
9338
9348
|
"path": "tests/project_stats.mjs",
|
|
9339
9349
|
"mode": "0000644",
|
|
9340
|
-
"sha256": "
|
|
9350
|
+
"sha256": "8cb5533aca29727c317450cf5730f309cdb5540265f8c150a8ea2242c7ef5656"
|
|
9341
9351
|
},
|
|
9342
9352
|
{
|
|
9343
9353
|
"path": "tests/project_visibility_db.mjs",
|
|
@@ -9347,12 +9357,12 @@
|
|
|
9347
9357
|
{
|
|
9348
9358
|
"path": "tests/projects_hub.mjs",
|
|
9349
9359
|
"mode": "0000644",
|
|
9350
|
-
"sha256": "
|
|
9360
|
+
"sha256": "56e5e0968838a82984bf46923349e5dc9caa8e9437cf68dd910a67445689c1ef"
|
|
9351
9361
|
},
|
|
9352
9362
|
{
|
|
9353
9363
|
"path": "tests/projects_hub_pre_uat.mjs",
|
|
9354
9364
|
"mode": "0000644",
|
|
9355
|
-
"sha256": "
|
|
9365
|
+
"sha256": "b99f0b272d40f655726597ca14546fda9799130522cbae70ce663094d8bd6efd"
|
|
9356
9366
|
},
|
|
9357
9367
|
{
|
|
9358
9368
|
"path": "tests/promote_goal_id.mjs",
|
|
@@ -9367,7 +9377,7 @@
|
|
|
9367
9377
|
{
|
|
9368
9378
|
"path": "tests/provision.mjs",
|
|
9369
9379
|
"mode": "0000644",
|
|
9370
|
-
"sha256": "
|
|
9380
|
+
"sha256": "32f6a64ed1da1fcfe703f16ee171592262268b24eb833a171d1b5e289ad3e804"
|
|
9371
9381
|
},
|
|
9372
9382
|
{
|
|
9373
9383
|
"path": "tests/provision_restart.mjs",
|
|
@@ -9382,12 +9392,12 @@
|
|
|
9382
9392
|
{
|
|
9383
9393
|
"path": "tests/provisioning_default_domain.mjs",
|
|
9384
9394
|
"mode": "0000644",
|
|
9385
|
-
"sha256": "
|
|
9395
|
+
"sha256": "735fc1f7f3cc4b0215a23706f50ef33301cf784fb45dda096e664d306ae47565"
|
|
9386
9396
|
},
|
|
9387
9397
|
{
|
|
9388
9398
|
"path": "tests/provisioning_domain_attach.mjs",
|
|
9389
9399
|
"mode": "0000644",
|
|
9390
|
-
"sha256": "
|
|
9400
|
+
"sha256": "62ea8ffc2c21c351289dc7f96cab38fcd5824afba1fed0df7a545cd5df9e396c"
|
|
9391
9401
|
},
|
|
9392
9402
|
{
|
|
9393
9403
|
"path": "tests/provisioning_github_app_routes.mjs",
|
|
@@ -9442,7 +9452,7 @@
|
|
|
9442
9452
|
{
|
|
9443
9453
|
"path": "tests/public_landing_projects.mjs",
|
|
9444
9454
|
"mode": "0000644",
|
|
9445
|
-
"sha256": "
|
|
9455
|
+
"sha256": "6b03476a51dc69314415038b4648ff433bf1f7a811523f9e1ac0e8bffc2faf6c"
|
|
9446
9456
|
},
|
|
9447
9457
|
{
|
|
9448
9458
|
"path": "tests/public_mirror_export.mjs",
|
|
@@ -299,7 +299,7 @@ export interface PostProjectsInviteRequest { client_id: string; github_login: st
|
|
|
299
299
|
export interface PostProjectsRequest { origin: string; name: string; tagline?: string; description?: string; art_url?: string; type?: string }
|
|
300
300
|
export interface PostProjectsResponse { project: unknown }
|
|
301
301
|
export interface PostProvisioningInstancesIdDomainRequest { domain: string }
|
|
302
|
-
export interface PostProvisioningInstancesIdDomainResponse { ok: boolean; changed: boolean; queued: unknown; domain: unknown; message: unknown }
|
|
302
|
+
export interface PostProvisioningInstancesIdDomainResponse { ok: boolean; changed: boolean; queued: unknown; domain: unknown; message: unknown; replaced?: unknown }
|
|
303
303
|
export interface PostProvisioningInstancesIdForceTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
|
|
304
304
|
export interface PostProvisioningInstancesIdGithubAppRequest { account?: string }
|
|
305
305
|
export interface PostProvisioningInstancesIdGithubAppResponse { state: unknown; account: unknown; post_url: unknown; personal_url: unknown; org_url: unknown; org_login: unknown; manifest: unknown; redirect_url: unknown; expires_at: unknown }
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# ADR 0200 — A mistyped bring-your-own domain can be corrected, the address it leaves is released to a blackhole, and the attach leg stops regenerating web.env from the row
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-08-28
|
|
5
|
+
- **Task:** [task 1003237](https://cloudbongos.com/builders#/task/1003237) (goal 1000058 — the non-cloudbongos project lifecycle)
|
|
6
|
+
- **Relates to:** ADR 0111 (provisioning trust boundary), ADR 0190 (settings-apply in-place env patch — the hazard this ADR pays off), ADR 0181 (teardown state gate + address retention — the half this one does *not* touch), ADR 0133 (GitHub App Manifest cred placement), task 1002692 (the attach route), task 1002704 (the in-apex squat rule), task 1002897 (teardown never reclaims the address), task 1002720 (F16/F19 truthfulness), idea 1000842 (the `webEnvBody` hazard)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
`POST /provisioning/instances/:id/domain` refused a second address with a deliberate `409 domain_already_set`, and its comment recorded the policy in as many words: *"A genuine BYO address stays un-re-pointable, as before."* The redesign direction §8 said the opposite — *"attach/change stays for custom domains."* The pre-UAT hub review (2026-08-24) filed the contradiction as a decision rather than a UI tweak, because rendering a field that always 409s would be worse than rendering none.
|
|
11
|
+
|
|
12
|
+
The founder-facing shape of the gap: a founder types their domain into the create wizard, mistypes one character, and the project stands up permanently addressed at a hostname they do not own — with no path back except tearing the project down and starting over.
|
|
13
|
+
|
|
14
|
+
Three things made this more than a route edit.
|
|
15
|
+
|
|
16
|
+
**The address is held in more than one place.** ADR 0181 §2 decided that a *torn-down* project keeps its `port` **and** its `domain`, because the two are one coupled decision: release the port while a stale Caddy block still answers, and a later instance handed that port begins serving under the torn-down project's hostname — one owner's project under another owner's name. A re-point is the opposite case (the owner has *asked* to leave the address), so it must release, and releasing means knowing what "release" consists of.
|
|
17
|
+
|
|
18
|
+
**The runner could not see what was left behind.** The web tier overwrites `domain` the instant it records the new one, and the runner — the only tier holding a DNS token (ADR 0111 §2) — reads the row. Without a carrier, an abandoned hostname's A record would sit pointed at platform infra with nothing left in the row to say so.
|
|
19
|
+
|
|
20
|
+
**`domainAttachInstance` re-wrote `web.env` from the template.** ADR 0190 §"Why the in-place patch is load-bearing" named this: `webEnvBody(inst, …)` regenerates the file **from the row**, and the row knows neither the OAuth client id/secret `placeManifestCreds` fetched (ADR 0133), nor the App private key, nor the federation block. Today it is masked by wizard order — the address is attached *before* the GitHub App exists, so there is nothing yet to blank. **A re-point is not masked.** It runs on a project the founder is already signed in to, so the same move would break sign-in on the exact project they had just corrected. This was the hazard that made the task's scope "fix it here or depend on the fix."
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
### 1. A bring-your-own address may be re-pointed, under the guards the first attach already applied
|
|
25
|
+
|
|
26
|
+
The `409 domain_already_set` is gone. A re-point runs the same gauntlet a first attach runs, in the same order, with no clause added and none weakened:
|
|
27
|
+
|
|
28
|
+
- `normalizeHostname` must yield a real multi-label host (`400 bad_domain`);
|
|
29
|
+
- `isReservedHostname` refuses a platform-reserved name (`400 domain_reserved`);
|
|
30
|
+
- inside the platform apex, the only address an instance may hold is its own `<slug>.<apex>` — the task-1002704 squat rule (`400 domain_reserved`);
|
|
31
|
+
- `getInstanceByDomain` refuses an address another instance holds (`409 domain_taken`);
|
|
32
|
+
- `DOMAIN_ATTACH_FROM` still gates on state, and already admitted `active` (`409 domain_not_attachable`).
|
|
33
|
+
|
|
34
|
+
The platform-assigned `<slug>.<apex>` is **not** re-pointable in the sense that matters: it is the platform's own name for that slug, it cannot be pointed anywhere else, and the squat rule is what enforces that. What changes is only that a *founder-supplied* address is no longer permanent.
|
|
35
|
+
|
|
36
|
+
An `active` instance re-points through a `domain-attach` intent — the same intent, because the wiring is the same wiring, and `DOMAIN_ATTACH_FROM` already admitted `active`. A `requested`/`error` instance only records it; its next provision run wires the domain itself.
|
|
37
|
+
|
|
38
|
+
### 2. The address it leaves is released — parked at a blackhole, not deleted
|
|
39
|
+
|
|
40
|
+
`provisioning_012` adds `released_domains text[]`, written in the **same statement** as the new domain (`updateInstanceDomain`'s third argument). A re-point that recorded the new address but crashed before queueing the old one would leave a hostname aimed at platform infra with nothing in the row to say so; one statement makes that unrepresentable.
|
|
41
|
+
|
|
42
|
+
An **array**, not a scalar: a founder who mistypes once can mistype twice, and a scalar would silently drop the middle address. The runner drains the whole list and empties it (`clearReleasedDomains`).
|
|
43
|
+
|
|
44
|
+
Only a **BYO** address is ever queued, and only from a state that actually stood up (`DOMAIN_RELEASE_FROM = {error, active}`). Two exclusions, for two different reasons:
|
|
45
|
+
|
|
46
|
+
- The platform-assigned `<slug>.<apex>` — the upgrade path task 1002704 already allowed — queues nothing: that name is the platform's own, and the revive path re-uses it (ADR 0181 §2).
|
|
47
|
+
- A `requested` instance queues nothing either: it has never stood up, so nothing ever wrote an A record for the address it is leaving. Parking that name would **create** a junk record in the owner's zone rather than release one — the inverse of the leak this exists to close. An `error` row is frequently a *partial* standup that did write it (ADR 0181 §1), so it counts.
|
|
48
|
+
|
|
49
|
+
The web tier decides both, because it is the tier that knows the apex and the lifecycle state.
|
|
50
|
+
|
|
51
|
+
**The queue is capped (`MAX_RELEASED_DOMAINS`), and the route that fills it is throttled.** The runner drains this list **synchronously, one <redacted> call per entry**, and every re-point is a write an authenticated owner can repeat — `normalizeHostname` checks a hostname's *shape*, never that it exists. So an uncapped array is a resource-exhaustion vector against a **platform-wide** resource (the control plane's DNS token and rate limit, and the drain loop itself), not merely against the owner's own project. Two bounds, at different layers:
|
|
52
|
+
|
|
53
|
+
- **The cap is enforced in `updateInstanceDomain`'s own SQL**, not trusted from the caller: past the bound the append is dropped, keeping the entries most likely to name a hostname the platform really wired. Dropping is the deliberate failure mode; growing without bound is not.
|
|
54
|
+
- **The route carries a per-builder limiter** (the task-1002898 slug-check shape — keyed on the builder, since per-IP starves co-located builders while an attacker rotates IPs). It had none before: until this task the route could only *record* an address, and recording had no downstream cost.
|
|
55
|
+
|
|
56
|
+
Release is **a repoint to `192.0.2.1`, not a delete.** This is the shape `scripts/gds/box-infra.js` already proved for a torn-down box (idea 309 → task 1234), adopted here for its two reasons:
|
|
57
|
+
|
|
58
|
+
- **No NXDOMAIN window.** Deleting a name opens a gap that resolvers negative-cache for the zone's SOA neg-TTL (~30 min on Cloudflare, not builder-editable), so a client that queried mid-gap stays broken long after. A name that always resolves — to a host RFC 5737 guarantees is never routable — has nothing to negative-cache.
|
|
59
|
+
- **No new hook contract.** `BOX_DNS_HOOK` is an operator-supplied script and the core cannot assume it implements a delete mode. A release expressed as an UPSERT needs only the contract every hook already implements.
|
|
60
|
+
|
|
61
|
+
Two halves of the address release themselves and need no separate step, which is worth writing down because it is why this leg is as small as it is: the Caddy snippet is per-**slug** and always carries the *current* domain, so the same write that wires the new host takes the old vhost away; and `/provisioning/tls-check` answers from the row, so on-demand TLS stops being minted for the old name the moment the row moves.
|
|
62
|
+
|
|
63
|
+
### 3. Both legs that wire a domain drain the queue
|
|
64
|
+
|
|
65
|
+
`domainAttachInstance` owns an `active` instance. It deliberately no-ops for anything else ("provision owns pre-active domains"), so a re-point on a `requested`/`error` project would queue a release nothing ever drained — and an `error` row is frequently a *partial standup* that already UPSERTed the address it is now leaving (ADR 0181 §1). `provisionInstance` therefore drains the same queue after its own DNS step, through the same `releaseAbandonedDomains` helper. One implementation, two callers.
|
|
66
|
+
|
|
67
|
+
### 4. The release is best-effort, and the queue is the retry
|
|
68
|
+
|
|
69
|
+
Every queued address is attempted — one host whose zone the token cannot reach must not strand the others behind it — and the queue is emptied only when all of them landed. Re-parking an address already at the sentinel is an idempotent UPSERT, so retrying the whole list costs nothing but the call. A hook that fails returns `ok: true` with `releaseFailed` naming the first host that did, and **does not** clear the queue — so the next attach retries it. A release that failed must never fail a re-point that has already landed; the founder's project is answering at its new address, and re-pending the intent would restart that work four more times and end by stamping an `error_note` over a correction that worked. With no hook configured at all, the outstanding manual step is **logged by name** rather than swallowed (the F16 rule).
|
|
70
|
+
|
|
71
|
+
### 5. `domainAttachInstance` patches `web.env` in place
|
|
72
|
+
|
|
73
|
+
The leg now reads the file and patches **only** the four `<PREFIX>_*_ORIGIN` lines through `upsertEnvVars` — the `settingsApplyInstance` shape (ADR 0190 §2), with the same refusals:
|
|
74
|
+
|
|
75
|
+
- a dry run **plans** the patch and writes nothing, rather than writing a synthetic body that would read as the exact overwrite this change exists to prevent;
|
|
76
|
+
- an unreadable or empty file is **refused** (`ok: false`), never patched — four origin lines written over a missing `PORT`/`PGDATABASE` would take down an instance that is *already serving*.
|
|
77
|
+
|
|
78
|
+
`originEnvVarsFor(inst)` (pure, in `provision-units.js`) is the domain-dependent half of `webEnvBody`, factored out so the two can never drift. `webEnvBody` remains the right thing for a **first** provision, where there is no file yet and nothing to preserve.
|
|
79
|
+
|
|
80
|
+
This closes idea 1000842 for the attach path. `placeManifestCreds` still writes a full `webEnvBody` — correctly, since it is the tier that *holds* the creds it is placing.
|
|
81
|
+
|
|
82
|
+
### 6. A changed address clears the liveness overlay
|
|
83
|
+
|
|
84
|
+
`last_verified_at`/`last_verified_up` are a verdict on an **address** (task 1002696). Carrying them across a re-point would let the card say *"Answering at `right.example.com` — last answered 2 minutes ago"* when only `typo.example.com` was ever probed. Both are set to NULL when — and only when — the domain actually changes, guarded in SQL so an idempotent re-record can never blank a good probe. NULL means "never probed", which is the truth for a name nothing has asked yet; the sweep re-probes within minutes.
|
|
85
|
+
|
|
86
|
+
### 7. The card gains a third door, and says what it costs
|
|
87
|
+
|
|
88
|
+
`canAttachDomain` no longer excludes an addressed project. The fold now reads its label from what the project is actually addressed as: **Give it an address** (none), **Use a domain I own** (on the platform-assigned name), **Use a different domain** (on a BYO name), and the F19 **Try the address again** door keeps its louder, self-opening shape. The correction door pre-fills the current address — a typo is corrected by editing one character, not by retyping the whole hostname — and carries one line under the button: *"Changing it lets `<host>` go — it stops answering for this project."* Letting the old address go is said where the decision is made, not discovered afterwards.
|
|
89
|
+
|
|
90
|
+
## Consequences
|
|
91
|
+
|
|
92
|
+
- **A mistyped domain is no longer a reason to tear a project down and start over** — the founder-facing point of the whole task.
|
|
93
|
+
- **The `webEnvBody` hazard is paid off on the attach path**, which also makes the *first* attach safer than it was: it was only ever masked by wizard order, and nothing enforced that order.
|
|
94
|
+
- **An abandoned address stops reaching platform infra.** It resolves to a dead end rather than 404ing off the platform's own edge, and it is immediately re-claimable by any instance, since the uniqueness check reads the row.
|
|
95
|
+
- **The parked record is left in the founder's zone.** A true `DELETE` is available to an operator through the hook's own `BOX_DNS_DELETE` mode; the platform does not reach for it, for the neg-TTL reason above. If a founder wants the name gone entirely, that is a change in their own DNS.
|
|
96
|
+
- **[Task 1002897](https://cloudbongos.com/builders#/task/1002897) (teardown never reclaims the address) can reuse this seam** — `dnsReleaseEnv` + `DNS_BLACKHOLE_IP` are exported and shape-agnostic. It still owns the questions this ADR does not answer: whether a torn-down address 404s or serves an honest "this project ended" page, and whether the port is released with it. **ADR 0181 §2's retention decision is untouched here**: a torn-down project still keeps its address, deliberately, because the revive path re-uses it.
|
|
97
|
+
- **A re-point costs a service restart**, like every other change that reaches a running instance's memoized branding pack (ADR 0190 §3).
|
|
98
|
+
- **The cap can, in principle, drop an address.** Only past `MAX_RELEASED_DOMAINS` queued releases on one instance — a state a founder correcting a typo cannot reach, and one the route's limiter makes slow to reach deliberately. The dropped hostname keeps its record until an operator removes it; that is strictly better than letting one owner queue unbounded work against the shared token.
|
|
99
|
+
|
|
100
|
+
## Alternatives considered
|
|
101
|
+
|
|
102
|
+
- **Amend direction §8 and make the card say the address is fixed once set.** The task's other branch. Rejected by the owner: a founder who mistypes a domain would have no path back but teardown, which loses the project's database and repo wiring for a one-character error.
|
|
103
|
+
- **Delete the old A record instead of parking it.** Cleaner in the founder's zone, but re-opens the NXDOMAIN negative-cache window the box lane already learned to avoid (idea 309), and assumes a hook mode the core cannot guarantee.
|
|
104
|
+
- **Sequence this task behind 1002897.** The owner's decision allowed either order. Carving the release leg here was chosen because the hazard in §4 is on *this* path and a re-point that leaked its old address would ship a known leak in the name of ordering.
|
|
105
|
+
- **A `previous_domain` scalar instead of an array.** One column less, but it silently drops the middle address when a founder corrects twice before the runner drains — the exact user this feature is for.
|
package/docs/adr/README.md
CHANGED
|
@@ -287,5 +287,6 @@ This keeps the decision history honest and traceable.
|
|
|
287
287
|
| 0197 | [**The ui-design module: design is a platform capability; the instance owns its world** ([task 1003324](https://cloudbongos.com/builders#/task/1003324), goal 1000080 — the first of the five ui-design tasks scoped with the owner 2026-08-28). ADR 0081 put the tool-agnostic design layer in core as Cloud Bongos's machinery; the whole-frontend pass then built the chrome world on it and left the three things a builder needs — the contract and its tooling, a way to look before shipping, the taste and the looks — scattered across core, scratchpads and personal skill installs. The owner's reframing: this is NOT the front door, it is a PLATFORM capability every builder on every instance gets, and Cloud Bongos's front door is its first customer, not its owner. Decisions: (1) `modules/ui-design/` is a default-on core-domain module beside grading/economy/memory — it ships METHOD, never a world; (2) ADR 0081's layer moves in (`src/ui/adapters/` → `adapters/`, the three `scripts/gds/` CLIs → `scripts/`, `docs/design-contract.md` → `docs/`) while `config/design-tokens.*`, `design-sources.json` and `DESIGN.md` STAY out as the host boundary — the ADR 0062 §7 split written for design; (3) declaration-only: three contributed skills, no routes/port/migrations, so `GET /modules` lists it and disabling it withdraws the skills and touches no served surface — and NO `ui` discipline yet, because the hall settings page and newcomer-restock don't know it; (4) the `/design` playbook is finally written — `discipline-modes.json` had routed `ui` tasks to a skill that did not exist since task 1267; (5) the module CLAUDE.md draws the platform FLOORS (the Fifteen Rule, the dark twins, no page `:root`, the 24px floor, AA in both modes, the Kill Switch) against the instance's WORLD (its packs + DESIGN.md), tightenable and never loosenable; (6) the CLIs keep thin `scripts/gds/` shims — the form `claude-materialize` rewrites to `bongos exec` on a packaged core, the form `doc-cli-guard` resolves, and the carve precedent — while inside the module they walk up from `__dirname` instead of the computed `require()` into `src/instance-config.js` the static boundary scanner could not see; (7) three reserved homes, each README'd for the task that fills it, the vendoring policy pointed at the skills task's ADR; (8) `public-landing` keeps its own key. Rejected: leaving the layer in core; moving the token files in; the module owning the front door; module-hosted CLIs with no shims; contributing the `ui` discipline now.](<redacted>.md) | modules / design system |
|
|
288
288
|
| 0199 | [**An unreachable ACTIVE project gets a restart of its own, not a re-provision — and the restart never claims the verdict its probe cannot reach** ([task 1003238](https://cloudbongos.com/builders#/task/1003238), goal 1000058). The liveness overlay (task 1002696) could report a project unreachable while its status stayed `active`, and that reading came with no action: `PROVISION_ENQUEUE_FROM` deliberately excludes `active` (task 1002691 — a blind re-enqueue left a stale provision intent blocking the owner’s own teardown), so the card’s existing *Try again* / *Bring it back* doors 409 on an active project by construction, and `settings-apply` — the only leg that runs from `active` — refuses unless a stored value actually changed, which is exactly the case a stuck project does not have. Decisions: (1) a `restart` intent (migration `provisioning_011`, `INTENT_ACTIONS` in lockstep) behind `RESTART_FROM = {active}` + `RESTART_SHAPES = {co-tenant, standalone}`; the web tier still only ENQUEUES (ADR 0111 §2). (2) `restartInstance` is `settingsApplyInstance` MINUS the env patch — one `systemctl restart`, then the same patient healthz budget; it reads and writes no file, so ADR 0190’s in-place-patch hazard cannot arise. (3) The `probeIsVerdict` narrowness carries over and is load-bearing: the liveness sweep probes the PUBLIC `https://<domain>/healthz` while the runner verifies LOOPBACK, so a project can answer here while DNS/Caddy/TLS is what is broken — no up-verdict is written for a domained instance, and the event says “answering on the box; whether its public address answers is for the next sweep to say” rather than a sentence the still-`unreachable` card would contradict. (4) A project that stays down is `ok:true` — the restart RAN; re-pending it to the attempt cap would restart a broken project four more times and end by stamping an `error_note` over the owner’s own action. Only a THROW returns `ok:false`, and it returns rather than throws because the drain loop’s catch would relabel a merely-unreachable instance `error` (ADR 0190 §2). (5) `enqueueRestart` is idempotent against its own kind in EITHER open state — where it differs from the settings push, which must refuse to ride a RUNNING sibling that may have read the row already; a restart carries no payload, so one already running IS the ask. (6) A pending restart joins the teardown’s supersede list, more sharply than its siblings since the owner reaches for Restart exactly when they might next give up and delete. (7) The door shows only at `active && last_verified_up === false && shape !== dedicated && !open_intent`, mirrored on card and manage page; `null` (never probed) is NOT `false` and raises no door. (8) Every refusal names the action that IS available there, the state gate is checked before the shape gate, and no branch promises a duration (F16). The `INTENT_ACTIONS`↔migration set-equality assertion moved to the NEWEST migration’s test — pinned to 010 it would fail for every future action. Rejected: widening `PROVISION_ENQUEUE_FROM`; re-sending unchanged settings to borrow their restart; reporting a loopback pass as “answering again”; retrying a restart that left the project down; a Restart door on every active card.](<redacted>.md) | provisioning / project lifecycle |
|
|
289
289
|
| 0198 | [**Third-party skill vendoring: a scan verdict the session cannot override, a licence allowlist, a provenance sidecar, one preamble block, and no auto-update** ([task 1003321](https://cloudbongos.com/builders#/task/1003321), goal 1000080 — the second of the five ui-design tasks). Twelve design skills installed on one builder's machine were to become the `ui-design` module's vendored set. Both origins reduced to DANGEROUS under `/scan-before-install` at the default tier: `Leonxlnx/taste-skill` on one floor critical (an injection-phrase hit the panel identifies as a filename placeholder) with a caution panel; `pbakaus/impeccable` on three floor criticals and a panel that upheld shipped PostToolUse/Stop hooks written into five harness configs, a child agent spawned with permissions bypassed from a loopback HTTP route, a directive telling the model to disregard its harness system prompt, a page-embedded live-server token and an unverified remote bundle download. DECISION: the scan verdict is the gate and a session cannot override it — `dangerous` lands a rebuild spec (a GDS task), never a copy, and vendoring one anyway is an owner ADR plus a test amendment; a licence allowlist (Apache-2.0, MIT, BSD-2/3, CC-BY-4.0); a `PROVENANCE.md` sidecar with the full pinned sha; ONE preamble block (`skills/PREAMBLE.md`, byte-identical, fenced by two markers so an upstream refresh is a three-way merge) that reads the instance's world before any taste rule; `skills/vendor/<name>/` as the home because `fitness-ratchets.js` already exempts `vendor/` from the first-party budgets; the manifest stays the single declaration and `claude-materialize.js` step 1b lands a declared module skill — sidecar included — in every instance's `.claude/skills/` and withdraws it with the module; no auto-update; the playwright plugin a documented prerequisite. The roster ships EMPTY and that is the policy working: the machinery is proven by fixture (`tests/ui_design_skills.mjs`), the twelve are named in `/design` with their verdicts, two rebuild-spec tasks hold the documented functionality. Rejected: treating the placeholder hit as a false positive; scanning a fork or subtree; vendoring impeccable with the hooks stripped; `.claude/skills/` as the home; a second roster file.](<redacted>.md) | modules / design system / security |
|
|
290
|
+
| 0200 | [**A mistyped bring-your-own domain can be corrected — the address it leaves is released to a blackhole, and the attach leg stops regenerating web.env from the row** ([task 1003237](https://cloudbongos.com/builders#/task/1003237), goal 1000058). `POST /provisioning/instances/:id/domain` refused a second address with a deliberate `409 domain_already_set` ("A genuine BYO address stays un-re-pointable, as before") while direction §8 said "attach/change stays for custom domains" — so a founder who mistyped one character in the create wizard was permanently addressed at a hostname they did not own, with no path back but teardown. Decisions: (1) a BYO address re-points under the guards the FIRST attach already applied — `isReservedHostname`, the task-1002704 in-apex squat rule, `getInstanceByDomain` uniqueness, `DOMAIN_ATTACH_FROM` (which already admitted `active`) — none added, none weakened; the platform-assigned `<slug>.<apex>` is un-re-pointable because the squat rule says so. (2) The address it leaves is RELEASED: `provisioning_012` adds `released_domains text[]`, written in the SAME statement as the new domain (a crash between the two would leave a hostname aimed at platform infra with nothing in the row to say so), an ARRAY because a founder can mistype twice before the runner drains. Only a BYO address is queued — the assigned `<slug>.<apex>` is the platform’s own name and the revive path re-uses it (ADR 0181 §2). (3) Release is a REPOINT to `192.0.2.1` (RFC 5737 TEST-NET-1), not a delete — the box lane’s idea-309 shape: a delete opens an NXDOMAIN window resolvers negative-cache for the zone’s SOA neg-TTL (~30 min, not editable), and an UPSERT needs only the contract every operator `BOX_DNS_HOOK` already implements. The Caddy vhost and the tls-check allow-list release THEMSELVES (the snippet is per-slug and carries the current domain; tls-check answers from the row). (4) A failed release is `ok:true` + `releaseFailed`, and KEEPS the queue so the next attach retries — a release that failed must never fail a re-point that already landed. (5) `domainAttachInstance` now patches web.env IN PLACE via `upsertEnvVars`/`originEnvVarsFor`, closing the ADR 0190 §2 hazard (idea 1000842) on this path: the template re-write regenerated the file FROM THE ROW, blanking the OAuth creds `placeManifestCreds` placed, the App private key and the federation block — masked for a FIRST attach by wizard order, and NOT masked for a re-point, which runs on a project the founder is already signed in to. Dry-run plans; an unreadable/empty file is refused, never patched. (6) A CHANGED domain clears `last_verified_{at,up}` — the overlay is a verdict on an ADDRESS (task 1002696), so carrying it would let the card claim the new name "last answered 2 minutes ago" when only the old one was ever probed (F16). (7) The card gains a third door — *Use a different domain*, pre-filled so a typo is edited not retyped — and says what it costs where the button is. Rejected: amending direction §8 to call the address fixed; deleting the old record; sequencing behind task 1002897; a `previous_domain` scalar (drops the middle address).](<redacted>.md) | provisioning / project lifecycle |
|
|
290
291
|
|
|
291
292
|
> ⚠️ **Numbering collisions are now machine-enforced, not narrated.** Twenty numbers are shared by two ADRs each — assigned in parallel sessions before anything checked. The files keep their filenames (renumbering would break every existing citation, and a number once assigned is never reused), and this table disambiguates each pair as `NNNN-a` / `NNNN-b`. The authoritative list is `LEGACY_DUPLICATE_ADRS` in [`scripts/gds/adr-namespace.js`](../../scripts/gds/adr-namespace.js), frozen by exact filename: a **new** collision — or a third file joining a legacy number, or a rename of either half — hard-fails the `unit` CI gate, as does an index row that points at no file or an ADR with no row. The list may only shrink. This paragraph used to narrate the collisions one by one and had fallen eight behind reality; see [ADR 0195](<redacted>.md) for why the check exists and why the pairs are grandfathered rather than renumbered.
|
package/docs/api/openapi.json
CHANGED
|
@@ -10425,7 +10425,7 @@
|
|
|
10425
10425
|
"provisioning"
|
|
10426
10426
|
],
|
|
10427
10427
|
"summary": "POST /provisioning/instances/:id/domain",
|
|
10428
|
-
"description": "POST /provisioning/instances/:id/domain — give the caller's OWN instance its address (task 1002692, gap 5: no path existed to add a domain after creation). Validates + records the domain; for an already-ACTIVE instance it also enqueues a 'domain-attach' intent the control-plane runner drains (web tier holds no cloud tokens — ADR 0111 §2). A requested/error instance only records it: the (re)provision run wires the domain itself.
|
|
10428
|
+
"description": "POST /provisioning/instances/:id/domain — give the caller's OWN instance its address (task 1002692, gap 5: no path existed to add a domain after creation). Validates + records the domain; for an already-ACTIVE instance it also enqueues a 'domain-attach' intent the control-plane runner drains (web tier holds no cloud tokens — ADR 0111 §2). A requested/error instance only records it: the (re)provision run wires the domain itself. A bring-your-own address may be RE-POINTED (task 1003237, ADR 0200): the same guards the first attach applies decide it, and the address it moved off is queued for release. Body: { domain (required) }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
10429
10429
|
"x-rank": "any-builder",
|
|
10430
10430
|
"x-source": "modules/provisioning/routes/provisioning.js",
|
|
10431
10431
|
"parameters": [
|
|
@@ -19147,7 +19147,8 @@
|
|
|
19147
19147
|
},
|
|
19148
19148
|
"queued": {},
|
|
19149
19149
|
"domain": {},
|
|
19150
|
-
"message": {}
|
|
19150
|
+
"message": {},
|
|
19151
|
+
"replaced": {}
|
|
19151
19152
|
},
|
|
19152
19153
|
"required": [
|
|
19153
19154
|
"ok",
|