@bongos/core 1.18.0 → 1.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/.bongos-core.json +132 -322
  2. package/README.md +1 -1
  3. package/config/branding.neutral.json +5 -1
  4. package/docs/adr/0142-project-context-is-prose-only.md +41 -0
  5. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  6. package/docs/adr/README.md +5 -2
  7. package/docs/api/openapi.json +1789 -450
  8. package/docs/api-reference.md +52 -5
  9. package/docs/file-map.md +7 -7
  10. package/docs/recipes/packaging-the-core.md +13 -0
  11. package/docs/recipes/upgrading-the-core.md +5 -2
  12. package/migrations/039_newcomer_friendly_column.sql +5 -0
  13. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  14. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  15. package/modules/hall-ui/public/my-projects.html +78 -0
  16. package/modules/hall-ui/public/my-projects.js +142 -0
  17. package/modules/hall-ui/public/scouting.html +45 -0
  18. package/modules/hall-ui/public/scouting.js +73 -0
  19. package/modules/status-ui/public/explore.html +54 -0
  20. package/modules/status-ui/public/explore.js +67 -0
  21. package/package-lock.json +2 -2
  22. package/package.json +1 -1
  23. package/public-landing/create.html +211 -14
  24. package/scripts/gds/cli-lib.js +11 -5
  25. package/scripts/gds/lint-migrations.js +102 -0
  26. package/scripts/gds/login.js +42 -10
  27. package/scripts/gds/mirror-redact.js +5 -0
  28. package/scripts/gds/package-core.js +263 -4
  29. package/scripts/gds/provision.js +145 -7
  30. package/scripts/gds/publish-manifest.js +15 -0
  31. package/scripts/gds/run-unit-tests.js +38 -14
  32. package/scripts/gds/setup.js +41 -0
  33. package/scripts/gds/ship.js +115 -31
  34. package/scripts/gds/upgrade.js +147 -5
  35. package/scripts/migrate.sh +10 -0
  36. package/src/bongos/auth.js +362 -5
  37. package/src/bongos/db.js +66 -0
  38. package/src/bongos/github-repos.js +93 -0
  39. package/src/bongos/routes/auth.js +93 -11
  40. package/src/bongos/routes/github.js +90 -0
  41. package/src/bongos/routes/instance.js +15 -3
  42. package/src/bongos/routes.js +2 -0
  43. package/src/branding.js +17 -2
  44. package/src/instance-config.js +16 -0
  45. package/src/module-api.js +29 -1
  46. package/tests/branding.mjs +29 -23
  47. package/tests/github_repos_helpers.mjs +91 -0
  48. package/tests/github_token_store.mjs +121 -0
  49. package/tests/idp_device_exchange.mjs +105 -0
  50. package/tests/idp_federation.mjs +100 -0
  51. package/tests/migrations_forward_safe.mjs +86 -0
  52. package/tests/module_api.mjs +1 -1
  53. package/tests/package_core.mjs +246 -1
  54. package/tests/provision.mjs +157 -0
  55. package/tests/pruned_lockfile_integrity.mjs +79 -0
  56. package/tests/ship_ci_deploy.mjs +60 -0
  57. package/tests/upgrade.mjs +254 -5
  58. package/.gitignore +0 -91
  59. package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +0 -94
  60. package/docs/adr/0140-cloudbongos-standalone-reprovision.md +0 -43
  61. package/scripts/hall-preview/fixtures/access-requests.json +0 -20
  62. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  63. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  64. package/scripts/hall-preview/fixtures/audit-log.json +0 -68
  65. package/scripts/hall-preview/fixtures/blockers__detail.json +0 -12
  66. package/scripts/hall-preview/fixtures/box__me.json +0 -5
  67. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -69
  68. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  69. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  70. package/scripts/hall-preview/fixtures/builders__roster.json +0 -48
  71. package/scripts/hall-preview/fixtures/goals.json +0 -502
  72. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  73. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  74. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  75. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  76. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  77. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  78. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  79. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  80. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -32
  81. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  82. package/scripts/hall-preview/fixtures/inbox__detail.json +0 -15
  83. package/scripts/hall-preview/fixtures/instance.json +0 -124
  84. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  85. package/scripts/hall-preview/fixtures/me.json +0 -476
  86. package/scripts/hall-preview/fixtures/me__art-key__own.json +0 -6
  87. package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +0 -209
  88. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  89. package/scripts/hall-preview/fixtures/me__render.json +0 -5
  90. package/scripts/hall-preview/fixtures/me__skill-prefs.json +0 -143
  91. package/scripts/hall-preview/fixtures/me__sound-prefs.json +0 -67
  92. package/scripts/hall-preview/fixtures/me__wandering.json +0 -43
  93. package/scripts/hall-preview/fixtures/override-requests.json +0 -15
  94. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  95. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  96. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  97. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  98. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  99. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  100. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  101. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  102. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  103. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  104. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  105. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  106. package/scripts/hall-preview/fixtures/security__docs.json +0 -10
  107. package/scripts/hall-preview/fixtures/security__reports.json +0 -31
  108. package/scripts/hall-preview/fixtures/sessions__search.json +0 -9
  109. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  110. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  111. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  112. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  113. package/scripts/hall-preview/fixtures/versions.json +0 -89
@@ -93,6 +93,10 @@
93
93
  "name": "gate-approvals",
94
94
  "description": "Endpoints under `/api/bongos/gate-approvals`."
95
95
  },
96
+ {
97
+ "name": "github",
98
+ "description": "Endpoints under `/api/bongos/github`."
99
+ },
96
100
  {
97
101
  "name": "goals",
98
102
  "description": "Endpoints under `/api/bongos/goals`."
@@ -141,10 +145,18 @@
141
145
  "name": "modules",
142
146
  "description": "Endpoints under `/api/bongos/modules`."
143
147
  },
148
+ {
149
+ "name": "my-projects",
150
+ "description": "Endpoints under `/api/bongos/my-projects`."
151
+ },
144
152
  {
145
153
  "name": "override-requests",
146
154
  "description": "Endpoints under `/api/bongos/override-requests`."
147
155
  },
156
+ {
157
+ "name": "projects",
158
+ "description": "Endpoints under `/api/bongos/projects`."
159
+ },
148
160
  {
149
161
  "name": "provisioning",
150
162
  "description": "Endpoints under `/api/bongos/provisioning`."
@@ -153,6 +165,10 @@
153
165
  "name": "public",
154
166
  "description": "Endpoints under `/api/bongos/public`."
155
167
  },
168
+ {
169
+ "name": "scouting",
170
+ "description": "Endpoints under `/api/bongos/scouting`."
171
+ },
156
172
  {
157
173
  "name": "search",
158
174
  "description": "Endpoints under `/api/bongos/search`."
@@ -169,6 +185,10 @@
169
185
  "name": "sessions",
170
186
  "description": "Endpoints under `/api/bongos/sessions`."
171
187
  },
188
+ {
189
+ "name": "sso",
190
+ "description": "Endpoints under `/api/bongos/sso`."
191
+ },
172
192
  {
173
193
  "name": "tasks",
174
194
  "description": "Endpoints under `/api/bongos/tasks`."
@@ -662,6 +682,45 @@
662
682
  ]
663
683
  }
664
684
  },
685
+ "/auth/device/exchange": {
686
+ "post": {
687
+ "operationId": "post_auth_device_exchange",
688
+ "tags": [
689
+ "auth"
690
+ ],
691
+ "summary": "POST /auth/device/exchange",
692
+ "description": "POST /auth/device/exchange — CLI federation (ADR 0141 §1). The CLI ran the device flow against the HUB and got a hub-signed assertion; it presents it here. The instance verifies the Ed25519 signature OFFLINE against the provisioned hub public key (aud must equal this instance's client_id, unexpired), then runs the instance's OWN admission gate + upsertBuilder + createSession(source='cli') and returns the existing { token, builder }. Only reachable when auth.idp is set. rank: public — an auth-establishment endpoint; the hub-signed assertion IS the bearer and is cryptographically verified before any session is minted.\n\n**Rank:** `public` — No authentication — any caller.",
693
+ "x-rank": "public",
694
+ "x-source": "src/bongos/routes/auth.js",
695
+ "requestBody": {
696
+ "required": true,
697
+ "content": {
698
+ "application/json": {
699
+ "schema": {
700
+ "$ref": "#/components/schemas/PostAuthDeviceExchangeRequest"
701
+ }
702
+ }
703
+ },
704
+ "x-validated": true
705
+ },
706
+ "responses": {
707
+ "200": {
708
+ "description": "Success.",
709
+ "content": {
710
+ "application/json": {
711
+ "schema": {
712
+ "$ref": "#/components/schemas/PostAuthDeviceExchangeResponse"
713
+ }
714
+ }
715
+ }
716
+ },
717
+ "400": {
718
+ "$ref": "#/components/responses/ValidationFailed"
719
+ }
720
+ },
721
+ "security": []
722
+ }
723
+ },
665
724
  "/auth/device/poll": {
666
725
  "post": {
667
726
  "operationId": "post_auth_device_poll",
@@ -3389,6 +3448,91 @@
3389
3448
  ]
3390
3449
  }
3391
3450
  },
3451
+ "/github/repos": {
3452
+ "get": {
3453
+ "operationId": "get_github_repos",
3454
+ "tags": [
3455
+ "github"
3456
+ ],
3457
+ "summary": "GET /github/repos",
3458
+ "description": "acts only on the caller's OWN GitHub identity (the token they granted). No rank gate beyond being a signed-in builder.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
3459
+ "x-rank": "any-builder",
3460
+ "x-source": "src/bongos/routes/github.js",
3461
+ "responses": {
3462
+ "200": {
3463
+ "description": "Success.",
3464
+ "content": {
3465
+ "application/json": {
3466
+ "schema": {
3467
+ "$ref": "#/components/schemas/GetGithubReposResponse"
3468
+ }
3469
+ }
3470
+ }
3471
+ },
3472
+ "400": {
3473
+ "$ref": "#/components/responses/BadRequest"
3474
+ },
3475
+ "401": {
3476
+ "$ref": "#/components/responses/Unauthorized"
3477
+ },
3478
+ "403": {
3479
+ "$ref": "#/components/responses/Forbidden"
3480
+ }
3481
+ },
3482
+ "security": [
3483
+ {
3484
+ "builderSession": []
3485
+ }
3486
+ ]
3487
+ },
3488
+ "post": {
3489
+ "operationId": "post_github_repos",
3490
+ "tags": [
3491
+ "github"
3492
+ ],
3493
+ "summary": "POST /github/repos",
3494
+ "description": "creates a repo in the caller's OWN account.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
3495
+ "x-rank": "any-builder",
3496
+ "x-source": "src/bongos/routes/github.js",
3497
+ "requestBody": {
3498
+ "required": true,
3499
+ "content": {
3500
+ "application/json": {
3501
+ "schema": {
3502
+ "$ref": "#/components/schemas/PostGithubReposRequest"
3503
+ }
3504
+ }
3505
+ },
3506
+ "x-validated": true
3507
+ },
3508
+ "responses": {
3509
+ "200": {
3510
+ "description": "Success.",
3511
+ "content": {
3512
+ "application/json": {
3513
+ "schema": {
3514
+ "$ref": "#/components/schemas/PostGithubReposResponse"
3515
+ }
3516
+ }
3517
+ }
3518
+ },
3519
+ "400": {
3520
+ "$ref": "#/components/responses/ValidationFailed"
3521
+ },
3522
+ "401": {
3523
+ "$ref": "#/components/responses/Unauthorized"
3524
+ },
3525
+ "403": {
3526
+ "$ref": "#/components/responses/Forbidden"
3527
+ }
3528
+ },
3529
+ "security": [
3530
+ {
3531
+ "builderSession": []
3532
+ }
3533
+ ]
3534
+ }
3535
+ },
3392
3536
  "/goals": {
3393
3537
  "get": {
3394
3538
  "operationId": "get_goals",
@@ -6656,23 +6800,23 @@
6656
6800
  ]
6657
6801
  }
6658
6802
  },
