@bongos/core 1.17.3 → 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 (163) hide show
  1. package/.bongos-core.json +212 -332
  2. package/.devcontainer/healthcheck.sh +0 -0
  3. package/.devcontainer/init-firewall.sh +0 -0
  4. package/.devcontainer/post-create.sh +0 -0
  5. package/GOVERNANCE.md +1 -1
  6. package/README.md +26 -22
  7. package/bin/bongos.js +0 -0
  8. package/config/branding.neutral.json +5 -1
  9. package/docker-entrypoint.sh +0 -0
  10. package/docs/adr/0142-project-context-is-prose-only.md +41 -0
  11. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  12. package/docs/adr/README.md +6 -0
  13. package/docs/api/openapi.json +1630 -632
  14. package/docs/api-reference.md +50 -15
  15. package/docs/file-map.md +0 -18
  16. package/docs/onboarding/diagrams/05-versioning.mmd +4 -6
  17. package/docs/onboarding/diagrams/assertions.json +5 -9
  18. package/docs/recipes/packaging-the-core.md +13 -0
  19. package/docs/recipes/upgrading-the-core.md +5 -2
  20. package/migrations/039_newcomer_friendly_column.sql +5 -0
  21. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  22. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  23. package/modules/hall-ui/public/builders.js +37 -0
  24. package/modules/hall-ui/public/goals-page.js +98 -176
  25. package/modules/hall-ui/public/goals.css +183 -0
  26. package/modules/hall-ui/public/goals.html +35 -261
  27. package/modules/hall-ui/public/goals.js +7 -2
  28. package/modules/hall-ui/public/hall-widgets.js +12 -4
  29. package/modules/hall-ui/public/my-projects.html +78 -0
  30. package/modules/hall-ui/public/my-projects.js +142 -0
  31. package/modules/hall-ui/public/scouting.html +45 -0
  32. package/modules/hall-ui/public/scouting.js +73 -0
  33. package/modules/hall-ui/public/settings.css +355 -0
  34. package/modules/hall-ui/public/settings.html +86 -414
  35. package/modules/hall-ui/public/settings.js +96 -35
  36. package/modules/hall-ui/public/style.css +31 -0
  37. package/modules/hall-ui/public/watch.css +184 -0
  38. package/modules/hall-ui/public/watch.html +111 -285
  39. package/modules/hall-ui/public/watch.js +59 -21
  40. package/modules/status-ui/public/explore.html +54 -0
  41. package/modules/status-ui/public/explore.js +67 -0
  42. package/package-lock.json +2 -2
  43. package/package.json +1 -1
  44. package/public-landing/create.html +292 -19
  45. package/public-landing/index.html +11 -76
  46. package/scripts/cron/style_guide_audit.sh +0 -0
  47. package/scripts/gds/api.js +0 -0
  48. package/scripts/gds/architect-audit.js +0 -0
  49. package/scripts/gds/audit-authorship.sh +0 -0
  50. package/scripts/gds/audit-replay.sh +0 -0
  51. package/scripts/gds/box.js +0 -0
  52. package/scripts/gds/capture.js +0 -0
  53. package/scripts/gds/cli-lib.js +11 -5
  54. package/scripts/gds/conductor-dispatch.js +0 -0
  55. package/scripts/gds/coreB-carve-proof.sh +0 -0
  56. package/scripts/gds/db-backup-nightly.sh +0 -0
  57. package/scripts/gds/db-backup-offsite.sh +0 -0
  58. package/scripts/gds/doctor.js +0 -0
  59. package/scripts/gds/grade-smoke.js +0 -0
  60. package/scripts/gds/hooks/pre-push.js +0 -0
  61. package/scripts/gds/install-git-hooks.js +0 -0
  62. package/scripts/gds/lint-migrations.js +102 -0
  63. package/scripts/gds/login.js +42 -10
  64. package/scripts/gds/main-audit.js +0 -0
  65. package/scripts/gds/mirror-redact.js +5 -0
  66. package/scripts/gds/oauth-secret.js +0 -0
  67. package/scripts/gds/onboarding-analyze.js +0 -0
  68. package/scripts/gds/onboarding-ship.js +0 -0
  69. package/scripts/gds/package-core.js +263 -4
  70. package/scripts/gds/paste-token.js +0 -0
  71. package/scripts/gds/portability-smoke-art.sh +0 -0
  72. package/scripts/gds/portability-smoke-memory.sh +0 -0
  73. package/scripts/gds/provision.js +270 -11
  74. package/scripts/gds/publish-manifest.js +15 -0
  75. package/scripts/gds/push-main.js +0 -0
  76. package/scripts/gds/render-ideas.js +0 -0
  77. package/scripts/gds/run-unit-tests.js +38 -14
  78. package/scripts/gds/security-baseline-check.sh +0 -0
  79. package/scripts/gds/session.js +0 -0
  80. package/scripts/gds/setup.js +41 -0
  81. package/scripts/gds/ship.js +126 -32
  82. package/scripts/gds/smoke-batch-claim.sh +0 -0
  83. package/scripts/gds/smoke-batch-release.sh +0 -0
  84. package/scripts/gds/smoke-box.sh +0 -0
  85. package/scripts/gds/smoke-claim-consistency.sh +0 -0
  86. package/scripts/gds/smoke-dependencies.sh +0 -0
  87. package/scripts/gds/smoke-write.sh +0 -0
  88. package/scripts/gds/upgrade.js +147 -5
  89. package/scripts/hall-preview/server.js +18 -1
  90. package/scripts/migrate.sh +10 -0
  91. package/scripts/migrate_cost_ledger.sh +0 -0
  92. package/scripts/render-diagrams.sh +0 -0
  93. package/scripts/security/dep-audit.js +0 -0
  94. package/scripts/setup-builder.js +0 -0
  95. package/scripts/setup-builder.sh +0 -0
  96. package/scripts/snapshots/maybe-render-on-deploy.sh +0 -0
  97. package/src/bongos/auth.js +362 -5
  98. package/src/bongos/db.js +66 -0
  99. package/src/bongos/github-repos.js +93 -0
  100. package/src/bongos/routes/auth.js +93 -11
  101. package/src/bongos/routes/github.js +90 -0
  102. package/src/bongos/routes/instance.js +15 -3
  103. package/src/bongos/routes.js +2 -0
  104. package/src/branding.js +17 -2
  105. package/src/instance-config.js +16 -0
  106. package/src/module-api.js +48 -1
  107. package/tests/branding.mjs +29 -23
  108. package/tests/github_repos_helpers.mjs +91 -0
  109. package/tests/github_token_store.mjs +121 -0
  110. package/tests/idp_device_exchange.mjs +105 -0
  111. package/tests/idp_federation.mjs +100 -0
  112. package/tests/migrations_forward_safe.mjs +86 -0
  113. package/tests/module_api.mjs +1 -1
  114. package/tests/package_core.mjs +246 -1
  115. package/tests/provision.mjs +226 -0
  116. package/tests/pruned_lockfile_integrity.mjs +79 -0
  117. package/tests/ship_ci_deploy.mjs +60 -0
  118. package/tests/upgrade.mjs +254 -5
  119. package/.gitignore +0 -91
  120. package/scripts/hall-preview/fixtures/access-requests.json +0 -1
  121. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  122. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  123. package/scripts/hall-preview/fixtures/audit-log.json +0 -1
  124. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -1
  125. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  126. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  127. package/scripts/hall-preview/fixtures/builders__roster.json +0 -1
  128. package/scripts/hall-preview/fixtures/goals.json +0 -502
  129. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  130. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  131. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  132. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  133. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  134. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  135. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  136. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  137. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -1
  138. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  139. package/scripts/hall-preview/fixtures/instance.json +0 -124
  140. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  141. package/scripts/hall-preview/fixtures/me.json +0 -476
  142. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  143. package/scripts/hall-preview/fixtures/override-requests.json +0 -1
  144. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  145. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  146. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  147. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  148. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  149. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  150. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  151. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  152. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  153. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  154. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  155. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  156. package/scripts/hall-preview/fixtures/security__docs.json +0 -1
  157. package/scripts/hall-preview/fixtures/security__reports.json +0 -1
  158. package/scripts/hall-preview/fixtures/sessions__search.json +0 -1
  159. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  160. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  161. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  162. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  163. package/scripts/hall-preview/fixtures/versions.json +0 -89
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
- "title": "Off the Boats — GDS API",
4
+ "title": "Cloud Bongos — GDS API",
5
5
  "version": "0.0.2",
6
6
  "license": {
7
7
  "name": "AGPL-3.0-or-later",
@@ -77,10 +77,6 @@
77
77
  "name": "cost",
78
78
  "description": "Endpoints under `/api/bongos/cost`."
79
79
  },
