@whooshbang/contracts 1.0.0-rc.20 → 1.0.0-rc.21

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 (107) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/contract-manifest.json +46 -32
  3. package/dist/generated/artifact-index.d.ts +34 -34
  4. package/dist/generated/artifact-index.js +46 -32
  5. package/dist/generated/artifact-index.js.map +1 -1
  6. package/dist/generated/validators-standalone.d.ts +384 -254
  7. package/dist/generated/validators-standalone.js +25492 -15741
  8. package/dist/generated/validators-standalone.js.map +1 -1
  9. package/dist/generated/validators.d.ts +11 -1
  10. package/dist/generated/validators.js +62 -17
  11. package/dist/generated/validators.js.map +1 -1
  12. package/dist/generated/whooshbang-v1.d.ts +809 -5
  13. package/dist/index.d.ts +6 -2
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/fixtures/core-v1/fixture-index.json +110 -1
  17. package/fixtures/core-v1/problems/credential-account-mismatch.json +9 -0
  18. package/fixtures/core-v1/requests/create-account-credential.json +4 -0
  19. package/fixtures/core-v1/requests/create-connection-test.json +3 -0
  20. package/fixtures/core-v1/requests/rotate-account-credential.json +3 -0
  21. package/fixtures/core-v1/scenarios/api-credential-invalid-indistinguishable.json +1 -1
  22. package/fixtures/core-v1/scenarios/api-credential-one-time-reveal.json +1 -1
  23. package/fixtures/core-v1/scenarios/api-credential-revocation-replay.json +1 -1
  24. package/fixtures/core-v1/scenarios/api-credential-rotation-overlap.json +1 -1
  25. package/fixtures/core-v1/scenarios/cancellation-too-late.json +1 -1
  26. package/fixtures/core-v1/scenarios/cross-account-project.json +1 -1
  27. package/fixtures/core-v1/scenarios/cross-project-resource.json +1 -1
  28. package/fixtures/core-v1/scenarios/environment-mismatch.json +1 -1
  29. package/fixtures/core-v1/scenarios/idempotency-conflict.json +1 -1
  30. package/fixtures/core-v1/scenarios/idempotency-equivalent-replay.json +1 -1
  31. package/fixtures/core-v1/scenarios/malformed-bearer.json +1 -1
  32. package/fixtures/core-v1/scenarios/metadata-overrun.json +1 -1
  33. package/fixtures/core-v1/scenarios/missing-scope.json +1 -1
  34. package/fixtures/core-v1/scenarios/project-create-equivalent-replay.json +1 -1
  35. package/fixtures/core-v1/scenarios/project-slug-conflict.json +1 -1
  36. package/fixtures/core-v1/scenarios/provider-outcome-unknown.json +1 -1
  37. package/fixtures/core-v1/scenarios/subscription-activation-replay.json +1 -1
  38. package/fixtures/core-v1/scenarios/subscription-authorization-capability-opacity.json +1 -1
  39. package/fixtures/core-v1/scenarios/subscription-cross-connection-callback-rejected.json +1 -1
  40. package/fixtures/core-v1/scenarios/subscription-expired-replay.json +1 -1
  41. package/fixtures/core-v1/scenarios/subscription-selected-connection-replay.json +1 -1
  42. package/fixtures/core-v1/success/account-credential-collection.json +17 -0
  43. package/fixtures/core-v1/success/account-credential-created.json +12 -0
  44. package/fixtures/core-v1/success/account-credential-revoked.json +11 -0
  45. package/fixtures/core-v1/success/account-credential-rotated.json +25 -0
  46. package/fixtures/core-v1/success/channel-connection-slack-customer-active.json +31 -0
  47. package/fixtures/core-v1/success/channel-connection-slack-customer-pending.json +36 -0
  48. package/fixtures/core-v1/success/connection-test-collection.json +39 -0
  49. package/fixtures/core-v1/success/connection-test-pending.json +16 -0
  50. package/fixtures/core-v1/success/connection-test-succeeded.json +20 -0
  51. package/fixtures/core-v1/success/customer-owned-slack-app-manifest.json +53 -0
  52. package/fixtures/interaction-machine-v1/scenarios/ack-conflict.json +1 -1
  53. package/fixtures/interaction-machine-v1/scenarios/ack-cross-machine.json +1 -1
  54. package/fixtures/interaction-machine-v1/scenarios/ack-out-of-order.json +1 -1
  55. package/fixtures/interaction-machine-v1/scenarios/ack-replay.json +1 -1
  56. package/fixtures/interaction-machine-v1/scenarios/ambiguous-free-text.json +1 -1
  57. package/fixtures/interaction-machine-v1/scenarios/callback-token-opacity.json +1 -1
  58. package/fixtures/interaction-machine-v1/scenarios/credential-registration-conflict.json +1 -1
  59. package/fixtures/interaction-machine-v1/scenarios/credential-registration-replay.json +1 -1
  60. package/fixtures/interaction-machine-v1/scenarios/credential-revocation-replay.json +1 -1
  61. package/fixtures/interaction-machine-v1/scenarios/credential-rotation.json +1 -1
  62. package/fixtures/interaction-machine-v1/scenarios/first-credential-activates.json +1 -1
  63. package/fixtures/interaction-machine-v1/scenarios/interaction-duplicate.json +1 -1
  64. package/fixtures/interaction-machine-v1/scenarios/interaction-expired.json +1 -1
  65. package/fixtures/interaction-machine-v1/scenarios/interaction-mismatch.json +1 -1
  66. package/fixtures/interaction-machine-v1/scenarios/interaction-retired.json +1 -1
  67. package/fixtures/interaction-machine-v1/scenarios/interaction-stale.json +1 -1
  68. package/fixtures/interaction-machine-v1/scenarios/machine-admin-denied.json +1 -1
  69. package/fixtures/interaction-machine-v1/scenarios/machine-bound-message-create.json +1 -1
  70. package/fixtures/interaction-machine-v1/scenarios/machine-cancel-denied.json +1 -1
  71. package/fixtures/interaction-machine-v1/scenarios/machine-crash-before-ack.json +1 -1
  72. package/fixtures/interaction-machine-v1/scenarios/machine-notifier-mismatch.json +1 -1
  73. package/fixtures/interaction-machine-v1/scenarios/machine-other-message-read.json +1 -1
  74. package/fixtures/interaction-machine-v1/scenarios/machine-owned-message-read.json +1 -1
  75. package/fixtures/interaction-machine-v1/scenarios/machine-subscriber-mismatch.json +1 -1
  76. package/fixtures/interaction-machine-v1/scenarios/poll-uncommitted-cursor-rejected.json +1 -1
  77. package/fixtures/interaction-machine-v1/scenarios/project-credential-machine-endpoint-denied.json +1 -1
  78. package/fixtures/interaction-machine-v1/scenarios/quarantine-integrity-rejected.json +1 -1
  79. package/fixtures/interaction-machine-v1/scenarios/quarantine-signature-rejected.json +1 -1
  80. package/fixtures/interaction-machine-v1/scenarios/quarantine-valid.json +1 -1
  81. package/fixtures/interaction-machine-v1/scenarios/revoked-machine-credential.json +1 -1
  82. package/fixtures/recipient-experience-v1/scenarios/membership-broadcast-snapshot.json +1 -1
  83. package/fixtures/recipient-experience-v1/scenarios/preferred-binding-resolution.json +1 -1
  84. package/fixtures/recipient-experience-v1/scenarios/recipient-session-security.json +1 -1
  85. package/fixtures/recipient-experience-v1/scenarios/subscriber-initial-groups-transaction.json +1 -1
  86. package/openapi/generated/whooshbang-v1.bundle.json +1581 -93
  87. package/openapi/whooshbang-v1.yaml +667 -10
  88. package/package.json +1 -1
  89. package/schemas/core-scenario.schema.json +1 -1
  90. package/schemas/events/agent-binding-degraded-v1.schema.json +1 -1
  91. package/schemas/events/interaction-expired-v1.schema.json +1 -1
  92. package/schemas/events/interaction-received-v1.schema.json +1 -1
  93. package/schemas/events/message-delivered-v1.schema.json +1 -1
  94. package/schemas/events/message-expired-v1.schema.json +1 -1
  95. package/schemas/events/message-failed-v1.schema.json +1 -1
  96. package/schemas/events/message-provider-accepted-v1.schema.json +1 -1
  97. package/schemas/events/subscription-activated-v1.schema.json +1 -1
  98. package/schemas/events/subscription-revoked-v1.schema.json +1 -1
  99. package/schemas/events/whooshbang-event-v1.schema.json +1 -1
  100. package/schemas/fixture-index.schema.json +1 -1
  101. package/schemas/interaction-machine-scenario.schema.json +1 -1
  102. package/schemas/interaction-v1.schema.json +1 -1
  103. package/schemas/machine-v1.schema.json +1 -1
  104. package/schemas/provider-capabilities-v1.schema.json +1 -1
  105. package/schemas/webhooks/webhook-delivery-case-v1.schema.json +1 -1
  106. package/schemas/webhooks/webhook-signing-vector-v1.schema.json +1 -1
  107. package/schemas/whooshbang-v1.schema.json +811 -23
@@ -1,10 +1,10 @@
1
1
  openapi: 3.1.1
2
2
  jsonSchemaDialect: https://json-schema.org/draft/2020-12/schema
3
3
  # whooshbang:public-origin production api https://api.whooshbang.com
4
- x-contract-version: 1.0.0-rc.20
4
+ x-contract-version: 1.0.0-rc.21
5
5
  info:
6
6
  title: WhooshBang API
7
- version: 1.0.0-rc.20
7
+ version: 1.0.0-rc.21
8
8
  description: |
9
9
  The V1 contract for human account/project administration, project-scoped
10
10
  subscription links, and asynchronous text messages. A Clerk session selects
@@ -41,6 +41,8 @@ tags:
41
41
  description: Account-scoped applications with transactionally bootstrapped test/live environments.
42
42
  - name: API credentials
43
43
  description: Human-administered, environment-scoped bearer credentials with one-time secret reveal.
44
+ - name: Account credentials
45
+ description: Human-administered, account-scoped bearer credentials that name their project and environment per call.
44
46
  - name: Subscription links
45
47
  description: Single-use, expiring Telegram authorization links.
46
48
  - name: Messages
@@ -97,6 +99,193 @@ paths:
97
99
  $ref: "#/components/responses/Forbidden"
98
100
  "429":
99
101
  $ref: "#/components/responses/RateLimited"
102
+ /v1/account/credentials:
103
+ get:
104
+ operationId: listAccountCredentials
105
+ summary: List safe account credential metadata
106
+ description: |
107
+ Returns only credentials owned by the account selected by the verified
108
+ Clerk organization session. Secrets and digest material are never
109
+ returned.
110
+ tags:
111
+ - Account credentials
112
+ security:
113
+ - clerkSession: []
114
+ x-account-membership: required
115
+ parameters:
116
+ - $ref: "#/components/parameters/ApiCredentialAfterCursor"
117
+ - $ref: "#/components/parameters/ApiCredentialPageLimit"
118
+ - $ref: "#/components/parameters/PageNumber"
119
+ responses:
120
+ "200":
121
+ description: A stable page of safe account credential metadata.
122
+ headers:
123
+ WhooshBang-Diagnostic-Id:
124
+ $ref: "#/components/headers/DiagnosticId"
125
+ content:
126
+ application/json:
127
+ schema:
128
+ $ref: "#/components/schemas/AccountCredentialCollection"
129
+ examples:
130
+ accountCredentials:
131
+ externalValue: ../fixtures/core-v1/success/account-credential-collection.json
132
+ "400":
133
+ $ref: "#/components/responses/BadRequest"
134
+ "401":
135
+ $ref: "#/components/responses/Unauthorized"
136
+ "403":
137
+ $ref: "#/components/responses/Forbidden"
138
+ "404":
139
+ $ref: "#/components/responses/NotFound"
140
+ "429":
141
+ $ref: "#/components/responses/RateLimited"
142
+ post:
143
+ operationId: createAccountCredential
144
+ summary: Create an account-scoped API credential
145
+ description: |
146
+ Creates one credential against the whole account. It names no project
147
+ and no environment: a request names them in its path, and the
148
+ credential's authority on that path is the intersection of its scopes
149
+ with the project-credential vocabulary, so it is never wider than a
150
+ project credential would have been for the same project environment.
151
+ The complete bearer secret appears only in this creation response. It
152
+ cannot be read later and is never replayed from an idempotency cache.
153
+ tags:
154
+ - Account credentials
155
+ security:
156
+ - clerkSession: []
157
+ x-account-membership: required
158
+ x-secret-reveal:
159
+ responses: 1
160
+ replayable: false
161
+ later_reads: metadata_only
162
+ requestBody:
163
+ required: true
164
+ content:
165
+ application/json:
166
+ schema:
167
+ $ref: "#/components/schemas/CreateAccountCredentialRequest"
168
+ examples:
169
+ createAccountCredential:
170
+ externalValue: ../fixtures/core-v1/requests/create-account-credential.json
171
+ responses:
172
+ "201":
173
+ description: Creation-only secret reveal and safe credential metadata.
174
+ headers:
175
+ WhooshBang-Diagnostic-Id:
176
+ $ref: "#/components/headers/DiagnosticId"
177
+ content:
178
+ application/json:
179
+ schema:
180
+ $ref: "#/components/schemas/AccountCredentialSecretReveal"
181
+ examples:
182
+ createdAccountCredential:
183
+ externalValue: ../fixtures/core-v1/success/account-credential-created.json
184
+ "400":
185
+ $ref: "#/components/responses/BadRequest"
186
+ "401":
187
+ $ref: "#/components/responses/Unauthorized"
188
+ "403":
189
+ $ref: "#/components/responses/Forbidden"
190
+ "404":
191
+ $ref: "#/components/responses/NotFound"
192
+ "429":
193
+ $ref: "#/components/responses/RateLimited"
194
+ /v1/account/credentials/{account_credential_id}/rotate:
195
+ parameters:
196
+ - $ref: "#/components/parameters/AccountCredentialId"
197
+ post:
198
+ operationId: rotateAccountCredential
199
+ summary: Rotate an account-scoped API credential
200
+ description: |
201
+ Creates one replacement with the same label and scopes. The complete new
202
+ bearer secret appears only in this response. The replaced credential
203
+ remains active for the explicitly declared overlap, from zero through
204
+ 86400 seconds, then becomes terminally revoked. A revoked credential
205
+ cannot be rotated. Missing and out-of-account credentials use the same
206
+ non-enumerating `404`.
207
+ tags:
208
+ - Account credentials
209
+ security:
210
+ - clerkSession: []
211
+ x-account-membership: required
212
+ x-secret-reveal:
213
+ responses: 1
214
+ replayable: false
215
+ later_reads: metadata_only
216
+ requestBody:
217
+ required: true
218
+ content:
219
+ application/json:
220
+ schema:
221
+ $ref: "#/components/schemas/RotateAccountCredentialRequest"
222
+ examples:
223
+ rotateAccountCredential:
224
+ externalValue: ../fixtures/core-v1/requests/rotate-account-credential.json
225
+ responses:
226
+ "201":
227
+ description: Creation-only replacement secret and safe metadata for both credentials.
228
+ headers:
229
+ WhooshBang-Diagnostic-Id:
230
+ $ref: "#/components/headers/DiagnosticId"
231
+ content:
232
+ application/json:
233
+ schema:
234
+ $ref: "#/components/schemas/AccountCredentialRotation"
235
+ examples:
236
+ rotatedAccountCredential:
237
+ externalValue: ../fixtures/core-v1/success/account-credential-rotated.json
238
+ "400":
239
+ $ref: "#/components/responses/BadRequest"
240
+ "401":
241
+ $ref: "#/components/responses/Unauthorized"
242
+ "403":
243
+ $ref: "#/components/responses/Forbidden"
244
+ "404":
245
+ $ref: "#/components/responses/NotFound"
246
+ "429":
247
+ $ref: "#/components/responses/RateLimited"
248
+ /v1/account/credentials/{account_credential_id}/revoke:
249
+ parameters:
250
+ - $ref: "#/components/parameters/AccountCredentialId"
251
+ post:
252
+ operationId: revokeAccountCredential
253
+ summary: Revoke an account-scoped API credential
254
+ description: |
255
+ Immediately and terminally revokes the selected credential. Repeating
256
+ the request for the same visible credential is safe and returns the
257
+ same revoked metadata without revealing secret or digest material.
258
+ Missing and out-of-account credentials use the same non-enumerating
259
+ `404`.
260
+ tags:
261
+ - Account credentials
262
+ security:
263
+ - clerkSession: []
264
+ x-account-membership: required
265
+ x-repeat-semantics:
266
+ same_target: idempotent
267
+ secret_returned: false
268
+ responses:
269
+ "200":
270
+ description: Safe terminal credential metadata.
271
+ headers:
272
+ WhooshBang-Diagnostic-Id:
273
+ $ref: "#/components/headers/DiagnosticId"
274
+ content:
275
+ application/json:
276
+ schema:
277
+ $ref: "#/components/schemas/AccountCredential"
278
+ examples:
279
+ revokedAccountCredential:
280
+ externalValue: ../fixtures/core-v1/success/account-credential-revoked.json
281
+ "401":
282
+ $ref: "#/components/responses/Unauthorized"
283
+ "403":
284
+ $ref: "#/components/responses/Forbidden"
285
+ "404":
286
+ $ref: "#/components/responses/NotFound"
287
+ "429":
288
+ $ref: "#/components/responses/RateLimited"
100
289
  /v1/projects:
101
290
  get:
102
291
  operationId: listProjects
@@ -110,6 +299,7 @@ paths:
110
299
  security:
111
300
  - clerkSession: []
112
301
  - bearerGrant: []
302
+ - bearerAccountCredential: []
113
303
  x-required-scopes:
114
304
  - projects:read
115
305
  x-account-membership: required
@@ -211,6 +401,7 @@ paths:
211
401
  security:
212
402
  - clerkSession: []
213
403
  - bearerGrant: []
404
+ - bearerAccountCredential: []
214
405
  x-required-scopes:
215
406
  - projects:read
216
407
  x-account-membership: required
@@ -731,6 +922,7 @@ paths:
731
922
  security:
732
923
  - bearerCredential: []
733
924
  - bearerGrant: []
925
+ - bearerAccountCredential: []
734
926
  x-required-scopes:
735
927
  - messages:write
736
928
  x-idempotency:
@@ -804,6 +996,7 @@ paths:
804
996
  security:
805
997
  - bearerCredential: []
806
998
  - bearerGrant: []
999
+ - bearerAccountCredential: []
807
1000
  x-required-scopes:
808
1001
  - messages:write
809
1002
  x-repeat-semantics:
@@ -1476,6 +1669,7 @@ paths:
1476
1669
  - clerkSession: []
1477
1670
  - bearerCredential: []
1478
1671
  - bearerGrant: []
1672
+ - bearerAccountCredential: []
1479
1673
  x-required-scopes:
1480
1674
  - messages:read
1481
1675
  parameters:
@@ -1515,6 +1709,7 @@ paths:
1515
1709
  - clerkSession: []
1516
1710
  - bearerCredential: []
1517
1711
  - bearerGrant: []
1712
+ - bearerAccountCredential: []
1518
1713
  x-required-scopes:
1519
1714
  - messages:write
1520
1715
  x-idempotency:
@@ -1589,6 +1784,7 @@ paths:
1589
1784
  - clerkSession: []
1590
1785
  - bearerCredential: []
1591
1786
  - bearerGrant: []
1787
+ - bearerAccountCredential: []
1592
1788
  x-required-scopes:
1593
1789
  - messages:read
1594
1790
  responses:
@@ -1618,6 +1814,7 @@ paths:
1618
1814
  - clerkSession: []
1619
1815
  - bearerCredential: []
1620
1816
  - bearerGrant: []
1817
+ - bearerAccountCredential: []
1621
1818
  x-required-scopes:
1622
1819
  - messages:write
1623
1820
  responses:
@@ -1651,6 +1848,7 @@ paths:
1651
1848
  - clerkSession: []
1652
1849
  - bearerCredential: []
1653
1850
  - bearerGrant: []
1851
+ - bearerAccountCredential: []
1654
1852
  x-required-scopes:
1655
1853
  - messages:write
1656
1854
  x-idempotency:
@@ -1723,6 +1921,7 @@ paths:
1723
1921
  - clerkSession: []
1724
1922
  - bearerCredential: []
1725
1923
  - bearerGrant: []
1924
+ - bearerAccountCredential: []
1726
1925
  x-required-scopes:
1727
1926
  - messages:write
1728
1927
  x-repeat-semantics:
@@ -1757,6 +1956,7 @@ paths:
1757
1956
  - clerkSession: []
1758
1957
  - bearerCredential: []
1759
1958
  - bearerGrant: []
1959
+ - bearerAccountCredential: []
1760
1960
  x-required-scopes:
1761
1961
  - messages:read
1762
1962
  parameters:
@@ -1797,6 +1997,7 @@ paths:
1797
1997
  - clerkSession: []
1798
1998
  - bearerCredential: []
1799
1999
  - bearerGrant: []
2000
+ - bearerAccountCredential: []
1800
2001
  x-required-scopes:
1801
2002
  - connections:read
1802
2003
  responses:
@@ -1833,6 +2034,7 @@ paths:
1833
2034
  - clerkSession: []
1834
2035
  - bearerCredential: []
1835
2036
  - bearerGrant: []
2037
+ - bearerAccountCredential: []
1836
2038
  x-required-scopes:
1837
2039
  - connections:read
1838
2040
  parameters:
@@ -1924,6 +2126,7 @@ paths:
1924
2126
  - clerkSession: []
1925
2127
  - bearerCredential: []
1926
2128
  - bearerGrant: []
2129
+ - bearerAccountCredential: []
1927
2130
  x-required-scopes:
1928
2131
  - connections:write
1929
2132
  x-idempotency:
@@ -2004,6 +2207,7 @@ paths:
2004
2207
  - clerkSession: []
2005
2208
  - bearerCredential: []
2006
2209
  - bearerGrant: []
2210
+ - bearerAccountCredential: []
2007
2211
  x-required-scopes:
2008
2212
  - connections:read
2009
2213
  responses:
@@ -2036,6 +2240,7 @@ paths:
2036
2240
  - clerkSession: []
2037
2241
  - bearerCredential: []
2038
2242
  - bearerGrant: []
2243
+ - bearerAccountCredential: []
2039
2244
  x-required-scopes:
2040
2245
  - connections:write
2041
2246
  requestBody:
@@ -2083,6 +2288,7 @@ paths:
2083
2288
  - clerkSession: []
2084
2289
  - bearerCredential: []
2085
2290
  - bearerGrant: []
2291
+ - bearerAccountCredential: []
2086
2292
  x-required-scopes:
2087
2293
  - connections:write
2088
2294
  responses:
@@ -2142,6 +2348,7 @@ paths:
2142
2348
  - clerkSession: []
2143
2349
  - bearerCredential: []
2144
2350
  - bearerGrant: []
2351
+ - bearerAccountCredential: []
2145
2352
  x-required-scopes:
2146
2353
  - connections:write
2147
2354
  responses:
@@ -2195,6 +2402,7 @@ paths:
2195
2402
  - clerkSession: []
2196
2403
  - bearerCredential: []
2197
2404
  - bearerGrant: []
2405
+ - bearerAccountCredential: []
2198
2406
  x-required-scopes:
2199
2407
  - connections:write
2200
2408
  x-idempotency:
@@ -2236,14 +2444,30 @@ paths:
2236
2444
  - $ref: "#/components/parameters/ChannelConnectionId"
2237
2445
  post:
2238
2446
  operationId: restartChannelConnectionSetup
2239
- summary: Start a fresh managed setup on a connection that never finished one
2447
+ summary: Start a fresh setup on a connection that never finished one
2240
2448
  description: |
2241
- Issues a new handoff for a `customer_managed` connection whose guided
2242
- setup expired, failed, or was simply abandoned, and returns the same
2243
- connection carrying a fresh `setup`. The connection is reused rather
2244
- than replaced because it is still `pending`: nothing was ever
2449
+ Issues a new guided setup for a `customer_managed` connection whose
2450
+ setup expired, failed, or was simply abandoned. Nothing was ever
2245
2451
  provisioned under it, no identity was claimed, and no subscriber ever
2246
- consented to anything through it.
2452
+ consented to anything through it, so nothing is lost.
2453
+
2454
+ **Telegram reuses the connection and answers `200`.** A fresh `setup`
2455
+ appears on the same resource.
2456
+
2457
+ **Customer-owned Slack replaces the connection and answers `201`.** The
2458
+ abandoned connection is archived and a new one is returned, carrying a
2459
+ new `app_setup` and a new creation link. The connection cannot be
2460
+ reused, because Slack bakes this deployment's request URLs into the app
2461
+ at the moment it is created and they are not ours to change afterwards:
2462
+ a second setup on one connection would mean two Slack apps answering to
2463
+ one address. **Read `id` on the response** — the connection you were
2464
+ polling is now archived. A Slack app the previous attempt already
2465
+ created is not withdrawn and cannot be; it is the customer's, and they
2466
+ delete it in Slack when they are ready.
2467
+
2468
+ Entering the three app-specific values again is not a restart, and does
2469
+ not need one. `rotate-credential` replaces them on the connection that
2470
+ already exists.
2247
2471
 
2248
2472
  Restart takes no body. The suggested identity recorded when the
2249
2473
  connection was created is what the new attempt proposes again, so a
@@ -2282,6 +2506,7 @@ paths:
2282
2506
  - clerkSession: []
2283
2507
  - bearerCredential: []
2284
2508
  - bearerGrant: []
2509
+ - bearerAccountCredential: []
2285
2510
  x-required-scopes:
2286
2511
  - connections:write
2287
2512
  x-repeat-semantics:
@@ -2300,6 +2525,21 @@ paths:
2300
2525
  examples:
2301
2526
  setupRestarted:
2302
2527
  externalValue: ../fixtures/core-v1/success/channel-connection-setup-restarted.json
2528
+ "201":
2529
+ description: |
2530
+ A replacement connection carrying a fresh setup, for a
2531
+ customer-owned Slack app whose request URLs cannot be re-pointed.
2532
+ The connection named in the request is now archived.
2533
+ headers:
2534
+ WhooshBang-Diagnostic-Id:
2535
+ $ref: "#/components/headers/DiagnosticId"
2536
+ content:
2537
+ application/json:
2538
+ schema:
2539
+ $ref: "#/components/schemas/ChannelConnection"
2540
+ examples:
2541
+ setupReplaced:
2542
+ externalValue: ../fixtures/core-v1/success/channel-connection-slack-customer-pending.json
2303
2543
  "401":
2304
2544
  $ref: "#/components/responses/Unauthorized"
2305
2545
  "403":
@@ -2381,6 +2621,7 @@ paths:
2381
2621
  - clerkSession: []
2382
2622
  - bearerCredential: []
2383
2623
  - bearerGrant: []
2624
+ - bearerAccountCredential: []
2384
2625
  x-required-scopes:
2385
2626
  - connections:write
2386
2627
  requestBody:
@@ -2459,6 +2700,7 @@ paths:
2459
2700
  - clerkSession: []
2460
2701
  - bearerCredential: []
2461
2702
  - bearerGrant: []
2703
+ - bearerAccountCredential: []
2462
2704
  x-required-scopes:
2463
2705
  - connections:write
2464
2706
  responses:
@@ -2522,6 +2764,7 @@ paths:
2522
2764
  - clerkSession: []
2523
2765
  - bearerCredential: []
2524
2766
  - bearerGrant: []
2767
+ - bearerAccountCredential: []
2525
2768
  x-required-scopes:
2526
2769
  - connections:write
2527
2770
  responses:
@@ -2547,6 +2790,262 @@ paths:
2547
2790
  $ref: "#/components/responses/ProviderOutcomeUnknown"
2548
2791
  "503":
2549
2792
  $ref: "#/components/responses/ProviderRetryable"
2793
+ /v1/projects/{project_id}/environments/{environment_id}/channel-connections/{connection_id}/app-manifest:
2794
+ parameters:
2795
+ - $ref: "#/components/parameters/ProjectId"
2796
+ - $ref: "#/components/parameters/EnvironmentId"
2797
+ - $ref: "#/components/parameters/ChannelConnectionId"
2798
+ get:
2799
+ operationId: getChannelConnectionAppManifest
2800
+ summary: Read the generated app configuration a customer-owned setup will create
2801
+ description: |
2802
+ Returns the exact configuration WhooshBang generated for this
2803
+ customer-owned Slack setup — the scopes it will ask for, the request
2804
+ URLs it will point at, the literal manifest document, and the same
2805
+ prefilled creation link the setup already carries.
2806
+
2807
+ It exists so the owner can read what they are about to approve, and a
2808
+ reviewer can check it, without opening Slack or decoding a URL. It
2809
+ carries configuration only: no account, project, or environment, no
2810
+ credential, and no provider-native identifier.
2811
+
2812
+ Only a `customer_managed` Slack connection has one. Every other
2813
+ provider and mode answers `404`, because a manifest they do not have is
2814
+ not a manifest that is empty.
2815
+ tags:
2816
+ - Channel connections
2817
+ security:
2818
+ - clerkSession: []
2819
+ - bearerCredential: []
2820
+ - bearerGrant: []
2821
+ - bearerAccountCredential: []
2822
+ x-required-scopes:
2823
+ - connections:read
2824
+ responses:
2825
+ "200":
2826
+ description: The generated app configuration for exactly this setup.
2827
+ headers:
2828
+ WhooshBang-Diagnostic-Id:
2829
+ $ref: "#/components/headers/DiagnosticId"
2830
+ content:
2831
+ application/json:
2832
+ schema:
2833
+ $ref: "#/components/schemas/CustomerOwnedSlackAppManifest"
2834
+ examples:
2835
+ manifest:
2836
+ externalValue: ../fixtures/core-v1/success/customer-owned-slack-app-manifest.json
2837
+ "401":
2838
+ $ref: "#/components/responses/Unauthorized"
2839
+ "403":
2840
+ $ref: "#/components/responses/Forbidden"
2841
+ "404":
2842
+ $ref: "#/components/responses/NotFound"
2843
+ /v1/projects/{project_id}/environments/{environment_id}/channel-connections/{connection_id}/tests:
2844
+ parameters:
2845
+ - $ref: "#/components/parameters/ProjectId"
2846
+ - $ref: "#/components/parameters/EnvironmentId"
2847
+ - $ref: "#/components/parameters/ChannelConnectionId"
2848
+ get:
2849
+ operationId: listConnectionTests
2850
+ summary: List this connection's recent owner-triggered tests
2851
+ description: |
2852
+ Newest first. This is the audit-safe failure history for one
2853
+ connection: what was tried, when, what came back, and what to do about
2854
+ it. Every entry is safe to render, log, and paste into an issue.
2855
+ tags:
2856
+ - Channel connections
2857
+ security:
2858
+ - clerkSession: []
2859
+ - bearerCredential: []
2860
+ - bearerGrant: []
2861
+ - bearerAccountCredential: []
2862
+ x-required-scopes:
2863
+ - connections:read
2864
+ parameters:
2865
+ - $ref: "#/components/parameters/ListAfterCursor"
2866
+ - $ref: "#/components/parameters/ListPageLimit"
2867
+ - $ref: "#/components/parameters/PageNumber"
2868
+ responses:
2869
+ "200":
2870
+ description: Tests placed against exactly this connection.
2871
+ headers:
2872
+ WhooshBang-Diagnostic-Id:
2873
+ $ref: "#/components/headers/DiagnosticId"
2874
+ content:
2875
+ application/json:
2876
+ schema:
2877
+ $ref: "#/components/schemas/ConnectionTestCollection"
2878
+ examples:
2879
+ tests:
2880
+ externalValue: ../fixtures/core-v1/success/connection-test-collection.json
2881
+ "401":
2882
+ $ref: "#/components/responses/Unauthorized"
2883
+ "403":
2884
+ $ref: "#/components/responses/Forbidden"
2885
+ "404":
2886
+ $ref: "#/components/responses/NotFound"
2887
+ post:
2888
+ operationId: createConnectionTest
2889
+ summary: Prove this exact connection still works
2890
+ description: |
2891
+ Runs one test against one connection, on demand, and answers with what
2892
+ it observed rather than with a claim.
2893
+
2894
+ Available on any Slack connection, whether the app is one the customer
2895
+ owns or the one WhooshBang operates. Every other provider and mode is
2896
+ refused rather than reporting a pass it never ran.
2897
+
2898
+ **A test addresses the workspace member who authorized this exact
2899
+ connection, and nobody else.** For an app the customer owns that is the
2900
+ person who installed it, once, for one connection. The
2901
+ WhooshBang-operated app's installation is shared across tenants, so
2902
+ "whoever installed the app" is not necessarily anybody the calling
2903
+ tenant named; what is recorded instead is the member who approved this
2904
+ environment's own connection, during its own authorization, and each
2905
+ later authorization replaces it. One tenant therefore cannot cause a
2906
+ message to somebody another tenant authorized.
2907
+
2908
+ `outbound_notification` sends one visible private message through this
2909
+ exact identity to that member, and settles when the provider accepts
2910
+ it. Nobody else can be addressed: a test cannot reach a channel, and it
2911
+ cannot reach a subscriber who has not authorized anything.
2912
+
2913
+ `signed_interaction` sends that person a message with one button and
2914
+ then waits. It settles when the provider calls this deployment's
2915
+ interactivity URL and the signature over the untouched body verifies
2916
+ against the secret this connection custodies — the only proof that the
2917
+ signing secret, the request URL, and public reachability are all
2918
+ correct at once. A window that closes with nothing arriving settles as
2919
+ `expired`, which says nobody pressed it, and a request that arrives and
2920
+ does not verify settles as `failed` with `unverified_request_received`.
2921
+
2922
+ The response is the placed test. An `outbound_notification` is usually
2923
+ already settled when it returns; a `signed_interaction` is `pending`
2924
+ until somebody presses the button, so read it again or list this
2925
+ connection's tests.
2926
+
2927
+ **A provider failure is an answer, not a refusal.** If the connection
2928
+ has not finished setup, or its grant is unavailable, or Slack refuses,
2929
+ rate-limits, or cannot be reached, the test is **recorded** and answers
2930
+ `201` carrying `status: failed`, a `failure_code` and a
2931
+ `recovery_action`. There is no `502` or `503` on this operation, and
2932
+ that is deliberate: a diagnostic that leaves no trace is the one thing
2933
+ an audit-safe failure history cannot have, so the failure goes in the
2934
+ history rather than into a problem document nobody keeps.
2935
+
2936
+ Three things are refused outright, because none describes a test that
2937
+ ran: the connection is archived, it is not a Slack connection, or it is
2938
+ a WhooshBang-operated Slack connection whose authorization has been
2939
+ revoked — `idempotency_conflict` 409, `invalid_connection_transition`
2940
+ at `/`. A connection that has never recorded who authorized it is not
2941
+ refused: it is a recorded failure with
2942
+ `verification_target_unknown`, because there is nobody a test could
2943
+ honestly address.
2944
+
2945
+ A test never carries customer notification content, never counts as a
2946
+ delivery to a subscriber, and never changes what any subscriber
2947
+ receives.
2948
+ tags:
2949
+ - Channel connections
2950
+ security:
2951
+ - clerkSession: []
2952
+ - bearerCredential: []
2953
+ - bearerGrant: []
2954
+ - bearerAccountCredential: []
2955
+ x-required-scopes:
2956
+ - connections:write
2957
+ x-idempotency:
2958
+ required: true
2959
+ retention_seconds: 604800
2960
+ scope:
2961
+ - authenticated_environment
2962
+ - operation_id
2963
+ - key
2964
+ equivalence: exact_request_body
2965
+ replay_retention_extends: false
2966
+ requestBody:
2967
+ required: true
2968
+ content:
2969
+ application/json:
2970
+ schema:
2971
+ $ref: "#/components/schemas/CreateConnectionTestRequest"
2972
+ examples:
2973
+ signedInteraction:
2974
+ externalValue: ../fixtures/core-v1/requests/create-connection-test.json
2975
+ responses:
2976
+ "201":
2977
+ description: The placed test, settled if it could settle immediately.
2978
+ headers:
2979
+ WhooshBang-Diagnostic-Id:
2980
+ $ref: "#/components/headers/DiagnosticId"
2981
+ content:
2982
+ application/json:
2983
+ schema:
2984
+ $ref: "#/components/schemas/ConnectionTest"
2985
+ examples:
2986
+ pending:
2987
+ externalValue: ../fixtures/core-v1/success/connection-test-pending.json
2988
+ "200":
2989
+ description: The equivalent test an idempotent replay already placed.
2990
+ headers:
2991
+ WhooshBang-Diagnostic-Id:
2992
+ $ref: "#/components/headers/DiagnosticId"
2993
+ content:
2994
+ application/json:
2995
+ schema:
2996
+ $ref: "#/components/schemas/ConnectionTest"
2997
+ "400":
2998
+ $ref: "#/components/responses/BadRequest"
2999
+ "401":
3000
+ $ref: "#/components/responses/Unauthorized"
3001
+ "403":
3002
+ $ref: "#/components/responses/Forbidden"
3003
+ "404":
3004
+ $ref: "#/components/responses/NotFound"
3005
+ "409":
3006
+ $ref: "#/components/responses/Conflict"
3007
+ /v1/projects/{project_id}/environments/{environment_id}/channel-connections/{connection_id}/tests/{test_id}:
3008
+ parameters:
3009
+ - $ref: "#/components/parameters/ProjectId"
3010
+ - $ref: "#/components/parameters/EnvironmentId"
3011
+ - $ref: "#/components/parameters/ChannelConnectionId"
3012
+ - $ref: "#/components/parameters/ConnectionTestId"
3013
+ get:
3014
+ operationId: getConnectionTest
3015
+ summary: Read one owner-triggered connection test
3016
+ description: |
3017
+ The durable answer to one test. A `signed_interaction` is read again
3018
+ here until it settles; a pending test whose window has closed reads as
3019
+ `expired` on the way out rather than waiting for a sweep, so the status
3020
+ the owner sees is the one they actually have.
3021
+ tags:
3022
+ - Channel connections
3023
+ security:
3024
+ - clerkSession: []
3025
+ - bearerCredential: []
3026
+ - bearerGrant: []
3027
+ - bearerAccountCredential: []
3028
+ x-required-scopes:
3029
+ - connections:read
3030
+ responses:
3031
+ "200":
3032
+ description: The exact test.
3033
+ headers:
3034
+ WhooshBang-Diagnostic-Id:
3035
+ $ref: "#/components/headers/DiagnosticId"
3036
+ content:
3037
+ application/json:
3038
+ schema:
3039
+ $ref: "#/components/schemas/ConnectionTest"
3040
+ examples:
3041
+ succeeded:
3042
+ externalValue: ../fixtures/core-v1/success/connection-test-succeeded.json
3043
+ "401":
3044
+ $ref: "#/components/responses/Unauthorized"
3045
+ "403":
3046
+ $ref: "#/components/responses/Forbidden"
3047
+ "404":
3048
+ $ref: "#/components/responses/NotFound"
2550
3049
  /v1/projects/{project_id}/environments/{environment_id}/notifier-connections:
2551
3050
  parameters:
2552
3051
  - $ref: "#/components/parameters/ProjectId"
@@ -2569,6 +3068,7 @@ paths:
2569
3068
  - clerkSession: []
2570
3069
  - bearerCredential: []
2571
3070
  - bearerGrant: []
3071
+ - bearerAccountCredential: []
2572
3072
  x-required-scopes:
2573
3073
  - connections:read
2574
3074
  parameters:
@@ -2633,6 +3133,7 @@ paths:
2633
3133
  - clerkSession: []
2634
3134
  - bearerCredential: []
2635
3135
  - bearerGrant: []
3136
+ - bearerAccountCredential: []
2636
3137
  x-required-scopes:
2637
3138
  - connections:write
2638
3139
  requestBody:
@@ -2695,6 +3196,7 @@ paths:
2695
3196
  - clerkSession: []
2696
3197
  - bearerCredential: []
2697
3198
  - bearerGrant: []
3199
+ - bearerAccountCredential: []
2698
3200
  x-required-scopes:
2699
3201
  - connections:write
2700
3202
  responses:
@@ -2850,6 +3352,7 @@ paths:
2850
3352
  - clerkSession: []
2851
3353
  - bearerGrant: []
2852
3354
  - bearerCredential: []
3355
+ - bearerAccountCredential: []
2853
3356
  x-required-scopes:
2854
3357
  - projects:read
2855
3358
  x-account-membership: required
@@ -2885,6 +3388,7 @@ paths:
2885
3388
  - clerkSession: []
2886
3389
  - bearerGrant: []
2887
3390
  - bearerCredential: []
3391
+ - bearerAccountCredential: []
2888
3392
  x-required-scopes:
2889
3393
  - projects:write
2890
3394
  x-account-membership: required
@@ -3735,6 +4239,7 @@ paths:
3735
4239
  - Subscription links
3736
4240
  security:
3737
4241
  - bearerGrant: []
4242
+ - bearerAccountCredential: []
3738
4243
  x-required-scopes:
3739
4244
  - subscriptions:write
3740
4245
  x-idempotency:
@@ -3794,6 +4299,7 @@ paths:
3794
4299
  - Subscription links
3795
4300
  security:
3796
4301
  - bearerGrant: []
4302
+ - bearerAccountCredential: []
3797
4303
  x-required-scopes:
3798
4304
  - subscriptions:read
3799
4305
  responses:
@@ -3833,6 +4339,7 @@ paths:
3833
4339
  - Messages
3834
4340
  security:
3835
4341
  - bearerGrant: []
4342
+ - bearerAccountCredential: []
3836
4343
  x-required-scopes:
3837
4344
  - messages:write
3838
4345
  x-idempotency:
@@ -3897,6 +4404,7 @@ paths:
3897
4404
  - Messages
3898
4405
  security:
3899
4406
  - bearerGrant: []
4407
+ - bearerAccountCredential: []
3900
4408
  x-required-scopes:
3901
4409
  - messages:read
3902
4410
  responses:
@@ -3939,6 +4447,7 @@ paths:
3939
4447
  - Messages
3940
4448
  security:
3941
4449
  - bearerGrant: []
4450
+ - bearerAccountCredential: []
3942
4451
  x-required-scopes:
3943
4452
  - messages:read
3944
4453
  responses:
@@ -3978,6 +4487,7 @@ paths:
3978
4487
  - Machine clients
3979
4488
  security:
3980
4489
  - bearerGrant: []
4490
+ - bearerAccountCredential: []
3981
4491
  x-required-scopes:
3982
4492
  - machine-clients:write
3983
4493
  x-idempotency:
@@ -4024,6 +4534,74 @@ paths:
4024
4534
  $ref: "#/components/responses/Unprocessable"
4025
4535
  "429":
4026
4536
  $ref: "#/components/responses/RateLimited"
4537
+ /v1/projects/{project_id}/environments/{environment_id}/machine-clients/{machine_client_id}/credentials:
4538
+ parameters:
4539
+ - $ref: "#/components/parameters/ProjectId"
4540
+ - $ref: "#/components/parameters/EnvironmentId"
4541
+ - $ref: "#/components/parameters/MachineClientId"
4542
+ post:
4543
+ operationId: registerMachineCredentialInEnvironment
4544
+ summary: Register a machine-credential digest in a named project environment
4545
+ description: |
4546
+ The environment-scoped form of `registerMachineCredential`. Registers
4547
+ only the credential ID and SHA-256 digest; the path only names where the
4548
+ owning machine client lives. Request and response shapes are that
4549
+ operation's exactly, including its published examples.
4550
+ tags:
4551
+ - Machine clients
4552
+ security:
4553
+ - bearerGrant: []
4554
+ - bearerAccountCredential: []
4555
+ x-required-scopes:
4556
+ - machine-clients:write
4557
+ x-idempotency:
4558
+ required: true
4559
+ retention_seconds: 604800
4560
+ scope:
4561
+ - authenticated_environment
4562
+ - operation_id
4563
+ - key
4564
+ equivalence: validated_request_after_documented_defaults
4565
+ replay_retention_extends: false
4566
+ parameters:
4567
+ - $ref: "#/components/parameters/IdempotencyKey"
4568
+ requestBody:
4569
+ required: true
4570
+ content:
4571
+ application/json:
4572
+ schema:
4573
+ $ref: "#/components/schemas/RegisterMachineCredentialRequest"
4574
+ responses:
4575
+ "200":
4576
+ description: Existing safe credential metadata on an equivalent registration replay; never secret or digest.
4577
+ headers:
4578
+ WhooshBang-Diagnostic-Id:
4579
+ $ref: "#/components/headers/DiagnosticId"
4580
+ content:
4581
+ application/json:
4582
+ schema:
4583
+ $ref: "#/components/schemas/MachineCredential"
4584
+ "201":
4585
+ description: Newly registered safe credential metadata; never secret or digest.
4586
+ headers:
4587
+ WhooshBang-Diagnostic-Id:
4588
+ $ref: "#/components/headers/DiagnosticId"
4589
+ content:
4590
+ application/json:
4591
+ schema:
4592
+ $ref: "#/components/schemas/MachineCredential"
4593
+ "400":
4594
+ $ref: "#/components/responses/BadRequest"
4595
+ "401":
4596
+ $ref: "#/components/responses/Unauthorized"
4597
+ "403":
4598
+ $ref: "#/components/responses/Forbidden"
4599
+ "404":
4600
+ $ref: "#/components/responses/NotFound"
4601
+ "409":
4602
+ $ref: "#/components/responses/Conflict"
4603
+ "429":
4604
+ $ref: "#/components/responses/RateLimited"
4027
4605
  /v1/projects/{project_id}/environments/{environment_id}/capabilities:
4028
4606
  parameters:
4029
4607
  - $ref: "#/components/parameters/ProjectId"
@@ -4039,6 +4617,7 @@ paths:
4039
4617
  - Capabilities
4040
4618
  security:
4041
4619
  - bearerGrant: []
4620
+ - bearerAccountCredential: []
4042
4621
  x-required-scopes:
4043
4622
  - capabilities:read
4044
4623
  responses:
@@ -4081,6 +4660,7 @@ paths:
4081
4660
  - clerkSession: []
4082
4661
  - bearerCredential: []
4083
4662
  - bearerGrant: []
4663
+ - bearerAccountCredential: []
4084
4664
  x-required-scopes:
4085
4665
  - subscriptions:write
4086
4666
  x-idempotency:
@@ -4144,6 +4724,7 @@ paths:
4144
4724
  - clerkSession: []
4145
4725
  - bearerCredential: []
4146
4726
  - bearerGrant: []
4727
+ - bearerAccountCredential: []
4147
4728
  x-required-scopes:
4148
4729
  - subscriptions:read
4149
4730
  responses:
@@ -4176,6 +4757,7 @@ paths:
4176
4757
  - clerkSession: []
4177
4758
  - bearerCredential: []
4178
4759
  - bearerGrant: []
4760
+ - bearerAccountCredential: []
4179
4761
  x-required-scopes:
4180
4762
  - subscriptions:read
4181
4763
  parameters:
@@ -4221,6 +4803,7 @@ paths:
4221
4803
  - clerkSession: []
4222
4804
  - bearerCredential: []
4223
4805
  - bearerGrant: []
4806
+ - bearerAccountCredential: []
4224
4807
  x-required-scopes:
4225
4808
  - subscriptions:write
4226
4809
  x-idempotency:
@@ -4285,6 +4868,7 @@ paths:
4285
4868
  - clerkSession: []
4286
4869
  - bearerCredential: []
4287
4870
  - bearerGrant: []
4871
+ - bearerAccountCredential: []
4288
4872
  x-required-scopes:
4289
4873
  - subscriptions:read
4290
4874
  responses:
@@ -4312,6 +4896,7 @@ paths:
4312
4896
  - clerkSession: []
4313
4897
  - bearerCredential: []
4314
4898
  - bearerGrant: []
4899
+ - bearerAccountCredential: []
4315
4900
  x-required-scopes:
4316
4901
  - subscriptions:write
4317
4902
  requestBody:
@@ -4350,6 +4935,7 @@ paths:
4350
4935
  - clerkSession: []
4351
4936
  - bearerCredential: []
4352
4937
  - bearerGrant: []
4938
+ - bearerAccountCredential: []
4353
4939
  x-required-scopes:
4354
4940
  - subscriptions:write
4355
4941
  responses:
@@ -4390,6 +4976,7 @@ paths:
4390
4976
  - clerkSession: []
4391
4977
  - bearerCredential: []
4392
4978
  - bearerGrant: []
4979
+ - bearerAccountCredential: []
4393
4980
  x-required-scopes:
4394
4981
  - subscriptions:read
4395
4982
  parameters:
@@ -4457,6 +5044,7 @@ paths:
4457
5044
  - clerkSession: []
4458
5045
  - bearerCredential: []
4459
5046
  - bearerGrant: []
5047
+ - bearerAccountCredential: []
4460
5048
  x-required-scopes:
4461
5049
  - subscriptions:write
4462
5050
  responses:
@@ -4490,6 +5078,7 @@ paths:
4490
5078
  - clerkSession: []
4491
5079
  - bearerCredential: []
4492
5080
  - bearerGrant: []
5081
+ - bearerAccountCredential: []
4493
5082
  x-required-scopes:
4494
5083
  - subscriptions:write
4495
5084
  responses:
@@ -4529,6 +5118,7 @@ paths:
4529
5118
  - clerkSession: []
4530
5119
  - bearerCredential: []
4531
5120
  - bearerGrant: []
5121
+ - bearerAccountCredential: []
4532
5122
  x-required-scopes:
4533
5123
  - messages:write
4534
5124
  x-idempotency:
@@ -4593,6 +5183,7 @@ paths:
4593
5183
  - clerkSession: []
4594
5184
  - bearerCredential: []
4595
5185
  - bearerGrant: []
5186
+ - bearerAccountCredential: []
4596
5187
  x-required-scopes:
4597
5188
  - messages:read
4598
5189
  responses:
@@ -4631,8 +5222,28 @@ components:
4631
5222
  consenting account member. It selects exactly one account and carries
4632
5223
  the scopes that member consented to, and never a project: an operation
4633
5224
  names its project and environment in the path, and the service checks
4634
- both against the granting person's membership before acting. It can
4635
- hold account-level scopes, which no credential can.
5225
+ both against the granting person's membership before acting. A project
5226
+ credential can name no project but its own; an account credential names
5227
+ one per call the same way this does.
5228
+ bearerAccountCredential:
5229
+ type: http
5230
+ scheme: bearer
5231
+ bearerFormat: wb_ac1.acred_<16-byte-base64url>.<32-byte-base64url-secret>
5232
+ description: |
5233
+ Selects exactly one account and nothing below it. It names no project
5234
+ and no environment, so it authenticates only operations whose path does,
5235
+ and its authority there is the intersection of its scopes with the
5236
+ project-credential vocabulary — never wider than a project credential
5237
+ would have been for the same project environment. A path naming a
5238
+ project outside its account is refused with `credential_account_mismatch`
5239
+ rather than a bare scope failure. `account:read` is the one scope it can
5240
+ hold that a project credential cannot, and it authorizes only the
5241
+ account's project directory: listing the account's projects and reading
5242
+ one, which is the account-wide question a project credential cannot ask
5243
+ and the reason a `--project <slug>` selector can work at all. It is
5244
+ required *in addition to* each of those operations' own
5245
+ `x-required-scopes`, never instead of them.
5246
+ Credentials cannot be read after creation.
4636
5247
  bearerCredential:
4637
5248
  type: http
4638
5249
  scheme: bearer
@@ -4701,6 +5312,13 @@ components:
4701
5312
  description: Canonical opaque project credential identity; never a readable secret.
4702
5313
  schema:
4703
5314
  $ref: "#/components/schemas/ApiCredentialId"
5315
+ AccountCredentialId:
5316
+ name: account_credential_id
5317
+ in: path
5318
+ required: true
5319
+ description: Canonical opaque account credential identity; never a readable secret.
5320
+ schema:
5321
+ $ref: "#/components/schemas/AccountCredentialId"
4704
5322
  ApiCredentialAfterCursor:
4705
5323
  name: after
4706
5324
  in: query
@@ -4828,6 +5446,13 @@ components:
4828
5446
  description: Opaque connection identity; never authorization.
4829
5447
  schema:
4830
5448
  $ref: "#/components/schemas/OpaqueIdentifier"
5449
+ ConnectionTestId:
5450
+ name: test_id
5451
+ in: path
5452
+ required: true
5453
+ description: Opaque identity of one owner-triggered connection test; never authorization.
5454
+ schema:
5455
+ $ref: "#/components/schemas/OpaqueIdentifier"
4831
5456
  NotifierId:
4832
5457
  name: notifier_id
4833
5458
  in: path
@@ -4922,6 +5547,24 @@ components:
4922
5547
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/UpdateChannelConnectionRequest
4923
5548
  RotateChannelConnectionCredentialRequest:
4924
5549
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/RotateChannelConnectionCredentialRequest
5550
+ ConnectionTestKind:
5551
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestKind
5552
+ ConnectionTestRecoveryAction:
5553
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestRecoveryAction
5554
+ ConnectionTestStatus:
5555
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestStatus
5556
+ ConnectionTestFailureCode:
5557
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestFailureCode
5558
+ ConnectionTestEvidence:
5559
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestEvidence
5560
+ ConnectionTest:
5561
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTest
5562
+ ConnectionTestCollection:
5563
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/ConnectionTestCollection
5564
+ CreateConnectionTestRequest:
5565
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/CreateConnectionTestRequest
5566
+ CustomerOwnedSlackAppManifest:
5567
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/CustomerOwnedSlackAppManifest
4925
5568
  NotifierConnectionRoute:
4926
5569
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/NotifierConnectionRoute
4927
5570
  NotifierConnectionCollection:
@@ -4956,6 +5599,20 @@ components:
4956
5599
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/UpdateRecipientCopyOverrideRequest
4957
5600
  CreateApiCredentialRequest:
4958
5601
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/CreateApiCredentialRequest
5602
+ CreateAccountCredentialRequest:
5603
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/CreateAccountCredentialRequest
5604
+ RotateAccountCredentialRequest:
5605
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/RotateAccountCredentialRequest
5606
+ AccountCredentialId:
5607
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/AccountCredentialId
5608
+ AccountCredential:
5609
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/AccountCredential
5610
+ AccountCredentialCollection:
5611
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/AccountCredentialCollection
5612
+ AccountCredentialSecretReveal:
5613
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/AccountCredentialSecretReveal
5614
+ AccountCredentialRotation:
5615
+ $ref: ../schemas/whooshbang-v1.schema.json#/$defs/AccountCredentialRotation
4959
5616
  RotateApiCredentialRequest:
4960
5617
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/RotateApiCredentialRequest
4961
5618
  ApiCredentialId: