@bongos/core 1.19.399 → 1.19.400
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 +47 -27
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +3 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/adr/0199-restart-an-unreachable-active-project.md +49 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +74 -3
- package/docs/api-reference.md +3 -2
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/provisioning/migrations/provisioning_011_restart.sql +28 -0
- package/modules/provisioning/provisioning.js +42 -4
- package/modules/provisioning/routes/provisioning.js +59 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/projects.html +88 -3
- package/scripts/gds/provision.js +104 -0
- package/src/module-api.js +3 -1
- package/tests/projects_hub_pre_uat.mjs +40 -0
- package/tests/provision_restart.mjs +242 -0
- package/tests/provisioning_restart.mjs +285 -0
- package/tests/provisioning_settings_apply.mjs +8 -3
- package/tests/provisioning_teardown_intent.mjs +9 -5
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.400",
|
|
6
|
+
"core_contract": "1.19.400",
|
|
7
|
+
"source_commit": "ebdbf689ffd8199fd47b418893de09f36d41578c",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-28T19:01:55.609Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 349,
|
|
13
13
|
"agent_docs_stubbed": 23,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1661,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 2033,
|
|
20
|
+
"tree_sha256": "ef49c427da55256bbb05e98dcdcf82cf504f930cca4cebf8e022bae2720b71f7",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -352,12 +352,12 @@
|
|
|
352
352
|
{
|
|
353
353
|
"path": "clients/bongos-client/README.md",
|
|
354
354
|
"mode": "0000644",
|
|
355
|
-
"sha256": "
|
|
355
|
+
"sha256": "96114ae5652241ae3bbc07b4b80cf744080d64831afaf684c4f8ec9b6f0da251"
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
"path": "clients/bongos-client/bongos-client.global.js",
|
|
359
359
|
"mode": "0000644",
|
|
360
|
-
"sha256": "
|
|
360
|
+
"sha256": "01949893edb52a4f393c3535159bf5ff8b93c7fad28fe451425cee73ea2a81d2"
|
|
361
361
|
},
|
|
362
362
|
{
|
|
363
363
|
"path": "clients/bongos-client/examples/hello-world.mjs",
|
|
@@ -367,17 +367,17 @@
|
|
|
367
367
|
{
|
|
368
368
|
"path": "clients/bongos-client/index.cjs",
|
|
369
369
|
"mode": "0000644",
|
|
370
|
-
"sha256": "
|
|
370
|
+
"sha256": "d20f616bddbd837754dcd8809b4db17d304e94aca5fd001d528b8b50d2358292"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"path": "clients/bongos-client/index.d.ts",
|
|
374
374
|
"mode": "0000644",
|
|
375
|
-
"sha256": "
|
|
375
|
+
"sha256": "1edab64d6ab54ccf2e4605b0272f7f692fd6c020c24415a0abc9fdb1d2ac24fb"
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
378
|
"path": "clients/bongos-client/index.mjs",
|
|
379
379
|
"mode": "0000644",
|
|
380
|
-
"sha256": "
|
|
380
|
+
"sha256": "a08520e80ffa8e11dfedcb83873cd3ad369dd9dcca9c4cf101449f73691fe42c"
|
|
381
381
|
},
|
|
382
382
|
{
|
|
383
383
|
"path": "clients/bongos-client/package.json",
|
|
@@ -1494,20 +1494,25 @@
|
|
|
1494
1494
|
"mode": "0000644",
|
|
1495
1495
|
"sha256": "f56d8dfb794186e5a4424d87d40b3ad72cc0fd9872b58c5952aa7313c4f5285a"
|
|
1496
1496
|
},
|
|
1497
|
+
{
|
|
1498
|
+
"path": "docs/adr/0199-restart-an-unreachable-active-project.md",
|
|
1499
|
+
"mode": "0000644",
|
|
1500
|
+
"sha256": "999c2eb382b51317a4f1fbf7a615855be7baeded04cf03c4e1a411b2f98386cd"
|
|
1501
|
+
},
|
|
1497
1502
|
{
|
|
1498
1503
|
"path": "docs/adr/README.md",
|
|
1499
1504
|
"mode": "0000644",
|
|
1500
|
-
"sha256": "
|
|
1505
|
+
"sha256": "823b42a6811419c2a89e3b09e7049ca0e3eea5bcafb87e463e7d7762ae7cd9e4"
|
|
1501
1506
|
},
|
|
1502
1507
|
{
|
|
1503
1508
|
"path": "docs/api-reference.md",
|
|
1504
1509
|
"mode": "0000644",
|
|
1505
|
-
"sha256": "
|
|
1510
|
+
"sha256": "005be3f999c348371b0adf79234454cecfb93d9448d2faf952bd816bb18ad9a4"
|
|
1506
1511
|
},
|
|
1507
1512
|
{
|
|
1508
1513
|
"path": "docs/api/openapi.json",
|
|
1509
1514
|
"mode": "0000644",
|
|
1510
|
-
"sha256": "
|
|
1515
|
+
"sha256": "3d48a3120bc31be0516645a8d0f730042678b921108f94d548f4e37adfa5aa88"
|
|
1511
1516
|
},
|
|
1512
1517
|
{
|
|
1513
1518
|
"path": "docs/architecture.md",
|
|
@@ -3137,7 +3142,7 @@
|
|
|
3137
3142
|
{
|
|
3138
3143
|
"path": "modules/dev-box/app/src/vendor/bongos-client.cjs",
|
|
3139
3144
|
"mode": "0000644",
|
|
3140
|
-
"sha256": "
|
|
3145
|
+
"sha256": "d20f616bddbd837754dcd8809b4db17d304e94aca5fd001d528b8b50d2358292"
|
|
3141
3146
|
},
|
|
3142
3147
|
{
|
|
3143
3148
|
"path": "modules/dev-box/app/test/unit.mjs",
|
|
@@ -4844,6 +4849,11 @@
|
|
|
4844
4849
|
"mode": "0000644",
|
|
4845
4850
|
"sha256": "416296ce60ce307628909d1847e52d024fd09fb8f882c0afe9db42331d06dc21"
|
|
4846
4851
|
},
|
|
4852
|
+
{
|
|
4853
|
+
"path": "modules/provisioning/migrations/provisioning_011_restart.sql",
|
|
4854
|
+
"mode": "0000644",
|
|
4855
|
+
"sha256": "99b0e59f165255643ba4d2a9e9c200985a7d4b162d93c1d169b0f738e9e09c77"
|
|
4856
|
+
},
|
|
4847
4857
|
{
|
|
4848
4858
|
"path": "modules/provisioning/module.json",
|
|
4849
4859
|
"mode": "0000644",
|
|
@@ -4862,7 +4872,7 @@
|
|
|
4862
4872
|
{
|
|
4863
4873
|
"path": "modules/provisioning/provisioning.js",
|
|
4864
4874
|
"mode": "0000644",
|
|
4865
|
-
"sha256": "
|
|
4875
|
+
"sha256": "e2b1f1a1f7146a1a76d5704671b0418026d4d6063e4c267eef47f9e618e5addb"
|
|
4866
4876
|
},
|
|
4867
4877
|
{
|
|
4868
4878
|
"path": "modules/provisioning/rate-limit.js",
|
|
@@ -4872,7 +4882,7 @@
|
|
|
4872
4882
|
{
|
|
4873
4883
|
"path": "modules/provisioning/routes/provisioning.js",
|
|
4874
4884
|
"mode": "0000644",
|
|
4875
|
-
"sha256": "
|
|
4885
|
+
"sha256": "2b15cecbbd0cf685398248ba754519b2a1f70ce808684f7c5152361eee57d230"
|
|
4876
4886
|
},
|
|
4877
4887
|
{
|
|
4878
4888
|
"path": "modules/provisioning/tests/liveness.mjs",
|
|
@@ -5307,12 +5317,12 @@
|
|
|
5307
5317
|
{
|
|
5308
5318
|
"path": "package-lock.json",
|
|
5309
5319
|
"mode": "0000644",
|
|
5310
|
-
"sha256": "
|
|
5320
|
+
"sha256": "a00a15392d358cca4d6a2dc6b282b61e23027631341a886e2ec5b371ab55f087"
|
|
5311
5321
|
},
|
|
5312
5322
|
{
|
|
5313
5323
|
"path": "package.json",
|
|
5314
5324
|
"mode": "0000644",
|
|
5315
|
-
"sha256": "
|
|
5325
|
+
"sha256": "cdb94db3e76a9fc556294eff04140ab2b2cc20e4824fc9291f3936879b6f1346"
|
|
5316
5326
|
},
|
|
5317
5327
|
{
|
|
5318
5328
|
"path": "public-docs/index.html",
|
|
@@ -5662,7 +5672,7 @@
|
|
|
5662
5672
|
{
|
|
5663
5673
|
"path": "public-landing/projects.html",
|
|
5664
5674
|
"mode": "0000644",
|
|
5665
|
-
"sha256": "
|
|
5675
|
+
"sha256": "8795a04bddd0e340a8202c4c3e160acd787ed0fafd663be2a439c7e4d2f0f69d"
|
|
5666
5676
|
},
|
|
5667
5677
|
{
|
|
5668
5678
|
"path": "public-landing/projects.probes.json",
|
|
@@ -6452,7 +6462,7 @@
|
|
|
6452
6462
|
{
|
|
6453
6463
|
"path": "scripts/gds/provision.js",
|
|
6454
6464
|
"mode": "0000644",
|
|
6455
|
-
"sha256": "
|
|
6465
|
+
"sha256": "abb85df9aab1f21a09a85fd430acca0261a1602a4b23ad0048e159aeda33f22e"
|
|
6456
6466
|
},
|
|
6457
6467
|
{
|
|
6458
6468
|
"path": "scripts/gds/publish-credential-check.js",
|
|
@@ -7327,7 +7337,7 @@
|
|
|
7327
7337
|
{
|
|
7328
7338
|
"path": "src/module-api.js",
|
|
7329
7339
|
"mode": "0000644",
|
|
7330
|
-
"sha256": "
|
|
7340
|
+
"sha256": "6ca3250ee5b3dbcfdae58ec3c4cf101ee616c7c75d6fae0e989f05017f767a60"
|
|
7331
7341
|
},
|
|
7332
7342
|
{
|
|
7333
7343
|
"path": "src/module-loader/catalog.js",
|
|
@@ -9342,7 +9352,7 @@
|
|
|
9342
9352
|
{
|
|
9343
9353
|
"path": "tests/projects_hub_pre_uat.mjs",
|
|
9344
9354
|
"mode": "0000644",
|
|
9345
|
-
"sha256": "
|
|
9355
|
+
"sha256": "462839095ba235057036b2e05b40f3214b7d18b2714f4ce6d5f1e05a207ad37b"
|
|
9346
9356
|
},
|
|
9347
9357
|
{
|
|
9348
9358
|
"path": "tests/promote_goal_id.mjs",
|
|
@@ -9359,6 +9369,11 @@
|
|
|
9359
9369
|
"mode": "0000644",
|
|
9360
9370
|
"sha256": "0fc6c6626b43458c2e065322bec5a2ecd87e50a44abd2838d81ff0f0b6abeae7"
|
|
9361
9371
|
},
|
|
9372
|
+
{
|
|
9373
|
+
"path": "tests/provision_restart.mjs",
|
|
9374
|
+
"mode": "0000644",
|
|
9375
|
+
"sha256": "a691cdc7b2500ca3f4fbea16bd2ffdb9743c5bf98983ff7b94fecd900cd42387"
|
|
9376
|
+
},
|
|
9362
9377
|
{
|
|
9363
9378
|
"path": "tests/provision_settings_apply.mjs",
|
|
9364
9379
|
"mode": "0000644",
|
|
@@ -9384,6 +9399,11 @@
|
|
|
9384
9399
|
"mode": "0000644",
|
|
9385
9400
|
"sha256": "97d04ee39cc06b720d4a5b42f3e3cc614f64d9462b27471a1af7598b5e2929be"
|
|
9386
9401
|
},
|
|
9402
|
+
{
|
|
9403
|
+
"path": "tests/provisioning_restart.mjs",
|
|
9404
|
+
"mode": "0000644",
|
|
9405
|
+
"sha256": "b4d57f8b32e0b6e7ab22e2c30c07b5fa622e63d6b29e5c4cca367d3603565874"
|
|
9406
|
+
},
|
|
9387
9407
|
{
|
|
9388
9408
|
"path": "tests/provisioning_settings.mjs",
|
|
9389
9409
|
"mode": "0000644",
|
|
@@ -9392,7 +9412,7 @@
|
|
|
9392
9412
|
{
|
|
9393
9413
|
"path": "tests/provisioning_settings_apply.mjs",
|
|
9394
9414
|
"mode": "0000644",
|
|
9395
|
-
"sha256": "
|
|
9415
|
+
"sha256": "f36148bcb14a666c95ddc4f0ac4d59af2e5409db01fcf338930a813a7f383f76"
|
|
9396
9416
|
},
|
|
9397
9417
|
{
|
|
9398
9418
|
"path": "tests/provisioning_settings_env.mjs",
|
|
@@ -9407,7 +9427,7 @@
|
|
|
9407
9427
|
{
|
|
9408
9428
|
"path": "tests/provisioning_teardown_intent.mjs",
|
|
9409
9429
|
"mode": "0000644",
|
|
9410
|
-
"sha256": "
|
|
9430
|
+
"sha256": "4a732a0e5f89b9251926f87b5fc37a07e0421487813b9e97b124fc670821fa78"
|
|
9411
9431
|
},
|
|
9412
9432
|
{
|
|
9413
9433
|
"path": "tests/provisioning_teardown_states.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
|
+
- 325 operations across 52 resource groups
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -621,6 +621,8 @@ function createClient(opts = {}) {
|
|
|
621
621
|
postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
|
|
622
622
|
// POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
|
|
623
623
|
postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
|
|
624
|
+
// POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
|
|
625
|
+
postProvisioningInstancesIdRestart: (args) => request("POST", "/provisioning/instances/{id}/restart", { hasBody: true }, args),
|
|
624
626
|
// GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
|
|
625
627
|
getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
|
|
626
628
|
// PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
|
|
@@ -620,6 +620,8 @@ function createClient(opts = {}) {
|
|
|
620
620
|
postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
|
|
621
621
|
// POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
|
|
622
622
|
postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
|
|
623
|
+
// POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
|
|
624
|
+
postProvisioningInstancesIdRestart: (args) => request("POST", "/provisioning/instances/{id}/restart", { hasBody: true }, args),
|
|
623
625
|
// GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
|
|
624
626
|
getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
|
|
625
627
|
// PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
|
|
@@ -303,6 +303,7 @@ export interface PostProvisioningInstancesIdDomainResponse { ok: boolean; change
|
|
|
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 }
|
|
306
|
+
export interface PostProvisioningInstancesIdRestartResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; message: unknown }
|
|
306
307
|
export interface PostProvisioningInstancesIdTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
|
|
307
308
|
export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; no_address?: boolean; tier?: string; onboard_mode?: string; type?: string }
|
|
308
309
|
export interface PostSearchMarkRequest { chunk_id?: StringifiableId; useful?: unknown }
|
|
@@ -913,6 +914,8 @@ export interface BongosClient {
|
|
|
913
914
|
postProvisioningInstancesIdForceTeardown(args?: RequestArgs): Promise<PostProvisioningInstancesIdForceTeardownResponse>;
|
|
914
915
|
/** POST /provisioning/instances/{id}/github-app — rank: any-builder */
|
|
915
916
|
postProvisioningInstancesIdGithubApp(args?: RequestArgs & { body?: PostProvisioningInstancesIdGithubAppRequest }): Promise<PostProvisioningInstancesIdGithubAppResponse>;
|
|
917
|
+
/** POST /provisioning/instances/{id}/restart — rank: any-builder */
|
|
918
|
+
postProvisioningInstancesIdRestart(args?: RequestArgs): Promise<PostProvisioningInstancesIdRestartResponse>;
|
|
916
919
|
/** GET /provisioning/instances/{id}/settings — rank: any-builder */
|
|
917
920
|
getProvisioningInstancesIdSettings(args?: RequestArgs): Promise<GetProvisioningInstancesIdSettingsResponse>;
|
|
918
921
|
/** PATCH /provisioning/instances/{id}/settings — rank: any-builder */
|
|
@@ -617,6 +617,8 @@ export function createClient(opts = {}) {
|
|
|
617
617
|
postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
|
|
618
618
|
// POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
|
|
619
619
|
postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
|
|
620
|
+
// POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
|
|
621
|
+
postProvisioningInstancesIdRestart: (args) => request("POST", "/provisioning/instances/{id}/restart", { hasBody: true }, args),
|
|
620
622
|
// GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
|
|
621
623
|
getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
|
|
622
624
|
// PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# ADR 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
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-08-28
|
|
5
|
+
- **Task:** [task 1003238](https://cloudbongos.com/builders#/task/1003238) (goal 1000058 — the non-cloudbongos project lifecycle)
|
|
6
|
+
- **Relates to:** ADR 0111 (provisioning trust boundary), ADR 0190 (settings-apply in-place env patch — the leg this one is carved from), ADR 0181 (teardown state gate + address retention), task 1002696 (the liveness overlay), task 1002691 (the open-intent slot), task 1002720 (F16/F19/F23 truthfulness)
|
|
7
|
+
|
|
8
|
+
> ADR **0198** is reserved by task 1003321, in flight in another session at the time of writing; this ADR takes 0199 rather than race it. The gap is deliberate.
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
|
|
12
|
+
The liveness overlay (task 1002696) is an *overlay*, never a seventh state: a project whose heartbeat cannot reach it is still `status='active'`, and the hub renders that reading four ways — an `unreachable` chip, an ashen orb, a "Not answering at …" address row, and a "Needs you" filter bucket.
|
|
13
|
+
|
|
14
|
+
None of them came with an action. The pre-UAT hub review (2026-08-24) recorded why: `PROVISION_ENQUEUE_FROM` is `{requested, provisioning, error, torn_down}` and **deliberately excludes `active`** (task 1002691 — a blind re-enqueue on a slug re-request left a stale open provision intent that then blocked the owner's own teardown). So the two re-enqueue doors the card already has, *Try again* and *Bring it back*, both refuse on an active project by construction. A Restart wired to that POST would have 409'd on every press, which is why the finding was filed as a task rather than fixed as a UI tweak.
|
|
15
|
+
|
|
16
|
+
`settings-apply` (ADR 0190) is the only existing action that runs *from* `active`, and it does restart the service — but only as the tail of a change whose value differs from the stored row (ADR 0190 §6: a save that changes nothing neither writes nor restarts). The one case where restarting is the whole point is exactly the case that leg refuses.
|
|
17
|
+
|
|
18
|
+
## Decision
|
|
19
|
+
|
|
20
|
+
1. **A `restart` intent** (migration `provisioning_011`, `INTENT_ACTIONS` in lockstep). `POST /provisioning/instances/:id/restart` gates on `RESTART_FROM = {active}` and `RESTART_SHAPES = {co-tenant, standalone}`, then enqueues; the control-plane runner performs it. The web tier still only enqueues — the trust boundary is unchanged (ADR 0111 §2).
|
|
21
|
+
|
|
22
|
+
2. **The runner leg is `settingsApplyInstance` minus the env patch.** `restartInstance` does one `systemctl restart <slug>` and then the same **patient** healthz verify (`MANIFEST_VERIFY_TRIES × MANIFEST_VERIFY_INTERVAL_MS`, the F23 lesson). It reads and writes **no file at all** — nothing about the instance's configuration is changing, so the in-place-patch hazard ADR 0190 exists to avoid does not arise here.
|
|
23
|
+
|
|
24
|
+
3. **The probe result is recorded with the same narrowness, and the event says which probe answered.** `probeIsVerdict = healthy === false || (healthy === true && !inst.domain)` — carried over verbatim, and it is load-bearing in a way worth naming: **the liveness sweep probes the public `https://<domain>/healthz` while the runner's verify probes loopback.** So a project can answer here while DNS, Caddy or TLS is the thing actually broken. The leg therefore never writes an up-verdict for a domained instance, and its event says *"restarted and answering on the box; whether its public address answers is for the next liveness sweep to say"* rather than "answering again" — a sentence the card, still reading `unreachable`, would contradict.
|
|
25
|
+
|
|
26
|
+
4. **A project that stays down is `ok:true`.** The restart *ran*; the instance not coming back is a truthful observation for the card, not a failed intent. Returning `ok:false` would re-pend it to `MAX_INTENT_ATTEMPTS`, restart a broken project four more times, and end by stamping an `error_note` over the owner's own deliberate action. Only a restart that **throws** returns `ok:false` — and it returns rather than throws, because the drain loop's `catch` flips the instance to `error`, and an instance that is merely unreachable must never be relabelled broken by the action meant to recover it (ADR 0190 §2).
|
|
27
|
+
|
|
28
|
+
5. **`enqueueRestart` is idempotent against its own kind in EITHER open state** — where it deliberately differs from `enqueueSettingsApply`. That one must refuse to ride a *running* sibling, because the runner may have read the settings row before this write, so the in-flight run would not carry the change. A restart carries no payload: one already running **is** the thing the owner asked for, so "already under way" is the truth, not a swallowed request. Any other action holding the single open slot is `409 intent_conflict`, naming it.
|
|
29
|
+
|
|
30
|
+
6. **A pending restart yields to a teardown.** It joins `provision` and `settings-apply` in `enqueueTeardown`'s supersede list — and more sharply than either, since the owner reaches for Restart precisely when a project looks broken, which is also when they give up and delete it. A running intent is still never yanked.
|
|
31
|
+
|
|
32
|
+
7. **The door appears only where it has a reason to exist:** `status === 'active' && last_verified_up === false && hosting_shape !== 'dedicated' && !open_intent`, mirrored on the list card and the manage page so the two can never disagree. `last_verified_up === null` (never probed) is **not** the same claim as `false` and does not raise the door — the distinction `publicInstance` maintains on purpose. A Restart button on every healthy card would only invite needless downtime.
|
|
33
|
+
|
|
34
|
+
8. **Every refusal names the action that IS available in that state**, and no branch promises a duration (the F16 rule): an offline or snagged project is told to stand it up again; a pre-active one that it hasn't finished standing up; a dedicated droplet is refused honestly and given the exact `systemctl restart <slug>` for whoever runs that machine. The state gate is checked before the shape gate, so a torn-down droplet hears the more useful of the two refusals.
|
|
35
|
+
|
|
36
|
+
## Consequences
|
|
37
|
+
|
|
38
|
+
- The "Needs you" bucket finally has a door: an owner whose project stopped answering can act on it themselves instead of only being told the platform keeps checking. The address row's sentence now names that action.
|
|
39
|
+
- A restart is visible while it runs — its own `FLOWS.restart` strip (`Restart queued → Restarting → Answering again`), whose final stage the queue never lights; only a probe earns that.
|
|
40
|
+
- An archon may restart any project; the override is stamped `api:archon:<id>` on both the intent and the audit event (the force-teardown convention).
|
|
41
|
+
- The lockstep assertion between `INTENT_ACTIONS` and the migration CHECK moved to the **newest** migration's test. Pinning strict set-equality to `provisioning_010` made every future action fail that test; 010 now asserts only that every value it admits is still a live action, which is the drift it can actually speak to.
|
|
42
|
+
|
|
43
|
+
## Rejected
|
|
44
|
+
|
|
45
|
+
- **Widening `PROVISION_ENQUEUE_FROM` to include `active`** — precisely the change task 1002691 reverted; a stale open provision intent blocks the owner's teardown, and `provisionInstance` is a no-op on an active instance anyway.
|
|
46
|
+
- **Reusing `settings-apply` by re-sending unchanged settings** — its no-change branch exists to stop a whole-form save bouncing a live project (ADR 0190 §6). Punching through it to get a restart would delete that protection for everyone.
|
|
47
|
+
- **Reporting `healthy:true` as "answering again" on a domained instance** — the loopback probe cannot see what the sweep sees; the card would still say unreachable and the event would read as a lie.
|
|
48
|
+
- **Retrying a restart that left the project down** — restarting a broken instance four more times fixes nothing and ends by overwriting the owner's action with an `error_note`.
|
|
49
|
+
- **Showing the door on every active card** — an always-available Restart invites downtime on projects that are fine, and there is no reading behind it to act on.
|
package/docs/adr/README.md
CHANGED
|
@@ -285,6 +285,7 @@ This keeps the decision history honest and traceable.
|
|
|
285
285
|
| 0195 | [**ADR numbers are checked like migration numbers, and the twenty existing collisions are grandfathered by name** ([task 1003164](https://cloudbongos.com/builders#/task/1003164)). Two ADRs could share a number and nothing flagged it — git sees no path collision, the index auto-merges into two rows, and every gate passes; it was found by a human reading `ls docs/adr/`, after a task note had already cited a number the collision made point at an unrelated document. Migrations had this guard already (`stemCollisions()` hard-fails CI, because a re-used migration number silently skips a migration); ADRs had only a best-effort allocator at claim time and nothing afterwards. `scripts/gds/adr-namespace.js` is the sibling module, wired into fitness as Check 31 and so into the required `unit` gate. Building it found twenty live collisions, not one, plus fourteen index defects of the same merge class — two ADRs listed twice and twelve with no row at all, ten of them the second file of a colliding pair, which is how a collision hides. The twenty pairs are grandfathered by EXACT FILENAME rather than renumbered: renumbering breaks every citation to them, which is the harm the check exists to prevent, and set-equality keeps the exemption as narrow as the history that earned it — a third file on a legacy number, or a rename of either half, still fails, and the list may only shrink. The index half is keyed on LINK TARGET, not number (a number rule cannot express a grandfathered pair): every file has exactly one row, every row points at a file that exists. Row ordering warns and never blocks — ten legacy rows are out of order and no PR author caused that (the ADR 0189 split). Rejected: renumbering; grandfathering by number; a numeric cutoff like LEGACY_BARE_CORE_MAX (a new ADR takes a number above the max, so it would catch nothing); fixing it in the claim-time allocator (which already tries, against a stale tree — that is how the collision happened).](<redacted>.md) | docs / numbering discipline |
|
|
286
286
|
| 0196 | [**The chrome world becomes the token contract; the landing gets its own world sheet beside the hub's** ([task 1003298](https://cloudbongos.com/builders#/task/1003298), goal 1000080). The owner picked the chrome-blobs world (1003296) and the v3 composition with light rebuilt to the dark standard (1003297); this build makes it the platform's token contract. Decisions: (1) the neutral pack moves to the world's LIGHT values (pale grey paper, black ink, salmon accent, Manrope + JetBrains Mono) and design-tokens mirrors it; --accent-deep is #a3481a rather than the mock's #d96a35 because the hub and the gate pages paint TEXT with it and #a3481a is the lightest burnt orange clearing 4.5:1 on all three light grounds; the rgba hairlines are flattened to hex so hex-maths consumers survive. (2) theme.ui.backdrop becomes var(--bg): a literal there paints the light ground under the dark page in both modes, since the body rule outranks every sheet. (3) The landing gets its own world sheet public-landing/assets/world.css (contract tier = pack, derived tier both modes, root-absolute plate token PAIRS, the kill switch; NO composition switches) and cosmos.css stays the hub's component sheet until A4 — folding the two tiers would have collided (--line is a width in the world and a colour in the hub; the world's warm --ok/--warn/--err would repaint the hub's fixed green/amber/red chips). cosmos.css's dark tier moves to the world's black and its derived tier is retuned for the salmon accent (dark ink on the fill, never white). (4) Plates ship under public-landing/assets/world/ with provenance embedded: black plates verbatim JPEG, cutouts as WebP with alpha at 1600px (85–170 KB vs 1.1–2.4 MB PNG), sidecars; plate URLs in custom properties escape the ?v= stamp (edge cache 4h), accepted. (5) Live figures are BAKED inside apex-only sentinels (real, dated; a child renders empty until its own feed answers) and refreshed at render time from the five public feeds with fixed definitions: tasks shipped = the sum over every version row, builders = leaderboard entries holding credits, the ledger line = the first building version; live titles have em dashes normalised to a comma and a trailing parenthetical dropped. Every pack-reading fallback site (the claude-design adapter, the status explore page, provisioning onboarding, dev-box brand artifacts + tray icons, the two gate pages) is moved in the same task so no page keeps a private palette. Rejected: one merged token tier; a landing-private palette; PNG cutouts; a script-only ledger; #d96a35 as accent-deep.](<redacted>.md) | apex / design system |
|
|
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
|
+
| 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 |
|
|
288
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 |
|
|
289
290
|
|
|
290
291
|
> ⚠️ **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
|
@@ -10599,6 +10599,58 @@
|
|
|
10599
10599
|
]
|
|
10600
10600
|
}
|
|
10601
10601
|
},
|
|
10602
|
+
"/provisioning/instances/{id}/restart": {
|
|
10603
|
+
"post": {
|
|
10604
|
+
"operationId": "post_provisioning_instances_id_restart",
|
|
10605
|
+
"tags": [
|
|
10606
|
+
"provisioning"
|
|
10607
|
+
],
|
|
10608
|
+
"summary": "POST /provisioning/instances/:id/restart",
|
|
10609
|
+
"description": "POST /provisioning/instances/:id/restart — restart an ACTIVE project the heartbeat cannot reach (task 1003238). rank: any authenticated builder (own resource; archon may restart any — the override is audited via the actor). WHY it is its own route. The liveness overlay (task 1002696) can say a project is unreachable while its lifecycle status is still 'active' — and until now that reading came with no action the owner could take. Re-provision is not it: PROVISION_ENQUEUE_FROM deliberately excludes 'active' (task 1002691), so a Restart wired to that path would have refused on every press — the finding this route closes. The web tier only ENQUEUES; the control-plane runner performs the restart and the patient healthz verify (ADR 0111 §2). Every refusal names the action that IS available in that state rather than hiding behind a code, and no branch promises a duration — a restart's downtime is exactly what this route cannot know (the F16 rule, ADR 0190 §7).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
10610
|
+
"x-rank": "any-builder",
|
|
10611
|
+
"x-source": "modules/provisioning/routes/provisioning.js",
|
|
10612
|
+
"parameters": [
|
|
10613
|
+
{
|
|
10614
|
+
"name": "id",
|
|
10615
|
+
"in": "path",
|
|
10616
|
+
"required": true,
|
|
10617
|
+
"schema": {
|
|
10618
|
+
"type": "string"
|
|
10619
|
+
},
|
|
10620
|
+
"description": "Path parameter `id`."
|
|
10621
|
+
}
|
|
10622
|
+
],
|
|
10623
|
+
"responses": {
|
|
10624
|
+
"200": {
|
|
10625
|
+
"description": "Success.",
|
|
10626
|
+
"content": {
|
|
10627
|
+
"application/json": {
|
|
10628
|
+
"schema": {
|
|
10629
|
+
"$ref": "#/components/schemas/PostProvisioningInstancesIdRestartResponse"
|
|
10630
|
+
}
|
|
10631
|
+
}
|
|
10632
|
+
}
|
|
10633
|
+
},
|
|
10634
|
+
"400": {
|
|
10635
|
+
"$ref": "#/components/responses/BadRequest"
|
|
10636
|
+
},
|
|
10637
|
+
"401": {
|
|
10638
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
10639
|
+
},
|
|
10640
|
+
"403": {
|
|
10641
|
+
"$ref": "#/components/responses/Forbidden"
|
|
10642
|
+
},
|
|
10643
|
+
"404": {
|
|
10644
|
+
"$ref": "#/components/responses/NotFound"
|
|
10645
|
+
}
|
|
10646
|
+
},
|
|
10647
|
+
"security": [
|
|
10648
|
+
{
|
|
10649
|
+
"builderSession": []
|
|
10650
|
+
}
|
|
10651
|
+
]
|
|
10652
|
+
}
|
|
10653
|
+
},
|
|
10602
10654
|
"/provisioning/instances/{id}/settings": {
|
|
10603
10655
|
"get": {
|
|
10604
10656
|
"operationId": "get_provisioning_instances_id_settings",
|
|
@@ -19161,6 +19213,25 @@
|
|
|
19161
19213
|
"expires_at"
|
|
19162
19214
|
]
|
|
19163
19215
|
},
|
|
19216
|
+
"PostProvisioningInstancesIdRestartResponse": {
|
|
19217
|
+
"type": "object",
|
|
19218
|
+
"properties": {
|
|
19219
|
+
"ok": {
|
|
19220
|
+
"type": "boolean"
|
|
19221
|
+
},
|
|
19222
|
+
"queued": {},
|
|
19223
|
+
"action": {},
|
|
19224
|
+
"status": {},
|
|
19225
|
+
"message": {}
|
|
19226
|
+
},
|
|
19227
|
+
"required": [
|
|
19228
|
+
"ok",
|
|
19229
|
+
"queued",
|
|
19230
|
+
"action",
|
|
19231
|
+
"status",
|
|
19232
|
+
"message"
|
|
19233
|
+
]
|
|
19234
|
+
},
|
|
19164
19235
|
"PostProvisioningInstancesIdTeardownResponse": {
|
|
19165
19236
|
"type": "object",
|
|
19166
19237
|
"properties": {
|
|
@@ -20456,9 +20527,9 @@
|
|
|
20456
20527
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
20457
20528
|
}
|
|
20458
20529
|
},
|
|
20459
|
-
"x-endpoint-count":
|
|
20460
|
-
"x-schema-count":
|
|
20530
|
+
"x-endpoint-count": 325,
|
|
20531
|
+
"x-schema-count": 360,
|
|
20461
20532
|
"x-undocumented-bodies": 9,
|
|
20462
|
-
"x-response-schemas":
|
|
20533
|
+
"x-response-schemas": 243,
|
|
20463
20534
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
20464
20535
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Bongos API reference
|
|
4
4
|
|
|
5
|
-
> **Generated from the live route files** — the route file is authoritative.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 325 endpoints across 52 route files.
|
|
6
6
|
> Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
|
|
7
7
|
|
|
8
8
|
Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
|
|
@@ -420,7 +420,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
420
420
|
| GET | `/api/bongos/projects/featured` | `public` | — | a curated public showcase; no auth by design. |
|
|
421
421
|
| POST | `/api/bongos/projects/invite` | `metic+archon` | `client_id`, `github_login` | invite a builder into a project (ADR 0141 §5, task #1002115). |
|
|
422
422
|
|
|
423
|
-
## `provisioning` (
|
|
423
|
+
## `provisioning` (18)
|
|
424
424
|
|
|
425
425
|
| Method | Path | Rank | Body | Description |
|
|
426
426
|
|---|---|---|---|---|
|
|
@@ -435,6 +435,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
435
435
|
| POST | `/api/bongos/provisioning/instances/:id/domain` | `any-builder` | `domain` | POST /provisioning/instances/:id/domain — give the caller's OWN instance its address (task 1002692, gap 5: no path existed to add a domai… |
|
|
436
436
|
| POST | `/api/bongos/provisioning/instances/:id/force-teardown` | `metic+archon` | — | POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. |
|
|
437
437
|
| POST | `/api/bongos/provisioning/instances/:id/github-app` | `any-builder` | `account` | POST /provisioning/instances/:id/github-app — mint a GitHub-App-Manifest onboarding link for the caller's OWN instance (task 2080, ADR 01… |
|
|
438
|
+
| POST | `/api/bongos/provisioning/instances/:id/restart` | `any-builder` | — | POST /provisioning/instances/:id/restart — restart an ACTIVE project the heartbeat cannot reach (task 1003238). |
|
|
438
439
|
| GET | `/api/bongos/provisioning/instances/:id/settings` | `any-builder` | — | GET /provisioning/instances/:id/settings — read a project's effective settings + the allowed values (so a form can render its choices). |
|
|
439
440
|
| PATCH | `/api/bongos/provisioning/instances/:id/settings` | `any-builder` | `platform_visibility`, `joinability` | PATCH /provisioning/instances/:id/settings — change a project's settings. |
|
|
440
441
|
| POST | `/api/bongos/provisioning/instances/:id/teardown` | `any-builder` | — | POST /provisioning/instances/:id/teardown — request teardown of the caller's OWN instance. |
|
|
@@ -620,6 +620,8 @@ function createClient(opts = {}) {
|
|
|
620
620
|
postProvisioningInstancesIdForceTeardown: (args) => request("POST", "/provisioning/instances/{id}/force-teardown", { hasBody: true }, args),
|
|
621
621
|
// POST /provisioning/instances/{id}/github-app — rank: any-builder — POST /provisioning/instances/:id/github-app
|
|
622
622
|
postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
|
|
623
|
+
// POST /provisioning/instances/{id}/restart — rank: any-builder — POST /provisioning/instances/:id/restart
|
|
624
|
+
postProvisioningInstancesIdRestart: (args) => request("POST", "/provisioning/instances/{id}/restart", { hasBody: true }, args),
|
|
623
625
|
// GET /provisioning/instances/{id}/settings — rank: any-builder — GET /provisioning/instances/:id/settings
|
|
624
626
|
getProvisioningInstancesIdSettings: (args) => request("GET", "/provisioning/instances/{id}/settings", { hasBody: false }, args),
|
|
625
627
|
// PATCH /provisioning/instances/{id}/settings — rank: any-builder — PATCH /provisioning/instances/:id/settings
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- provisioning_011_restart.sql — the restart intent action (task 1003238,
|
|
2
|
+
-- goal 1000058: an honest owner action for an ACTIVE instance whose probe is
|
|
3
|
+
-- down).
|
|
4
|
+
--
|
|
5
|
+
-- WHY. The liveness overlay (task 1002696) can say an instance is unreachable
|
|
6
|
+
-- while its lifecycle status is still 'active' — liveness is an overlay, never a
|
|
7
|
+
-- seventh state. Until now the owner had no action for that: PROVISION_ENQUEUE_FROM
|
|
8
|
+
-- deliberately excludes 'active' (task 1002691 — a blind re-enqueue left a stale
|
|
9
|
+
-- open provision intent that then blocked teardown), so a Restart button wired to
|
|
10
|
+
-- the provision path would have refused on every press. 'settings-apply' does
|
|
11
|
+
-- restart an active instance, but only as the tail of a change that must differ
|
|
12
|
+
-- from the stored row — the one case where restarting is useless.
|
|
13
|
+
--
|
|
14
|
+
-- So: its own action, whose whole job is the restart + the patient healthz verify
|
|
15
|
+
-- that settings-apply already performs (ADR 0190 §3), minus the env patch. The
|
|
16
|
+
-- web tier still only ENQUEUES; the control-plane runner remains the sole
|
|
17
|
+
-- token-holder (ADR 0111 §2).
|
|
18
|
+
--
|
|
19
|
+
-- Widening a CHECK enum is additive (permits MORE values; no row changes) — the
|
|
20
|
+
-- provisioning_003/005/010 precedent. Applied only when the provisioning module
|
|
21
|
+
-- is enabled. Safe to re-run. Keep INTENT_ACTIONS in provisioning.js in lockstep.
|
|
22
|
+
|
|
23
|
+
ALTER TABLE provisioning_intents DROP CONSTRAINT IF EXISTS provisioning_intents_action_check;
|
|
24
|
+
ALTER TABLE provisioning_intents ADD CONSTRAINT provisioning_intents_action_check
|
|
25
|
+
CHECK (action IN ('provision', 'teardown', 'oauth-manifest', 'domain-attach', 'settings-apply', 'restart'));
|
|
26
|
+
|
|
27
|
+
INSERT INTO schema_migrations (version) VALUES ('provisioning_011_restart')
|
|
28
|
+
ON CONFLICT (version) DO NOTHING;
|