80
- {
81
- "name": "demo",
82
- "description": "Endpoints under `/api/bongos/demo`."
83
- },
84
80
  {
85
81
  "name": "dependencies",
86
82
  "description": "Endpoints under `/api/bongos/dependencies`."
@@ -97,6 +93,10 @@
97
93
  "name": "gate-approvals",
98
94
  "description": "Endpoints under `/api/bongos/gate-approvals`."
99
95
  },
96
+ {
97
+ "name": "github",
98
+ "description": "Endpoints under `/api/bongos/github`."
99
+ },
100
100
  {
101
101
  "name": "goals",
102
102
  "description": "Endpoints under `/api/bongos/goals`."
@@ -145,10 +145,18 @@
145
145
  "name": "modules",
146
146
  "description": "Endpoints under `/api/bongos/modules`."
147
147
  },
148
+ {
149
+ "name": "my-projects",
150
+ "description": "Endpoints under `/api/bongos/my-projects`."
151
+ },
148
152
  {
149
153
  "name": "override-requests",
150
154
  "description": "Endpoints under `/api/bongos/override-requests`."
151
155
  },
156
+ {
157
+ "name": "projects",
158
+ "description": "Endpoints under `/api/bongos/projects`."
159
+ },
152
160
  {
153
161
  "name": "provisioning",
154
162
  "description": "Endpoints under `/api/bongos/provisioning`."
@@ -157,6 +165,10 @@
157
165
  "name": "public",
158
166
  "description": "Endpoints under `/api/bongos/public`."
159
167
  },
168
+ {
169
+ "name": "scouting",
170
+ "description": "Endpoints under `/api/bongos/scouting`."
171
+ },
160
172
  {
161
173
  "name": "search",
162
174
  "description": "Endpoints under `/api/bongos/search`."
@@ -173,6 +185,10 @@
173
185
  "name": "sessions",
174
186
  "description": "Endpoints under `/api/bongos/sessions`."
175
187
  },
188
+ {
189
+ "name": "sso",
190
+ "description": "Endpoints under `/api/bongos/sso`."
191
+ },
176
192
  {
177
193
  "name": "tasks",
178
194
  "description": "Endpoints under `/api/bongos/tasks`."
@@ -666,6 +682,45 @@
666
682
  ]
667
683
  }
668
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
+ },
669
724
  "/auth/device/poll": {
670
725
  "post": {
671
726
  "operationId": "post_auth_device_poll",
@@ -3007,83 +3062,6 @@
3007
3062
  ]
3008
3063
  }
3009
3064
  },
3010
- "/demo/health": {
3011
- "get": {
3012
- "operationId": "get_demo_health",
3013
- "tags": [
3014
- "demo"
3015
- ],
3016
- "summary": "GET /demo/health",
3017
- "description": "READ — liveness + the core version this module was mounted against. No rank gate beyond the requireBuilder the loader composes around every module route. rank: public\n\n**Rank:** `public` — No authentication — any caller.",
3018
- "x-rank": "public",
3019
- "x-source": "modules/demo/routes/demo.js",
3020
- "responses": {
3021
- "200": {
3022
- "description": "Success.",
3023
- "content": {
3024
- "application/json": {
3025
- "schema": {
3026
- "$ref": "#/components/schemas/GetDemoHealthResponse"
3027
- }
3028
- }
3029
- }
3030
- },
3031
- "400": {
3032
- "$ref": "#/components/responses/BadRequest"
3033
- }
3034
- },
3035
- "security": []
3036
- }
3037
- },
3038
- "/demo/ping": {
3039
- "post": {
3040
- "operationId": "post_demo_ping",
3041
- "tags": [
3042
- "demo"
3043
- ],
3044
- "summary": "POST /demo/ping",
3045
- "description": "WRITE — EVERY module write route MUST be rank-gated (the BV1.R44 fitness check reds the build on an ungated module write route). `requireRank('metic', 'archon')` is Metic-and-above (the route-rank classifier records it as metic+archon). This records a ping into the module's own namespaced table (demo_pings) via the doorway pool.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).",
3046
- "x-rank": "metic+archon",
3047
- "x-source": "modules/demo/routes/demo.js",
3048
- "requestBody": {
3049
- "required": false,
3050
- "content": {
3051
- "application/json": {
3052
- "schema": {
3053
- "$ref": "#/components/schemas/PostDemoPingRequest"
3054
- }
3055
- }
3056
- },
3057
- "x-validated": true
3058
- },
3059
- "responses": {
3060
- "200": {
3061
- "description": "Success.",
3062
- "content": {
3063
- "application/json": {
3064
- "schema": {
3065
- "$ref": "#/components/schemas/PostDemoPingResponse"
3066
- }
3067
- }
3068
- }
3069
- },
3070
- "400": {
3071
- "$ref": "#/components/responses/ValidationFailed"
3072
- },
3073
- "401": {
3074
- "$ref": "#/components/responses/Unauthorized"
3075
- },
3076
- "403": {
3077
- "$ref": "#/components/responses/Forbidden"
3078
- }
3079
- },
3080
- "security": [
3081
- {
3082
- "builderSession": []
3083
- }
3084
- ]
3085
- }
3086
- },
3087
3065
  "/dependencies": {
3088
3066
  "post": {
3089
3067
  "operationId": "post_dependencies",
@@ -3470,6 +3448,91 @@
3470
3448
  ]
3471
3449
  }
3472
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
+ },
3473
3536
  "/goals": {
3474
3537
  "get": {
3475
3538
  "operationId": "get_goals",
@@ -5475,22 +5538,40 @@
5475
5538
  ]
5476
5539
  }
5477
5540
  },
