@productcraft/platform-auth 0.2.0 → 1.0.0

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.
@@ -0,0 +1,691 @@
1
+ 'use strict';
2
+
3
+ // src/_generated/testing.ts
4
+ var ROUTES = [
5
+ { op: "wellKnown.oauthAuthorizationServer", method: "GET", pattern: /^\/\.well-known\/oauth-authorization-server$/, status: 200, contentType: "application/json", body: {
6
+ authority_model: "policy",
7
+ authorization_endpoint: "string",
8
+ code_challenge_methods_supported: ["S256"],
9
+ grant_types_supported: ["authorization_code", "refresh_token"],
10
+ introspection_endpoint: "string",
11
+ issuer: "https://api.platform-auth.productcraft.co",
12
+ jwks_uri: "string",
13
+ registration_endpoint: "string",
14
+ resource_indicators_supported: ["string"],
15
+ response_types_supported: ["code"],
16
+ revocation_endpoint: "string",
17
+ scope_descriptions: {},
18
+ scope_labels: {
19
+ full: "Full access",
20
+ mail: "Email",
21
+ readonly: "Read-only",
22
+ support: "Support assistant"
23
+ },
24
+ scopes_supported: ["readonly", "mail", "support", "full"],
25
+ service_documentation: "string",
26
+ token_endpoint: "string",
27
+ token_endpoint_auth_methods_supported: ["none", "client_secret_basic", "client_secret_post"]
28
+ } },
29
+ { op: "auth.password.requestReset", method: "POST", pattern: /^\/v1\/auth\/password\/request-reset$/, status: 204, contentType: null, body: null },
30
+ { op: "workspaces.invites.accept", method: "POST", pattern: /^\/v1\/workspaces\/invites\/accept$/, status: 201, contentType: "application/json", body: {
31
+ created_at: "2026-01-01T00:00:00.000Z",
32
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
33
+ display_name: "Acme Corp",
34
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
35
+ settings: {},
36
+ slug: "acme-corp",
37
+ status: "active",
38
+ updated_at: "2026-01-01T00:00:00.000Z"
39
+ } },
40
+ { op: "sessions.revokeOthers", method: "POST", pattern: /^\/v1\/session\/revoke-others$/, status: 200, contentType: "application/json", body: { revoked: 3 } },
41
+ { op: "wellKnown.jwks", method: "GET", pattern: /^\/\.well-known\/jwks\.json$/, status: 200, contentType: "application/json", body: { keys: [{ alg: "RS256", kid: "k_2026_05_01", kty: "RSA", use: "sig" }] } },
42
+ { op: "auth.logoutCurrent", method: "POST", pattern: /^\/v1\/auth\/logout-current$/, status: 204, contentType: null, body: null },
43
+ { op: "auth.password.reset", method: "POST", pattern: /^\/v1\/auth\/password\/reset$/, status: 204, contentType: null, body: null },
44
+ { op: "verification.resend", method: "POST", pattern: /^\/v1\/verification\/resend$/, status: 200, contentType: "application/json", body: { message: "Email verified successfully" } },
45
+ { op: "verification.verify", method: "POST", pattern: /^\/v1\/verification\/verify$/, status: 200, contentType: "application/json", body: { message: "Email verified successfully" } },
46
+ { op: "introspect.apiKey", method: "POST", pattern: /^\/v1\/introspect\/api-key$/, status: 201, contentType: "application/json", body: {
47
+ api_key_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
48
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
49
+ is_valid: true,
50
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
51
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
52
+ } },
53
+ { op: "oauth.connections.list", method: "GET", pattern: /^\/v1\/oauth\/connections$/, status: 200, contentType: "application/json", body: {
54
+ data: [
55
+ {
56
+ account_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
57
+ client_id: "string",
58
+ client_name: "string",
59
+ created_at: "2026-01-01T00:00:00.000Z",
60
+ first_tool_call_at: "2026-01-01T00:00:00.000Z",
61
+ grant_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
62
+ is_verified: true,
63
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
64
+ preset: "mail",
65
+ products: ["mail"],
66
+ resource: "string",
67
+ revoked_at: "2026-01-01T00:00:00.000Z",
68
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
69
+ }
70
+ ],
71
+ pagination: { next_cursor: null, has_more: false }
72
+ } },
73
+ { op: "me.hiddenGuides.list", method: "GET", pattern: /^\/v1\/me\/hidden-guides$/, status: 200, contentType: "application/json", body: {
74
+ guides: [
75
+ {
76
+ hidden_at: "2026-01-01T00:00:00.000Z",
77
+ key: "auth_app:3f2c9a4e-8b1d-4c6e-9f2a-1b2c3d4e5f60"
78
+ }
79
+ ]
80
+ } },
81
+ { op: "me.hiddenGuides.reset", method: "DELETE", pattern: /^\/v1\/me\/hidden-guides$/, status: 204, contentType: null, body: null },
82
+ { op: "apiKeys.self", method: "GET", pattern: /^\/v1\/api-keys\/self$/, status: 200, contentType: "application/json", body: {
83
+ actions: ["mail.read", "mail.send"],
84
+ allowed: ["Mail: Read domains and templates", "Mail: Send email from your verified domains"],
85
+ expires_at: "2026-01-01T00:00:00.000Z",
86
+ key_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
87
+ name: "Production mailer",
88
+ workspace: { id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b", name: "Acme", slug: "acme" },
89
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
90
+ } },
91
+ { op: "auth.refresh", method: "POST", pattern: /^\/v1\/auth\/refresh$/, status: 200, contentType: "application/json", body: {
92
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
93
+ expires_in: 3600,
94
+ refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
95
+ token_type: "Bearer"
96
+ } },
97
+ { op: "auth.logout", method: "POST", pattern: /^\/v1\/auth\/logout$/, status: 204, contentType: null, body: null },
98
+ { op: "auth.signin", method: "POST", pattern: /^\/v1\/auth\/signin$/, status: 200, contentType: "application/json", body: {
99
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
100
+ expires_in: 3600,
101
+ refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
102
+ token_type: "Bearer"
103
+ } },
104
+ { op: "auth.signup", method: "POST", pattern: /^\/v1\/auth\/signup$/, status: 200, contentType: "application/json", body: {
105
+ access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
106
+ expires_in: 3600,
107
+ refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
108
+ token_type: "Bearer"
109
+ } },
110
+ { op: "introspect.retrieve", method: "GET", pattern: /^\/v1\/introspect$/, status: 200, contentType: "application/json", body: {
111
+ account: {
112
+ avatar_url: "string",
113
+ display_name: "string",
114
+ email: "string",
115
+ email_verified_at: "2026-01-01T00:00:00.000Z",
116
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
117
+ status: "string",
118
+ username: "string"
119
+ },
120
+ is_authenticated: true,
121
+ principal: {
122
+ email: "string",
123
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
124
+ name: "string",
125
+ sub: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
126
+ },
127
+ workspaces: [
128
+ {
129
+ avatar_url: "string",
130
+ display_name: "string",
131
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
132
+ role: "owner",
133
+ services: ["mail", "waitlist"],
134
+ slug: "string"
135
+ }
136
+ ]
137
+ } },
138
+ { op: "me.profile.update", method: "PATCH", pattern: /^\/v1\/me\/profile$/, status: 200, contentType: "application/json", body: {
139
+ avatar_url: "string",
140
+ display_name: "string",
141
+ email: "string",
142
+ email_verified_at: "2026-01-01T00:00:00.000Z",
143
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
144
+ status: "string",
145
+ username: "string"
146
+ } },
147
+ { op: "workspaces.create", method: "POST", pattern: /^\/v1\/workspaces$/, status: 201, contentType: "application/json", body: {
148
+ created_at: "2026-01-01T00:00:00.000Z",
149
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
150
+ display_name: "Acme Corp",
151
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
152
+ settings: {},
153
+ slug: "acme-corp",
154
+ status: "active",
155
+ updated_at: "2026-01-01T00:00:00.000Z"
156
+ } },
157
+ { op: "workspaces.list", method: "GET", pattern: /^\/v1\/workspaces$/, status: 200, contentType: "application/json", body: {
158
+ data: [
159
+ {
160
+ created_at: "2026-01-01T00:00:00.000Z",
161
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
162
+ display_name: "Acme Corp",
163
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
164
+ member_role: "owner",
165
+ member_role_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
166
+ settings: {},
167
+ slug: "acme-corp",
168
+ status: "active",
169
+ updated_at: "2026-01-01T00:00:00.000Z"
170
+ }
171
+ ],
172
+ pagination: { next_cursor: null, has_more: false }
173
+ } },
174
+ { op: "me.avatar.clear", method: "DELETE", pattern: /^\/v1\/me\/avatar$/, status: 204, contentType: null, body: null },
175
+ { op: "me.avatar.upload", method: "POST", pattern: /^\/v1\/me\/avatar$/, status: 200, contentType: "application/json", body: { avatar_url: "string" } },
176
+ { op: "account.erase", method: "DELETE", pattern: /^\/v1\/account$/, status: 204, contentType: null, body: null },
177
+ { op: "sessions.list", method: "GET", pattern: /^\/v1\/session$/, status: 200, contentType: "application/json", body: [
178
+ {
179
+ account_id: "acc_01HZY2F2B6N7M8Q9W4E6R2",
180
+ created_at: "2025-09-20T12:34:56.000Z",
181
+ current: true,
182
+ expires_at: "2025-09-21T12:34:56.000Z",
183
+ id: "sess_01HZY2G3A7M8Q9W4E6R2K1",
184
+ ip: "203.0.113.42",
185
+ last_used_at: "2025-09-20T18:00:00.000Z",
186
+ user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
187
+ }
188
+ ] },
189
+ { op: "me.retrieve", method: "GET", pattern: /^\/v1\/me$/, status: 200, contentType: "application/json", body: {
190
+ avatar_url: "string",
191
+ display_name: "string",
192
+ email: "string",
193
+ email_verified_at: "2026-01-01T00:00:00.000Z",
194
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
195
+ status: "string",
196
+ username: "string"
197
+ } },
198
+ { op: "workspaces.policies.actions.catalog", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/policies\/actions\/catalog$/, status: 200, contentType: "application/json", body: { actions: ["string"] } },
199
+ { op: "oauth.workspaces.connections.list", method: "GET", pattern: /^\/v1\/oauth\/workspaces\/[^\/]+\/connections$/, status: 200, contentType: "application/json", body: {
200
+ data: [
201
+ {
202
+ account_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
203
+ client_id: "string",
204
+ client_name: "string",
205
+ created_at: "2026-01-01T00:00:00.000Z",
206
+ first_tool_call_at: "2026-01-01T00:00:00.000Z",
207
+ grant_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
208
+ is_verified: true,
209
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
210
+ preset: "mail",
211
+ products: ["mail"],
212
+ resource: "string",
213
+ revoked_at: "2026-01-01T00:00:00.000Z",
214
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
215
+ }
216
+ ],
217
+ pagination: { next_cursor: null, has_more: false }
218
+ } },
219
+ { op: "workspaces.auditLogs.export", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/audit-logs\/export$/, status: 200, contentType: "application/x-ndjson", body: "" },
220
+ { op: "workspaces.apiKeys.presets.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/presets$/, status: 200, contentType: "application/json", body: {
221
+ data: [
222
+ {
223
+ actions: ["mail.send"],
224
+ allowed: ["Mail: Send email from your verified domains"],
225
+ description: "Send email from your verified domains and check what happened to it. Cannot read message bodies or change domains.",
226
+ key: "mail-send",
227
+ label: "Send email",
228
+ policy_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
229
+ }
230
+ ],
231
+ pagination: { next_cursor: null, has_more: false }
232
+ } },
233
+ { op: "workspaces.apiKeys.preview", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/preview$/, status: 200, contentType: "application/json", body: {
234
+ actions: ["mail.read", "mail.send"],
235
+ allowed: ["Mail: Read domains and templates", "Mail: Send email from your verified domains"],
236
+ grantable: true,
237
+ refusal: null
238
+ } },
239
+ { op: "introspect.workspaces.retrieve", method: "GET", pattern: /^\/v1\/introspect\/workspaces\/[^\/]+$/, status: 200, contentType: "application/json", body: {
240
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
241
+ is_member: true,
242
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
243
+ role: { id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b", name: "string" },
244
+ services: ["mail", "waitlist"]
245
+ } },
246
+ { op: "workspaces.auditFeed.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/audit-feed$/, status: 200, contentType: "application/json", body: {
247
+ data: [
248
+ {
249
+ action: "mail.domain.verified",
250
+ actor_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
251
+ actor_type: "platform_user",
252
+ metadata: {},
253
+ resource: "workspace_membership",
254
+ resource_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
255
+ source: "workspace_audit",
256
+ source_ref: "4e5f5c9e-b4ee-4401-9275-283feb66c178",
257
+ timestamp: "2026-01-01T00:00:00.000Z"
258
+ }
259
+ ],
260
+ pagination: { next_cursor: null, has_more: false },
261
+ sources: [{ count: 1, error: "string", included: true, source: "workspace_audit" }]
262
+ } },
263
+ { op: "workspaces.auditLogs.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/audit-logs$/, status: 200, contentType: "application/json", body: {
264
+ data: [
265
+ {
266
+ action: "workspace.member.removed",
267
+ actor_id: "string",
268
+ actor_type: "platform_user",
269
+ created_at: "2026-01-01T00:00:00.000Z",
270
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
271
+ ip: "string",
272
+ metadata: {},
273
+ resource: "workspace_membership",
274
+ resource_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
275
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
276
+ }
277
+ ],
278
+ pagination: { next_cursor: null, has_more: false }
279
+ } },
280
+ { op: "workspaces.apiKeys.create", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys$/, status: 201, contentType: "application/json", body: {
281
+ record: {
282
+ created_at: "2026-01-01T00:00:00.000Z",
283
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
284
+ description: "string",
285
+ expires_at: "2026-01-01T00:00:00.000Z",
286
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
287
+ last_used_at: "2026-01-01T00:00:00.000Z",
288
+ name: "string",
289
+ policies: [
290
+ {
291
+ description: "string",
292
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
293
+ name: "mail-readonly"
294
+ }
295
+ ],
296
+ revoked_at: "2026-01-01T00:00:00.000Z",
297
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
298
+ status: "active",
299
+ token_prefix: "pcft_live_abc123",
300
+ updated_at: "2026-01-01T00:00:00.000Z",
301
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
302
+ },
303
+ token: "pcft_live_abc123XYZ..."
304
+ } },
305
+ { op: "workspaces.apiKeys.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys$/, status: 200, contentType: "application/json", body: {
306
+ data: [
307
+ {
308
+ created_at: "2026-01-01T00:00:00.000Z",
309
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
310
+ description: "string",
311
+ expires_at: "2026-01-01T00:00:00.000Z",
312
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
313
+ last_used_at: "2026-01-01T00:00:00.000Z",
314
+ name: "string",
315
+ policies: [
316
+ {
317
+ description: "string",
318
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
319
+ name: "mail-readonly"
320
+ }
321
+ ],
322
+ revoked_at: "2026-01-01T00:00:00.000Z",
323
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
324
+ status: "active",
325
+ token_prefix: "pcft_live_abc123",
326
+ updated_at: "2026-01-01T00:00:00.000Z",
327
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
328
+ }
329
+ ],
330
+ pagination: { next_cursor: null, has_more: false }
331
+ } },
332
+ { op: "workspaces.policies.create", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/policies$/, status: 201, contentType: "application/json", body: {
333
+ created_at: "2026-01-01T00:00:00.000Z",
334
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
335
+ description: "string",
336
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
337
+ name: "mail-readonly",
338
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
339
+ preset_key: "mail-send",
340
+ updated_at: "2026-01-01T00:00:00.000Z",
341
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
342
+ } },
343
+ { op: "workspaces.policies.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/policies$/, status: 200, contentType: "application/json", body: {
344
+ data: [
345
+ {
346
+ created_at: "2026-01-01T00:00:00.000Z",
347
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
348
+ description: "string",
349
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
350
+ name: "mail-readonly",
351
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
352
+ preset_key: "mail-send",
353
+ updated_at: "2026-01-01T00:00:00.000Z",
354
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
355
+ }
356
+ ],
357
+ pagination: { next_cursor: null, has_more: false }
358
+ } },
359
+ { op: "workspaces.services.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/services$/, status: 200, contentType: "application/json", body: {
360
+ data: [
361
+ {
362
+ disabled_at: "2026-01-01T00:00:00.000Z",
363
+ disabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
364
+ enabled: true,
365
+ enabled_at: "2026-01-01T00:00:00.000Z",
366
+ enabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
367
+ service: "mail",
368
+ settings: {},
369
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
370
+ }
371
+ ]
372
+ } },
373
+ { op: "workspaces.invites.create", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/invites$/, status: 201, contentType: "application/json", body: {
374
+ code: "string",
375
+ created_at: "2026-01-01T00:00:00.000Z",
376
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
377
+ email: "ada@example.com",
378
+ expires_at: "2026-01-01T00:00:00.000Z",
379
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
380
+ max_uses: 1,
381
+ revoked_at: "2026-01-01T00:00:00.000Z",
382
+ role_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
383
+ use_count: 1,
384
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
385
+ } },
386
+ { op: "workspaces.invites.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/invites$/, status: 200, contentType: "application/json", body: {
387
+ data: [
388
+ {
389
+ code: "string",
390
+ created_at: "2026-01-01T00:00:00.000Z",
391
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
392
+ email: "ada@example.com",
393
+ expires_at: "2026-01-01T00:00:00.000Z",
394
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
395
+ max_uses: 1,
396
+ revoked_at: "2026-01-01T00:00:00.000Z",
397
+ role_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
398
+ role_name: "string",
399
+ use_count: 1,
400
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
401
+ }
402
+ ],
403
+ pagination: { next_cursor: null, has_more: false }
404
+ } },
405
+ { op: "workspaces.members.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/members$/, status: 200, contentType: "application/json", body: {
406
+ data: [
407
+ {
408
+ account_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
409
+ avatar_url: "string",
410
+ display_name: "string",
411
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
412
+ joined_at: "2026-01-01T00:00:00.000Z",
413
+ primary_email: "string",
414
+ role: "string",
415
+ role_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
416
+ role_is_system: true,
417
+ username: "string"
418
+ }
419
+ ],
420
+ pagination: { next_cursor: null, has_more: false }
421
+ } },
422
+ { op: "oauth.connections.delete", method: "DELETE", pattern: /^\/v1\/oauth\/connections\/[^\/]+$/, status: 204, contentType: null, body: null },
423
+ { op: "workspaces.avatar.clear", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/avatar$/, status: 204, contentType: null, body: null },
424
+ { op: "workspaces.avatar.upload", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/avatar$/, status: 200, contentType: "application/json", body: { avatar_url: "string" } },
425
+ { op: "me.hiddenGuides.hide", method: "PUT", pattern: /^\/v1\/me\/hidden-guides\/[^\/]+$/, status: 200, contentType: "application/json", body: {
426
+ hidden_at: "2026-01-01T00:00:00.000Z",
427
+ key: "auth_app:3f2c9a4e-8b1d-4c6e-9f2a-1b2c3d4e5f60"
428
+ } },
429
+ { op: "me.hiddenGuides.unhide", method: "DELETE", pattern: /^\/v1\/me\/hidden-guides\/[^\/]+$/, status: 204, contentType: null, body: null },
430
+ { op: "stats.retrieve", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/stats$/, status: 200, contentType: "application/json", body: {
431
+ generated_at: "2026-10-07T09:00:00.000Z",
432
+ in_window: { audit_events: 57, last_api_key_use_at: "2026-10-07T06:12:40.000Z" },
433
+ last_activity_at: "2026-10-07T08:41:12.000Z",
434
+ series: { granularity: "day", metric: "audit_events", points: [{ date: "2026-10-07", value: 7 }] },
435
+ totals: { active_api_keys: 2, members: 4 },
436
+ window: "30d"
437
+ } },
438
+ { op: "workspaces.roles.create", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/roles$/, status: 201, contentType: "application/json", body: {
439
+ description: "string",
440
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
441
+ is_system: true,
442
+ name: "string",
443
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
444
+ policy_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
445
+ } },
446
+ { op: "workspaces.roles.list", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/roles$/, status: 200, contentType: "application/json", body: {
447
+ data: [
448
+ {
449
+ description: "string",
450
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
451
+ is_system: true,
452
+ name: "string",
453
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
454
+ policy_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
455
+ }
456
+ ],
457
+ pagination: { next_cursor: null, has_more: false }
458
+ } },
459
+ { op: "workspaces.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+$/, status: 204, contentType: null, body: null },
460
+ { op: "workspaces.retrieve", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+$/, status: 200, contentType: "application/json", body: {
461
+ created_at: "2026-01-01T00:00:00.000Z",
462
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
463
+ display_name: "Acme Corp",
464
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
465
+ settings: {},
466
+ slug: "acme-corp",
467
+ status: "active",
468
+ updated_at: "2026-01-01T00:00:00.000Z"
469
+ } },
470
+ { op: "workspaces.update", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+$/, status: 200, contentType: "application/json", body: {
471
+ created_at: "2026-01-01T00:00:00.000Z",
472
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
473
+ display_name: "Acme Corp",
474
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
475
+ settings: {},
476
+ slug: "acme-corp",
477
+ status: "active",
478
+ updated_at: "2026-01-01T00:00:00.000Z"
479
+ } },
480
+ { op: "sessions.delete", method: "DELETE", pattern: /^\/v1\/session\/[^\/]+$/, status: 200, contentType: "application/json", body: { revoked: true } },
481
+ { op: "oauth.workspaces.connections.restore", method: "POST", pattern: /^\/v1\/oauth\/workspaces\/[^\/]+\/connections\/[^\/]+\/restore$/, status: 204, contentType: null, body: null },
482
+ { op: "oauth.workspaces.connections.delete", method: "DELETE", pattern: /^\/v1\/oauth\/workspaces\/[^\/]+\/connections\/[^\/]+$/, status: 204, contentType: null, body: null },
483
+ { op: "workspaces.apiKeys.updateBindings", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/[^\/]+\/bindings$/, status: 200, contentType: "application/json", body: {
484
+ created_at: "2026-01-01T00:00:00.000Z",
485
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
486
+ description: "string",
487
+ expires_at: "2026-01-01T00:00:00.000Z",
488
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
489
+ last_used_at: "2026-01-01T00:00:00.000Z",
490
+ name: "string",
491
+ policies: [
492
+ {
493
+ description: "string",
494
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
495
+ name: "mail-readonly"
496
+ }
497
+ ],
498
+ revoked_at: "2026-01-01T00:00:00.000Z",
499
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
500
+ status: "active",
501
+ token_prefix: "pcft_live_abc123",
502
+ updated_at: "2026-01-01T00:00:00.000Z",
503
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
504
+ } },
505
+ { op: "workspaces.services.updateSettings", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/services\/[^\/]+\/settings$/, status: 200, contentType: "application/json", body: {
506
+ disabled_at: "2026-01-01T00:00:00.000Z",
507
+ disabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
508
+ enabled: true,
509
+ enabled_at: "2026-01-01T00:00:00.000Z",
510
+ enabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
511
+ service: "mail",
512
+ settings: {},
513
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
514
+ } },
515
+ { op: "workspaces.apiKeys.rotate", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/[^\/]+\/rotate$/, status: 201, contentType: "application/json", body: {
516
+ previous_key_expires_at: "2026-01-01T00:00:00.000Z",
517
+ record: {
518
+ created_at: "2026-01-01T00:00:00.000Z",
519
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
520
+ description: "string",
521
+ expires_at: "2026-01-01T00:00:00.000Z",
522
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
523
+ last_used_at: "2026-01-01T00:00:00.000Z",
524
+ name: "string",
525
+ policies: [
526
+ {
527
+ description: "string",
528
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
529
+ name: "mail-readonly"
530
+ }
531
+ ],
532
+ revoked_at: "2026-01-01T00:00:00.000Z",
533
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
534
+ status: "active",
535
+ token_prefix: "pcft_live_abc123",
536
+ updated_at: "2026-01-01T00:00:00.000Z",
537
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
538
+ },
539
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
540
+ token: "pcft_live_abc123XYZ..."
541
+ } },
542
+ { op: "workspaces.members.updateRole", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/members\/[^\/]+\/role$/, status: 200, contentType: "application/json", body: {
543
+ account_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
544
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
545
+ invited_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
546
+ joined_at: "2026-01-01T00:00:00.000Z",
547
+ role_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
548
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
549
+ } },
550
+ { op: "workspaces.apiKeys.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/[^\/]+$/, status: 204, contentType: null, body: null },
551
+ { op: "workspaces.apiKeys.retrieve", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/[^\/]+$/, status: 200, contentType: "application/json", body: {
552
+ created_at: "2026-01-01T00:00:00.000Z",
553
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
554
+ description: "string",
555
+ expires_at: "2026-01-01T00:00:00.000Z",
556
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
557
+ last_used_at: "2026-01-01T00:00:00.000Z",
558
+ name: "string",
559
+ policies: [
560
+ {
561
+ description: "string",
562
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
563
+ name: "mail-readonly"
564
+ }
565
+ ],
566
+ revoked_at: "2026-01-01T00:00:00.000Z",
567
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
568
+ status: "active",
569
+ token_prefix: "pcft_live_abc123",
570
+ updated_at: "2026-01-01T00:00:00.000Z",
571
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
572
+ } },
573
+ { op: "workspaces.apiKeys.update", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/api-keys\/[^\/]+$/, status: 200, contentType: "application/json", body: {
574
+ created_at: "2026-01-01T00:00:00.000Z",
575
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
576
+ description: "string",
577
+ expires_at: "2026-01-01T00:00:00.000Z",
578
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
579
+ last_used_at: "2026-01-01T00:00:00.000Z",
580
+ name: "string",
581
+ policies: [
582
+ {
583
+ description: "string",
584
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
585
+ name: "mail-readonly"
586
+ }
587
+ ],
588
+ revoked_at: "2026-01-01T00:00:00.000Z",
589
+ rotated_from: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
590
+ status: "active",
591
+ token_prefix: "pcft_live_abc123",
592
+ updated_at: "2026-01-01T00:00:00.000Z",
593
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
594
+ } },
595
+ { op: "workspaces.policies.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/policies\/[^\/]+$/, status: 200, contentType: "application/json", body: { bound_key_count: 3, deleted: true, id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b" } },
596
+ { op: "workspaces.policies.retrieve", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/policies\/[^\/]+$/, status: 200, contentType: "application/json", body: {
597
+ binding_count: { pak: 1, role: 1 },
598
+ bound_key_count: 3,
599
+ created_at: "2026-01-01T00:00:00.000Z",
600
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
601
+ description: "string",
602
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
603
+ name: "mail-readonly",
604
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
605
+ preset_key: "mail-send",
606
+ updated_at: "2026-01-01T00:00:00.000Z",
607
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
608
+ } },
609
+ { op: "workspaces.policies.update", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/policies\/[^\/]+$/, status: 200, contentType: "application/json", body: {
610
+ binding_count: { pak: 1, role: 1 },
611
+ bound_key_count: 3,
612
+ created_at: "2026-01-01T00:00:00.000Z",
613
+ created_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
614
+ description: "string",
615
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
616
+ name: "mail-readonly",
617
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
618
+ preset_key: "mail-send",
619
+ updated_at: "2026-01-01T00:00:00.000Z",
620
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
621
+ } },
622
+ { op: "workspaces.services.disable", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/services\/[^\/]+$/, status: 204, contentType: null, body: null },
623
+ { op: "workspaces.services.enable", method: "POST", pattern: /^\/v1\/workspaces\/[^\/]+\/services\/[^\/]+$/, status: 201, contentType: "application/json", body: {
624
+ disabled_at: "2026-01-01T00:00:00.000Z",
625
+ disabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
626
+ enabled: true,
627
+ enabled_at: "2026-01-01T00:00:00.000Z",
628
+ enabled_by: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
629
+ service: "mail",
630
+ settings: {},
631
+ workspace_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
632
+ } },
633
+ { op: "workspaces.invites.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/invites\/[^\/]+$/, status: 204, contentType: null, body: null },
634
+ { op: "workspaces.members.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/members\/[^\/]+$/, status: 204, contentType: null, body: null },
635
+ { op: "workspaces.roles.delete", method: "DELETE", pattern: /^\/v1\/workspaces\/[^\/]+\/roles\/[^\/]+$/, status: 204, contentType: null, body: null },
636
+ { op: "workspaces.roles.retrieve", method: "GET", pattern: /^\/v1\/workspaces\/[^\/]+\/roles\/[^\/]+$/, status: 200, contentType: "application/json", body: {
637
+ description: "string",
638
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
639
+ is_system: true,
640
+ name: "string",
641
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
642
+ policy_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
643
+ } },
644
+ { op: "workspaces.roles.update", method: "PATCH", pattern: /^\/v1\/workspaces\/[^\/]+\/roles\/[^\/]+$/, status: 200, contentType: "application/json", body: {
645
+ description: "string",
646
+ id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b",
647
+ is_system: true,
648
+ name: "string",
649
+ policy: [{ actions: ["social.read", "social.list"], effect: "allow", resources: ["*"] }],
650
+ policy_id: "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
651
+ } }
652
+ ];
653
+ function createMockFetch(overrides = {}) {
654
+ const calls = [];
655
+ const mock = async (input, init) => {
656
+ const request = input instanceof Request ? input : void 0;
657
+ const url = new URL(request ? request.url : String(input));
658
+ const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
659
+ const headers = new Headers(init?.headers ?? request?.headers);
660
+ const raw = init?.body ?? (request ? await request.text() : void 0);
661
+ let body = raw;
662
+ if (typeof raw === "string") {
663
+ try {
664
+ body = JSON.parse(raw);
665
+ } catch {
666
+ body = raw;
667
+ }
668
+ }
669
+ const route = ROUTES.find((r) => r.method === method && r.pattern.test(url.pathname));
670
+ const call = { operation: route?.op, method, url, headers, body };
671
+ calls.push(call);
672
+ const requestId = `req_mock_${calls.length}`;
673
+ if (!route) {
674
+ return Response.json({ statusCode: 404, code: "NOT_FOUND", message: `No mock for ${method} ${url.pathname}` }, { status: 404, headers: { "x-request-id": requestId } });
675
+ }
676
+ let value = route.body;
677
+ if (route.op in overrides) {
678
+ const o = overrides[route.op];
679
+ value = typeof o === "function" ? await o(call) : o;
680
+ if (value instanceof Response) return value;
681
+ }
682
+ if (route.contentType === null || route.status === 204) return new Response(null, { status: route.status, headers: { "x-request-id": requestId } });
683
+ const text = route.contentType === "application/json" ? JSON.stringify(value) : String(value);
684
+ return new Response(text, { status: route.status, headers: { "content-type": route.contentType, "x-request-id": requestId } });
685
+ };
686
+ return Object.assign(mock, { calls });
687
+ }
688
+
689
+ exports.createMockFetch = createMockFetch;
690
+ //# sourceMappingURL=testing.cjs.map
691
+ //# sourceMappingURL=testing.cjs.map