6659
- "/override-requests": {
6803
+ "/my-projects": {
6660
6804
  "get": {
6661
- "operationId": "get_override_requests",
6805
+ "operationId": "get_my_projects",
6662
6806
  "tags": [
6663
- "override-requests"
6807
+ "my-projects"
6664
6808
  ],
6665
- "summary": "GET /override-requests",
6666
- "description": "GET /override-requests?status=open — Archon queue. Status defaults to open; pass ?status=approved or ?status=denied for the resolved history. rank: archon — same gate as the audit log + Archon view.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
6667
- "x-rank": "archon",
6668
- "x-source": "modules/lifecycle/routes/tasks.js",
6809
+ "summary": "GET /my-projects",
6810
+ "description": "the caller's OWN cross-project memberships (own data).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6811
+ "x-rank": "any-builder",
6812
+ "x-source": "modules/platform-identity/routes/my-projects.js",
6669
6813
  "responses": {
6670
6814
  "200": {
6671
6815
  "description": "Success.",
6672
6816
  "content": {
6673
6817
  "application/json": {
6674
6818
  "schema": {
6675
- "$ref": "#/components/schemas/GetOverrideRequestsResponse"
6819
+ "$ref": "#/components/schemas/GetMyProjectsResponse"
6676
6820
  }
6677
6821
  }
6678
6822
  }
@@ -6694,44 +6838,78 @@
6694
6838
  ]
6695
6839
  }
6696
6840
  },
6697
- "/override-requests/{id}/decide": {
6841
+ "/my-projects/invites": {
6842
+ "get": {
6843
+ "operationId": "get_my_projects_invites",
6844
+ "tags": [
6845
+ "my-projects"
6846
+ ],
6847
+ "summary": "GET /my-projects/invites",
6848
+ "description": "the caller's OWN pending invitations (ADR 0141 §5).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6849
+ "x-rank": "any-builder",
6850
+ "x-source": "modules/platform-identity/routes/my-projects.js",
6851
+ "responses": {
6852
+ "200": {
6853
+ "description": "Success.",
6854
+ "content": {
6855
+ "application/json": {
6856
+ "schema": {
6857
+ "$ref": "#/components/schemas/GetMyProjectsInvitesResponse"
6858
+ }
6859
+ }
6860
+ }
6861
+ },
6862
+ "400": {
6863
+ "$ref": "#/components/responses/BadRequest"
6864
+ },
6865
+ "401": {
6866
+ "$ref": "#/components/responses/Unauthorized"
6867
+ },
6868
+ "403": {
6869
+ "$ref": "#/components/responses/Forbidden"
6870
+ }
6871
+ },
6872
+ "security": [
6873
+ {
6874
+ "builderSession": []
6875
+ }
6876
+ ]
6877
+ }
6878
+ },
6879
+ "/my-projects/invites/{clientId}/accept": {
6698
6880
  "post": {
6699
- "operationId": "post_override_requests_id_decide",
6881
+ "operationId": "post_my_projects_invites_clientId_accept",
6700
6882
  "tags": [
6701
- "override-requests"
6883
+ "my-projects"
6702
6884
  ],
6703
- "summary": "POST /override-requests/:id/decide",
6704
- "description": "POST /override-requests/:id/decide — body: { decision: 'approve'|'deny', note? } On approve, atomically flips the task completed→confirmed and awards the credits to the original requester (NOT the Archon). On deny, only the row updates; the task stays at completed and the builder must release or re-ship after fixing whatever the grader caught. rank: archon — grader-bypass authority; same gate as POST /tasks/:id/confirm.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
6705
- "x-rank": "archon",
6706
- "x-source": "modules/lifecycle/routes/tasks.js",
6885
+ "summary": "POST /my-projects/invites/:clientId/accept",
6886
+ "description": "accept an invite (pending → builder) for the caller's OWN account.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6887
+ "x-rank": "any-builder",
6888
+ "x-source": "modules/platform-identity/routes/my-projects.js",
6707
6889
  "parameters": [
6708
6890
  {
6709
- "name": "id",
6891
+ "name": "clientId",
6710
6892
  "in": "path",
6711
6893
  "required": true,
6712
6894
  "schema": {
6713
6895
  "type": "string"
6714
6896
  },
6715
- "description": "Path parameter `id`."
6897
+ "description": "Path parameter `clientId`."
6716
6898
  }
6717
6899
  ],
6718
- "requestBody": {
6719
- "required": true,
6720
- "content": {
6721
- "application/json": {
6722
- "schema": {
6723
- "$ref": "#/components/schemas/PostOverrideRequestsIdDecideRequest"
6724
- }
6725
- }
6726
- },
6727
- "x-validated": true
6728
- },
6729
6900
  "responses": {
6730
6901
  "200": {
6731
- "description": "Success."
6902
+ "description": "Success.",
6903
+ "content": {
6904
+ "application/json": {
6905
+ "schema": {
6906
+ "$ref": "#/components/schemas/PostMyProjectsInvitesClientIdAcceptResponse"
6907
+ }
6908
+ }
6909
+ }
6732
6910
  },
6733
6911
  "400": {
6734
- "$ref": "#/components/responses/ValidationFailed"
6912
+ "$ref": "#/components/responses/BadRequest"
6735
6913
  },
6736
6914
  "401": {
6737
6915
  "$ref": "#/components/responses/Unauthorized"
@@ -6750,23 +6928,34 @@
6750
6928
  ]
6751
6929
  }
6752
6930
  },
6753
- "/provisioning/fleet": {
6754
- "get": {
6755
- "operationId": "get_provisioning_fleet",
6931
+ "/my-projects/invites/{clientId}/decline": {
6932
+ "post": {
6933
+ "operationId": "post_my_projects_invites_clientId_decline",
6756
6934
  "tags": [
6757
- "provisioning"
6935
+ "my-projects"
6936
+ ],
6937
+ "summary": "POST /my-projects/invites/:clientId/decline",
6938
+ "description": "decline an invite (delete the pending row) for the caller's OWN account.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6939
+ "x-rank": "any-builder",
6940
+ "x-source": "modules/platform-identity/routes/my-projects.js",
6941
+ "parameters": [
6942
+ {
6943
+ "name": "clientId",
6944
+ "in": "path",
6945
+ "required": true,
6946
+ "schema": {
6947
+ "type": "string"
6948
+ },
6949
+ "description": "Path parameter `clientId`."
6950
+ }
6758
6951
  ],
6759
- "summary": "GET /provisioning/fleet",
6760
- "description": "GET /provisioning/fleet — the full instance roster across all owners. rank: archon (exposes every owner's instance + cost; the /boxes precedent).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
6761
- "x-rank": "archon",
6762
- "x-source": "modules/provisioning/routes/provisioning.js",
6763
6952
  "responses": {
6764
6953
  "200": {
6765
6954
  "description": "Success.",
6766
6955
  "content": {
6767
6956
  "application/json": {
6768
6957
  "schema": {
6769
- "$ref": "#/components/schemas/GetProvisioningFleetResponse"
6958
+ "$ref": "#/components/schemas/PostMyProjectsInvitesClientIdDeclineResponse"
6770
6959
  }
6771
6960
  }
6772
6961
  }
@@ -6779,6 +6968,9 @@
6779
6968
  },
6780
6969
  "403": {
6781
6970
  "$ref": "#/components/responses/Forbidden"
6971
+ },
6972
+ "404": {
6973
+ "$ref": "#/components/responses/NotFound"
6782
6974
  }
6783
6975
  },
6784
6976
  "security": [
@@ -6788,22 +6980,40 @@
6788
6980
  ]
6789
6981
  }
6790
6982
  },
6791
- "/provisioning/fleet/cost-ledger": {
6792
- "get": {
6793
- "operationId": "get_provisioning_fleet_cost_ledger",
6983
+ "/my-projects/join": {
6984
+ "post": {
6985
+ "operationId": "post_my_projects_join",
6794
6986
  "tags": [
6795
- "provisioning"
6987
+ "my-projects"
6796
6988
  ],
6797
- "summary": "GET /provisioning/fleet/cost-ledger",
6798
- "description": "GET /provisioning/fleet/cost-ledger — per-instance monthly estimate + total. rank: archon — cost oversight across the fleet (the /boxes/cost-ledger precedent). Declared among the archon routes (archon-first) for correct auditor classification.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
6799
- "x-rank": "archon",
6800
- "x-source": "modules/provisioning/routes/provisioning.js",
6989
+ "summary": "POST /my-projects/join",
6990
+ "description": "request to join a project. The hub RELAYS the request to the target project's own admission surface (it does NOT admit locally — authority stays local). SSRF guard: only relay to an origin that is a REGISTERED, active client — never an arbitrary builder-supplied URL.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6991
+ "x-rank": "any-builder",
6992
+ "x-source": "modules/platform-identity/routes/my-projects.js",
6993
+ "requestBody": {
6994
+ "required": true,
6995
+ "content": {
6996
+ "application/json": {
6997
+ "schema": {
6998
+ "$ref": "#/components/schemas/PostMyProjectsJoinRequest"
6999
+ }
7000
+ }
7001
+ },
7002
+ "x-validated": true
7003
+ },
6801
7004
  "responses": {
6802
7005
  "200": {
6803
- "description": "Success."
7006
+ "description": "Success.",
7007
+ "content": {
7008
+ "application/json": {
7009
+ "schema": {
7010
+ "$ref": "#/components/schemas/PostMyProjectsJoinResponse"
7011
+ }
7012
+ }
7013
+ }
6804
7014
  },
6805
7015
  "400": {
6806
- "$ref": "#/components/responses/BadRequest"
7016
+ "$ref": "#/components/responses/ValidationFailed"
6807
7017
  },
6808
7018
  "401": {
6809
7019
  "$ref": "#/components/responses/Unauthorized"
@@ -6819,100 +7029,75 @@
6819
7029
  ]
6820
7030
  }
6821
7031
  },
6822
- "/provisioning/github-app/callback": {
6823
- "get": {
6824
- "operationId": "get_provisioning_github_app_callback",
7032
+ "/my-projects/{clientId}/leave": {
7033
+ "post": {
7034
+ "operationId": "post_my_projects_clientId_leave",
6825
7035
  "tags": [
6826
- "provisioning"
7036
+ "my-projects"
6827
7037
  ],
6828
- "summary": "GET /provisioning/github-app/callback",
6829
- "description": "GET /provisioning/github-app/callback?code=&state= — GitHub redirects the owner's BROWSER here after they approve the App Manifest (task 2080, ADR 0133). It is a browser redirect with no session guaranteed, so it is PUBLIC — the unguessable, single-use, TTL'd `state` token (minted only for the signed-in owner and matched against provisioning_oauth_manifests) is the authorization, exactly as GitHub's own conversion `code` is \"the code IS the auth\". The web tier ONLY stores the code + flips status → 'code_received'; the control-plane runner (the sole token-holder) exchanges it for the client secret and places it in web.env. The secret NEVER touches the browser or the web tier. rank: public — no session, no mutation of authority, no secret revealed; a bad/expired/replayed state is a no-op error page.\n\n**Rank:** `public` — No authentication — any caller.",
6830
- "x-rank": "public",
6831
- "x-source": "modules/provisioning/routes/provisioning.js",
6832
- "responses": {
6833
- "200": {
6834
- "description": "Success."
6835
- },
6836
- "400": {
6837
- "$ref": "#/components/responses/BadRequest"
6838
- }
6839
- },
6840
- "security": []
6841
- }
6842
- },
6843
- "/provisioning/github-app/status": {
6844
- "get": {
6845
- "operationId": "get_provisioning_github_app_status",
6846
- "tags": [
6847
- "provisioning"
6848
- ],
6849
- "summary": "GET /provisioning/github-app/status",
6850
- "description": "GET /provisioning/github-app/status?state=<> — the PUBLIC progress read the onboarding callback page polls (task 2096) to know when setup is done + where to send the owner. Same public-by-state model as the callback: the unguessable, single-use `state` token is the only key, and the response reveals only the manifest lifecycle status + the instance's own (already-public) domain — never a secret. Per-IP rate-limited because the page polls it every ~3s. `ready` is true iff the manifest reached 'done' (creds placed + /healthz verified) — the page then auto-redirects to https://<domain>. rank: public — no session, no mutation, no secret; an unknown state is a 404 no-op.\n\n**Rank:** `public` — No authentication — any caller.",
6851
- "x-rank": "public",
6852
- "x-source": "modules/provisioning/routes/provisioning.js",
6853
- "responses": {
6854
- "200": {
6855
- "description": "Success.",
6856
- "content": {
6857
- "application/json": {
6858
- "schema": {
6859
- "$ref": "#/components/schemas/GetProvisioningGithubAppStatusResponse"
6860
- }
6861
- }
6862
- }
6863
- },
6864
- "400": {
6865
- "$ref": "#/components/responses/BadRequest"
7038
+ "summary": "POST /my-projects/:clientId/leave",
7039
+ "description": "leave a project from the caller's OWN membership list.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7040
+ "x-rank": "any-builder",
7041
+ "x-source": "modules/platform-identity/routes/my-projects.js",
7042
+ "parameters": [
7043
+ {
7044
+ "name": "clientId",
7045
+ "in": "path",
7046
+ "required": true,
7047
+ "schema": {
7048
+ "type": "string"
7049
+ },
7050
+ "description": "Path parameter `clientId`."
6866
7051
  }
6867
- },
6868
- "security": []
6869
- }
6870
- },
6871
- "/provisioning/health": {
6872
- "get": {
6873
- "operationId": "get_provisioning_health",
6874
- "tags": [
6875
- "provisioning"
6876
7052
  ],
6877
- "summary": "GET /provisioning/health",
6878
- "description": "GET /provisioning/health — liveness + the core version this module mounted against. rank: public (a plain liveness read; no write, no sensitive data).\n\n**Rank:** `public` — No authentication — any caller.",
6879
- "x-rank": "public",
6880
- "x-source": "modules/provisioning/routes/provisioning.js",
6881
7053
  "responses": {
6882
7054
  "200": {
6883
7055
  "description": "Success.",
6884
7056
  "content": {
6885
7057
  "application/json": {
6886
7058
  "schema": {
6887
- "$ref": "#/components/schemas/GetProvisioningHealthResponse"
7059
+ "$ref": "#/components/schemas/PostMyProjectsClientIdLeaveResponse"
6888
7060
  }
6889
7061
  }
6890
7062
  }
6891
7063
  },
6892
7064
  "400": {
6893
7065
  "$ref": "#/components/responses/BadRequest"
7066
+ },
7067
+ "401": {
7068
+ "$ref": "#/components/responses/Unauthorized"
7069
+ },
7070
+ "403": {
7071
+ "$ref": "#/components/responses/Forbidden"
7072
+ },
7073
+ "404": {
7074
+ "$ref": "#/components/responses/NotFound"
6894
7075
  }
6895
7076
  },
6896
- "security": []
7077
+ "security": [
7078
+ {
7079
+ "builderSession": []
7080
+ }
7081
+ ]
6897
7082
  }
6898
7083
  },
6899
- "/provisioning/instances": {
7084
+ "/override-requests": {
6900
7085
  "get": {
6901
- "operationId": "get_provisioning_instances",
7086
+ "operationId": "get_override_requests",
6902
7087
  "tags": [
6903
- "provisioning"
7088
+ "override-requests"
6904
7089
  ],
6905
- "summary": "GET /provisioning/instances",
6906
- "description": "GET /provisioning/instances — the caller's own instances + each open intent. rank: any authenticated builder (own resource read).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6907
- "x-rank": "any-builder",
6908
- "x-source": "modules/provisioning/routes/provisioning.js",
7090
+ "summary": "GET /override-requests",
7091
+ "description": "GET /override-requests?status=open — Archon queue. Status defaults to open; pass ?status=approved or ?status=denied for the resolved history. rank: archon — same gate as the audit log + Archon view.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7092
+ "x-rank": "archon",
7093
+ "x-source": "modules/lifecycle/routes/tasks.js",
6909
7094
  "responses": {
6910
7095
  "200": {
6911
7096
  "description": "Success.",
6912
7097
  "content": {
6913
7098
  "application/json": {
6914
7099
  "schema": {
6915
- "$ref": "#/components/schemas/GetProvisioningInstancesResponse"
7100
+ "$ref": "#/components/schemas/GetOverrideRequestsResponse"
6916
7101
  }
6917
7102
  }
6918
7103
  }
@@ -6932,22 +7117,35 @@
6932
7117
  "builderSession": []
6933
7118
  }
6934
7119
  ]
6935
- },
7120
+ }
7121
+ },
7122
+ "/override-requests/{id}/decide": {
6936
7123
  "post": {
6937
- "operationId": "post_provisioning_instances",
7124
+ "operationId": "post_override_requests_id_decide",
6938
7125
  "tags": [
6939
- "provisioning"
7126
+ "override-requests"
7127
+ ],
7128
+ "summary": "POST /override-requests/:id/decide",
7129
+ "description": "POST /override-requests/:id/decide — body: { decision: 'approve'|'deny', note? } On approve, atomically flips the task completed→confirmed and awards the credits to the original requester (NOT the Archon). On deny, only the row updates; the task stays at completed and the builder must release or re-ship after fixing whatever the grader caught. rank: archon — grader-bypass authority; same gate as POST /tasks/:id/confirm.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7130
+ "x-rank": "archon",
7131
+ "x-source": "modules/lifecycle/routes/tasks.js",
7132
+ "parameters": [
7133
+ {
7134
+ "name": "id",
7135
+ "in": "path",
7136
+ "required": true,
7137
+ "schema": {
7138
+ "type": "string"
7139
+ },
7140
+ "description": "Path parameter `id`."
7141
+ }
6940
7142
  ],
6941
- "summary": "POST /provisioning/instances",
6942
- "description": "POST /provisioning/instances — request a new instance. rank: any authenticated builder (own resource). ENQUEUES a 'provision' intent + records the request; the runner (task P3) does the real standup. Idempotent on slug for the SAME owner (re-request returns the existing row); a slug owned by ANOTHER builder → 409. Body: { slug (required), target_ref?, hosting_shape? (co-tenant|dedicated), domain?, tier? }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6943
- "x-rank": "any-builder",
6944
- "x-source": "modules/provisioning/routes/provisioning.js",
6945
7143
  "requestBody": {
6946
7144
  "required": true,
6947
7145
  "content": {
6948
7146
  "application/json": {
6949
7147
  "schema": {
6950
- "$ref": "#/components/schemas/PostProvisioningInstancesRequest"
7148
+ "$ref": "#/components/schemas/PostOverrideRequestsIdDecideRequest"
6951
7149
  }
6952
7150
  }
6953
7151
  },
@@ -6965,6 +7163,9 @@
6965
7163
  },
6966
7164
  "403": {
6967
7165
  "$ref": "#/components/responses/Forbidden"
7166
+ },
7167
+ "404": {
7168
+ "$ref": "#/components/responses/NotFound"
6968
7169
  }
6969
7170
  },
6970
7171
  "security": [
@@ -6974,34 +7175,23 @@
6974
7175
  ]
6975
7176
  }
6976
7177
  },
6977
- "/provisioning/instances/{id}": {
7178
+ "/projects": {
6978
7179
  "get": {
6979
- "operationId": "get_provisioning_instances_id",
7180
+ "operationId": "get_projects",
6980
7181
  "tags": [
6981
- "provisioning"
6982
- ],
6983
- "summary": "GET /provisioning/instances/:id",
6984
- "description": "GET /provisioning/instances/:id — read one of the caller's own instances. rank: any authenticated builder (own resource). 404 when the id isn't the caller's (own-scoped; does not leak another owner's instance existence).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
6985
- "x-rank": "any-builder",
6986
- "x-source": "modules/provisioning/routes/provisioning.js",
6987
- "parameters": [
6988
- {
6989
- "name": "id",
6990
- "in": "path",
6991
- "required": true,
6992
- "schema": {
6993
- "type": "string"
6994
- },
6995
- "description": "Path parameter `id`."
6996
- }
7182
+ "projects"
6997
7183
  ],
7184
+ "summary": "GET /projects",
7185
+ "description": "the full curation list (includes unfeatured + owner attribution).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7186
+ "x-rank": "archon",
7187
+ "x-source": "modules/platform-identity/routes/projects.js",
6998
7188
  "responses": {
6999
7189
  "200": {
7000
7190
  "description": "Success.",
7001
7191
  "content": {
7002
7192
  "application/json": {
7003
7193
  "schema": {
7004
- "$ref": "#/components/schemas/GetProvisioningInstancesIdResponse"
7194
+ "$ref": "#/components/schemas/GetProjectsResponse"
7005
7195
  }
7006
7196
  }
7007
7197
  }
@@ -7014,9 +7204,6 @@
7014
7204
  },
7015
7205
  "403": {
7016
7206
  "$ref": "#/components/responses/Forbidden"
7017
- },
7018
- "404": {
7019
- "$ref": "#/components/responses/NotFound"
7020
7207
  }
7021
7208
  },
7022
7209
  "security": [
@@ -7024,51 +7211,46 @@
7024
7211
  "builderSession": []
7025
7212
  }
7026
7213
  ]
7027
- }
7028
- },
7029
- "/provisioning/instances/{id}/force-teardown": {
7214
+ },
7030
7215
  "post": {
7031
- "operationId": "post_provisioning_instances_id_force_teardown",
7216
+ "operationId": "post_projects",
7032
7217
  "tags": [
7033
- "provisioning"
7218
+ "projects"
7034
7219
  ],
7035
- "summary": "POST /provisioning/instances/:id/force-teardown",
7036
- "description": "POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. Trust-safe by the same mechanism as the owner's own teardown: it ENQUEUES a 'teardown' intent for the control-plane runner; the web tier never holds cloud tokens. rank: archon (acts on another owner's infrastructure). Declared among the archon routes (archon-first).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7220
+ "summary": "POST /projects",
7221
+ "description": "create / update a catalog entry (manual seed for hand-wired instances; federated projects auto-catalogue at registration).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7037
7222
  "x-rank": "archon",
7038
- "x-source": "modules/provisioning/routes/provisioning.js",
7039
- "parameters": [
7040
- {
7041
- "name": "id",
7042
- "in": "path",
7043
- "required": true,
7044
- "schema": {
7045
- "type": "string"
7046
- },
7047
- "description": "Path parameter `id`."
7048
- }
7049
- ],
7223
+ "x-source": "modules/platform-identity/routes/projects.js",
7224
+ "requestBody": {
7225
+ "required": true,
7226
+ "content": {
7227
+ "application/json": {
7228
+ "schema": {
7229
+ "$ref": "#/components/schemas/PostProjectsRequest"
7230
+ }
7231
+ }
7232
+ },
7233
+ "x-validated": true
7234
+ },
7050
7235
  "responses": {
7051
7236
  "200": {
7052
7237
  "description": "Success.",
7053
7238
  "content": {
7054
7239
  "application/json": {
7055
7240
  "schema": {
7056
- "$ref": "#/components/schemas/PostProvisioningInstancesIdForceTeardownResponse"
7241
+ "$ref": "#/components/schemas/PostProjectsResponse"
7057
7242
  }
7058
7243
  }
7059
7244
  }
7060
7245
  },
7061
7246
  "400": {
7062
- "$ref": "#/components/responses/BadRequest"
7247
+ "$ref": "#/components/responses/ValidationFailed"
7063
7248
  },
7064
7249
  "401": {
7065
7250
  "$ref": "#/components/responses/Unauthorized"
7066
7251
  },
7067
7252
  "403": {
7068
7253
  "$ref": "#/components/responses/Forbidden"
7069
- },
7070
- "404": {
7071
- "$ref": "#/components/responses/NotFound"
7072
7254
  }
7073
7255
  },
7074
7256
  "security": [
@@ -7078,33 +7260,50 @@
7078
7260
  ]
7079
7261
  }
7080
7262
  },
7081
- "/provisioning/instances/{id}/github-app": {
7082
- "post": {
7083
- "operationId": "post_provisioning_instances_id_github_app",
7263
+ "/projects/featured": {
7264
+ "get": {
7265
+ "operationId": "get_projects_featured",
7084
7266
  "tags": [
7085
- "provisioning"
7267
+ "projects"
7086
7268
  ],
7087
- "summary": "POST /provisioning/instances/:id/github-app",
7088
- "description": "POST /provisioning/instances/:id/github-app — mint a GitHub-App-Manifest onboarding link for the caller's OWN instance (task 2080, ADR 0133). rank: any authenticated builder (own resource). Returns the pre-filled manifest + the GitHub form-POST target (personal + org variants) + a one-time `state`; the browser POSTs the manifest to GitHub, the owner approves, and GitHub redirects back to the public callback below. The web tier only RECORDS the attempt (state token) — the control-plane runner does the token exchange + cred placement (trust boundary intact, ADR 0111 §2). Body: { account? ('personal'|'org') }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7089
- "x-rank": "any-builder",
7090
- "x-source": "modules/provisioning/routes/provisioning.js",
7091
- "parameters": [
7092
- {
7093
- "name": "id",
7094
- "in": "path",
7095
- "required": true,
7096
- "schema": {
7097
- "type": "string"
7098
- },
7099
- "description": "Path parameter `id`."
7269
+ "summary": "GET /projects/featured",
7270
+ "description": "a curated public showcase; no auth by design.\n\n**Rank:** `public` — No authentication — any caller.",
7271
+ "x-rank": "public",
7272
+ "x-source": "modules/platform-identity/routes/projects.js",
7273
+ "responses": {
7274
+ "200": {
7275
+ "description": "Success.",
7276
+ "content": {
7277
+ "application/json": {
7278
+ "schema": {
7279
+ "$ref": "#/components/schemas/GetProjectsFeaturedResponse"
7280
+ }
7281
+ }
7282
+ }
7283
+ },
7284
+ "400": {
7285
+ "$ref": "#/components/responses/BadRequest"
7100
7286
  }
7287
+ },
7288
+ "security": []
7289
+ }
7290
+ },
7291
+ "/projects/invite": {
7292
+ "post": {
7293
+ "operationId": "post_projects_invite",
7294
+ "tags": [
7295
+ "projects"
7101
7296
  ],
7297
+ "summary": "POST /projects/invite",
7298
+ "description": "invite a builder into a project (ADR 0141 §5, task #1002115). Pre-seeds a 'pending' membership the invitee accepts from My Projects. V1 invites by github_login and requires the invitee to already have a platform account (they build on some project); inviting someone entirely new to the platform (GitHub-id resolution) is a follow-up.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7299
+ "x-rank": "archon",
7300
+ "x-source": "modules/platform-identity/routes/projects.js",
7102
7301
  "requestBody": {
7103
- "required": false,
7302
+ "required": true,
7104
7303
  "content": {
7105
7304
  "application/json": {
7106
7305
  "schema": {
7107
- "$ref": "#/components/schemas/PostProvisioningInstancesIdGithubAppRequest"
7306
+ "$ref": "#/components/schemas/PostProjectsInviteRequest"
7108
7307
  }
7109
7308
  }
7110
7309
  },
@@ -7112,14 +7311,7 @@
7112
7311
  },
7113
7312
  "responses": {
7114
7313
  "200": {
7115
- "description": "Success.",
7116
- "content": {
7117
- "application/json": {
7118
- "schema": {
7119
- "$ref": "#/components/schemas/PostProvisioningInstancesIdGithubAppResponse"
7120
- }
7121
- }
7122
- }
7314
+ "description": "Success."
7123
7315
  },
7124
7316
  "400": {
7125
7317
  "$ref": "#/components/responses/ValidationFailed"
@@ -7129,9 +7321,6 @@
7129
7321
  },
7130
7322
  "403": {
7131
7323
  "$ref": "#/components/responses/Forbidden"
7132
- },
7133
- "404": {
7134
- "$ref": "#/components/responses/NotFound"
7135
7324
  }
7136
7325
  },
7137
7326
  "security": [
@@ -7141,16 +7330,16 @@
7141
7330
  ]
7142
7331
  }
7143
7332
  },
7144
- "/provisioning/instances/{id}/teardown": {
7145
- "post": {
7146
- "operationId": "post_provisioning_instances_id_teardown",
7333
+ "/projects/{id}/featured": {
7334
+ "patch": {
7335
+ "operationId": "patch_projects_id_featured",
7147
7336
  "tags": [
7148
- "provisioning"
7337
+ "projects"
7149
7338
  ],
7150
- "summary": "POST /provisioning/instances/:id/teardown",
7151
- "description": "POST /provisioning/instances/:id/teardown — request teardown of the caller's OWN instance. rank: any authenticated builder (own resource). Enqueues a 'teardown' intent; the runner executes it (web tier holds no tokens). 404 when the id isn't the caller's; 409 when the instance isn't in a teardownable state.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7152
- "x-rank": "any-builder",
7153
- "x-source": "modules/provisioning/routes/provisioning.js",
7339
+ "summary": "PATCH /projects/:id/featured",
7340
+ "description": "the feature / unfeature control (the ADR 0141 §5 curation gate).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7341
+ "x-rank": "archon",
7342
+ "x-source": "modules/platform-identity/routes/projects.js",
7154
7343
  "parameters": [
7155
7344
  {
7156
7345
  "name": "id",
@@ -7162,19 +7351,30 @@
7162
7351
  "description": "Path parameter `id`."
7163
7352
  }
7164
7353
  ],
7354
+ "requestBody": {
7355
+ "required": true,
7356
+ "content": {
7357
+ "application/json": {
7358
+ "schema": {
7359
+ "$ref": "#/components/schemas/PatchProjectsIdFeaturedRequest"
7360
+ }
7361
+ }
7362
+ },
7363
+ "x-validated": true
7364
+ },
7165
7365
  "responses": {
7166
7366
  "200": {
7167
7367
  "description": "Success.",
7168
7368
  "content": {
7169
7369
  "application/json": {
7170
7370
  "schema": {
7171
- "$ref": "#/components/schemas/PostProvisioningInstancesIdTeardownResponse"
7371
+ "$ref": "#/components/schemas/PatchProjectsIdFeaturedResponse"
7172
7372
  }
7173
7373
  }
7174
7374
  }
7175
7375
  },
7176
7376
  "400": {
7177
- "$ref": "#/components/responses/BadRequest"
7377
+ "$ref": "#/components/responses/ValidationFailed"
7178
7378
  },
7179
7379
  "401": {
7180
7380
  "$ref": "#/components/responses/Unauthorized"
@@ -7193,15 +7393,15 @@
7193
7393
  ]
7194
7394
  }
7195
7395
  },
7196
- "/provisioning/onboard-plan": {
7396
+ "/provisioning/fleet": {
7197
7397
  "get": {
7198
- "operationId": "get_provisioning_onboard_plan",
7398
+ "operationId": "get_provisioning_fleet",
7199
7399
  "tags": [
7200
7400
  "provisioning"
7201
7401
  ],
7202
- "summary": "GET /provisioning/onboard-plan",
7203
- "description": "GET /provisioning/onboard-plan?mode=greenfield|adopt — the CANONICAL onboarding step sequence (task 2085; goal 35 / criterion 165: \"the canonical step sequence is the source of truth; skill/CLI/hall are forms over it\"). The branded /create page + the hall wizard fetch it so their human-steps checklist can't drift from the CLI's (scripts/gds/onboard.js reads the same modules/provisioning/onboard-plan.js). rank: public — the signed-out /create landing page reads it; it is the same public runbook the /new-project skill documents (no write, no secret).\n\n**Rank:** `public` — No authentication — any caller.",
7204
- "x-rank": "public",
7402
+ "summary": "GET /provisioning/fleet",
7403
+ "description": "GET /provisioning/fleet — the full instance roster across all owners. rank: archon (exposes every owner's instance + cost; the /boxes precedent).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7404
+ "x-rank": "archon",
7205
7405
  "x-source": "modules/provisioning/routes/provisioning.js",
7206
7406
  "responses": {
7207
7407
  "200": {
@@ -7209,7 +7409,450 @@
7209
7409
  "content": {
7210
7410
  "application/json": {
7211
7411
  "schema": {
7212
- "$ref": "#/components/schemas/GetProvisioningOnboardPlanResponse"
7412
+ "$ref": "#/components/schemas/GetProvisioningFleetResponse"
7413
+ }
7414
+ }
7415
+ }
7416
+ },
7417
+ "400": {
7418
+ "$ref": "#/components/responses/BadRequest"
7419
+ },
7420
+ "401": {
7421
+ "$ref": "#/components/responses/Unauthorized"
7422
+ },
7423
+ "403": {
7424
+ "$ref": "#/components/responses/Forbidden"
7425
+ }
7426
+ },
7427
+ "security": [
7428
+ {
7429
+ "builderSession": []
7430
+ }
7431
+ ]
7432
+ }
7433
+ },
7434
+ "/provisioning/fleet/cost-ledger": {
7435
+ "get": {
7436
+ "operationId": "get_provisioning_fleet_cost_ledger",
7437
+ "tags": [
7438
+ "provisioning"
7439
+ ],
7440
+ "summary": "GET /provisioning/fleet/cost-ledger",
7441
+ "description": "GET /provisioning/fleet/cost-ledger — per-instance monthly estimate + total. rank: archon — cost oversight across the fleet (the /boxes/cost-ledger precedent). Declared among the archon routes (archon-first) for correct auditor classification.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7442
+ "x-rank": "archon",
7443
+ "x-source": "modules/provisioning/routes/provisioning.js",
7444
+ "responses": {
7445
+ "200": {
7446
+ "description": "Success."
7447
+ },
7448
+ "400": {
7449
+ "$ref": "#/components/responses/BadRequest"
7450
+ },
7451
+ "401": {
7452
+ "$ref": "#/components/responses/Unauthorized"
7453
+ },
7454
+ "403": {
7455
+ "$ref": "#/components/responses/Forbidden"
7456
+ }
7457
+ },
7458
+ "security": [
7459
+ {
7460
+ "builderSession": []
7461
+ }
7462
+ ]
7463
+ }
7464
+ },
7465
+ "/provisioning/github-app/callback": {
7466
+ "get": {
7467
+ "operationId": "get_provisioning_github_app_callback",
7468
+ "tags": [
7469
+ "provisioning"
7470
+ ],
7471
+ "summary": "GET /provisioning/github-app/callback",
7472
+ "description": "GET /provisioning/github-app/callback?code=&state= — GitHub redirects the owner's BROWSER here after they approve the App Manifest (task 2080, ADR 0133). It is a browser redirect with no session guaranteed, so it is PUBLIC — the unguessable, single-use, TTL'd `state` token (minted only for the signed-in owner and matched against provisioning_oauth_manifests) is the authorization, exactly as GitHub's own conversion `code` is \"the code IS the auth\". The web tier ONLY stores the code + flips status → 'code_received'; the control-plane runner (the sole token-holder) exchanges it for the client secret and places it in web.env. The secret NEVER touches the browser or the web tier. rank: public — no session, no mutation of authority, no secret revealed; a bad/expired/replayed state is a no-op error page.\n\n**Rank:** `public` — No authentication — any caller.",
7473
+ "x-rank": "public",
7474
+ "x-source": "modules/provisioning/routes/provisioning.js",
7475
+ "responses": {
7476
+ "200": {
7477
+ "description": "Success."
7478
+ },
7479
+ "400": {
7480
+ "$ref": "#/components/responses/BadRequest"
7481
+ }
7482
+ },
7483
+ "security": []
7484
+ }
7485
+ },
7486
+ "/provisioning/github-app/status": {
7487
+ "get": {
7488
+ "operationId": "get_provisioning_github_app_status",
7489
+ "tags": [
7490
+ "provisioning"
7491
+ ],
7492
+ "summary": "GET /provisioning/github-app/status",
7493
+ "description": "GET /provisioning/github-app/status?state=<> — the PUBLIC progress read the onboarding callback page polls (task 2096) to know when setup is done + where to send the owner. Same public-by-state model as the callback: the unguessable, single-use `state` token is the only key, and the response reveals only the manifest lifecycle status + the instance's own (already-public) domain — never a secret. Per-IP rate-limited because the page polls it every ~3s. `ready` is true iff the manifest reached 'done' (creds placed + /healthz verified) — the page then auto-redirects to https://<domain>. rank: public — no session, no mutation, no secret; an unknown state is a 404 no-op.\n\n**Rank:** `public` — No authentication — any caller.",
7494
+ "x-rank": "public",
7495
+ "x-source": "modules/provisioning/routes/provisioning.js",
7496
+ "responses": {
7497
+ "200": {
7498
+ "description": "Success.",
7499
+ "content": {
7500
+ "application/json": {
7501
+ "schema": {
7502
+ "$ref": "#/components/schemas/GetProvisioningGithubAppStatusResponse"
7503
+ }
7504
+ }
7505
+ }
7506
+ },
7507
+ "400": {
7508
+ "$ref": "#/components/responses/BadRequest"
7509
+ }
7510
+ },
7511
+ "security": []
7512
+ }
7513
+ },
7514
+ "/provisioning/health": {
7515
+ "get": {
7516
+ "operationId": "get_provisioning_health",
7517
+ "tags": [
7518
+ "provisioning"
7519
+ ],
7520
+ "summary": "GET /provisioning/health",
7521
+ "description": "GET /provisioning/health — liveness + the core version this module mounted against. rank: public (a plain liveness read; no write, no sensitive data).\n\n**Rank:** `public` — No authentication — any caller.",
7522
+ "x-rank": "public",
7523
+ "x-source": "modules/provisioning/routes/provisioning.js",
7524
+ "responses": {
7525
+ "200": {
7526
+ "description": "Success.",
7527
+ "content": {
7528
+ "application/json": {
7529
+ "schema": {
7530
+ "$ref": "#/components/schemas/GetProvisioningHealthResponse"
7531
+ }
7532
+ }
7533
+ }
7534
+ },
7535
+ "400": {
7536
+ "$ref": "#/components/responses/BadRequest"
7537
+ }
7538
+ },
7539
+ "security": []
7540
+ }
7541
+ },
7542
+ "/provisioning/instances": {
7543
+ "get": {
7544
+ "operationId": "get_provisioning_instances",
7545
+ "tags": [
7546
+ "provisioning"
7547
+ ],
7548
+ "summary": "GET /provisioning/instances",
7549
+ "description": "GET /provisioning/instances — the caller's own instances + each open intent. rank: any authenticated builder (own resource read).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7550
+ "x-rank": "any-builder",
7551
+ "x-source": "modules/provisioning/routes/provisioning.js",
7552
+ "responses": {
7553
+ "200": {
7554
+ "description": "Success.",
7555
+ "content": {
7556
+ "application/json": {
7557
+ "schema": {
7558
+ "$ref": "#/components/schemas/GetProvisioningInstancesResponse"
7559
+ }
7560
+ }
7561
+ }
7562
+ },
7563
+ "400": {
7564
+ "$ref": "#/components/responses/BadRequest"
7565
+ },
7566
+ "401": {
7567
+ "$ref": "#/components/responses/Unauthorized"
7568
+ },
7569
+ "403": {
7570
+ "$ref": "#/components/responses/Forbidden"
7571
+ }
7572
+ },
7573
+ "security": [
7574
+ {
7575
+ "builderSession": []
7576
+ }
7577
+ ]
7578
+ },
7579
+ "post": {
7580
+ "operationId": "post_provisioning_instances",
7581
+ "tags": [
7582
+ "provisioning"
7583
+ ],
7584
+ "summary": "POST /provisioning/instances",
7585
+ "description": "POST /provisioning/instances — request a new instance. rank: any authenticated builder (own resource). ENQUEUES a 'provision' intent + records the request; the runner (task P3) does the real standup. Idempotent on slug for the SAME owner (re-request returns the existing row); a slug owned by ANOTHER builder → 409. Body: { slug (required), target_ref?, hosting_shape? (co-tenant|dedicated), domain?, tier? }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7586
+ "x-rank": "any-builder",
7587
+ "x-source": "modules/provisioning/routes/provisioning.js",
7588
+ "requestBody": {
7589
+ "required": true,
7590
+ "content": {
7591
+ "application/json": {
7592
+ "schema": {
7593
+ "$ref": "#/components/schemas/PostProvisioningInstancesRequest"
7594
+ }
7595
+ }
7596
+ },
7597
+ "x-validated": true
7598
+ },
7599
+ "responses": {
7600
+ "200": {
7601
+ "description": "Success."
7602
+ },
7603
+ "400": {
7604
+ "$ref": "#/components/responses/ValidationFailed"
7605
+ },
7606
+ "401": {
7607
+ "$ref": "#/components/responses/Unauthorized"
7608
+ },
7609
+ "403": {
7610
+ "$ref": "#/components/responses/Forbidden"
7611
+ }
7612
+ },
7613
+ "security": [
7614
+ {
7615
+ "builderSession": []
7616
+ }
7617
+ ]
7618
+ }
7619
+ },
7620
+ "/provisioning/instances/{id}": {
7621
+ "get": {
7622
+ "operationId": "get_provisioning_instances_id",
7623
+ "tags": [
7624
+ "provisioning"
7625
+ ],
7626
+ "summary": "GET /provisioning/instances/:id",
7627
+ "description": "GET /provisioning/instances/:id — read one of the caller's own instances. rank: any authenticated builder (own resource). 404 when the id isn't the caller's (own-scoped; does not leak another owner's instance existence).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7628
+ "x-rank": "any-builder",
7629
+ "x-source": "modules/provisioning/routes/provisioning.js",
7630
+ "parameters": [
7631
+ {
7632
+ "name": "id",
7633
+ "in": "path",
7634
+ "required": true,
7635
+ "schema": {
7636
+ "type": "string"
7637
+ },
7638
+ "description": "Path parameter `id`."
7639
+ }
7640
+ ],
7641
+ "responses": {
7642
+ "200": {
7643
+ "description": "Success.",
7644
+ "content": {
7645
+ "application/json": {
7646
+ "schema": {
7647
+ "$ref": "#/components/schemas/GetProvisioningInstancesIdResponse"
7648
+ }
7649
+ }
7650
+ }
7651
+ },
7652
+ "400": {
7653
+ "$ref": "#/components/responses/BadRequest"
7654
+ },
7655
+ "401": {
7656
+ "$ref": "#/components/responses/Unauthorized"
7657
+ },
7658
+ "403": {
7659
+ "$ref": "#/components/responses/Forbidden"
7660
+ },
7661
+ "404": {
7662
+ "$ref": "#/components/responses/NotFound"
7663
+ }
7664
+ },
7665
+ "security": [
7666
+ {
7667
+ "builderSession": []
7668
+ }
7669
+ ]
7670
+ }
7671
+ },
7672
+ "/provisioning/instances/{id}/force-teardown": {
7673
+ "post": {
7674
+ "operationId": "post_provisioning_instances_id_force_teardown",
7675
+ "tags": [
7676
+ "provisioning"
7677
+ ],
7678
+ "summary": "POST /provisioning/instances/:id/force-teardown",
7679
+ "description": "POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. Trust-safe by the same mechanism as the owner's own teardown: it ENQUEUES a 'teardown' intent for the control-plane runner; the web tier never holds cloud tokens. rank: archon (acts on another owner's infrastructure). Declared among the archon routes (archon-first).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7680
+ "x-rank": "archon",
7681
+ "x-source": "modules/provisioning/routes/provisioning.js",
7682
+ "parameters": [
7683
+ {
7684
+ "name": "id",
7685
+ "in": "path",
7686
+ "required": true,
7687
+ "schema": {
7688
+ "type": "string"
7689
+ },
7690
+ "description": "Path parameter `id`."
7691
+ }
7692
+ ],
7693
+ "responses": {
7694
+ "200": {
7695
+ "description": "Success.",
7696
+ "content": {
7697
+ "application/json": {
7698
+ "schema": {
7699
+ "$ref": "#/components/schemas/PostProvisioningInstancesIdForceTeardownResponse"
7700
+ }
7701
+ }
7702
+ }
7703
+ },
7704
+ "400": {
7705
+ "$ref": "#/components/responses/BadRequest"
7706
+ },
7707
+ "401": {
7708
+ "$ref": "#/components/responses/Unauthorized"
7709
+ },
7710
+ "403": {
7711
+ "$ref": "#/components/responses/Forbidden"
7712
+ },
7713
+ "404": {
7714
+ "$ref": "#/components/responses/NotFound"
7715
+ }
7716
+ },
7717
+ "security": [
7718
+ {
7719
+ "builderSession": []
7720
+ }
7721
+ ]
7722
+ }
7723
+ },
7724
+ "/provisioning/instances/{id}/github-app": {
7725
+ "post": {
7726
+ "operationId": "post_provisioning_instances_id_github_app",
7727
+ "tags": [
7728
+ "provisioning"
7729
+ ],
7730
+ "summary": "POST /provisioning/instances/:id/github-app",
7731
+ "description": "POST /provisioning/instances/:id/github-app — mint a GitHub-App-Manifest onboarding link for the caller's OWN instance (task 2080, ADR 0133). rank: any authenticated builder (own resource). Returns the pre-filled manifest + the GitHub form-POST target (personal + org variants) + a one-time `state`; the browser POSTs the manifest to GitHub, the owner approves, and GitHub redirects back to the public callback below. The web tier only RECORDS the attempt (state token) — the control-plane runner does the token exchange + cred placement (trust boundary intact, ADR 0111 §2). Body: { account? ('personal'|'org') }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7732
+ "x-rank": "any-builder",
7733
+ "x-source": "modules/provisioning/routes/provisioning.js",
7734
+ "parameters": [
7735
+ {
7736
+ "name": "id",
7737
+ "in": "path",
7738
+ "required": true,
7739
+ "schema": {
7740
+ "type": "string"
7741
+ },
7742
+ "description": "Path parameter `id`."
7743
+ }
7744
+ ],
7745
+ "requestBody": {
7746
+ "required": false,
7747
+ "content": {
7748
+ "application/json": {
7749
+ "schema": {
7750
+ "$ref": "#/components/schemas/PostProvisioningInstancesIdGithubAppRequest"
7751
+ }
7752
+ }
7753
+ },
7754
+ "x-validated": true
7755
+ },
7756
+ "responses": {
7757
+ "200": {
7758
+ "description": "Success.",
7759
+ "content": {
7760
+ "application/json": {
7761
+ "schema": {
7762
+ "$ref": "#/components/schemas/PostProvisioningInstancesIdGithubAppResponse"
7763
+ }
7764
+ }
7765
+ }
7766
+ },
7767
+ "400": {
7768
+ "$ref": "#/components/responses/ValidationFailed"
7769
+ },
7770
+ "401": {
7771
+ "$ref": "#/components/responses/Unauthorized"
7772
+ },
7773
+ "403": {
7774
+ "$ref": "#/components/responses/Forbidden"
7775
+ },
7776
+ "404": {
7777
+ "$ref": "#/components/responses/NotFound"
7778
+ }
7779
+ },
7780
+ "security": [
7781
+ {
7782
+ "builderSession": []
7783
+ }
7784
+ ]
7785
+ }
7786
+ },
7787
+ "/provisioning/instances/{id}/teardown": {
7788
+ "post": {
7789
+ "operationId": "post_provisioning_instances_id_teardown",
7790
+ "tags": [
7791
+ "provisioning"
7792
+ ],
7793
+ "summary": "POST /provisioning/instances/:id/teardown",
7794
+ "description": "POST /provisioning/instances/:id/teardown — request teardown of the caller's OWN instance. rank: any authenticated builder (own resource). Enqueues a 'teardown' intent; the runner executes it (web tier holds no tokens). 404 when the id isn't the caller's; 409 when the instance isn't in a teardownable state.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7795
+ "x-rank": "any-builder",
7796
+ "x-source": "modules/provisioning/routes/provisioning.js",
7797
+ "parameters": [
7798
+ {
7799
+ "name": "id",
7800
+ "in": "path",
7801
+ "required": true,
7802
+ "schema": {
7803
+ "type": "string"
7804
+ },
7805
+ "description": "Path parameter `id`."
7806
+ }
7807
+ ],
7808
+ "responses": {
7809
+ "200": {
7810
+ "description": "Success.",
7811
+ "content": {
7812
+ "application/json": {
7813
+ "schema": {
7814
+ "$ref": "#/components/schemas/PostProvisioningInstancesIdTeardownResponse"
7815
+ }
7816
+ }
7817
+ }
7818
+ },
7819
+ "400": {
7820
+ "$ref": "#/components/responses/BadRequest"
7821
+ },
7822
+ "401": {
7823
+ "$ref": "#/components/responses/Unauthorized"
7824
+ },
7825
+ "403": {
7826
+ "$ref": "#/components/responses/Forbidden"
7827
+ },
7828
+ "404": {
7829
+ "$ref": "#/components/responses/NotFound"
7830
+ }
7831
+ },
7832
+ "security": [
7833
+ {
7834
+ "builderSession": []
7835
+ }
7836
+ ]
7837
+ }
7838
+ },
7839
+ "/provisioning/onboard-plan": {
7840
+ "get": {
7841
+ "operationId": "get_provisioning_onboard_plan",
7842
+ "tags": [
7843
+ "provisioning"
7844
+ ],
7845
+ "summary": "GET /provisioning/onboard-plan",
7846
+ "description": "GET /provisioning/onboard-plan?mode=greenfield|adopt — the CANONICAL onboarding step sequence (task 2085; goal 35 / criterion 165: \"the canonical step sequence is the source of truth; skill/CLI/hall are forms over it\"). The branded /create page + the hall wizard fetch it so their human-steps checklist can't drift from the CLI's (scripts/gds/onboard.js reads the same modules/provisioning/onboard-plan.js). rank: public — the signed-out /create landing page reads it; it is the same public runbook the /new-project skill documents (no write, no secret).\n\n**Rank:** `public` — No authentication — any caller.",
7847
+ "x-rank": "public",
7848
+ "x-source": "modules/provisioning/routes/provisioning.js",
7849
+ "responses": {
7850
+ "200": {
7851
+ "description": "Success.",
7852
+ "content": {
7853
+ "application/json": {
7854
+ "schema": {
7855
+ "$ref": "#/components/schemas/GetProvisioningOnboardPlanResponse"
7213
7856
  }
7214
7857
  }
7215
7858
  }
@@ -7687,88 +8330,354 @@
7687
8330
  }
7688
8331
  }
7689
8332
  },
7690
- "400": {
7691
- "$ref": "#/components/responses/BadRequest"
7692
- },
7693
- "404": {
7694
- "$ref": "#/components/responses/NotFound"
7695
- }
8333
+ "400": {
8334
+ "$ref": "#/components/responses/BadRequest"
8335
+ },
8336
+ "404": {
8337
+ "$ref": "#/components/responses/NotFound"
8338
+ }
8339
+ },
8340
+ "security": []
8341
+ }
8342
+ },
8343
+ "/public/uptime": {
8344
+ "get": {
8345
+ "operationId": "get_public_uptime",
8346
+ "tags": [
8347
+ "public"
8348
+ ],
8349
+ "summary": "GET /public/uptime",
8350
+ "description": "Uptime: current status + 90-day history bucketed by hour. Returns per-service: current_status, uptime_pct_90d, history (array of { hour: ISO string, up: n, total: n } for the last 90*24 hours). rank: public — uptime feed (90-day hourly history).\n\n**Rank:** `public` — No authentication — any caller.",
8351
+ "x-rank": "public",
8352
+ "x-source": "src/bongos/routes/public.js",
8353
+ "responses": {
8354
+ "200": {
8355
+ "description": "Success.",
8356
+ "content": {
8357
+ "application/json": {
8358
+ "schema": {
8359
+ "$ref": "#/components/schemas/GetPublicUptimeResponse"
8360
+ }
8361
+ }
8362
+ }
8363
+ },
8364
+ "400": {
8365
+ "$ref": "#/components/responses/BadRequest"
8366
+ }
8367
+ },
8368
+ "security": []
8369
+ }
8370
+ },
8371
+ "/public/versions": {
8372
+ "get": {
8373
+ "operationId": "get_public_versions",
8374
+ "tags": [
8375
+ "public"
8376
+ ],
8377
+ "summary": "GET /public/versions",
8378
+ "description": "read-only surface for status.amazonprimea.com.\n\n**Rank:** `public` — No authentication — any caller.",
8379
+ "x-rank": "public",
8380
+ "x-source": "src/bongos/routes/public.js",
8381
+ "responses": {
8382
+ "200": {
8383
+ "description": "Success.",
8384
+ "content": {
8385
+ "application/json": {
8386
+ "schema": {
8387
+ "$ref": "#/components/schemas/GetPublicVersionsResponse"
8388
+ }
8389
+ }
8390
+ }
8391
+ },
8392
+ "400": {
8393
+ "$ref": "#/components/responses/BadRequest"
8394
+ }
8395
+ },
8396
+ "security": []
8397
+ }
8398
+ },
8399
+ "/scouting": {
8400
+ "get": {
8401
+ "operationId": "get_scouting",
8402
+ "tags": [
8403
+ "scouting"
8404
+ ],
8405
+ "summary": "GET /scouting",
8406
+ "description": "the internal talent directory across every project. The Archon gate here is the load-bearing protection (\"NOT shown to builders\"): a non-Archon is 403'd before any cross-builder data is read.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8407
+ "x-rank": "archon",
8408
+ "x-source": "modules/platform-identity/routes/scouting.js",
8409
+ "responses": {
8410
+ "200": {
8411
+ "description": "Success.",
8412
+ "content": {
8413
+ "application/json": {
8414
+ "schema": {
8415
+ "$ref": "#/components/schemas/GetScoutingResponse"
8416
+ }
8417
+ }
8418
+ }
8419
+ },
8420
+ "400": {
8421
+ "$ref": "#/components/responses/BadRequest"
8422
+ },
8423
+ "401": {
8424
+ "$ref": "#/components/responses/Unauthorized"
8425
+ },
8426
+ "403": {
8427
+ "$ref": "#/components/responses/Forbidden"
8428
+ }
8429
+ },
8430
+ "security": [
8431
+ {
8432
+ "builderSession": []
8433
+ }
8434
+ ]
8435
+ }
8436
+ },
8437
+ "/search": {
8438
+ "post": {
8439
+ "operationId": "post_search",
8440
+ "tags": [
8441
+ "search"
8442
+ ],
8443
+ "summary": "POST /search",
8444
+ "description": "POST /search — two modes (ADR 0095 C1 / task 1658, progressive disclosure): 1. SUMMARY (default): body { q: string, limit?: 1..50, source_kind? }. Returns the ranked compact layer — each hit carries a snippet plus `snippet_tokens` (what you already see) and `full_tokens` (what a full expansion would COST), so the caller sees the price before paying it. 2. EXPAND: body { expand: <chunkId> } (with q optional). Returns that one chunk's FULL body + `body_tokens`, scoped exactly like search (rank + owner from the session), so expand can't widen visibility. Both shapes stay backward-compatible: the old { q } request still returns { query, count, results } — the new per-hit fields are additive. Single-line opener so the deterministic route-rank auditor classifies the chain (requireBuilder → 'any-builder') — ADR 0016 / route-rank-check.js.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8445
+ "x-rank": "any-builder",
8446
+ "x-source": "modules/memory/routes/search.js",
8447
+ "requestBody": {
8448
+ "required": false,
8449
+ "content": {
8450
+ "application/json": {
8451
+ "schema": {
8452
+ "$ref": "#/components/schemas/PostSearchRequest"
8453
+ }
8454
+ }
8455
+ },
8456
+ "x-validated": true
8457
+ },
8458
+ "responses": {
8459
+ "200": {
8460
+ "description": "Success.",
8461
+ "content": {
8462
+ "application/json": {
8463
+ "schema": {
8464
+ "$ref": "#/components/schemas/PostSearchResponse"
8465
+ }
8466
+ }
8467
+ }
8468
+ },
8469
+ "400": {
8470
+ "$ref": "#/components/responses/ValidationFailed"
8471
+ },
8472
+ "401": {
8473
+ "$ref": "#/components/responses/Unauthorized"
8474
+ },
8475
+ "403": {
8476
+ "$ref": "#/components/responses/Forbidden"
8477
+ }
8478
+ },
8479
+ "security": [
8480
+ {
8481
+ "builderSession": []
8482
+ }
8483
+ ]
8484
+ }
8485
+ },
8486
+ "/search/mark": {
8487
+ "post": {
8488
+ "operationId": "post_search_mark",
8489
+ "tags": [
8490
+ "search"
8491
+ ],
8492
+ "summary": "POST /search/mark",
8493
+ "description": "POST /search/mark — the write half of the memory-usefulness feedback loop (ADR 0095 C3, task 1660). Body { chunk_id: int, useful?: bool }. Records that a recalled chunk did (useful=true, the default) or did NOT (useful=false) help, so the ranker lifts the useful and fades the dead-end. SCOPING (ADR 0016): the caller's id + rank come ONLY from the session, never the body — searchChunks-equivalent scope is re-applied in the UPDATE WHERE, so a chunk the caller couldn't have seen can't be voted on (→ updated:false). Single-line opener so the route-rank auditor classifies the chain.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8494
+ "x-rank": "any-builder",
8495
+ "x-source": "modules/memory/routes/search.js",
8496
+ "requestBody": {
8497
+ "required": false,
8498
+ "content": {
8499
+ "application/json": {
8500
+ "schema": {
8501
+ "$ref": "#/components/schemas/PostSearchMarkRequest"
8502
+ }
8503
+ }
8504
+ },
8505
+ "x-validated": true
8506
+ },
8507
+ "responses": {
8508
+ "200": {
8509
+ "description": "Success."
8510
+ },
8511
+ "400": {
8512
+ "$ref": "#/components/responses/ValidationFailed"
8513
+ },
8514
+ "401": {
8515
+ "$ref": "#/components/responses/Unauthorized"
8516
+ },
8517
+ "403": {
8518
+ "$ref": "#/components/responses/Forbidden"
8519
+ }
8520
+ },
8521
+ "security": [
8522
+ {
8523
+ "builderSession": []
8524
+ }
8525
+ ]
8526
+ }
8527
+ },
8528
+ "/security/docs": {
8529
+ "get": {
8530
+ "operationId": "get_security_docs",
8531
+ "tags": [
8532
+ "security"
8533
+ ],
8534
+ "summary": "GET /security/docs",
8535
+ "description": "GET /api/gds/security/docs — list doc METADATA (no content). rank: archon — index of exploit-detail engagement reports.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8536
+ "x-rank": "archon",
8537
+ "x-source": "src/bongos/routes/security.js",
8538
+ "responses": {
8539
+ "200": {
8540
+ "description": "Success.",
8541
+ "content": {
8542
+ "application/json": {
8543
+ "schema": {
8544
+ "$ref": "#/components/schemas/GetSecurityDocsResponse"
8545
+ }
8546
+ }
8547
+ }
8548
+ },
8549
+ "400": {
8550
+ "$ref": "#/components/responses/BadRequest"
8551
+ },
8552
+ "401": {
8553
+ "$ref": "#/components/responses/Unauthorized"
8554
+ },
8555
+ "403": {
8556
+ "$ref": "#/components/responses/Forbidden"
8557
+ }
8558
+ },
8559
+ "security": [
8560
+ {
8561
+ "builderSession": []
8562
+ }
8563
+ ]
8564
+ },
8565
+ "post": {
8566
+ "operationId": "post_security_docs",
8567
+ "tags": [
8568
+ "security"
8569
+ ],
8570
+ "summary": "POST /security/docs",
8571
+ "description": "POST /api/gds/security/docs — upsert a doc by slug. The director uploads each dated engagement report here after deploy. Body: { slug, title, content_md }. content_md uses a large explicit cap (full reports), NOT the small LIMITS.DESCRIPTION. Returns 201 + the row. rank: archon — writes exploit-detail report bodies.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8572
+ "x-rank": "archon",
8573
+ "x-source": "src/bongos/routes/security.js",
8574
+ "requestBody": {
8575
+ "required": true,
8576
+ "content": {
8577
+ "application/json": {
8578
+ "schema": {
8579
+ "$ref": "#/components/schemas/PostSecurityDocsRequest"
8580
+ }
8581
+ }
8582
+ },
8583
+ "x-validated": true
7696
8584
  },
7697
- "security": []
7698
- }
7699
- },
7700
- "/public/uptime": {
7701
- "get": {
7702
- "operationId": "get_public_uptime",
7703
- "tags": [
7704
- "public"
7705
- ],
7706
- "summary": "GET /public/uptime",
7707
- "description": "Uptime: current status + 90-day history bucketed by hour. Returns per-service: current_status, uptime_pct_90d, history (array of { hour: ISO string, up: n, total: n } for the last 90*24 hours). rank: public — uptime feed (90-day hourly history).\n\n**Rank:** `public` — No authentication — any caller.",
7708
- "x-rank": "public",
7709
- "x-source": "src/bongos/routes/public.js",
7710
8585
  "responses": {
7711
8586
  "200": {
7712
8587
  "description": "Success.",
7713
8588
  "content": {
7714
8589
  "application/json": {
7715
8590
  "schema": {
7716
- "$ref": "#/components/schemas/GetPublicUptimeResponse"
8591
+ "$ref": "#/components/schemas/PostSecurityDocsResponse"
7717
8592
  }
7718
8593
  }
7719
8594
  }
7720
8595
  },
7721
8596
  "400": {
7722
- "$ref": "#/components/responses/BadRequest"
8597
+ "$ref": "#/components/responses/ValidationFailed"
8598
+ },
8599
+ "401": {
8600
+ "$ref": "#/components/responses/Unauthorized"
8601
+ },
8602
+ "403": {
8603
+ "$ref": "#/components/responses/Forbidden"
7723
8604
  }
7724
8605
  },
7725
- "security": []
8606
+ "security": [
8607
+ {
8608
+ "builderSession": []
8609
+ }
8610
+ ]
7726
8611
  }
7727
8612
  },
7728
- "/public/versions": {
8613
+ "/security/docs/{slug}": {
7729
8614
  "get": {
7730
- "operationId": "get_public_versions",
8615
+ "operationId": "get_security_docs_slug",
7731
8616
  "tags": [
7732
- "public"
8617
+ "security"
8618
+ ],
8619
+ "summary": "GET /security/docs/:slug",
8620
+ "description": "GET /api/gds/security/docs/:slug — one doc WITH content, or 404. rank: archon — reads the full exploit-detail report body.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8621
+ "x-rank": "archon",
8622
+ "x-source": "src/bongos/routes/security.js",
8623
+ "parameters": [
8624
+ {
8625
+ "name": "slug",
8626
+ "in": "path",
8627
+ "required": true,
8628
+ "schema": {
8629
+ "type": "string"
8630
+ },
8631
+ "description": "Path parameter `slug`."
8632
+ }
7733
8633
  ],
7734
- "summary": "GET /public/versions",
7735
- "description": "read-only surface for status.amazonprimea.com.\n\n**Rank:** `public` — No authentication — any caller.",
7736
- "x-rank": "public",
7737
- "x-source": "src/bongos/routes/public.js",
7738
8634
  "responses": {
7739
8635
  "200": {
7740
8636
  "description": "Success.",
7741
8637
  "content": {
7742
8638
  "application/json": {
7743
8639
  "schema": {
7744
- "$ref": "#/components/schemas/GetPublicVersionsResponse"
8640
+ "$ref": "#/components/schemas/GetSecurityDocsSlugResponse"
7745
8641
  }
7746
8642
  }
7747
8643
  }
7748
8644
  },
7749
8645
  "400": {
7750
8646
  "$ref": "#/components/responses/BadRequest"
8647
+ },
8648
+ "401": {
8649
+ "$ref": "#/components/responses/Unauthorized"
8650
+ },
8651
+ "403": {
8652
+ "$ref": "#/components/responses/Forbidden"
8653
+ },
8654
+ "404": {
8655
+ "$ref": "#/components/responses/NotFound"
7751
8656
  }
7752
8657
  },
7753
- "security": []
8658
+ "security": [
8659
+ {
8660
+ "builderSession": []
8661
+ }
8662
+ ]
7754
8663
  }
7755
8664
  },
7756
- "/search": {
8665
+ "/session/optimize": {
7757
8666
  "post": {
7758
- "operationId": "post_search",
8667
+ "operationId": "post_session_optimize",
7759
8668
  "tags": [
7760
- "search"
8669
+ "session"
7761
8670
  ],
7762
- "summary": "POST /search",
7763
- "description": "POST /search — two modes (ADR 0095 C1 / task 1658, progressive disclosure): 1. SUMMARY (default): body { q: string, limit?: 1..50, source_kind? }. Returns the ranked compact layer — each hit carries a snippet plus `snippet_tokens` (what you already see) and `full_tokens` (what a full expansion would COST), so the caller sees the price before paying it. 2. EXPAND: body { expand: <chunkId> } (with q optional). Returns that one chunk's FULL body + `body_tokens`, scoped exactly like search (rank + owner from the session), so expand can't widen visibility. Both shapes stay backward-compatible: the old { q } request still returns { query, count, results } — the new per-hit fields are additive. Single-line opener so the deterministic route-rank auditor classifies the chain (requireBuilder → 'any-builder') — ADR 0016 / route-rank-check.js.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8671
+ "summary": "POST /session/optimize",
8672
+ "description": "pick own next work; the optimizer reads/recommends only.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7764
8673
  "x-rank": "any-builder",
7765
- "x-source": "modules/memory/routes/search.js",
8674
+ "x-source": "src/bongos/routes/optimizer.js",
7766
8675
  "requestBody": {
7767
8676
  "required": false,
7768
8677
  "content": {
7769
8678
  "application/json": {
7770
8679
  "schema": {
7771
- "$ref": "#/components/schemas/PostSearchRequest"
8680
+ "$ref": "#/components/schemas/PostSessionOptimizeRequest"
7772
8681
  }
7773
8682
  }
7774
8683
  },
@@ -7776,14 +8685,7 @@
7776
8685
  },
7777
8686
  "responses": {
7778
8687
  "200": {
7779
- "description": "Success.",
7780
- "content": {
7781
- "application/json": {
7782
- "schema": {
7783
- "$ref": "#/components/schemas/PostSearchResponse"
7784
- }
7785
- }
7786
- }
8688
+ "description": "Success."
7787
8689
  },
7788
8690
  "400": {
7789
8691
  "$ref": "#/components/responses/ValidationFailed"
@@ -7802,22 +8704,22 @@
7802
8704
  ]
7803
8705
  }
7804
8706
  },
7805
- "/search/mark": {
8707
+ "/sessions": {
7806
8708
  "post": {
7807
- "operationId": "post_search_mark",
8709
+ "operationId": "post_sessions",
7808
8710
  "tags": [
7809
- "search"
8711
+ "sessions"
7810
8712
  ],
7811
- "summary": "POST /search/mark",
7812
- "description": "POST /search/mark — the write half of the memory-usefulness feedback loop (ADR 0095 C3, task 1660). Body { chunk_id: int, useful?: bool }. Records that a recalled chunk did (useful=true, the default) or did NOT (useful=false) help, so the ranker lifts the useful and fades the dead-end. SCOPING (ADR 0016): the caller's id + rank come ONLY from the session, never the body — searchChunks-equivalent scope is re-applied in the UPDATE WHERE, so a chunk the caller couldn't have seen can't be voted on (→ updated:false). Single-line opener so the route-rank auditor classifies the chain.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8713
+ "summary": "POST /sessions",
8714
+ "description": "upload your OWN session digest. Owner is forced to the authenticated caller; the body cannot attribute a record to another builder.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7813
8715
  "x-rank": "any-builder",
7814
- "x-source": "modules/memory/routes/search.js",
8716
+ "x-source": "modules/sessions/routes/sessions.js",
7815
8717
  "requestBody": {
7816
- "required": false,
8718
+ "required": true,
7817
8719
  "content": {
7818
8720
  "application/json": {
7819
8721
  "schema": {
7820
- "$ref": "#/components/schemas/PostSearchMarkRequest"
8722
+ "$ref": "#/components/schemas/PostSessionsRequest"
7821
8723
  }
7822
8724
  }
7823
8725
  },
@@ -7825,7 +8727,14 @@
7825
8727
  },
7826
8728
  "responses": {
7827
8729
  "200": {
7828
- "description": "Success."
8730
+ "description": "Success.",
8731
+ "content": {
8732
+ "application/json": {
8733
+ "schema": {
8734
+ "$ref": "#/components/schemas/PostSessionsResponse"
8735
+ }
8736
+ }
8737
+ }
7829
8738
  },
7830
8739
  "400": {
7831
8740
  "$ref": "#/components/responses/ValidationFailed"
@@ -7844,23 +8753,23 @@
7844
8753
  ]
7845
8754
  }
7846
8755
  },
7847
- "/security/docs": {
8756
+ "/sessions/mine": {
7848
8757
  "get": {
7849
- "operationId": "get_security_docs",
8758
+ "operationId": "get_sessions_mine",
7850
8759
  "tags": [
7851
- "security"
8760
+ "sessions"
7852
8761
  ],
7853
- "summary": "GET /security/docs",
7854
- "description": "GET /api/gds/security/docs — list doc METADATA (no content). rank: archon — index of exploit-detail engagement reports.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7855
- "x-rank": "archon",
7856
- "x-source": "src/bongos/routes/security.js",
8762
+ "summary": "GET /sessions/mine",
8763
+ "description": "your OWN sessions (self-serve; no audit needed).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8764
+ "x-rank": "any-builder",
8765
+ "x-source": "modules/sessions/routes/sessions.js",
7857
8766
  "responses": {
7858
8767
  "200": {
7859
8768
  "description": "Success.",
7860
8769
  "content": {
7861
8770
  "application/json": {
7862
8771
  "schema": {
7863
- "$ref": "#/components/schemas/GetSecurityDocsResponse"
8772
+ "$ref": "#/components/schemas/GetSessionsMineResponse"
7864
8773
  }
7865
8774
  }
7866
8775
  }
@@ -7880,40 +8789,31 @@
7880
8789
  "builderSession": []
7881
8790
  }
7882
8791
  ]
7883
- },
7884
- "post": {
7885
- "operationId": "post_security_docs",
8792
+ }
8793
+ },
8794
+ "/sessions/search": {
8795
+ "get": {
8796
+ "operationId": "get_sessions_search",
7886
8797
  "tags": [
7887
- "security"
8798
+ "sessions"
7888
8799
  ],
7889
- "summary": "POST /security/docs",
7890
- "description": "POST /api/gds/security/docs — upsert a doc by slug. The director uploads each dated engagement report here after deploy. Body: { slug, title, content_md }. content_md uses a large explicit cap (full reports), NOT the small LIMITS.DESCRIPTION. Returns 201 + the row. rank: archon — writes exploit-detail report bodies.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8800
+ "summary": "GET /sessions/search",
8801
+ "description": "cross-builder corpus search (BFG-principal posture until 6C.1).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7891
8802
  "x-rank": "archon",
7892
- "x-source": "src/bongos/routes/security.js",
7893
- "requestBody": {
7894
- "required": true,
7895
- "content": {
7896
- "application/json": {
7897
- "schema": {
7898
- "$ref": "#/components/schemas/PostSecurityDocsRequest"
7899
- }
7900
- }
7901
- },
7902
- "x-validated": true
7903
- },
8803
+ "x-source": "modules/sessions/routes/sessions.js",
7904
8804
  "responses": {
7905
8805
  "200": {
7906
8806
  "description": "Success.",
7907
8807
  "content": {
7908
8808
  "application/json": {
7909
8809
  "schema": {
7910
- "$ref": "#/components/schemas/PostSecurityDocsResponse"
8810
+ "$ref": "#/components/schemas/GetSessionsSearchResponse"
7911
8811
  }
7912
8812
  }
7913
8813
  }
7914
8814
  },
7915
8815
  "400": {
7916
- "$ref": "#/components/responses/ValidationFailed"
8816
+ "$ref": "#/components/responses/BadRequest"
7917
8817
  },
7918
8818
  "401": {
7919
8819
  "$ref": "#/components/responses/Unauthorized"
@@ -7929,25 +8829,25 @@
7929
8829
  ]
7930
8830
  }
7931
8831
  },
7932
- "/security/docs/{slug}": {
8832
+ "/sessions/{id}": {
7933
8833
  "get": {
7934
- "operationId": "get_security_docs_slug",
8834
+ "operationId": "get_sessions_id",
7935
8835
  "tags": [
7936
- "security"
8836
+ "sessions"
7937
8837
  ],
7938
- "summary": "GET /security/docs/:slug",
7939
- "description": "GET /api/gds/security/docs/:slug — one doc WITH content, or 404. rank: archon — reads the full exploit-detail report body.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
7940
- "x-rank": "archon",
7941
- "x-source": "src/bongos/routes/security.js",
8838
+ "summary": "GET /sessions/:id",
8839
+ "description": "own session full detail (deep-dive); cross-builder fetch requires Archon + a fail-closed audit row (BFG-principal posture until 6C.1).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8840
+ "x-rank": "any-builder",
8841
+ "x-source": "modules/sessions/routes/sessions.js",
7942
8842
  "parameters": [
7943
8843
  {
7944
- "name": "slug",
8844
+ "name": "id",
7945
8845
  "in": "path",
7946
8846
  "required": true,
7947
8847
  "schema": {
7948
8848
  "type": "string"
7949
8849
  },
7950
- "description": "Path parameter `slug`."
8850
+ "description": "Path parameter `id`."
7951
8851
  }
7952
8852
  ],
7953
8853
  "responses": {
@@ -7956,7 +8856,7 @@
7956
8856
  "content": {
7957
8857
  "application/json": {
7958
8858
  "schema": {
7959
- "$ref": "#/components/schemas/GetSecurityDocsSlugResponse"
8859
+ "$ref": "#/components/schemas/GetSessionsIdResponse"
7960
8860
  }
7961
8861
  }
7962
8862
  }
@@ -7970,33 +8870,93 @@
7970
8870
  "403": {
7971
8871
  "$ref": "#/components/responses/Forbidden"
7972
8872
  },
7973
- "404": {
7974
- "$ref": "#/components/responses/NotFound"
8873
+ "404": {
8874
+ "$ref": "#/components/responses/NotFound"
8875
+ }
8876
+ },
8877
+ "security": [
8878
+ {
8879
+ "builderSession": []
8880
+ }
8881
+ ]
8882
+ }
8883
+ },
8884
+ "/sso/activity/rollup": {
8885
+ "post": {
8886
+ "operationId": "post_sso_activity_rollup",
8887
+ "tags": [
8888
+ "sso"
8889
+ ],
8890
+ "summary": "POST /sso/activity/rollup",
8891
+ "description": "POST /sso/activity/rollup — a federated instance reports a builder's activity snapshot (ADR 0141 §4). Server-to-server, client_id+client_secret auth. Keyed to the AUTHENTICATED client_id. Descriptive analytics for the Archon-only scouting view — never authority. rank: public — authenticated by client_id + client_secret, not a builder rank.\n\n**Rank:** `public` — No authentication — any caller.",
8892
+ "x-rank": "public",
8893
+ "x-source": "modules/platform-identity/routes/sso.js",
8894
+ "requestBody": {
8895
+ "required": true,
8896
+ "content": {
8897
+ "application/json": {
8898
+ "schema": {
8899
+ "$ref": "#/components/schemas/PostSsoActivityRollupRequest"
8900
+ }
8901
+ }
8902
+ },
8903
+ "x-validated": true
8904
+ },
8905
+ "responses": {
8906
+ "200": {
8907
+ "description": "Success.",
8908
+ "content": {
8909
+ "application/json": {
8910
+ "schema": {
8911
+ "$ref": "#/components/schemas/PostSsoActivityRollupResponse"
8912
+ }
8913
+ }
8914
+ }
8915
+ },
8916
+ "400": {
8917
+ "$ref": "#/components/responses/ValidationFailed"
8918
+ }
8919
+ },
8920
+ "security": []
8921
+ }
8922
+ },
8923
+ "/sso/authorize": {
8924
+ "get": {
8925
+ "operationId": "get_sso_authorize",
8926
+ "tags": [
8927
+ "sso"
8928
+ ],
8929
+ "summary": "GET /sso/authorize",
8930
+ "description": "GET /sso/authorize?client_id=&redirect_uri=&state= — the browser authorize leg. rank: public — this is an authentication entry point, not an authorization surface. It is gated on a LIVE HUB SESSION (resolved inline via resolveSession; a missing session 302s to the hub's own web sign-in and returns here), NOT on a builder RANK. It mints identity-only codes.\n\n**Rank:** `public` — No authentication — any caller.",
8931
+ "x-rank": "public",
8932
+ "x-source": "modules/platform-identity/routes/sso.js",
8933
+ "responses": {
8934
+ "200": {
8935
+ "description": "Success."
8936
+ },
8937
+ "400": {
8938
+ "$ref": "#/components/responses/BadRequest"
7975
8939
  }
7976
8940
  },
7977
- "security": [
7978
- {
7979
- "builderSession": []
7980
- }
7981
- ]
8941
+ "security": []
7982
8942
  }
7983
8943
  },
7984
- "/session/optimize": {
8944
+ "/sso/device/poll": {
7985
8945
  "post": {
7986
- "operationId": "post_session_optimize",
8946
+ "operationId": "post_sso_device_poll",
7987
8947
  "tags": [
7988
- "session"
8948
+ "sso"
7989
8949
  ],
7990
- "summary": "POST /session/optimize",
7991
- "description": "pick own next work; the optimizer reads/recommends only.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
7992
- "x-rank": "any-builder",
7993
- "x-source": "src/bongos/routes/optimizer.js",
8950
+ "summary": "POST /sso/device/poll",
8951
+ "description": "POST /sso/device/poll — poll the hub device flow. On GitHub approval, upsert the platform account and mint an audience-scoped EdDSA assertion for the client that was BOUND at start (from the origin) — the poll takes NO client_id, so the CLI cannot influence the audience. Returns the SAME poll states as the core device flow, plus { state:'ok', assertion } on success. rank: public — the device_code (GitHub's) is the bearer; the assertion carries identity ONLY and is useless to anyone but the origin-bound client (aud-scoped).\n\n**Rank:** `public` — No authentication — any caller.",
8952
+ "x-rank": "public",
8953
+ "x-source": "modules/platform-identity/routes/sso.js",
7994
8954
  "requestBody": {
7995
- "required": false,
8955
+ "required": true,
7996
8956
  "content": {
7997
8957
  "application/json": {
7998
8958
  "schema": {
7999
- "$ref": "#/components/schemas/PostSessionOptimizeRequest"
8959
+ "$ref": "#/components/schemas/PostSsoDevicePollRequest"
8000
8960
  }
8001
8961
  }
8002
8962
  },
@@ -8008,37 +8968,27 @@
8008
8968
  },
8009
8969
  "400": {
8010
8970
  "$ref": "#/components/responses/ValidationFailed"
8011
- },
8012
- "401": {
8013
- "$ref": "#/components/responses/Unauthorized"
8014
- },
8015
- "403": {
8016
- "$ref": "#/components/responses/Forbidden"
8017
8971
  }
8018
8972
  },
8019
- "security": [
8020
- {
8021
- "builderSession": []
8022
- }
8023
- ]
8973
+ "security": []
8024
8974
  }
8025
8975
  },
8026
- "/sessions": {
8976
+ "/sso/device/start": {
8027
8977
  "post": {
8028
- "operationId": "post_sessions",
8978
+ "operationId": "post_sso_device_start",
8029
8979
  "tags": [
8030
- "sessions"
8980
+ "sso"
8031
8981
  ],
8032
- "summary": "POST /sessions",
8033
- "description": "upload your OWN session digest. Owner is forced to the authenticated caller; the body cannot attribute a record to another builder.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8034
- "x-rank": "any-builder",
8035
- "x-source": "modules/sessions/routes/sessions.js",
8982
+ "summary": "POST /sso/device/start",
8983
+ "description": "POST /sso/device/start — begin CLI federation. The client is resolved from the USER-TYPED instance ORIGIN via the registry (getClientByOrigin) and BOUND to the device flow — the CLI never names the audience. This closes the confused-deputy where a malicious instance manifest could steer the mint at a victim client_id (ADR 0141 §1 security fix). Runs the GitHub device flow against the HUB's app and returns the codes. Identity is established as a platform ACCOUNT at poll time — never a hub-builder session (ADR 0141: identity federated, authority local). rank: public — an authentication entry point; the origin is public, and the poll's GitHub approval is the real gate.\n\n**Rank:** `public` — No authentication — any caller.",
8984
+ "x-rank": "public",
8985
+ "x-source": "modules/platform-identity/routes/sso.js",
8036
8986
  "requestBody": {
8037
8987
  "required": true,
8038
8988
  "content": {
8039
8989
  "application/json": {
8040
8990
  "schema": {
8041
- "$ref": "#/components/schemas/PostSessionsRequest"
8991
+ "$ref": "#/components/schemas/PostSsoDeviceStartRequest"
8042
8992
  }
8043
8993
  }
8044
8994
  },
@@ -8046,158 +8996,119 @@
8046
8996
  },
8047
8997
  "responses": {
8048
8998
  "200": {
8049
- "description": "Success.",
8050
- "content": {
8051
- "application/json": {
8052
- "schema": {
8053
- "$ref": "#/components/schemas/PostSessionsResponse"
8054
- }
8055
- }
8056
- }
8999
+ "description": "Success."
8057
9000
  },
8058
9001
  "400": {
8059
9002
  "$ref": "#/components/responses/ValidationFailed"
8060
- },
8061
- "401": {
8062
- "$ref": "#/components/responses/Unauthorized"
8063
- },
8064
- "403": {
8065
- "$ref": "#/components/responses/Forbidden"
8066
9003
  }
8067
9004
  },
8068
- "security": [
8069
- {
8070
- "builderSession": []
8071
- }
8072
- ]
9005
+ "security": []
8073
9006
  }
8074
9007
  },
8075
- "/sessions/mine": {
8076
- "get": {
8077
- "operationId": "get_sessions_mine",
9008
+ "/sso/membership/check-in": {
9009
+ "post": {
9010
+ "operationId": "post_sso_membership_check_in",
8078
9011
  "tags": [
8079
- "sessions"
9012
+ "sso"
8080
9013
  ],
8081
- "summary": "GET /sessions/mine",
8082
- "description": "your OWN sessions (self-serve; no audit needed).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8083
- "x-rank": "any-builder",
8084
- "x-source": "modules/sessions/routes/sessions.js",
9014
+ "summary": "POST /sso/membership/check-in",
9015
+ "description": "POST /sso/membership/check-in — a federated instance reports, on every sign-in, that a builder builds on its project (ADR 0141 §3). Server-to-server, authed by client_id + client_secret (same constant-time check as /sso/token). Upserts the account (so a CLI-only builder still appears in My Projects) + the membership with a COARSE role. The client_id is taken from the AUTHENTICATED client — the caller cannot report membership for a project it doesn't hold the secret for. rank: public — authenticated by client_id + client_secret, not a builder rank.\n\n**Rank:** `public` — No authentication — any caller.",
9016
+ "x-rank": "public",
9017
+ "x-source": "modules/platform-identity/routes/sso.js",
9018
+ "requestBody": {
9019
+ "required": true,
9020
+ "content": {
9021
+ "application/json": {
9022
+ "schema": {
9023
+ "$ref": "#/components/schemas/PostSsoMembershipCheckInRequest"
9024
+ }
9025
+ }
9026
+ },
9027
+ "x-validated": true
9028
+ },
8085
9029
  "responses": {
8086
9030
  "200": {
8087
9031
  "description": "Success.",
8088
9032
  "content": {
8089
9033
  "application/json": {
8090
9034
  "schema": {
8091
- "$ref": "#/components/schemas/GetSessionsMineResponse"
9035
+ "$ref": "#/components/schemas/PostSsoMembershipCheckInResponse"
8092
9036
  }
8093
9037
  }
8094
9038
  }
8095
9039
  },
8096
9040
  "400": {
8097
- "$ref": "#/components/responses/BadRequest"
8098
- },
8099
- "401": {
8100
- "$ref": "#/components/responses/Unauthorized"
8101
- },
8102
- "403": {
8103
- "$ref": "#/components/responses/Forbidden"
9041
+ "$ref": "#/components/responses/ValidationFailed"
8104
9042
  }
8105
9043
  },
8106
- "security": [
8107
- {
8108
- "builderSession": []
8109
- }
8110
- ]
9044
+ "security": []
8111
9045
  }
8112
9046
  },
8113
- "/sessions/search": {
9047
+ "/sso/pubkey": {
8114
9048
  "get": {
8115
- "operationId": "get_sessions_search",
9049
+ "operationId": "get_sso_pubkey",
8116
9050
  "tags": [
8117
- "sessions"
9051
+ "sso"
8118
9052
  ],
8119
- "summary": "GET /sessions/search",
8120
- "description": "cross-builder corpus search (BFG-principal posture until 6C.1).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8121
- "x-rank": "archon",
8122
- "x-source": "modules/sessions/routes/sessions.js",
9053
+ "summary": "GET /sso/pubkey",
9054
+ "description": "GET /sso/pubkey — the hub's Ed25519 assertion-verification key (public). An instance provisioned WITHOUT the key in env can fetch it here; the value is public by design (it only VERIFIES assertions, never signs). rank: public — a public key is not a secret; no auth needed.\n\n**Rank:** `public` — No authentication — any caller.",
9055
+ "x-rank": "public",
9056
+ "x-source": "modules/platform-identity/routes/sso.js",
8123
9057
  "responses": {
8124
9058
  "200": {
8125
9059
  "description": "Success.",
8126
9060
  "content": {
8127
9061
  "application/json": {
8128
9062
  "schema": {
8129
- "$ref": "#/components/schemas/GetSessionsSearchResponse"
9063
+ "$ref": "#/components/schemas/GetSsoPubkeyResponse"
8130
9064
  }
8131
9065
  }
8132
9066
  }
8133
9067
  },
8134
9068
  "400": {
8135
9069
  "$ref": "#/components/responses/BadRequest"
8136
- },
8137
- "401": {
8138
- "$ref": "#/components/responses/Unauthorized"
8139
- },
8140
- "403": {
8141
- "$ref": "#/components/responses/Forbidden"
8142
9070
  }
8143
9071
  },
8144
- "security": [
8145
- {
8146
- "builderSession": []
8147
- }
8148
- ]
9072
+ "security": []
8149
9073
  }
8150
9074
  },
8151
- "/sessions/{id}": {
8152
- "get": {
8153
- "operationId": "get_sessions_id",
9075
+ "/sso/token": {
9076
+ "post": {
9077
+ "operationId": "post_sso_token",
8154
9078
  "tags": [
8155
- "sessions"
8156
- ],
8157
- "summary": "GET /sessions/:id",
8158
- "description": "own session full detail (deep-dive); cross-builder fetch requires Archon + a fail-closed audit row (BFG-principal posture until 6C.1).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8159
- "x-rank": "any-builder",
8160
- "x-source": "modules/sessions/routes/sessions.js",
8161
- "parameters": [
8162
- {
8163
- "name": "id",
8164
- "in": "path",
8165
- "required": true,
8166
- "schema": {
8167
- "type": "string"
8168
- },
8169
- "description": "Path parameter `id`."
8170
- }
9079
+ "sso"
8171
9080
  ],
9081
+ "summary": "POST /sso/token",
9082
+ "description": "POST /sso/token — server-to-server code redemption. rank: public — authenticated by client_id + client_secret (constant-time hash compare in clientSecretValid), NOT a builder session/rank. This is the confidential-client leg; the instance calls it from its server, never the browser. Returns IDENTITY ONLY (github_id, login, display_name, avatar_url).\n\n**Rank:** `public` — No authentication — any caller.",
9083
+ "x-rank": "public",
9084
+ "x-source": "modules/platform-identity/routes/sso.js",
9085
+ "requestBody": {
9086
+ "required": true,
9087
+ "content": {
9088
+ "application/json": {
9089
+ "schema": {
9090
+ "$ref": "#/components/schemas/PostSsoTokenRequest"
9091
+ }
9092
+ }
9093
+ },
9094
+ "x-validated": true
9095
+ },
8172
9096
  "responses": {
8173
9097
  "200": {
8174
9098
  "description": "Success.",
8175
9099
  "content": {
8176
9100
  "application/json": {
8177
9101
  "schema": {
8178
- "$ref": "#/components/schemas/GetSessionsIdResponse"
9102
+ "$ref": "#/components/schemas/PostSsoTokenResponse"
8179
9103
  }
8180
9104
  }
8181
9105
  }
8182
9106
  },
8183
9107
  "400": {
8184
- "$ref": "#/components/responses/BadRequest"
8185
- },
8186
- "401": {
8187
- "$ref": "#/components/responses/Unauthorized"
8188
- },
8189
- "403": {
8190
- "$ref": "#/components/responses/Forbidden"
8191
- },
8192
- "404": {
8193
- "$ref": "#/components/responses/NotFound"
9108
+ "$ref": "#/components/responses/ValidationFailed"
8194
9109
  }
8195
9110
  },
8196
- "security": [
8197
- {
8198
- "builderSession": []
8199
- }
8200
- ]
9111
+ "security": []
8201
9112
  }
8202
9113
  },
8203
9114
  "/tasks": {
@@ -10229,6 +11140,15 @@
10229
11140
  "count"
10230
11141
  ]
10231
11142
  },
11143
+ "GetGithubReposResponse": {
11144
+ "type": "object",
11145
+ "properties": {
11146
+ "repos": {}
11147
+ },
11148
+ "required": [
11149
+ "repos"
11150
+ ]
11151
+ },
10232
11152
  "GetGoalsIdConflictsResponse": {
10233
11153
  "type": "object",
10234
11154
  "properties": {
@@ -10540,6 +11460,26 @@
10540
11460
  "submissions"
10541
11461
  ]
10542
11462
  },
11463
+ "GetMyProjectsInvitesResponse": {
11464
+ "type": "object",
11465
+ "properties": {
11466
+ "invites": {}
11467
+ },
11468
+ "required": [
11469
+ "invites"
11470
+ ]
11471
+ },
11472
+ "GetMyProjectsResponse": {
11473
+ "type": "object",
11474
+ "properties": {
11475
+ "owned": {},
11476
+ "building": {}
11477
+ },
11478
+ "required": [
11479
+ "owned",
11480
+ "building"
11481
+ ]
11482
+ },
10543
11483
  "GetOverrideRequestsResponse": {
10544
11484
  "type": "object",
10545
11485
  "properties": {
@@ -10549,6 +11489,24 @@
10549
11489
  "requests"
10550
11490
  ]
10551
11491
  },
11492
+ "GetProjectsFeaturedResponse": {
11493
+ "type": "object",
11494
+ "properties": {
11495
+ "projects": {}
11496
+ },
11497
+ "required": [
11498
+ "projects"
11499
+ ]
11500
+ },
11501
+ "GetProjectsResponse": {
11502
+ "type": "object",
11503
+ "properties": {
11504
+ "projects": {}
11505
+ },
11506
+ "required": [
11507
+ "projects"
11508
+ ]
11509
+ },
10552
11510
  "GetProvisioningFleetResponse": {
10553
11511
  "type": "object",
10554
11512
  "properties": {
@@ -10776,6 +11734,15 @@
10776
11734
  "page"
10777
11735
  ]
10778
11736
  },
11737
+ "GetScoutingResponse": {
11738
+ "type": "object",
11739
+ "properties": {
11740
+ "builders": {}
11741
+ },
11742
+ "required": [
11743
+ "builders"
11744
+ ]
11745
+ },
10779
11746
  "GetSecurityDocsResponse": {
10780
11747
  "type": "object",
10781
11748
  "properties": {
@@ -10833,6 +11800,19 @@
10833
11800
  "offset"
10834
11801
  ]
10835
11802
  },
11803
+ "GetSsoPubkeyResponse": {
11804
+ "type": "object",
11805
+ "properties": {
11806
+ "alg": {},
11807
+ "format": {},
11808
+ "public_key_b64": {}
11809
+ },
11810
+ "required": [
11811
+ "alg",
11812
+ "format",
11813
+ "public_key_b64"
11814
+ ]
11815
+ },
10836
11816
  "GetTasksClaimableResponse": {
10837
11817
  "type": "object",
10838
11818
  "properties": {
@@ -11258,6 +12238,27 @@
11258
12238
  "known_sounds"
11259
12239
  ]
11260
12240
  },
12241
+ "PatchProjectsIdFeaturedRequest": {
12242
+ "type": "object",
12243
+ "properties": {
12244
+ "featured": {
12245
+ "type": "boolean"
12246
+ }
12247
+ },
12248
+ "required": [
12249
+ "featured"
12250
+ ],
12251
+ "additionalProperties": false
12252
+ },
12253
+ "PatchProjectsIdFeaturedResponse": {
12254
+ "type": "object",
12255
+ "properties": {
12256
+ "project": {}
12257
+ },
12258
+ "required": [
12259
+ "project"
12260
+ ]
12261
+ },
11261
12262
  "PatchTasksIdRequest": {
11262
12263
  "type": "object",
11263
12264
  "properties": {
@@ -11408,23 +12409,47 @@
11408
12409
  "interval"
11409
12410
  ]
11410
12411
  },
11411
- "PostAuthCliTokenIssueResponse": {
12412
+ "PostAuthCliTokenIssueResponse": {
12413
+ "type": "object",
12414
+ "properties": {
12415
+ "ok": {
12416
+ "type": "boolean"
12417
+ },
12418
+ "token": {},
12419
+ "expires_at": {},
12420
+ "builder_login": {},
12421
+ "paste_command": {}
12422
+ },
12423
+ "required": [
12424
+ "ok",
12425
+ "token",
12426
+ "expires_at",
12427
+ "builder_login",
12428
+ "paste_command"
12429
+ ]
12430
+ },
12431
+ "PostAuthDeviceExchangeRequest": {
12432
+ "type": "object",
12433
+ "properties": {
12434
+ "assertion": {
12435
+ "type": "string",
12436
+ "maxLength": 4096
12437
+ }
12438
+ },
12439
+ "required": [
12440
+ "assertion"
12441
+ ],
12442
+ "additionalProperties": false
12443
+ },
12444
+ "PostAuthDeviceExchangeResponse": {
11412
12445
  "type": "object",
11413
12446
  "properties": {
11414
- "ok": {
11415
- "type": "boolean"
11416
- },
11417
12447
  "token": {},
11418
- "expires_at": {},
11419
- "builder_login": {},
11420
- "paste_command": {}
12448
+ "builder": {}
11421
12449
  },
11422
12450
  "required": [
11423
- "ok",
11424
12451
  "token",
11425
- "expires_at",
11426
- "builder_login",
11427
- "paste_command"
12452
+ "builder"
11428
12453
  ]
11429
12454
  },
11430
12455
  "PostAuthDevicePollRequest": {
@@ -12114,6 +13139,28 @@
12114
13139
  "message"
12115
13140
  ]
12116
13141
  },
13142
+ "PostGithubReposRequest": {
13143
+ "type": "object",
13144
+ "properties": {
13145
+ "name": {
13146
+ "type": "string",
13147
+ "maxLength": 100
13148
+ }
13149
+ },
13150
+ "required": [
13151
+ "name"
13152
+ ],
13153
+ "additionalProperties": false
13154
+ },
13155
+ "PostGithubReposResponse": {
13156
+ "type": "object",
13157
+ "properties": {
13158
+ "repo": {}
13159
+ },
13160
+ "required": [
13161
+ "repo"
13162
+ ]
13163
+ },
12117
13164
  "PostGoalsIdArchiveResponse": {
12118
13165
  "type": "object",
12119
13166
  "properties": {
@@ -12844,6 +13891,79 @@
12844
13891
  "submission"
12845
13892
  ]
12846
13893
  },
13894
+ "PostMyProjectsClientIdLeaveResponse": {
13895
+ "type": "object",
13896
+ "properties": {
13897
+ "ok": {
13898
+ "type": "boolean"
13899
+ },
13900
+ "left": {}
13901
+ },
13902
+ "required": [
13903
+ "ok",
13904
+ "left"
13905
+ ]
13906
+ },
13907
+ "PostMyProjectsInvitesClientIdAcceptResponse": {
13908
+ "type": "object",
13909
+ "properties": {
13910
+ "ok": {
13911
+ "type": "boolean"
13912
+ },
13913
+ "accepted": {
13914
+ "type": "boolean"
13915
+ }
13916
+ },
13917
+ "required": [
13918
+ "ok",
13919
+ "accepted"
13920
+ ]
13921
+ },
13922
+ "PostMyProjectsInvitesClientIdDeclineResponse": {
13923
+ "type": "object",
13924
+ "properties": {
13925
+ "ok": {
13926
+ "type": "boolean"
13927
+ },
13928
+ "accepted": {
13929
+ "type": "boolean"
13930
+ }
13931
+ },
13932
+ "required": [
13933
+ "ok",
13934
+ "accepted"
13935
+ ]
13936
+ },
13937
+ "PostMyProjectsJoinRequest": {
13938
+ "type": "object",
13939
+ "properties": {
13940
+ "origin": {
13941
+ "type": "string",
13942
+ "maxLength": 512
13943
+ }
13944
+ },
13945
+ "required": [
13946
+ "origin"
13947
+ ],
13948
+ "additionalProperties": false
13949
+ },
13950
+ "PostMyProjectsJoinResponse": {
13951
+ "type": "object",
13952
+ "properties": {
13953
+ "ok": {
13954
+ "type": "boolean"
13955
+ },
13956
+ "status": {},
13957
+ "project": {},
13958
+ "message": {}
13959
+ },
13960
+ "required": [
13961
+ "ok",
13962
+ "status",
13963
+ "project",
13964
+ "message"
13965
+ ]
13966
+ },
12847
13967
  "PostOverrideRequestsIdDecideRequest": {
12848
13968
  "type": "object",
12849
13969
  "properties": {
@@ -12860,6 +13980,59 @@
12860
13980
  ],
12861
13981
  "additionalProperties": false
12862
13982
  },
13983
+ "PostProjectsInviteRequest": {
13984
+ "type": "object",
13985
+ "properties": {
13986
+ "client_id": {
13987
+ "type": "string",
13988
+ "maxLength": 200
13989
+ },
13990
+ "github_login": {
13991
+ "type": "string",
13992
+ "maxLength": 200
13993
+ }
13994
+ },
13995
+ "required": [
13996
+ "client_id",
13997
+ "github_login"
13998
+ ],
13999
+ "additionalProperties": false
14000
+ },
14001
+ "PostProjectsRequest": {
14002
+ "type": "object",
14003
+ "properties": {
14004
+ "origin": {
14005
+ "type": "string",
14006
+ "maxLength": 512
14007
+ },
14008
+ "name": {
14009
+ "type": "string",
14010
+ "maxLength": 200
14011
+ },
14012
+ "tagline": {
14013
+ "type": "string",
14014
+ "maxLength": 400
14015
+ },
14016
+ "art_url": {
14017
+ "type": "string",
14018
+ "maxLength": 2048
14019
+ }
14020
+ },
14021
+ "required": [
14022
+ "origin",
14023
+ "name"
14024
+ ],
14025
+ "additionalProperties": false
14026
+ },
14027
+ "PostProjectsResponse": {
14028
+ "type": "object",
14029
+ "properties": {
14030
+ "project": {}
14031
+ },
14032
+ "required": [
14033
+ "project"
14034
+ ]
14035
+ },
12863
14036
  "PostProvisioningInstancesIdForceTeardownResponse": {
12864
14037
  "type": "object",
12865
14038
  "properties": {
@@ -13105,6 +14278,172 @@
13105
14278
  "token_reward": {}
13106
14279
  }
13107
14280
  },
14281
+ "PostSsoActivityRollupRequest": {
14282
+ "type": "object",
14283
+ "properties": {
14284
+ "client_id": {
14285
+ "type": "string",
14286
+ "maxLength": 200
14287
+ },
14288
+ "client_secret": {
14289
+ "type": "string",
14290
+ "maxLength": 512
14291
+ },
14292
+ "github_id": {
14293
+ "$ref": "#/components/schemas/StringifiableId"
14294
+ },
14295
+ "credits": {
14296
+ "type": "number"
14297
+ },
14298
+ "tasks_shipped": {
14299
+ "type": "number"
14300
+ },
14301
+ "karma": {
14302
+ "type": "number"
14303
+ },
14304
+ "rank": {
14305
+ "type": "string",
14306
+ "maxLength": 32
14307
+ },
14308
+ "disciplines": {}
14309
+ },
14310
+ "required": [
14311
+ "client_id",
14312
+ "client_secret",
14313
+ "github_id"
14314
+ ],
14315
+ "additionalProperties": false
14316
+ },
14317
+ "PostSsoActivityRollupResponse": {
14318
+ "type": "object",
14319
+ "properties": {
14320
+ "ok": {
14321
+ "type": "boolean"
14322
+ }
14323
+ },
14324
+ "required": [
14325
+ "ok"
14326
+ ]
14327
+ },
14328
+ "PostSsoDevicePollRequest": {
14329
+ "type": "object",
14330
+ "properties": {
14331
+ "device_code": {
14332
+ "type": "string",
14333
+ "maxLength": 512
14334
+ }
14335
+ },
14336
+ "required": [
14337
+ "device_code"
14338
+ ],
14339
+ "additionalProperties": false
14340
+ },
14341
+ "PostSsoDeviceStartRequest": {
14342
+ "type": "object",
14343
+ "properties": {
14344
+ "origin": {
14345
+ "type": "string",
14346
+ "maxLength": 512
14347
+ }
14348
+ },
14349
+ "required": [
14350
+ "origin"
14351
+ ],
14352
+ "additionalProperties": false
14353
+ },
14354
+ "PostSsoMembershipCheckInRequest": {
14355
+ "type": "object",
14356
+ "properties": {
14357
+ "client_id": {
14358
+ "type": "string",
14359
+ "maxLength": 200
14360
+ },
14361
+ "client_secret": {
14362
+ "type": "string",
14363
+ "maxLength": 512
14364
+ },
14365
+ "github_id": {
14366
+ "$ref": "#/components/schemas/StringifiableId"
14367
+ },
14368
+ "github_login": {
14369
+ "type": "string",
14370
+ "maxLength": 200
14371
+ },
14372
+ "display_name": {
14373
+ "type": "string",
14374
+ "maxLength": 400
14375
+ },
14376
+ "avatar_url": {
14377
+ "type": "string",
14378
+ "maxLength": 2048
14379
+ },
14380
+ "role": {
14381
+ "type": "string",
14382
+ "maxLength": 16
14383
+ }
14384
+ },
14385
+ "required": [
14386
+ "client_id",
14387
+ "client_secret",
14388
+ "github_id",
14389
+ "github_login"
14390
+ ],
14391
+ "additionalProperties": false
14392
+ },
14393
+ "PostSsoMembershipCheckInResponse": {
14394
+ "type": "object",
14395
+ "properties": {
14396
+ "ok": {
14397
+ "type": "boolean"
14398
+ }
14399
+ },
14400
+ "required": [
14401
+ "ok"
14402
+ ]
14403
+ },
14404
+ "PostSsoTokenRequest": {
14405
+ "type": "object",
14406
+ "properties": {
14407
+ "client_id": {
14408
+ "type": "string",
14409
+ "maxLength": 200
14410
+ },
14411
+ "client_secret": {
14412
+ "type": "string",
14413
+ "maxLength": 512
14414
+ },
14415
+ "code": {
14416
+ "type": "string",
14417
+ "maxLength": 512
14418
+ },
14419
+ "redirect_uri": {
14420
+ "type": "string",
14421
+ "maxLength": 2048
14422
+ }
14423
+ },
14424
+ "required": [
14425
+ "client_id",
14426
+ "client_secret",
14427
+ "code",
14428
+ "redirect_uri"
14429
+ ],
14430
+ "additionalProperties": false
14431
+ },
14432
+ "PostSsoTokenResponse": {
14433
+ "type": "object",
14434
+ "properties": {
14435
+ "github_id": {},
14436
+ "github_login": {},
14437
+ "display_name": {},
14438
+ "avatar_url": {}
14439
+ },
14440
+ "required": [
14441
+ "github_id",
14442
+ "github_login",
14443
+ "display_name",
14444
+ "avatar_url"
14445
+ ]
14446
+ },
13108
14447
  "PostTasksIdAbandonRequest": {
13109
14448
  "type": "object",
13110
14449
  "properties": {
@@ -13719,9 +15058,9 @@
13719
15058
  "description": "A required dependency/feature is not configured or is temporarily down."
13720
15059
  }
13721
15060
  },
13722
- "x-endpoint-count": 223,
13723
- "x-schema-count": 244,
15061
+ "x-endpoint-count": 245,
15062
+ "x-schema-count": 273,
13724
15063
  "x-undocumented-bodies": 8,
13725
- "x-response-schemas": 166,
15064
+ "x-response-schemas": 184,
13726
15065
  "x-generated-by": "scripts/gds/gen-api-docs.js"
13727
15066
  }