5478
- "/me/art-key": {
5479
- "get": {
5480
- "operationId": "get_me_art_key",
5541
+ "/me/disciplines": {
5542
+ "patch": {
5543
+ "operationId": "patch_me_disciplines",
5481
5544
  "tags": [
5482
5545
  "me"
5483
5546
  ],
5484
- "summary": "GET /me/art-key",
5485
- "description": "Shared art key for newcomers (task 1281 / ADR 0068). Hands a SHARED Google AI Studio (Gemini) key to rank=xenos builders so their first art task works without their own key — we pay up front. The session-start sync (scripts/gds/fetch-art-key.js) calls this and writes/removes the local shared_gemini_api_key slot from the response. Thetes+ get a 200 with entitled:false (NOT a 403) — the sync needs an unambiguous \"remove the shared key\" signal it can tell apart from an auth failure, and the rank is the gate, not the route. The secret is attached ONLY when entitled && configured; the response is no-store and the key is never logged. Rank is read live from the DB (no caching, per ADR 0016). rank: any-builder — any authenticated builder may ask; `entitled` in the body is the server-enforced gate. A non-newcomer never receives the secret.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5547
+ "summary": "PATCH /me/disciplines",
5548
+ "description": "Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). Body: { preferred_disciplines: [\"artist\", ...] }. Valid elements are engineer|artist|ideator; [] clears the preference (a multi-element set just means several lanes). No rank gate — a builder owns their own profile. 422 invalid_discipline if any element is out of range. rank: any-builder — self-service profile edit; documented \"no rank gate\" in the handler comment above (a builder owns their own preference).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5486
5549
  "x-rank": "any-builder",
5487
- "x-source": "modules/art-pipeline/routes/art-key.js",
5550
+ "x-source": "src/bongos/routes/me.js",
5551
+ "requestBody": {
5552
+ "required": true,
5553
+ "content": {
5554
+ "application/json": {
5555
+ "schema": {
5556
+ "$ref": "#/components/schemas/PatchMeDisciplinesRequest"
5557
+ }
5558
+ }
5559
+ },
5560
+ "x-validated": true
5561
+ },
5488
5562
  "responses": {
5489
5563
  "200": {
5490
- "description": "Success."
5564
+ "description": "Success.",
5565
+ "content": {
5566
+ "application/json": {
5567
+ "schema": {
5568
+ "$ref": "#/components/schemas/PatchMeDisciplinesResponse"
5569
+ }
5570
+ }
5571
+ }
5491
5572
  },
5492
5573
  "400": {
5493
- "$ref": "#/components/responses/BadRequest"
5574
+ "$ref": "#/components/responses/ValidationFailed"
5494
5575
  },
5495
5576
  "401": {
5496
5577
  "$ref": "#/components/responses/Unauthorized"
@@ -5506,23 +5587,23 @@
5506
5587
  ]
5507
5588
  }
5508
5589
  },
5509
- "/me/art-key/own": {
5590
+ "/me/display-name": {
5510
5591
  "get": {
5511
- "operationId": "get_me_art_key_own",
5592
+ "operationId": "get_me_display_name",
5512
5593
  "tags": [
5513
5594
  "me"
5514
5595
  ],
5515
- "summary": "GET /me/art-key/own",
5516
- "description": "Masked metadata for the browser: { set, last4, set_at, storage_configured }.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5596
+ "summary": "GET /me/display-name",
5597
+ "description": "Per-builder DISPLAY NAME (task 1669). The free label shown next to a builder's work in the hall (header, leaderboard, work feed — all already read display_name, so a DB update propagates). Seeded once from GitHub at account creation; these routes are the only way to change it afterward. Stable identity stays github_login/id — the display name is just the rendered label. rank: any-builder — own profile config; mirrors the skill/sound/render routes.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5517
5598
  "x-rank": "any-builder",
5518
- "x-source": "modules/art-pipeline/routes/art-key.js",
5599
+ "x-source": "modules/builder-settings/routes/settings.js",
5519
5600
  "responses": {
5520
5601
  "200": {
5521
5602
  "description": "Success.",
5522
5603
  "content": {
5523
5604
  "application/json": {
5524
5605
  "schema": {
5525
- "$ref": "#/components/schemas/GetMeArtKeyOwnResponse"
5606
+ "$ref": "#/components/schemas/GetMeDisplayNameResponse"
5526
5607
  }
5527
5608
  }
5528
5609
  }
@@ -5543,32 +5624,41 @@
5543
5624
  }
5544
5625
  ]
5545
5626
  },
5546
- "put": {
5547
- "operationId": "put_me_art_key_own",
5627
+ "patch": {
5628
+ "operationId": "patch_me_display_name",
5548
5629
  "tags": [
5549
5630
  "me"
5550
5631
  ],
5551
- "summary": "PUT /me/art-key/own",
5552
- "description": "Set or replace the builder's own key. Body: { key }. Validates the key with one cheap call to Google (catches typos), encrypts it, stores it. Returns the masked metadata — never the key.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5632
+ "summary": "PATCH /me/display-name",
5633
+ "description": "PATCH the display name. Body: { display_name: \"<new name>\" }. Validated + trimmed by display-name.js: empty/whitespace-only, control chars, and names over the length ceiling → 422 with an errors array; nothing is written when validation fails. Own-scoped — only the AUTHENTICATED builder's row is touched (api.requireBuilder + req.builder.id), never another builder. Uniqueness is NOT required (display names may collide).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5553
5634
  "x-rank": "any-builder",
5554
- "x-source": "modules/art-pipeline/routes/art-key.js",
5635
+ "x-source": "modules/builder-settings/routes/settings.js",
5555
5636
  "requestBody": {
5556
- "required": true,
5637
+ "required": false,
5557
5638
  "content": {
5558
5639
  "application/json": {
5559
5640
  "schema": {
5560
- "$ref": "#/components/schemas/PutMeArtKeyOwnRequest"
5641
+ "type": "object",
5642
+ "additionalProperties": true
5561
5643
  }
5562
5644
  }
5563
5645
  },
5564
- "x-validated": true
5646
+ "x-validated": false,
5647
+ "x-body-undocumented": true
5565
5648
  },
5566
5649
  "responses": {
5567
5650
  "200": {
5568
- "description": "Success."
5651
+ "description": "Success.",
5652
+ "content": {
5653
+ "application/json": {
5654
+ "schema": {
5655
+ "$ref": "#/components/schemas/PatchMeDisplayNameResponse"
5656
+ }
5657
+ }
5658
+ }
5569
5659
  },
5570
5660
  "400": {
5571
- "$ref": "#/components/responses/ValidationFailed"
5661
+ "$ref": "#/components/responses/BadRequest"
5572
5662
  },
5573
5663
  "401": {
5574
5664
  "$ref": "#/components/responses/Unauthorized"
@@ -5582,231 +5672,28 @@
5582
5672
  "builderSession": []
5583
5673
  }
5584
5674
  ]
5585
- },
5586
- "delete": {
5587
- "operationId": "delete_me_art_key_own",
5675
+ }
5676
+ },
5677
+ "/me/event-sound-prefs": {
5678
+ "get": {
5679
+ "operationId": "get_me_event_sound_prefs",
5588
5680
  "tags": [
5589
5681
  "me"
5590
5682
  ],
5591
- "summary": "DELETE /me/art-key/own",
5592
- "description": "Remove the builder's own key (back to \"not set\"). The session-start sync then withdraws the managed local copy on its next run.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5683
+ "summary": "GET /me/event-sound-prefs",
5684
+ "description": "Per-builder per-event sound variant selection (task 582, migration 164). Returns each of the 5 build events with their available world-themed variants, the builder's current selection (or the default), and the resolved .wav file name. The local player uses a mirror written by fetch-sound-prefs.js. rank: any-builder — own profile config; mirrors the sound-prefs route.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5593
5685
  "x-rank": "any-builder",
5594
- "x-source": "modules/art-pipeline/routes/art-key.js",
5686
+ "x-source": "modules/builder-settings/routes/settings.js",
5595
5687
  "responses": {
5596
5688
  "200": {
5597
- "description": "Success."
5598
- },
5599
- "400": {
5600
- "$ref": "#/components/responses/BadRequest"
5601
- },
5602
- "401": {
5603
- "$ref": "#/components/responses/Unauthorized"
5604
- },
5605
- "403": {
5606
- "$ref": "#/components/responses/Forbidden"
5607
- }
5608
- },
5609
- "security": [
5610
- {
5611
- "builderSession": []
5612
- }
5613
- ]
5614
- }
5615
- },
5616
- "/me/art-key/storage-init": {
5617
- "post": {
5618
- "operationId": "post_me_art_key_storage_init",
5619
- "tags": [
5620
- "me"
5621
- ],
5622
- "summary": "POST /me/art-key/storage-init",
5623
- "description": "Archon-only: provision the server's secret-box master key so per-builder key storage can turn on (task 1398, blocker 41). Idempotent — NEVER overwrites an existing key. Lives under /me/art-key/* for client locality, but is a server-wide admin action — hence the requireRank('archon') gate.\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
5624
- "x-rank": "archon",
5625
- "x-source": "modules/art-pipeline/routes/art-key.js",
5626
- "responses": {
5627
- "200": {
5628
- "description": "Success.",
5629
- "content": {
5630
- "application/json": {
5631
- "schema": {
5632
- "$ref": "#/components/schemas/PostMeArtKeyStorageInitResponse"
5633
- }
5634
- }
5635
- }
5636
- },
5637
- "400": {
5638
- "$ref": "#/components/responses/BadRequest"
5639
- },
5640
- "401": {
5641
- "$ref": "#/components/responses/Unauthorized"
5642
- },
5643
- "403": {
5644
- "$ref": "#/components/responses/Forbidden"
5645
- }
5646
- },
5647
- "security": [
5648
- {
5649
- "builderSession": []
5650
- }
5651
- ]
5652
- }
5653
- },
5654
- "/me/disciplines": {
5655
- "patch": {
5656
- "operationId": "patch_me_disciplines",
5657
- "tags": [
5658
- "me"
5659
- ],
5660
- "summary": "PATCH /me/disciplines",
5661
- "description": "Self-service edit of the authenticated builder's preferred disciplines (migrations 027 + 086 / V3.R80). Body: { preferred_disciplines: [\"artist\", ...] }. Valid elements are engineer|artist|ideator; [] clears the preference (a multi-element set just means several lanes). No rank gate — a builder owns their own profile. 422 invalid_discipline if any element is out of range. rank: any-builder — self-service profile edit; documented \"no rank gate\" in the handler comment above (a builder owns their own preference).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5662
- "x-rank": "any-builder",
5663
- "x-source": "src/bongos/routes/me.js",
5664
- "requestBody": {
5665
- "required": true,
5666
- "content": {
5667
- "application/json": {
5668
- "schema": {
5669
- "$ref": "#/components/schemas/PatchMeDisciplinesRequest"
5670
- }
5671
- }
5672
- },
5673
- "x-validated": true
5674
- },
5675
- "responses": {
5676
- "200": {
5677
- "description": "Success.",
5678
- "content": {
5679
- "application/json": {
5680
- "schema": {
5681
- "$ref": "#/components/schemas/PatchMeDisciplinesResponse"
5682
- }
5683
- }
5684
- }
5685
- },
5686
- "400": {
5687
- "$ref": "#/components/responses/ValidationFailed"
5688
- },
5689
- "401": {
5690
- "$ref": "#/components/responses/Unauthorized"
5691
- },
5692
- "403": {
5693
- "$ref": "#/components/responses/Forbidden"
5694
- }
5695
- },
5696
- "security": [
5697
- {
5698
- "builderSession": []
5699
- }
5700
- ]
5701
- }
5702
- },
5703
- "/me/display-name": {
5704
- "get": {
5705
- "operationId": "get_me_display_name",
5706
- "tags": [
5707
- "me"
5708
- ],
5709
- "summary": "GET /me/display-name",
5710
- "description": "Per-builder DISPLAY NAME (task 1669). The free label shown next to a builder's work in the hall (header, leaderboard, work feed — all already read display_name, so a DB update propagates). Seeded once from GitHub at account creation; these routes are the only way to change it afterward. Stable identity stays github_login/id — the display name is just the rendered label. rank: any-builder — own profile config; mirrors the skill/sound/render routes.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5711
- "x-rank": "any-builder",
5712
- "x-source": "modules/builder-settings/routes/settings.js",
5713
- "responses": {
5714
- "200": {
5715
- "description": "Success.",
5716
- "content": {
5717
- "application/json": {
5718
- "schema": {
5719
- "$ref": "#/components/schemas/GetMeDisplayNameResponse"
5720
- }
5721
- }
5722
- }
5723
- },
5724
- "400": {
5725
- "$ref": "#/components/responses/BadRequest"
5726
- },
5727
- "401": {
5728
- "$ref": "#/components/responses/Unauthorized"
5729
- },
5730
- "403": {
5731
- "$ref": "#/components/responses/Forbidden"
5732
- }
5733
- },
5734
- "security": [
5735
- {
5736
- "builderSession": []
5737
- }
5738
- ]
5739
- },
5740
- "patch": {
5741
- "operationId": "patch_me_display_name",
5742
- "tags": [
5743
- "me"
5744
- ],
5745
- "summary": "PATCH /me/display-name",
5746
- "description": "PATCH the display name. Body: { display_name: \"<new name>\" }. Validated + trimmed by display-name.js: empty/whitespace-only, control chars, and names over the length ceiling → 422 with an errors array; nothing is written when validation fails. Own-scoped — only the AUTHENTICATED builder's row is touched (api.requireBuilder + req.builder.id), never another builder. Uniqueness is NOT required (display names may collide).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5747
- "x-rank": "any-builder",
5748
- "x-source": "modules/builder-settings/routes/settings.js",
5749
- "requestBody": {
5750
- "required": false,
5751
- "content": {
5752
- "application/json": {
5753
- "schema": {
5754
- "type": "object",
5755
- "additionalProperties": true
5756
- }
5757
- }
5758
- },
5759
- "x-validated": false,
5760
- "x-body-undocumented": true
5761
- },
5762
- "responses": {
5763
- "200": {
5764
- "description": "Success.",
5765
- "content": {
5766
- "application/json": {
5767
- "schema": {
5768
- "$ref": "#/components/schemas/PatchMeDisplayNameResponse"
5769
- }
5770
- }
5771
- }
5772
- },
5773
- "400": {
5774
- "$ref": "#/components/responses/BadRequest"
5775
- },
5776
- "401": {
5777
- "$ref": "#/components/responses/Unauthorized"
5778
- },
5779
- "403": {
5780
- "$ref": "#/components/responses/Forbidden"
5781
- }
5782
- },
5783
- "security": [
5784
- {
5785
- "builderSession": []
5786
- }
5787
- ]
5788
- }
5789
- },
5790
- "/me/event-sound-prefs": {
5791
- "get": {
5792
- "operationId": "get_me_event_sound_prefs",
5793
- "tags": [
5794
- "me"
5795
- ],
5796
- "summary": "GET /me/event-sound-prefs",
5797
- "description": "Per-builder per-event sound variant selection (task 582, migration 164). Returns each of the 5 build events with their available world-themed variants, the builder's current selection (or the default), and the resolved .wav file name. The local player uses a mirror written by fetch-sound-prefs.js. rank: any-builder — own profile config; mirrors the sound-prefs route.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
5798
- "x-rank": "any-builder",
5799
- "x-source": "modules/builder-settings/routes/settings.js",
5800
- "responses": {
5801
- "200": {
5802
- "description": "Success.",
5803
- "content": {
5804
- "application/json": {
5805
- "schema": {
5806
- "$ref": "#/components/schemas/GetMeEventSoundPrefsResponse"
5807
- }
5808
- }
5809
- }
5689
+ "description": "Success.",
5690
+ "content": {
5691
+ "application/json": {
5692
+ "schema": {
5693
+ "$ref": "#/components/schemas/GetMeEventSoundPrefsResponse"
5694
+ }
5695
+ }
5696
+ }
5810
5697
  },
5811
5698
  "400": {
5812
5699
  "$ref": "#/components/responses/BadRequest"
@@ -6913,23 +6800,23 @@
6913
6800
  ]
6914
6801
  }
6915
6802
  },
6916
- "/override-requests": {
6803
+ "/my-projects": {
6917
6804
  "get": {
6918
- "operationId": "get_override_requests",
6805
+ "operationId": "get_my_projects",
6919
6806
  "tags": [
6920
- "override-requests"
6807
+ "my-projects"
6921
6808
  ],
6922
- "summary": "GET /override-requests",
6923
- "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).",
6924
- "x-rank": "archon",
6925
- "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",
6926
6813
  "responses": {
6927
6814
  "200": {
6928
6815
  "description": "Success.",
6929
6816
  "content": {
6930
6817
  "application/json": {
6931
6818
  "schema": {
6932
- "$ref": "#/components/schemas/GetOverrideRequestsResponse"
6819
+ "$ref": "#/components/schemas/GetMyProjectsResponse"
6933
6820
  }
6934
6821
  }
6935
6822
  }
@@ -6951,25 +6838,517 @@
6951
6838
  ]
6952
6839
  }
6953
6840
  },
6954
- "/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": {
6955
6880
  "post": {
6956
- "operationId": "post_override_requests_id_decide",
6881
+ "operationId": "post_my_projects_invites_clientId_accept",
6957
6882
  "tags": [
6958
- "override-requests"
6883
+ "my-projects"
6959
6884
  ],
6960
- "summary": "POST /override-requests/:id/decide",
6961
- "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).",
6962
- "x-rank": "archon",
6963
- "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",
6964
6889
  "parameters": [
6965
6890
  {
6966
- "name": "id",
6891
+ "name": "clientId",
6967
6892
  "in": "path",
6968
6893
  "required": true,
6969
6894
  "schema": {
6970
6895
  "type": "string"
6971
6896
  },
6972
- "description": "Path parameter `id`."
6897
+ "description": "Path parameter `clientId`."
6898
+ }
6899
+ ],
6900
+ "responses": {
6901
+ "200": {
6902
+ "description": "Success.",
6903
+ "content": {
6904
+ "application/json": {
6905
+ "schema": {
6906
+ "$ref": "#/components/schemas/PostMyProjectsInvitesClientIdAcceptResponse"
6907
+ }
6908
+ }
6909
+ }
6910
+ },
6911
+ "400": {
6912
+ "$ref": "#/components/responses/BadRequest"
6913
+ },
6914
+ "401": {
6915
+ "$ref": "#/components/responses/Unauthorized"
6916
+ },
6917
+ "403": {
6918
+ "$ref": "#/components/responses/Forbidden"
6919
+ },
6920
+ "404": {
6921
+ "$ref": "#/components/responses/NotFound"
6922
+ }
6923
+ },
6924
+ "security": [
6925
+ {
6926
+ "builderSession": []
6927
+ }
6928
+ ]
6929
+ }
6930
+ },
6931
+ "/my-projects/invites/{clientId}/decline": {
6932
+ "post": {
6933
+ "operationId": "post_my_projects_invites_clientId_decline",
6934
+ "tags": [
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
+ }
6951
+ ],
6952
+ "responses": {
6953
+ "200": {
6954
+ "description": "Success.",
6955
+ "content": {
6956
+ "application/json": {
6957
+ "schema": {
6958
+ "$ref": "#/components/schemas/PostMyProjectsInvitesClientIdDeclineResponse"
6959
+ }
6960
+ }
6961
+ }
6962
+ },
6963
+ "400": {
6964
+ "$ref": "#/components/responses/BadRequest"
6965
+ },
6966
+ "401": {
6967
+ "$ref": "#/components/responses/Unauthorized"
6968
+ },
6969
+ "403": {
6970
+ "$ref": "#/components/responses/Forbidden"
6971
+ },
6972
+ "404": {
6973
+ "$ref": "#/components/responses/NotFound"
6974
+ }
6975
+ },
6976
+ "security": [
6977
+ {
6978
+ "builderSession": []
6979
+ }
6980
+ ]
6981
+ }
6982
+ },
6983
+ "/my-projects/join": {
6984
+ "post": {
6985
+ "operationId": "post_my_projects_join",
6986
+ "tags": [
6987
+ "my-projects"
6988
+ ],
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
+ },
7004
+ "responses": {
7005
+ "200": {
7006
+ "description": "Success.",
7007
+ "content": {
7008
+ "application/json": {
7009
+ "schema": {
7010
+ "$ref": "#/components/schemas/PostMyProjectsJoinResponse"
7011
+ }
7012
+ }
7013
+ }
7014
+ },
7015
+ "400": {
7016
+ "$ref": "#/components/responses/ValidationFailed"
7017
+ },
7018
+ "401": {
7019
+ "$ref": "#/components/responses/Unauthorized"
7020
+ },
7021
+ "403": {
7022
+ "$ref": "#/components/responses/Forbidden"
7023
+ }
7024
+ },
7025
+ "security": [
7026
+ {
7027
+ "builderSession": []
7028
+ }
7029
+ ]
7030
+ }
7031
+ },
7032
+ "/my-projects/{clientId}/leave": {
7033
+ "post": {
7034
+ "operationId": "post_my_projects_clientId_leave",
7035
+ "tags": [
7036
+ "my-projects"
7037
+ ],
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`."
7051
+ }
7052
+ ],
7053
+ "responses": {
7054
+ "200": {
7055
+ "description": "Success.",
7056
+ "content": {
7057
+ "application/json": {
7058
+ "schema": {
7059
+ "$ref": "#/components/schemas/PostMyProjectsClientIdLeaveResponse"
7060
+ }
7061
+ }
7062
+ }
7063
+ },
7064
+ "400": {
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"
7075
+ }
7076
+ },
7077
+ "security": [
7078
+ {
7079
+ "builderSession": []
7080
+ }
7081
+ ]
7082
+ }
7083
+ },
7084
+ "/override-requests": {
7085
+ "get": {
7086
+ "operationId": "get_override_requests",
7087
+ "tags": [
7088
+ "override-requests"
7089
+ ],
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",
7094
+ "responses": {
7095
+ "200": {
7096
+ "description": "Success.",
7097
+ "content": {
7098
+ "application/json": {
7099
+ "schema": {
7100
+ "$ref": "#/components/schemas/GetOverrideRequestsResponse"
7101
+ }
7102
+ }
7103
+ }
7104
+ },
7105
+ "400": {
7106
+ "$ref": "#/components/responses/BadRequest"
7107
+ },
7108
+ "401": {
7109
+ "$ref": "#/components/responses/Unauthorized"
7110
+ },
7111
+ "403": {
7112
+ "$ref": "#/components/responses/Forbidden"
7113
+ }
7114
+ },
7115
+ "security": [
7116
+ {
7117
+ "builderSession": []
7118
+ }
7119
+ ]
7120
+ }
7121
+ },
7122
+ "/override-requests/{id}/decide": {
7123
+ "post": {
7124
+ "operationId": "post_override_requests_id_decide",
7125
+ "tags": [
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
+ }
7142
+ ],
7143
+ "requestBody": {
7144
+ "required": true,
7145
+ "content": {
7146
+ "application/json": {
7147
+ "schema": {
7148
+ "$ref": "#/components/schemas/PostOverrideRequestsIdDecideRequest"
7149
+ }
7150
+ }
7151
+ },
7152
+ "x-validated": true
7153
+ },
7154
+ "responses": {
7155
+ "200": {
7156
+ "description": "Success."
7157
+ },
7158
+ "400": {
7159
+ "$ref": "#/components/responses/ValidationFailed"
7160
+ },
7161
+ "401": {
7162
+ "$ref": "#/components/responses/Unauthorized"
7163
+ },
7164
+ "403": {
7165
+ "$ref": "#/components/responses/Forbidden"
7166
+ },
7167
+ "404": {
7168
+ "$ref": "#/components/responses/NotFound"
7169
+ }
7170
+ },
7171
+ "security": [
7172
+ {
7173
+ "builderSession": []
7174
+ }
7175
+ ]
7176
+ }
7177
+ },
7178
+ "/projects": {
7179
+ "get": {
7180
+ "operationId": "get_projects",
7181
+ "tags": [
7182
+ "projects"
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",
7188
+ "responses": {
7189
+ "200": {
7190
+ "description": "Success.",
7191
+ "content": {
7192
+ "application/json": {
7193
+ "schema": {
7194
+ "$ref": "#/components/schemas/GetProjectsResponse"
7195
+ }
7196
+ }
7197
+ }
7198
+ },
7199
+ "400": {
7200
+ "$ref": "#/components/responses/BadRequest"
7201
+ },
7202
+ "401": {
7203
+ "$ref": "#/components/responses/Unauthorized"
7204
+ },
7205
+ "403": {
7206
+ "$ref": "#/components/responses/Forbidden"
7207
+ }
7208
+ },
7209
+ "security": [
7210
+ {
7211
+ "builderSession": []
7212
+ }
7213
+ ]
7214
+ },
7215
+ "post": {
7216
+ "operationId": "post_projects",
7217
+ "tags": [
7218
+ "projects"
7219
+ ],
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).",
7222
+ "x-rank": "archon",
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
+ },
7235
+ "responses": {
7236
+ "200": {
7237
+ "description": "Success.",
7238
+ "content": {
7239
+ "application/json": {
7240
+ "schema": {
7241
+ "$ref": "#/components/schemas/PostProjectsResponse"
7242
+ }
7243
+ }
7244
+ }
7245
+ },
7246
+ "400": {
7247
+ "$ref": "#/components/responses/ValidationFailed"
7248
+ },
7249
+ "401": {
7250
+ "$ref": "#/components/responses/Unauthorized"
7251
+ },
7252
+ "403": {
7253
+ "$ref": "#/components/responses/Forbidden"
7254
+ }
7255
+ },
7256
+ "security": [
7257
+ {
7258
+ "builderSession": []
7259
+ }
7260
+ ]
7261
+ }
7262
+ },
7263
+ "/projects/featured": {
7264
+ "get": {
7265
+ "operationId": "get_projects_featured",
7266
+ "tags": [
7267
+ "projects"
7268
+ ],
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"
7286
+ }
7287
+ },
7288
+ "security": []
7289
+ }
7290
+ },
7291
+ "/projects/invite": {
7292
+ "post": {
7293
+ "operationId": "post_projects_invite",
7294
+ "tags": [
7295
+ "projects"
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",
7301
+ "requestBody": {
7302
+ "required": true,
7303
+ "content": {
7304
+ "application/json": {
7305
+ "schema": {
7306
+ "$ref": "#/components/schemas/PostProjectsInviteRequest"
7307
+ }
7308
+ }
7309
+ },
7310
+ "x-validated": true
7311
+ },
7312
+ "responses": {
7313
+ "200": {
7314
+ "description": "Success."
7315
+ },
7316
+ "400": {
7317
+ "$ref": "#/components/responses/ValidationFailed"
7318
+ },
7319
+ "401": {
7320
+ "$ref": "#/components/responses/Unauthorized"
7321
+ },
7322
+ "403": {
7323
+ "$ref": "#/components/responses/Forbidden"
7324
+ }
7325
+ },
7326
+ "security": [
7327
+ {
7328
+ "builderSession": []
7329
+ }
7330
+ ]
7331
+ }
7332
+ },
7333
+ "/projects/{id}/featured": {
7334
+ "patch": {
7335
+ "operationId": "patch_projects_id_featured",
7336
+ "tags": [
7337
+ "projects"
7338
+ ],
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",
7343
+ "parameters": [
7344
+ {
7345
+ "name": "id",
7346
+ "in": "path",
7347
+ "required": true,
7348
+ "schema": {
7349
+ "type": "string"
7350
+ },
7351
+ "description": "Path parameter `id`."
6973
7352
  }
6974
7353
  ],
6975
7354
  "requestBody": {
@@ -6977,7 +7356,7 @@
6977
7356
  "content": {
6978
7357
  "application/json": {
6979
7358
  "schema": {
6980
- "$ref": "#/components/schemas/PostOverrideRequestsIdDecideRequest"
7359
+ "$ref": "#/components/schemas/PatchProjectsIdFeaturedRequest"
6981
7360
  }
6982
7361
  }
6983
7362
  },
@@ -6985,7 +7364,14 @@
6985
7364
  },
6986
7365
  "responses": {
6987
7366
  "200": {
6988
- "description": "Success."
7367
+ "description": "Success.",
7368
+ "content": {
7369
+ "application/json": {
7370
+ "schema": {
7371
+ "$ref": "#/components/schemas/PatchProjectsIdFeaturedResponse"
7372
+ }
7373
+ }
7374
+ }
6989
7375
  },
6990
7376
  "400": {
6991
7377
  "$ref": "#/components/responses/ValidationFailed"
@@ -7979,53 +8365,319 @@
7979
8365
  "$ref": "#/components/responses/BadRequest"
7980
8366
  }
7981
8367
  },
7982
- "security": []
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
8584
+ },
8585
+ "responses": {
8586
+ "200": {
8587
+ "description": "Success.",
8588
+ "content": {
8589
+ "application/json": {
8590
+ "schema": {
8591
+ "$ref": "#/components/schemas/PostSecurityDocsResponse"
8592
+ }
8593
+ }
8594
+ }
8595
+ },
8596
+ "400": {
8597
+ "$ref": "#/components/responses/ValidationFailed"
8598
+ },
8599
+ "401": {
8600
+ "$ref": "#/components/responses/Unauthorized"
8601
+ },
8602
+ "403": {
8603
+ "$ref": "#/components/responses/Forbidden"
8604
+ }
8605
+ },
8606
+ "security": [
8607
+ {
8608
+ "builderSession": []
8609
+ }
8610
+ ]
7983
8611
  }
7984
8612
  },
7985
- "/public/versions": {
8613
+ "/security/docs/{slug}": {
7986
8614
  "get": {
7987
- "operationId": "get_public_versions",
8615
+ "operationId": "get_security_docs_slug",
7988
8616
  "tags": [
7989
- "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
+ }
7990
8633
  ],
7991
- "summary": "GET /public/versions",
7992
- "description": "read-only surface for status.amazonprimea.com.\n\n**Rank:** `public` — No authentication — any caller.",
7993
- "x-rank": "public",
7994
- "x-source": "src/bongos/routes/public.js",
7995
8634
  "responses": {
7996
8635
  "200": {
7997
8636
  "description": "Success.",
7998
8637
  "content": {
7999
8638
  "application/json": {
8000
8639
  "schema": {
8001
- "$ref": "#/components/schemas/GetPublicVersionsResponse"
8640
+ "$ref": "#/components/schemas/GetSecurityDocsSlugResponse"
8002
8641
  }
8003
8642
  }
8004
8643
  }
8005
8644
  },
8006
8645
  "400": {
8007
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"
8008
8656
  }
8009
8657
  },
8010
- "security": []
8658
+ "security": [
8659
+ {
8660
+ "builderSession": []
8661
+ }
8662
+ ]
8011
8663
  }
8012
8664
  },
8013
- "/search": {
8665
+ "/session/optimize": {
8014
8666
  "post": {
8015
- "operationId": "post_search",
8667
+ "operationId": "post_session_optimize",
8016
8668
  "tags": [
8017
- "search"
8669
+ "session"
8018
8670
  ],
8019
- "summary": "POST /search",
8020
- "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).",
8021
8673
  "x-rank": "any-builder",
8022
- "x-source": "modules/memory/routes/search.js",
8674
+ "x-source": "src/bongos/routes/optimizer.js",
8023
8675
  "requestBody": {
8024
8676
  "required": false,
8025
8677
  "content": {
8026
8678
  "application/json": {
8027
8679
  "schema": {
8028
- "$ref": "#/components/schemas/PostSearchRequest"
8680
+ "$ref": "#/components/schemas/PostSessionOptimizeRequest"
8029
8681
  }
8030
8682
  }
8031
8683
  },
@@ -8033,14 +8685,7 @@
8033
8685
  },
8034
8686
  "responses": {
8035
8687
  "200": {
8036
- "description": "Success.",
8037
- "content": {
8038
- "application/json": {
8039
- "schema": {
8040
- "$ref": "#/components/schemas/PostSearchResponse"
8041
- }
8042
- }
8043
- }
8688
+ "description": "Success."
8044
8689
  },
8045
8690
  "400": {
8046
8691
  "$ref": "#/components/responses/ValidationFailed"
@@ -8059,22 +8704,22 @@
8059
8704
  ]
8060
8705
  }
8061
8706
  },
8062
- "/search/mark": {
8707
+ "/sessions": {
8063
8708
  "post": {
8064
- "operationId": "post_search_mark",
8709
+ "operationId": "post_sessions",
8065
8710
  "tags": [
8066
- "search"
8711
+ "sessions"
8067
8712
  ],
8068
- "summary": "POST /search/mark",
8069
- "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).",
8070
8715
  "x-rank": "any-builder",
8071
- "x-source": "modules/memory/routes/search.js",
8716
+ "x-source": "modules/sessions/routes/sessions.js",
8072
8717
  "requestBody": {
8073
- "required": false,
8718
+ "required": true,
8074
8719
  "content": {
8075
8720
  "application/json": {
8076
8721
  "schema": {
8077
- "$ref": "#/components/schemas/PostSearchMarkRequest"
8722
+ "$ref": "#/components/schemas/PostSessionsRequest"
8078
8723
  }
8079
8724
  }
8080
8725
  },
@@ -8082,7 +8727,14 @@
8082
8727
  },
8083
8728
  "responses": {
8084
8729
  "200": {
8085
- "description": "Success."
8730
+ "description": "Success.",
8731
+ "content": {
8732
+ "application/json": {
8733
+ "schema": {
8734
+ "$ref": "#/components/schemas/PostSessionsResponse"
8735
+ }
8736
+ }
8737
+ }
8086
8738
  },
8087
8739
  "400": {
8088
8740
  "$ref": "#/components/responses/ValidationFailed"
@@ -8101,23 +8753,23 @@
8101
8753
  ]
8102
8754
  }
8103
8755
  },
8104
- "/security/docs": {
8756
+ "/sessions/mine": {
8105
8757
  "get": {
8106
- "operationId": "get_security_docs",
8758
+ "operationId": "get_sessions_mine",
8107
8759
  "tags": [
8108
- "security"
8760
+ "sessions"
8109
8761
  ],
8110
- "summary": "GET /security/docs",
8111
- "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).",
8112
- "x-rank": "archon",
8113
- "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",
8114
8766
  "responses": {
8115
8767
  "200": {
8116
8768
  "description": "Success.",
8117
8769
  "content": {
8118
8770
  "application/json": {
8119
8771
  "schema": {
8120
- "$ref": "#/components/schemas/GetSecurityDocsResponse"
8772
+ "$ref": "#/components/schemas/GetSessionsMineResponse"
8121
8773
  }
8122
8774
  }
8123
8775
  }
@@ -8137,40 +8789,31 @@
8137
8789
  "builderSession": []
8138
8790
  }
8139
8791
  ]
8140
- },
8141
- "post": {
8142
- "operationId": "post_security_docs",
8792
+ }
8793
+ },
8794
+ "/sessions/search": {
8795
+ "get": {
8796
+ "operationId": "get_sessions_search",
8143
8797
  "tags": [
8144
- "security"
8798
+ "sessions"
8145
8799
  ],
8146
- "summary": "POST /security/docs",
8147
- "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).",
8148
8802
  "x-rank": "archon",
8149
- "x-source": "src/bongos/routes/security.js",
8150
- "requestBody": {
8151
- "required": true,
8152
- "content": {
8153
- "application/json": {
8154
- "schema": {
8155
- "$ref": "#/components/schemas/PostSecurityDocsRequest"
8156
- }
8157
- }
8158
- },
8159
- "x-validated": true
8160
- },
8803
+ "x-source": "modules/sessions/routes/sessions.js",
8161
8804
  "responses": {
8162
8805
  "200": {
8163
8806
  "description": "Success.",
8164
8807
  "content": {
8165
8808
  "application/json": {
8166
8809
  "schema": {
8167
- "$ref": "#/components/schemas/PostSecurityDocsResponse"
8810
+ "$ref": "#/components/schemas/GetSessionsSearchResponse"
8168
8811
  }
8169
8812
  }
8170
8813
  }
8171
8814
  },
8172
8815
  "400": {
8173
- "$ref": "#/components/responses/ValidationFailed"
8816
+ "$ref": "#/components/responses/BadRequest"
8174
8817
  },
8175
8818
  "401": {
8176
8819
  "$ref": "#/components/responses/Unauthorized"
@@ -8186,25 +8829,25 @@
8186
8829
  ]
8187
8830
  }
8188
8831
  },
8189
- "/security/docs/{slug}": {
8832
+ "/sessions/{id}": {
8190
8833
  "get": {
8191
- "operationId": "get_security_docs_slug",
8834
+ "operationId": "get_sessions_id",
8192
8835
  "tags": [
8193
- "security"
8836
+ "sessions"
8194
8837
  ],
8195
- "summary": "GET /security/docs/:slug",
8196
- "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).",
8197
- "x-rank": "archon",
8198
- "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",
8199
8842
  "parameters": [
8200
8843
  {
8201
- "name": "slug",
8844
+ "name": "id",
8202
8845
  "in": "path",
8203
8846
  "required": true,
8204
8847
  "schema": {
8205
8848
  "type": "string"
8206
8849
  },
8207
- "description": "Path parameter `slug`."
8850
+ "description": "Path parameter `id`."
8208
8851
  }
8209
8852
  ],
8210
8853
  "responses": {
@@ -8213,7 +8856,7 @@
8213
8856
  "content": {
8214
8857
  "application/json": {
8215
8858
  "schema": {
8216
- "$ref": "#/components/schemas/GetSecurityDocsSlugResponse"
8859
+ "$ref": "#/components/schemas/GetSessionsIdResponse"
8217
8860
  }
8218
8861
  }
8219
8862
  }
@@ -8238,22 +8881,22 @@
8238
8881
  ]
8239
8882
  }
8240
8883
  },
8241
- "/session/optimize": {
8884
+ "/sso/activity/rollup": {
8242
8885
  "post": {
8243
- "operationId": "post_session_optimize",
8886
+ "operationId": "post_sso_activity_rollup",
8244
8887
  "tags": [
8245
- "session"
8888
+ "sso"
8246
8889
  ],
8247
- "summary": "POST /session/optimize",
8248
- "description": "pick own next work; the optimizer reads/recommends only.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8249
- "x-rank": "any-builder",
8250
- "x-source": "src/bongos/routes/optimizer.js",
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",
8251
8894
  "requestBody": {
8252
- "required": false,
8895
+ "required": true,
8253
8896
  "content": {
8254
8897
  "application/json": {
8255
8898
  "schema": {
8256
- "$ref": "#/components/schemas/PostSessionOptimizeRequest"
8899
+ "$ref": "#/components/schemas/PostSsoActivityRollupRequest"
8257
8900
  }
8258
8901
  }
8259
8902
  },
@@ -8261,41 +8904,123 @@
8261
8904
  },
8262
8905
  "responses": {
8263
8906
  "200": {
8264
- "description": "Success."
8907
+ "description": "Success.",
8908
+ "content": {
8909
+ "application/json": {
8910
+ "schema": {
8911
+ "$ref": "#/components/schemas/PostSsoActivityRollupResponse"
8912
+ }
8913
+ }
8914
+ }
8265
8915
  },
8266
8916
  "400": {
8267
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."
8268
8936
  },
8269
- "401": {
8270
- "$ref": "#/components/responses/Unauthorized"
8937
+ "400": {
8938
+ "$ref": "#/components/responses/BadRequest"
8939
+ }
8940
+ },
8941
+ "security": []
8942
+ }
8943
+ },
8944
+ "/sso/device/poll": {
8945
+ "post": {
8946
+ "operationId": "post_sso_device_poll",
8947
+ "tags": [
8948
+ "sso"
8949
+ ],
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",
8954
+ "requestBody": {
8955
+ "required": true,
8956
+ "content": {
8957
+ "application/json": {
8958
+ "schema": {
8959
+ "$ref": "#/components/schemas/PostSsoDevicePollRequest"
8960
+ }
8961
+ }
8271
8962
  },
8272
- "403": {
8273
- "$ref": "#/components/responses/Forbidden"
8963
+ "x-validated": true
8964
+ },
8965
+ "responses": {
8966
+ "200": {
8967
+ "description": "Success."
8968
+ },
8969
+ "400": {
8970
+ "$ref": "#/components/responses/ValidationFailed"
8274
8971
  }
8275
8972
  },
8276
- "security": [
8277
- {
8278
- "builderSession": []
8973
+ "security": []
8974
+ }
8975
+ },
8976
+ "/sso/device/start": {
8977
+ "post": {
8978
+ "operationId": "post_sso_device_start",
8979
+ "tags": [
8980
+ "sso"
8981
+ ],
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",
8986
+ "requestBody": {
8987
+ "required": true,
8988
+ "content": {
8989
+ "application/json": {
8990
+ "schema": {
8991
+ "$ref": "#/components/schemas/PostSsoDeviceStartRequest"
8992
+ }
8993
+ }
8994
+ },
8995
+ "x-validated": true
8996
+ },
8997
+ "responses": {
8998
+ "200": {
8999
+ "description": "Success."
9000
+ },
9001
+ "400": {
9002
+ "$ref": "#/components/responses/ValidationFailed"
8279
9003
  }
8280
- ]
9004
+ },
9005
+ "security": []
8281
9006
  }
8282
9007
  },
8283
- "/sessions": {
9008
+ "/sso/membership/check-in": {
8284
9009
  "post": {
8285
- "operationId": "post_sessions",
9010
+ "operationId": "post_sso_membership_check_in",
8286
9011
  "tags": [
8287
- "sessions"
9012
+ "sso"
8288
9013
  ],
8289
- "summary": "POST /sessions",
8290
- "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).",
8291
- "x-rank": "any-builder",
8292
- "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",
8293
9018
  "requestBody": {
8294
9019
  "required": true,
8295
9020
  "content": {
8296
9021
  "application/json": {
8297
9022
  "schema": {
8298
- "$ref": "#/components/schemas/PostSessionsRequest"
9023
+ "$ref": "#/components/schemas/PostSsoMembershipCheckInRequest"
8299
9024
  }
8300
9025
  }
8301
9026
  },
@@ -8307,154 +9032,83 @@
8307
9032
  "content": {
8308
9033
  "application/json": {
8309
9034
  "schema": {
8310
- "$ref": "#/components/schemas/PostSessionsResponse"
9035
+ "$ref": "#/components/schemas/PostSsoMembershipCheckInResponse"
8311
9036
  }
8312
9037
  }
8313
9038
  }
8314
9039
  },
8315
9040
  "400": {
8316
9041
  "$ref": "#/components/responses/ValidationFailed"
8317
- },
8318
- "401": {
8319
- "$ref": "#/components/responses/Unauthorized"
8320
- },
8321
- "403": {
8322
- "$ref": "#/components/responses/Forbidden"
8323
9042
  }
8324
9043
  },
8325
- "security": [
8326
- {
8327
- "builderSession": []
8328
- }
8329
- ]
9044
+ "security": []
8330
9045
  }
8331
9046
  },
8332
- "/sessions/mine": {
9047
+ "/sso/pubkey": {
8333
9048
  "get": {
8334
- "operationId": "get_sessions_mine",
9049
+ "operationId": "get_sso_pubkey",
8335
9050
  "tags": [
8336
- "sessions"
9051
+ "sso"
8337
9052
  ],
8338
- "summary": "GET /sessions/mine",
8339
- "description": "your OWN sessions (self-serve; no audit needed).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
8340
- "x-rank": "any-builder",
8341
- "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",
8342
9057
  "responses": {
8343
9058
  "200": {
8344
9059
  "description": "Success.",
8345
9060
  "content": {
8346
9061
  "application/json": {
8347
9062
  "schema": {
8348
- "$ref": "#/components/schemas/GetSessionsMineResponse"
9063
+ "$ref": "#/components/schemas/GetSsoPubkeyResponse"
8349
9064
  }
8350
9065
  }
8351
9066
  }
8352
9067
  },
8353
9068
  "400": {
8354
9069
  "$ref": "#/components/responses/BadRequest"
8355
- },
8356
- "401": {
8357
- "$ref": "#/components/responses/Unauthorized"
8358
- },
8359
- "403": {
8360
- "$ref": "#/components/responses/Forbidden"
8361
9070
  }
8362
9071
  },
8363
- "security": [
8364
- {
8365
- "builderSession": []
8366
- }
8367
- ]
9072
+ "security": []
8368
9073
  }
8369
9074
  },
8370
- "/sessions/search": {
8371
- "get": {
8372
- "operationId": "get_sessions_search",
9075
+ "/sso/token": {
9076
+ "post": {
9077
+ "operationId": "post_sso_token",
8373
9078
  "tags": [
8374
- "sessions"
9079
+ "sso"
8375
9080
  ],
8376
- "summary": "GET /sessions/search",
8377
- "description": "cross-builder corpus search (BFG-principal posture until 6C.1).\n\n**Rank:** `archon` — Archon only (the single owner — ratification, infra, rank changes).",
8378
- "x-rank": "archon",
8379
- "x-source": "modules/sessions/routes/sessions.js",
8380
- "responses": {
8381
- "200": {
8382
- "description": "Success.",
8383
- "content": {
8384
- "application/json": {
8385
- "schema": {
8386
- "$ref": "#/components/schemas/GetSessionsSearchResponse"
8387
- }
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"
8388
9091
  }
8389
9092
  }
8390
9093
  },
8391
- "400": {
8392
- "$ref": "#/components/responses/BadRequest"
8393
- },
8394
- "401": {
8395
- "$ref": "#/components/responses/Unauthorized"
8396
- },
8397
- "403": {
8398
- "$ref": "#/components/responses/Forbidden"
8399
- }
9094
+ "x-validated": true
8400
9095
  },
8401
- "security": [
8402
- {
8403
- "builderSession": []
8404
- }
8405
- ]
8406
- }
8407
- },
8408
- "/sessions/{id}": {
8409
- "get": {
8410
- "operationId": "get_sessions_id",
8411
- "tags": [
8412
- "sessions"
8413
- ],
8414
- "summary": "GET /sessions/:id",
8415
- "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).",
8416
- "x-rank": "any-builder",
8417
- "x-source": "modules/sessions/routes/sessions.js",
8418
- "parameters": [
8419
- {
8420
- "name": "id",
8421
- "in": "path",
8422
- "required": true,
8423
- "schema": {
8424
- "type": "string"
8425
- },
8426
- "description": "Path parameter `id`."
8427
- }
8428
- ],
8429
9096
  "responses": {
8430
9097
  "200": {
8431
9098
  "description": "Success.",
8432
9099
  "content": {
8433
9100
  "application/json": {
8434
9101
  "schema": {
8435
- "$ref": "#/components/schemas/GetSessionsIdResponse"
9102
+ "$ref": "#/components/schemas/PostSsoTokenResponse"
8436
9103
  }
8437
9104
  }
8438
9105
  }
8439
9106
  },
8440
9107
  "400": {
8441
- "$ref": "#/components/responses/BadRequest"
8442
- },
8443
- "401": {
8444
- "$ref": "#/components/responses/Unauthorized"
8445
- },
8446
- "403": {
8447
- "$ref": "#/components/responses/Forbidden"
8448
- },
8449
- "404": {
8450
- "$ref": "#/components/responses/NotFound"
9108
+ "$ref": "#/components/responses/ValidationFailed"
8451
9109
  }
8452
9110
  },
8453
- "security": [
8454
- {
8455
- "builderSession": []
8456
- }
8457
- ]
9111
+ "security": []
8458
9112
  }
8459
9113
  },
8460
9114
  "/tasks": {
@@ -10456,21 +11110,6 @@
10456
11110
  "stale_hours"
10457
11111
  ]
10458
11112
  },
10459
- "GetDemoHealthResponse": {
10460
- "type": "object",
10461
- "properties": {
10462
- "module": {},
10463
- "ok": {
10464
- "type": "boolean"
10465
- },
10466
- "coreVersion": {}
10467
- },
10468
- "required": [
10469
- "module",
10470
- "ok",
10471
- "coreVersion"
10472
- ]
10473
- },
10474
11113
  "GetDiscordChannelsPlanResponse": {
10475
11114
  "type": "object",
10476
11115
  "properties": {
@@ -10501,6 +11140,15 @@
10501
11140
  "count"
10502
11141
  ]
10503
11142
  },
11143
+ "GetGithubReposResponse": {
11144
+ "type": "object",
11145
+ "properties": {
11146
+ "repos": {}
11147
+ },
11148
+ "required": [
11149
+ "repos"
11150
+ ]
11151
+ },
10504
11152
  "GetGoalsIdConflictsResponse": {
10505
11153
  "type": "object",
10506
11154
  "properties": {
@@ -10635,21 +11283,6 @@
10635
11283
  "unlocked"
10636
11284
  ]
10637
11285
  },
10638
- "GetMeArtKeyOwnResponse": {
10639
- "type": "object",
10640
- "properties": {
10641
- "set": {},
10642
- "last4": {},
10643
- "set_at": {},
10644
- "storage_configured": {}
10645
- },
10646
- "required": [
10647
- "set",
10648
- "last4",
10649
- "set_at",
10650
- "storage_configured"
10651
- ]
10652
- },
10653
11286
  "GetMeDisplayNameResponse": {
10654
11287
  "type": "object",
10655
11288
  "properties": {
@@ -10827,6 +11460,26 @@
10827
11460
  "submissions"
10828
11461
  ]
10829
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
+ },
10830
11483
  "GetOverrideRequestsResponse": {
10831
11484
  "type": "object",
10832
11485
  "properties": {
@@ -10836,6 +11489,24 @@
10836
11489
  "requests"
10837
11490
  ]
10838
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
+ },
10839
11510
  "GetProvisioningFleetResponse": {
10840
11511
  "type": "object",
10841
11512
  "properties": {
@@ -11063,6 +11734,15 @@
11063
11734
  "page"
11064
11735
  ]
11065
11736
  },
11737
+ "GetScoutingResponse": {
11738
+ "type": "object",
11739
+ "properties": {
11740
+ "builders": {}
11741
+ },
11742
+ "required": [
11743
+ "builders"
11744
+ ]
11745
+ },
11066
11746
  "GetSecurityDocsResponse": {
11067
11747
  "type": "object",
11068
11748
  "properties": {
@@ -11120,6 +11800,19 @@
11120
11800
  "offset"
11121
11801
  ]
11122
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
+ },
11123
11816
  "GetTasksClaimableResponse": {
11124
11817
  "type": "object",
11125
11818
  "properties": {
@@ -11545,6 +12238,27 @@
11545
12238
  "known_sounds"
11546
12239
  ]
11547
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
+ },
11548
12262
  "PatchTasksIdRequest": {
11549
12263
  "type": "object",
11550
12264
  "properties": {
@@ -11714,6 +12428,30 @@
11714
12428
  "paste_command"
11715
12429
  ]
11716
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": {
12445
+ "type": "object",
12446
+ "properties": {
12447
+ "token": {},
12448
+ "builder": {}
12449
+ },
12450
+ "required": [
12451
+ "token",
12452
+ "builder"
12453
+ ]
12454
+ },
11717
12455
  "PostAuthDevicePollRequest": {
11718
12456
  "type": "object",
11719
12457
  "properties": {
@@ -12314,30 +13052,6 @@
12314
13052
  "recorded_at": {}
12315
13053
  }
12316
13054
  },
12317
- "PostDemoPingRequest": {
12318
- "type": "object",
12319
- "properties": {
12320
- "note": {
12321
- "type": "string"
12322
- }
12323
- },
12324
- "additionalProperties": false
12325
- },
12326
- "PostDemoPingResponse": {
12327
- "type": "object",
12328
- "properties": {
12329
- "module": {},
12330
- "ok": {
12331
- "type": "boolean"
12332
- },
12333
- "ping": {}
12334
- },
12335
- "required": [
12336
- "module",
12337
- "ok",
12338
- "ping"
12339
- ]
12340
- },
12341
13055
  "PostDependenciesResponse": {
12342
13056
  "type": "object",
12343
13057
  "properties": {
@@ -12420,9 +13134,31 @@
12420
13134
  "recheck": {}
12421
13135
  },
12422
13136
  "required": [
12423
- "ok",
12424
- "pr",
12425
- "message"
13137
+ "ok",
13138
+ "pr",
13139
+ "message"
13140
+ ]
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"
12426
13162
  ]
12427
13163
  },
12428
13164
  "PostGoalsIdArchiveResponse": {
@@ -13048,23 +13784,6 @@
13048
13784
  "linked"
13049
13785
  ]
13050
13786
  },
13051
- "PostMeArtKeyStorageInitResponse": {
13052
- "type": "object",
13053
- "properties": {
13054
- "ok": {
13055
- "type": "boolean"
13056
- },
13057
- "created": {},
13058
- "reason": {},
13059
- "storage_configured": {}
13060
- },
13061
- "required": [
13062
- "ok",
13063
- "created",
13064
- "reason",
13065
- "storage_configured"
13066
- ]
13067
- },
13068
13787
  "PostMemoryBuildersBuilderIdBfgWriteRequest": {
13069
13788
  "type": "object",
13070
13789
  "properties": {
@@ -13172,6 +13891,79 @@
13172
13891
  "submission"
13173
13892
  ]
13174
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
+ },
13175
13967
  "PostOverrideRequestsIdDecideRequest": {
13176
13968
  "type": "object",
13177
13969
  "properties": {
@@ -13188,6 +13980,59 @@
13188
13980
  ],
13189
13981
  "additionalProperties": false
13190
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
+ },
13191
14036
  "PostProvisioningInstancesIdForceTeardownResponse": {
13192
14037
  "type": "object",
13193
14038
  "properties": {
@@ -13433,6 +14278,172 @@
13433
14278
  "token_reward": {}
13434
14279
  }
13435
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
+ },
13436
14447
  "PostTasksIdAbandonRequest": {
13437
14448
  "type": "object",
13438
14449
  "properties": {
@@ -13896,19 +14907,6 @@
13896
14907
  "criteria"
13897
14908
  ]
13898
14909
  },
13899
- "PutMeArtKeyOwnRequest": {
13900
- "type": "object",
13901
- "properties": {
13902
- "key": {
13903
- "type": "string",
13904
- "maxLength": 400
13905
- }
13906
- },
13907
- "required": [
13908
- "key"
13909
- ],
13910
- "additionalProperties": false
13911
- },
13912
14910
  "PutTasksIdDependenciesRequest": {
13913
14911
  "type": "object",
13914
14912
  "properties": {
@@ -14060,9 +15058,9 @@
14060
15058
  "description": "A required dependency/feature is not configured or is temporarily down."
14061
15059
  }
14062
15060
  },
14063
- "x-endpoint-count": 230,
14064
- "x-schema-count": 250,
15061
+ "x-endpoint-count": 245,
15062
+ "x-schema-count": 273,
14065
15063
  "x-undocumented-bodies": 8,
14066
- "x-response-schemas": 170,
15064
+ "x-response-schemas": 184,
14067
15065
  "x-generated-by": "scripts/gds/gen-api-docs.js"
14068
15066
  }