@whooshbang/contracts 1.0.0-rc.19 → 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 +44 -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 +25421 -15666
  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 +132 -31
  11. package/dist/generated/validators.js.map +1 -1
  12. package/dist/generated/whooshbang-v1.d.ts +836 -9
  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 +1623 -99
  87. package/openapi/whooshbang-v1.yaml +687 -14
  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 +798 -8
@@ -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.19
4
+ x-contract-version: 1.0.0-rc.21
5
5
  info:
6
6
  title: WhooshBang API
7
- version: 1.0.0-rc.19
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
@@ -252,6 +443,7 @@ paths:
252
443
  security:
253
444
  - clerkSession: []
254
445
  - bearerGrant: []
446
+ - bearerCredential: []
255
447
  x-required-scopes:
256
448
  - projects:read
257
449
  x-account-membership: required
@@ -309,6 +501,7 @@ paths:
309
501
  security:
310
502
  - clerkSession: []
311
503
  - bearerGrant: []
504
+ - bearerCredential: []
312
505
  x-required-scopes:
313
506
  - projects:write
314
507
  x-account-membership: required
@@ -350,6 +543,7 @@ paths:
350
543
  security:
351
544
  - clerkSession: []
352
545
  - bearerGrant: []
546
+ - bearerCredential: []
353
547
  x-required-scopes:
354
548
  - projects:write
355
549
  x-account-membership: required
@@ -728,6 +922,7 @@ paths:
728
922
  security:
729
923
  - bearerCredential: []
730
924
  - bearerGrant: []
925
+ - bearerAccountCredential: []
731
926
  x-required-scopes:
732
927
  - messages:write
733
928
  x-idempotency:
@@ -801,6 +996,7 @@ paths:
801
996
  security:
802
997
  - bearerCredential: []
803
998
  - bearerGrant: []
999
+ - bearerAccountCredential: []
804
1000
  x-required-scopes:
805
1001
  - messages:write
806
1002
  x-repeat-semantics:
@@ -1473,6 +1669,7 @@ paths:
1473
1669
  - clerkSession: []
1474
1670
  - bearerCredential: []
1475
1671
  - bearerGrant: []
1672
+ - bearerAccountCredential: []
1476
1673
  x-required-scopes:
1477
1674
  - messages:read
1478
1675
  parameters:
@@ -1512,6 +1709,7 @@ paths:
1512
1709
  - clerkSession: []
1513
1710
  - bearerCredential: []
1514
1711
  - bearerGrant: []
1712
+ - bearerAccountCredential: []
1515
1713
  x-required-scopes:
1516
1714
  - messages:write
1517
1715
  x-idempotency:
@@ -1586,6 +1784,7 @@ paths:
1586
1784
  - clerkSession: []
1587
1785
  - bearerCredential: []
1588
1786
  - bearerGrant: []
1787
+ - bearerAccountCredential: []
1589
1788
  x-required-scopes:
1590
1789
  - messages:read
1591
1790
  responses:
@@ -1615,6 +1814,7 @@ paths:
1615
1814
  - clerkSession: []
1616
1815
  - bearerCredential: []
1617
1816
  - bearerGrant: []
1817
+ - bearerAccountCredential: []
1618
1818
  x-required-scopes:
1619
1819
  - messages:write
1620
1820
  responses:
@@ -1648,6 +1848,7 @@ paths:
1648
1848
  - clerkSession: []
1649
1849
  - bearerCredential: []
1650
1850
  - bearerGrant: []
1851
+ - bearerAccountCredential: []
1651
1852
  x-required-scopes:
1652
1853
  - messages:write
1653
1854
  x-idempotency:
@@ -1720,6 +1921,7 @@ paths:
1720
1921
  - clerkSession: []
1721
1922
  - bearerCredential: []
1722
1923
  - bearerGrant: []
1924
+ - bearerAccountCredential: []
1723
1925
  x-required-scopes:
1724
1926
  - messages:write
1725
1927
  x-repeat-semantics:
@@ -1754,6 +1956,7 @@ paths:
1754
1956
  - clerkSession: []
1755
1957
  - bearerCredential: []
1756
1958
  - bearerGrant: []
1959
+ - bearerAccountCredential: []
1757
1960
  x-required-scopes:
1758
1961
  - messages:read
1759
1962
  parameters:
@@ -1794,6 +1997,7 @@ paths:
1794
1997
  - clerkSession: []
1795
1998
  - bearerCredential: []
1796
1999
  - bearerGrant: []
2000
+ - bearerAccountCredential: []
1797
2001
  x-required-scopes:
1798
2002
  - connections:read
1799
2003
  responses:
@@ -1830,6 +2034,7 @@ paths:
1830
2034
  - clerkSession: []
1831
2035
  - bearerCredential: []
1832
2036
  - bearerGrant: []
2037
+ - bearerAccountCredential: []
1833
2038
  x-required-scopes:
1834
2039
  - connections:read
1835
2040
  parameters:
@@ -1921,6 +2126,7 @@ paths:
1921
2126
  - clerkSession: []
1922
2127
  - bearerCredential: []
1923
2128
  - bearerGrant: []
2129
+ - bearerAccountCredential: []
1924
2130
  x-required-scopes:
1925
2131
  - connections:write
1926
2132
  x-idempotency:
@@ -2001,6 +2207,7 @@ paths:
2001
2207
  - clerkSession: []
2002
2208
  - bearerCredential: []
2003
2209
  - bearerGrant: []
2210
+ - bearerAccountCredential: []
2004
2211
  x-required-scopes:
2005
2212
  - connections:read
2006
2213
  responses:
@@ -2033,6 +2240,7 @@ paths:
2033
2240
  - clerkSession: []
2034
2241
  - bearerCredential: []
2035
2242
  - bearerGrant: []
2243
+ - bearerAccountCredential: []
2036
2244
  x-required-scopes:
2037
2245
  - connections:write
2038
2246
  requestBody:
@@ -2080,6 +2288,7 @@ paths:
2080
2288
  - clerkSession: []
2081
2289
  - bearerCredential: []
2082
2290
  - bearerGrant: []
2291
+ - bearerAccountCredential: []
2083
2292
  x-required-scopes:
2084
2293
  - connections:write
2085
2294
  responses:
@@ -2139,6 +2348,7 @@ paths:
2139
2348
  - clerkSession: []
2140
2349
  - bearerCredential: []
2141
2350
  - bearerGrant: []
2351
+ - bearerAccountCredential: []
2142
2352
  x-required-scopes:
2143
2353
  - connections:write
2144
2354
  responses:
@@ -2192,6 +2402,7 @@ paths:
2192
2402
  - clerkSession: []
2193
2403
  - bearerCredential: []
2194
2404
  - bearerGrant: []
2405
+ - bearerAccountCredential: []
2195
2406
  x-required-scopes:
2196
2407
  - connections:write
2197
2408
  x-idempotency:
@@ -2233,14 +2444,30 @@ paths:
2233
2444
  - $ref: "#/components/parameters/ChannelConnectionId"
2234
2445
  post:
2235
2446
  operationId: restartChannelConnectionSetup
2236
- 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
2237
2448
  description: |
2238
- Issues a new handoff for a `customer_managed` connection whose guided
2239
- setup expired, failed, or was simply abandoned, and returns the same
2240
- connection carrying a fresh `setup`. The connection is reused rather
2241
- 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
2242
2451
  provisioned under it, no identity was claimed, and no subscriber ever
2243
- 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.
2244
2471
 
2245
2472
  Restart takes no body. The suggested identity recorded when the
2246
2473
  connection was created is what the new attempt proposes again, so a
@@ -2279,6 +2506,7 @@ paths:
2279
2506
  - clerkSession: []
2280
2507
  - bearerCredential: []
2281
2508
  - bearerGrant: []
2509
+ - bearerAccountCredential: []
2282
2510
  x-required-scopes:
2283
2511
  - connections:write
2284
2512
  x-repeat-semantics:
@@ -2297,6 +2525,21 @@ paths:
2297
2525
  examples:
2298
2526
  setupRestarted:
2299
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
2300
2543
  "401":
2301
2544
  $ref: "#/components/responses/Unauthorized"
2302
2545
  "403":
@@ -2378,6 +2621,7 @@ paths:
2378
2621
  - clerkSession: []
2379
2622
  - bearerCredential: []
2380
2623
  - bearerGrant: []
2624
+ - bearerAccountCredential: []
2381
2625
  x-required-scopes:
2382
2626
  - connections:write
2383
2627
  requestBody:
@@ -2456,6 +2700,7 @@ paths:
2456
2700
  - clerkSession: []
2457
2701
  - bearerCredential: []
2458
2702
  - bearerGrant: []
2703
+ - bearerAccountCredential: []
2459
2704
  x-required-scopes:
2460
2705
  - connections:write
2461
2706
  responses:
@@ -2519,6 +2764,7 @@ paths:
2519
2764
  - clerkSession: []
2520
2765
  - bearerCredential: []
2521
2766
  - bearerGrant: []
2767
+ - bearerAccountCredential: []
2522
2768
  x-required-scopes:
2523
2769
  - connections:write
2524
2770
  responses:
@@ -2544,6 +2790,262 @@ paths:
2544
2790
  $ref: "#/components/responses/ProviderOutcomeUnknown"
2545
2791
  "503":
2546
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"
2547
3049
  /v1/projects/{project_id}/environments/{environment_id}/notifier-connections:
2548
3050
  parameters:
2549
3051
  - $ref: "#/components/parameters/ProjectId"
@@ -2566,6 +3068,7 @@ paths:
2566
3068
  - clerkSession: []
2567
3069
  - bearerCredential: []
2568
3070
  - bearerGrant: []
3071
+ - bearerAccountCredential: []
2569
3072
  x-required-scopes:
2570
3073
  - connections:read
2571
3074
  parameters:
@@ -2630,6 +3133,7 @@ paths:
2630
3133
  - clerkSession: []
2631
3134
  - bearerCredential: []
2632
3135
  - bearerGrant: []
3136
+ - bearerAccountCredential: []
2633
3137
  x-required-scopes:
2634
3138
  - connections:write
2635
3139
  requestBody:
@@ -2692,6 +3196,7 @@ paths:
2692
3196
  - clerkSession: []
2693
3197
  - bearerCredential: []
2694
3198
  - bearerGrant: []
3199
+ - bearerAccountCredential: []
2695
3200
  x-required-scopes:
2696
3201
  - connections:write
2697
3202
  responses:
@@ -2724,6 +3229,7 @@ paths:
2724
3229
  security:
2725
3230
  - clerkSession: []
2726
3231
  - bearerGrant: []
3232
+ - bearerCredential: []
2727
3233
  x-required-scopes:
2728
3234
  - projects:read
2729
3235
  x-account-membership: required
@@ -2751,6 +3257,7 @@ paths:
2751
3257
  security:
2752
3258
  - clerkSession: []
2753
3259
  - bearerGrant: []
3260
+ - bearerCredential: []
2754
3261
  x-required-scopes:
2755
3262
  - projects:write
2756
3263
  x-account-membership: required
@@ -2795,6 +3302,7 @@ paths:
2795
3302
  security:
2796
3303
  - clerkSession: []
2797
3304
  - bearerGrant: []
3305
+ - bearerCredential: []
2798
3306
  x-required-scopes:
2799
3307
  - projects:write
2800
3308
  x-account-membership: required
@@ -2842,6 +3350,11 @@ paths:
2842
3350
  - Recipient experience
2843
3351
  security:
2844
3352
  - clerkSession: []
3353
+ - bearerGrant: []
3354
+ - bearerCredential: []
3355
+ - bearerAccountCredential: []
3356
+ x-required-scopes:
3357
+ - projects:read
2845
3358
  x-account-membership: required
2846
3359
  responses:
2847
3360
  "200":
@@ -2863,14 +3376,21 @@ paths:
2863
3376
  operationId: updateEnvironmentRecipientExperience
2864
3377
  summary: Replace one environment's enabled channels and exact browser policy
2865
3378
  description: |
2866
- Origins are exact scheme/host/port values. Return destinations are
2867
- registered developer keys resolving to exact URLs. Wildcards,
2868
- templates, arbitrary recipient-time URLs, and channels not backed by
2869
- an offered compatible connection are refused.
3379
+ Origins are exact scheme/host/port values, written in any spelling that
3380
+ means that same origin: a trailing slash, an uppercase host, and an
3381
+ explicitly written default port are accepted and stored in canonical
3382
+ form. Return destinations are registered developer keys resolving to
3383
+ exact URLs. Wildcards, templates, arbitrary recipient-time URLs, and
3384
+ channels not backed by an offered compatible connection are refused.
2870
3385
  tags:
2871
3386
  - Recipient experience
2872
3387
  security:
2873
3388
  - clerkSession: []
3389
+ - bearerGrant: []
3390
+ - bearerCredential: []
3391
+ - bearerAccountCredential: []
3392
+ x-required-scopes:
3393
+ - projects:write
2874
3394
  x-account-membership: required
2875
3395
  requestBody:
2876
3396
  required: true
@@ -3719,6 +4239,7 @@ paths:
3719
4239
  - Subscription links
3720
4240
  security:
3721
4241
  - bearerGrant: []
4242
+ - bearerAccountCredential: []
3722
4243
  x-required-scopes:
3723
4244
  - subscriptions:write
3724
4245
  x-idempotency:
@@ -3778,6 +4299,7 @@ paths:
3778
4299
  - Subscription links
3779
4300
  security:
3780
4301
  - bearerGrant: []
4302
+ - bearerAccountCredential: []
3781
4303
  x-required-scopes:
3782
4304
  - subscriptions:read
3783
4305
  responses:
@@ -3817,6 +4339,7 @@ paths:
3817
4339
  - Messages
3818
4340
  security:
3819
4341
  - bearerGrant: []
4342
+ - bearerAccountCredential: []
3820
4343
  x-required-scopes:
3821
4344
  - messages:write
3822
4345
  x-idempotency:
@@ -3881,6 +4404,7 @@ paths:
3881
4404
  - Messages
3882
4405
  security:
3883
4406
  - bearerGrant: []
4407
+ - bearerAccountCredential: []
3884
4408
  x-required-scopes:
3885
4409
  - messages:read
3886
4410
  responses:
@@ -3923,6 +4447,7 @@ paths:
3923
4447
  - Messages
3924
4448
  security:
3925
4449
  - bearerGrant: []
4450
+ - bearerAccountCredential: []
3926
4451
  x-required-scopes:
3927
4452
  - messages:read
3928
4453
  responses:
@@ -3962,6 +4487,7 @@ paths:
3962
4487
  - Machine clients
3963
4488
  security:
3964
4489
  - bearerGrant: []
4490
+ - bearerAccountCredential: []
3965
4491
  x-required-scopes:
3966
4492
  - machine-clients:write
3967
4493
  x-idempotency:
@@ -4008,6 +4534,74 @@ paths:
4008
4534
  $ref: "#/components/responses/Unprocessable"
4009
4535
  "429":
4010
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"
4011
4605
  /v1/projects/{project_id}/environments/{environment_id}/capabilities:
4012
4606
  parameters:
4013
4607
  - $ref: "#/components/parameters/ProjectId"
@@ -4023,6 +4617,7 @@ paths:
4023
4617
  - Capabilities
4024
4618
  security:
4025
4619
  - bearerGrant: []
4620
+ - bearerAccountCredential: []
4026
4621
  x-required-scopes:
4027
4622
  - capabilities:read
4028
4623
  responses:
@@ -4065,6 +4660,7 @@ paths:
4065
4660
  - clerkSession: []
4066
4661
  - bearerCredential: []
4067
4662
  - bearerGrant: []
4663
+ - bearerAccountCredential: []
4068
4664
  x-required-scopes:
4069
4665
  - subscriptions:write
4070
4666
  x-idempotency:
@@ -4128,6 +4724,7 @@ paths:
4128
4724
  - clerkSession: []
4129
4725
  - bearerCredential: []
4130
4726
  - bearerGrant: []
4727
+ - bearerAccountCredential: []
4131
4728
  x-required-scopes:
4132
4729
  - subscriptions:read
4133
4730
  responses:
@@ -4160,6 +4757,7 @@ paths:
4160
4757
  - clerkSession: []
4161
4758
  - bearerCredential: []
4162
4759
  - bearerGrant: []
4760
+ - bearerAccountCredential: []
4163
4761
  x-required-scopes:
4164
4762
  - subscriptions:read
4165
4763
  parameters:
@@ -4205,6 +4803,7 @@ paths:
4205
4803
  - clerkSession: []
4206
4804
  - bearerCredential: []
4207
4805
  - bearerGrant: []
4806
+ - bearerAccountCredential: []
4208
4807
  x-required-scopes:
4209
4808
  - subscriptions:write
4210
4809
  x-idempotency:
@@ -4269,6 +4868,7 @@ paths:
4269
4868
  - clerkSession: []
4270
4869
  - bearerCredential: []
4271
4870
  - bearerGrant: []
4871
+ - bearerAccountCredential: []
4272
4872
  x-required-scopes:
4273
4873
  - subscriptions:read
4274
4874
  responses:
@@ -4296,6 +4896,7 @@ paths:
4296
4896
  - clerkSession: []
4297
4897
  - bearerCredential: []
4298
4898
  - bearerGrant: []
4899
+ - bearerAccountCredential: []
4299
4900
  x-required-scopes:
4300
4901
  - subscriptions:write
4301
4902
  requestBody:
@@ -4334,6 +4935,7 @@ paths:
4334
4935
  - clerkSession: []
4335
4936
  - bearerCredential: []
4336
4937
  - bearerGrant: []
4938
+ - bearerAccountCredential: []
4337
4939
  x-required-scopes:
4338
4940
  - subscriptions:write
4339
4941
  responses:
@@ -4374,6 +4976,7 @@ paths:
4374
4976
  - clerkSession: []
4375
4977
  - bearerCredential: []
4376
4978
  - bearerGrant: []
4979
+ - bearerAccountCredential: []
4377
4980
  x-required-scopes:
4378
4981
  - subscriptions:read
4379
4982
  parameters:
@@ -4441,6 +5044,7 @@ paths:
4441
5044
  - clerkSession: []
4442
5045
  - bearerCredential: []
4443
5046
  - bearerGrant: []
5047
+ - bearerAccountCredential: []
4444
5048
  x-required-scopes:
4445
5049
  - subscriptions:write
4446
5050
  responses:
@@ -4474,6 +5078,7 @@ paths:
4474
5078
  - clerkSession: []
4475
5079
  - bearerCredential: []
4476
5080
  - bearerGrant: []
5081
+ - bearerAccountCredential: []
4477
5082
  x-required-scopes:
4478
5083
  - subscriptions:write
4479
5084
  responses:
@@ -4513,6 +5118,7 @@ paths:
4513
5118
  - clerkSession: []
4514
5119
  - bearerCredential: []
4515
5120
  - bearerGrant: []
5121
+ - bearerAccountCredential: []
4516
5122
  x-required-scopes:
4517
5123
  - messages:write
4518
5124
  x-idempotency:
@@ -4577,6 +5183,7 @@ paths:
4577
5183
  - clerkSession: []
4578
5184
  - bearerCredential: []
4579
5185
  - bearerGrant: []
5186
+ - bearerAccountCredential: []
4580
5187
  x-required-scopes:
4581
5188
  - messages:read
4582
5189
  responses:
@@ -4615,8 +5222,28 @@ components:
4615
5222
  consenting account member. It selects exactly one account and carries
4616
5223
  the scopes that member consented to, and never a project: an operation
4617
5224
  names its project and environment in the path, and the service checks
4618
- both against the granting person's membership before acting. It can
4619
- 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.
4620
5247
  bearerCredential:
4621
5248
  type: http
4622
5249
  scheme: bearer
@@ -4685,6 +5312,13 @@ components:
4685
5312
  description: Canonical opaque project credential identity; never a readable secret.
4686
5313
  schema:
4687
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"
4688
5322
  ApiCredentialAfterCursor:
4689
5323
  name: after
4690
5324
  in: query
@@ -4812,6 +5446,13 @@ components:
4812
5446
  description: Opaque connection identity; never authorization.
4813
5447
  schema:
4814
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"
4815
5456
  NotifierId:
4816
5457
  name: notifier_id
4817
5458
  in: path
@@ -4906,6 +5547,24 @@ components:
4906
5547
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/UpdateChannelConnectionRequest
4907
5548
  RotateChannelConnectionCredentialRequest:
4908
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
4909
5568
  NotifierConnectionRoute:
4910
5569
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/NotifierConnectionRoute
4911
5570
  NotifierConnectionCollection:
@@ -4940,6 +5599,20 @@ components:
4940
5599
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/UpdateRecipientCopyOverrideRequest
4941
5600
  CreateApiCredentialRequest:
4942
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
4943
5616
  RotateApiCredentialRequest:
4944
5617
  $ref: ../schemas/whooshbang-v1.schema.json#/$defs/RotateApiCredentialRequest
4945
5618
  ApiCredentialId: