@workos/openapi-spec 0.4.0 → 0.6.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,122 @@
1
+ {
2
+ "POST /organizations/{organizationId}/groups": {
3
+ "methodName": "create_group",
4
+ "optionsType": "CreateGroupOptions"
5
+ },
6
+ "GET /organizations/{organizationId}/groups": {
7
+ "methodName": "list_groups",
8
+ "optionsType": "ListGroupsOptions"
9
+ },
10
+ "GET /organizations/{organizationId}/groups/{groupId}": {
11
+ "methodName": "get_group",
12
+ "optionsType": "GetGroupOptions"
13
+ },
14
+ "PATCH /organizations/{organizationId}/groups/{groupId}": {
15
+ "methodName": "update_group",
16
+ "optionsType": "UpdateGroupOptions"
17
+ },
18
+ "DELETE /organizations/{organizationId}/groups/{groupId}": {
19
+ "methodName": "delete_group",
20
+ "optionsType": "DeleteGroupOptions"
21
+ },
22
+ "POST /organizations/{organizationId}/groups/{groupId}/organization-memberships": {
23
+ "methodName": "add_organization_membership",
24
+ "optionsType": "AddGroupOrganizationMembershipOptions"
25
+ },
26
+ "GET /organizations/{organizationId}/groups/{groupId}/organization-memberships": {
27
+ "methodName": "list_organization_memberships",
28
+ "optionsType": "ListGroupOrganizationMembershipsOptions"
29
+ },
30
+ "DELETE /organizations/{organizationId}/groups/{groupId}/organization-memberships/{omId}": {
31
+ "methodName": "remove_organization_membership",
32
+ "optionsType": "RemoveGroupOrganizationMembershipOptions"
33
+ },
34
+ "GET /user_management/organization_memberships": {
35
+ "methodName": "list_organization_memberships",
36
+ "mountOn": "UserManagement"
37
+ },
38
+ "POST /user_management/organization_memberships": {
39
+ "methodName": "create_organization_membership",
40
+ "mountOn": "UserManagement"
41
+ },
42
+ "GET /user_management/organization_memberships/{id}": {
43
+ "methodName": "get_organization_membership",
44
+ "mountOn": "UserManagement"
45
+ },
46
+ "PUT /user_management/organization_memberships/{id}": {
47
+ "methodName": "update_organization_membership",
48
+ "mountOn": "UserManagement"
49
+ },
50
+ "DELETE /user_management/organization_memberships/{id}": {
51
+ "methodName": "delete_organization_membership",
52
+ "mountOn": "UserManagement"
53
+ },
54
+ "PUT /user_management/organization_memberships/{id}/deactivate": {
55
+ "methodName": "deactivate_organization_membership",
56
+ "mountOn": "UserManagement"
57
+ },
58
+ "PUT /user_management/organization_memberships/{id}/reactivate": {
59
+ "methodName": "reactivate_organization_membership",
60
+ "mountOn": "UserManagement"
61
+ },
62
+ "GET /user_management/organization_memberships/{omId}/groups": {
63
+ "methodName": "list_groups_for_organization_membership",
64
+ "mountOn": "UserManagement"
65
+ },
66
+ "POST /vault/v1/kv": {
67
+ "methodName": "create_object",
68
+ "optionsType": "CreateObjectOptions",
69
+ "bodyFieldMap": {
70
+ "context": "keyContext"
71
+ }
72
+ },
73
+ "GET /vault/v1/kv": {
74
+ "methodName": "list_objects"
75
+ },
76
+ "GET /vault/v1/kv/{id}": {
77
+ "methodName": "read_object",
78
+ "optionsType": "ReadObjectOptions"
79
+ },
80
+ "GET /vault/v1/kv/name/{name}": {
81
+ "methodName": "read_object_by_name"
82
+ },
83
+ "GET /vault/v1/kv/{id}/metadata": {
84
+ "methodName": "describe_object",
85
+ "optionsType": "ReadObjectOptions",
86
+ "returnType": "Promise<VaultObject>",
87
+ "returnExpression": "({ ...result, value: undefined })"
88
+ },
89
+ "PUT /vault/v1/kv/{id}": {
90
+ "methodName": "update_object",
91
+ "optionsType": "UpdateObjectOptions",
92
+ "returnType": "Promise<VaultObject>",
93
+ "returnExpression": "({ ...result, value: undefined })"
94
+ },
95
+ "DELETE /vault/v1/kv/{id}": {
96
+ "methodName": "delete_object",
97
+ "optionsType": "DeleteObjectOptions"
98
+ },
99
+ "GET /vault/v1/kv/{id}/versions": {
100
+ "methodName": "list_object_versions",
101
+ "optionsType": "ReadObjectOptions",
102
+ "returnType": "Promise<VersionListResponse['data']>",
103
+ "returnDataProperty": "data"
104
+ },
105
+ "POST /vault/v1/keys/data-key": {
106
+ "optionsType": "CreateDataKeyOptions",
107
+ "returnType": "Promise<DataKeyPair>",
108
+ "returnTypeImports": [
109
+ "DataKeyPair"
110
+ ],
111
+ "returnExpression": "({ context: result.context, dataKey: { key: result.dataKey!, id: result.id }, encryptedKeys: result.encryptedKeys! })"
112
+ },
113
+ "POST /vault/v1/keys/decrypt": {
114
+ "methodName": "decrypt_data_key",
115
+ "optionsType": "DecryptDataKeyOptions",
116
+ "returnType": "Promise<DataKey>",
117
+ "returnTypeImports": [
118
+ "DataKey"
119
+ ],
120
+ "returnExpression": "({ key: result.dataKey, id: result.id })"
121
+ }
122
+ }
@@ -0,0 +1,85 @@
1
+ //#region src/policy/types.d.ts
2
+ /**
3
+ * Vendored type definitions for the policy module.
4
+ *
5
+ * `OperationHint`, `SplitHint`, and `OpenApiDocument` are inlined from
6
+ * `@workos/oagen` so the published `@workos/openapi-spec/policy` .d.mts is
7
+ * self-contained — consumers get full autocomplete without resolving types
8
+ * through `@workos/oagen`. Keep these in sync with the upstream definitions
9
+ * in `oagen/src/ir/operation-hints.ts` and `oagen/src/parser/parse.ts`; bump
10
+ * when the upstream schema gains a field this repo wants to use.
11
+ */
12
+ type OpenApiDocument = Record<string, unknown>;
13
+ interface SplitHint {
14
+ /** Wrapper method name (snake_case). */
15
+ name: string;
16
+ /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */
17
+ targetVariant: string;
18
+ /** Constant body fields injected by the wrapper. */
19
+ defaults?: Record<string, string | number | boolean>;
20
+ /** Fields the SDK reads from client config at runtime. */
21
+ inferFromClient?: string[];
22
+ /** Only these body fields are exposed as method params. */
23
+ exposedParams?: string[];
24
+ /** Subset of exposedParams that should be emitted as optional. */
25
+ optionalParams?: string[];
26
+ }
27
+ interface OperationHint {
28
+ /** Override the algorithm-derived method name. */
29
+ name?: string;
30
+ /** Remount this operation to a different service/namespace (PascalCase). */
31
+ mountOn?: string;
32
+ /** Split a union-body operation into N typed wrapper methods. */
33
+ split?: SplitHint[];
34
+ /** Inject constant body defaults (e.g. { grant_type: 'password' }). */
35
+ defaults?: Record<string, string | number | boolean>;
36
+ /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */
37
+ inferFromClient?: string[];
38
+ /**
39
+ * Marks this operation as a URL builder rather than a real HTTP call.
40
+ * Emitters generate a method that returns the constructed URL (typically
41
+ * as a string) without performing any I/O. Used for OAuth-style redirect
42
+ * endpoints such as /sso/authorize and /user_management/sessions/logout.
43
+ */
44
+ urlBuilder?: boolean;
45
+ }
46
+ //#endregion
47
+ //#region src/policy/operation-hints.d.ts
48
+ /**
49
+ * Per-operation overrides for the operation resolver. Keyed by `"METHOD /path"`.
50
+ * Only operations that need overrides are listed; the algorithm handles the rest.
51
+ */
52
+ declare const operationHints: Record<string, OperationHint>;
53
+ //#endregion
54
+ //#region src/policy/mount-rules.d.ts
55
+ /**
56
+ * Service-level remounting. Maps IR service name → target service/namespace
57
+ * (PascalCase). All operations in the source service are mounted on the
58
+ * target unless overridden per-operation in {@link operationHints}.
59
+ */
60
+ declare const mountRules: Record<string, string>;
61
+ //#endregion
62
+ //#region src/policy/model-hints.d.ts
63
+ /**
64
+ * Model placement hints — used by emitters that call
65
+ * `assignModelsToServices` so hinted models land in the configured service
66
+ * instead of the default first-reference winner.
67
+ */
68
+ declare const modelHints: Record<string, string>;
69
+ //#endregion
70
+ //#region src/policy/transforms.d.ts
71
+ /**
72
+ * NestJS-style operationId transform. Strips "Controller" and extracts the
73
+ * action after the first underscore: `FooController_bar` -> `bar`.
74
+ */
75
+ declare function nestjsOperationIdTransform(id: string): string;
76
+ declare function schemaNameTransform(name: string): string;
77
+ /**
78
+ * Pre-IR spec overlay — patch around upstream spec quirks that would otherwise
79
+ * emit breaking SDK changes. See docs/breaking-change-playbook.md and the
80
+ * oagen `transformSpec` docs for usage. Reach for this only when the upstream
81
+ * fix can't land in time AND the change is genuinely additive.
82
+ */
83
+ declare function transformSpec(spec: OpenApiDocument): OpenApiDocument;
84
+ //#endregion
85
+ export { type OpenApiDocument, type OperationHint, type SplitHint, modelHints, mountRules, nestjsOperationIdTransform, operationHints, schemaNameTransform, transformSpec };
@@ -0,0 +1,398 @@
1
+ import { toCamelCase } from "@workos/oagen";
2
+ //#region src/policy/operation-hints.ts
3
+ /**
4
+ * Per-operation overrides for the operation resolver. Keyed by `"METHOD /path"`.
5
+ * Only operations that need overrides are listed; the algorithm handles the rest.
6
+ */
7
+ const operationHints = {
8
+ "POST /radar/lists/{type}/{action}": { name: "add_list_entry" },
9
+ "DELETE /radar/lists/{type}/{action}": { name: "remove_list_entry" },
10
+ "GET /sso/authorize": {
11
+ name: "get_authorization_url",
12
+ defaults: { response_type: "code" },
13
+ inferFromClient: ["client_id"],
14
+ urlBuilder: true
15
+ },
16
+ "GET /sso/logout": {
17
+ name: "get_logout_url",
18
+ urlBuilder: true
19
+ },
20
+ "GET /sso/profile": { name: "get_profile" },
21
+ "POST /sso/token": {
22
+ name: "get_profile_and_token",
23
+ defaults: { grant_type: "authorization_code" },
24
+ inferFromClient: ["client_id", "client_secret"]
25
+ },
26
+ "GET /sso/jwks/{clientId}": { name: "get_jwks" },
27
+ "GET /user_management/authorize": {
28
+ name: "get_authorization_url",
29
+ defaults: { response_type: "code" },
30
+ inferFromClient: ["client_id"],
31
+ urlBuilder: true
32
+ },
33
+ "GET /user_management/sessions/logout": {
34
+ name: "get_logout_url",
35
+ urlBuilder: true
36
+ },
37
+ "POST /portal/generate_link": { name: "generate_link" },
38
+ "GET /organizations/{organizationId}/feature-flags": { name: "list_organization_feature_flags" },
39
+ "GET /user_management/users/{userId}/feature-flags": { name: "list_user_feature_flags" },
40
+ "GET /organizations/external_id/{external_id}": { name: "get_organization_by_external_id" },
41
+ "GET /user_management/users/external_id/{external_id}": { name: "get_user_by_external_id" },
42
+ "GET /authorization/roles": { name: "list_environment_roles" },
43
+ "POST /authorization/roles": { name: "create_environment_role" },
44
+ "GET /authorization/roles/{slug}": { name: "get_environment_role" },
45
+ "PATCH /authorization/roles/{slug}": { name: "update_environment_role" },
46
+ "PUT /authorization/roles/{slug}/permissions": { name: "set_environment_role_permissions" },
47
+ "POST /authorization/roles/{slug}/permissions": { name: "add_environment_role_permission" },
48
+ "POST /authorization/permissions": { name: "create_permission" },
49
+ "POST /authorization/resources": { name: "create_resource" },
50
+ "POST /authorization/organization_memberships/{organization_membership_id}/check": { name: "check" },
51
+ "GET /authorization/organization_memberships/{organization_membership_id}/resources": { name: "list_resources_for_membership" },
52
+ "GET /authorization/organization_memberships/{organization_membership_id}/resources/{resource_id}/permissions": { name: "list_effective_permissions" },
53
+ "GET /authorization/organization_memberships/{organization_membership_id}/resources/{resource_type_slug}/{external_id}/permissions": { name: "list_effective_permissions_by_external_id" },
54
+ "GET /authorization/organization_memberships/{organization_membership_id}/role_assignments": { name: "list_role_assignments" },
55
+ "POST /authorization/organization_memberships/{organization_membership_id}/role_assignments": { name: "assign_role" },
56
+ "DELETE /authorization/organization_memberships/{organization_membership_id}/role_assignments": { name: "remove_role" },
57
+ "DELETE /authorization/organization_memberships/{organization_membership_id}/role_assignments/{role_assignment_id}": { name: "remove_role_assignment" },
58
+ "POST /authorization/organizations/{organizationId}/roles": { name: "create_organization_role" },
59
+ "PUT /authorization/organizations/{organizationId}/roles/{slug}/permissions": { name: "set_organization_role_permissions" },
60
+ "POST /authorization/organizations/{organizationId}/roles/{slug}/permissions": { name: "add_organization_role_permission" },
61
+ "DELETE /authorization/organizations/{organizationId}/roles/{slug}/permissions/{permissionSlug}": { name: "remove_organization_role_permission" },
62
+ "GET /authorization/organizations/{organization_id}/resources/{resource_type_slug}/{external_id}": { name: "get_resource_by_external_id" },
63
+ "PATCH /authorization/organizations/{organization_id}/resources/{resource_type_slug}/{external_id}": { name: "update_resource_by_external_id" },
64
+ "DELETE /authorization/organizations/{organization_id}/resources/{resource_type_slug}/{external_id}": { name: "delete_resource_by_external_id" },
65
+ "GET /authorization/organizations/{organization_id}/resources/{resource_type_slug}/{external_id}/organization_memberships": { name: "list_memberships_for_resource_by_external_id" },
66
+ "GET /authorization/organizations/{organization_id}/resources/{resource_type_slug}/{external_id}/role_assignments": { name: "list_role_assignments_for_resource_by_external_id" },
67
+ "GET /authorization/resources/{resource_id}/organization_memberships": { name: "list_memberships_for_resource" },
68
+ "GET /authorization/resources/{resource_id}/role_assignments": { name: "list_role_assignments_for_resource" },
69
+ "POST /user_management/users": { name: "create_user" },
70
+ "POST /user_management/invitations": { name: "send_invitation" },
71
+ "GET /user_management/invitations/by_token/{token}": { name: "find_invitation_by_token" },
72
+ "POST /user_management/users/{id}/email_verification/send": { name: "send_verification_email" },
73
+ "POST /user_management/users/{id}/email_verification/confirm": { name: "verify_email" },
74
+ "POST /user_management/password_reset": { name: "reset_password" },
75
+ "POST /user_management/password_reset/confirm": { name: "confirm_password_reset" },
76
+ "GET /user_management/users/{id}/sessions": { name: "list_sessions" },
77
+ "GET /user_management/users/{id}/identities": { name: "get_user_identities" },
78
+ "POST /user_management/cors_origins": { name: "create_cors_origin" },
79
+ "POST /user_management/redirect_uris": { name: "create_redirect_uri" },
80
+ "POST /organizations": { name: "create_organization" },
81
+ "GET /directory_groups": { name: "list_groups" },
82
+ "GET /directory_groups/{id}": { name: "get_group" },
83
+ "GET /directory_users": { name: "list_users" },
84
+ "GET /directory_users/{id}": { name: "get_user" },
85
+ "POST /audit_logs/events": { name: "create_event" },
86
+ "POST /audit_logs/exports": { name: "create_export" },
87
+ "POST /audit_logs/actions/{actionName}/schemas": { name: "create_schema" },
88
+ "POST /feature-flags/{slug}/targets/{resourceId}": { name: "add_flag_target" },
89
+ "DELETE /feature-flags/{slug}/targets/{resourceId}": { name: "remove_flag_target" },
90
+ "GET /organizations/{id}/audit_log_configuration": { name: "get_audit_log_configuration" },
91
+ "GET /organizations/{id}/audit_logs_retention": {
92
+ name: "get_organization_audit_logs_retention",
93
+ mountOn: "AuditLogs"
94
+ },
95
+ "PUT /organizations/{id}/audit_logs_retention": { mountOn: "AuditLogs" },
96
+ "POST /user_management/authenticate": { split: [
97
+ {
98
+ name: "authenticate_with_password",
99
+ targetVariant: "PasswordSessionAuthenticateRequest",
100
+ defaults: { grant_type: "password" },
101
+ inferFromClient: ["client_id", "client_secret"],
102
+ exposedParams: [
103
+ "email",
104
+ "password",
105
+ "invitation_token",
106
+ "ip_address",
107
+ "device_id",
108
+ "user_agent"
109
+ ],
110
+ optionalParams: [
111
+ "invitation_token",
112
+ "ip_address",
113
+ "device_id",
114
+ "user_agent"
115
+ ]
116
+ },
117
+ {
118
+ name: "authenticate_with_code",
119
+ targetVariant: "AuthorizationCodeSessionAuthenticateRequest",
120
+ defaults: { grant_type: "authorization_code" },
121
+ inferFromClient: ["client_id", "client_secret"],
122
+ exposedParams: [
123
+ "code",
124
+ "code_verifier",
125
+ "invitation_token",
126
+ "ip_address",
127
+ "device_id",
128
+ "user_agent"
129
+ ],
130
+ optionalParams: [
131
+ "code_verifier",
132
+ "invitation_token",
133
+ "ip_address",
134
+ "device_id",
135
+ "user_agent"
136
+ ]
137
+ },
138
+ {
139
+ name: "authenticate_with_refresh_token",
140
+ targetVariant: "RefreshTokenSessionAuthenticateRequest",
141
+ defaults: { grant_type: "refresh_token" },
142
+ inferFromClient: ["client_id", "client_secret"],
143
+ exposedParams: [
144
+ "refresh_token",
145
+ "organization_id",
146
+ "ip_address",
147
+ "device_id",
148
+ "user_agent"
149
+ ],
150
+ optionalParams: [
151
+ "organization_id",
152
+ "ip_address",
153
+ "device_id",
154
+ "user_agent"
155
+ ]
156
+ },
157
+ {
158
+ name: "authenticate_with_magic_auth",
159
+ targetVariant: "MagicAuthCodeSessionAuthenticateRequest",
160
+ defaults: { grant_type: "urn:workos:oauth:grant-type:magic-auth:code" },
161
+ inferFromClient: ["client_id", "client_secret"],
162
+ exposedParams: [
163
+ "code",
164
+ "email",
165
+ "invitation_token",
166
+ "ip_address",
167
+ "device_id",
168
+ "user_agent"
169
+ ],
170
+ optionalParams: [
171
+ "invitation_token",
172
+ "ip_address",
173
+ "device_id",
174
+ "user_agent"
175
+ ]
176
+ },
177
+ {
178
+ name: "authenticate_with_email_verification",
179
+ targetVariant: "EmailVerificationCodeSessionAuthenticateRequest",
180
+ defaults: { grant_type: "urn:workos:oauth:grant-type:email-verification:code" },
181
+ inferFromClient: ["client_id", "client_secret"],
182
+ exposedParams: [
183
+ "code",
184
+ "pending_authentication_token",
185
+ "ip_address",
186
+ "device_id",
187
+ "user_agent"
188
+ ],
189
+ optionalParams: [
190
+ "ip_address",
191
+ "device_id",
192
+ "user_agent"
193
+ ]
194
+ },
195
+ {
196
+ name: "authenticate_with_totp",
197
+ targetVariant: "MFATotpSessionAuthenticateRequest",
198
+ defaults: { grant_type: "urn:workos:oauth:grant-type:mfa-totp" },
199
+ inferFromClient: ["client_id", "client_secret"],
200
+ exposedParams: [
201
+ "code",
202
+ "pending_authentication_token",
203
+ "authentication_challenge_id",
204
+ "ip_address",
205
+ "device_id",
206
+ "user_agent"
207
+ ],
208
+ optionalParams: [
209
+ "ip_address",
210
+ "device_id",
211
+ "user_agent"
212
+ ]
213
+ },
214
+ {
215
+ name: "authenticate_with_organization_selection",
216
+ targetVariant: "OrganizationSelectionSessionAuthenticateRequest",
217
+ defaults: { grant_type: "urn:workos:oauth:grant-type:organization-selection" },
218
+ inferFromClient: ["client_id", "client_secret"],
219
+ exposedParams: [
220
+ "pending_authentication_token",
221
+ "organization_id",
222
+ "ip_address",
223
+ "device_id",
224
+ "user_agent"
225
+ ],
226
+ optionalParams: [
227
+ "ip_address",
228
+ "device_id",
229
+ "user_agent"
230
+ ]
231
+ },
232
+ {
233
+ name: "authenticate_with_device_code",
234
+ targetVariant: "DeviceCodeSessionAuthenticateRequest",
235
+ defaults: { grant_type: "urn:ietf:params:oauth:grant-type:device_code" },
236
+ inferFromClient: ["client_id"],
237
+ exposedParams: [
238
+ "device_code",
239
+ "ip_address",
240
+ "device_id",
241
+ "user_agent"
242
+ ],
243
+ optionalParams: [
244
+ "ip_address",
245
+ "device_id",
246
+ "user_agent"
247
+ ]
248
+ }
249
+ ] },
250
+ "POST /connect/applications": { split: [{
251
+ name: "create_oauth_application",
252
+ targetVariant: "CreateOAuthApplication",
253
+ defaults: { application_type: "oauth" },
254
+ exposedParams: [
255
+ "name",
256
+ "is_first_party",
257
+ "description",
258
+ "scopes",
259
+ "redirect_uris",
260
+ "uses_pkce",
261
+ "organization_id"
262
+ ]
263
+ }, {
264
+ name: "create_m2m_application",
265
+ targetVariant: "CreateM2MApplication",
266
+ defaults: { application_type: "m2m" },
267
+ exposedParams: [
268
+ "name",
269
+ "organization_id",
270
+ "description",
271
+ "scopes"
272
+ ]
273
+ }] }
274
+ };
275
+ //#endregion
276
+ //#region src/policy/mount-rules.ts
277
+ /**
278
+ * Service-level remounting. Maps IR service name → target service/namespace
279
+ * (PascalCase). All operations in the source service are mounted on the
280
+ * target unless overridden per-operation in {@link operationHints}.
281
+ */
282
+ const mountRules = {
283
+ MultiFactorAuthChallenges: "MultiFactorAuth",
284
+ Permissions: "Authorization",
285
+ WorkosConnect: "Connect",
286
+ Applications: "Connect",
287
+ ApplicationClientSecrets: "Connect",
288
+ Connections: "SSO",
289
+ Directories: "DirectorySync",
290
+ DirectoryGroups: "DirectorySync",
291
+ DirectoryUsers: "DirectorySync",
292
+ FeatureFlagsTargets: "FeatureFlags",
293
+ OrganizationsFeatureFlags: "FeatureFlags",
294
+ UserManagementUsersFeatureFlags: "FeatureFlags",
295
+ OrganizationsApiKeys: "ApiKeys",
296
+ UserManagementSessionTokens: "UserManagement",
297
+ UserManagementAuthentication: "UserManagement",
298
+ UserManagementCorsOrigins: "UserManagement",
299
+ UserManagementUsers: "UserManagement",
300
+ UserManagementInvitations: "UserManagement",
301
+ UserManagementJWTTemplate: "UserManagement",
302
+ UserManagementMagicAuth: "UserManagement",
303
+ UserManagementOrganizationMembership: "OrganizationMembership",
304
+ UserManagementOrganizationMembershipGroups: "OrganizationMembership",
305
+ UserManagementRedirectUris: "UserManagement",
306
+ UserManagementUsersAuthorizedApplications: "UserManagement",
307
+ UserManagementDataProviders: "Pipes",
308
+ UserManagementMultiFactorAuthentication: "MultiFactorAuth"
309
+ };
310
+ //#endregion
311
+ //#region src/policy/model-hints.ts
312
+ /**
313
+ * Model placement hints — used by emitters that call
314
+ * `assignModelsToServices` so hinted models land in the configured service
315
+ * instead of the default first-reference winner.
316
+ */
317
+ const modelHints = {
318
+ User: "UserManagementUsers",
319
+ UserOrganizationMembershipBaseListData: "Groups",
320
+ UserApiKeyOwner: "UserManagementUsers"
321
+ };
322
+ //#endregion
323
+ //#region src/policy/transforms.ts
324
+ /**
325
+ * NestJS-style operationId transform. Strips "Controller" and extracts the
326
+ * action after the first underscore: `FooController_bar` -> `bar`.
327
+ */
328
+ function nestjsOperationIdTransform(id) {
329
+ const stripped = id.replace(/Controller/g, "");
330
+ const idx = stripped.indexOf("_");
331
+ return idx !== -1 ? toCamelCase(stripped.slice(idx + 1)) : toCamelCase(stripped);
332
+ }
333
+ /**
334
+ * Explicit renames plus suffix stripping applied during IR schema extraction.
335
+ * Keeps `Dto`/`Json`/`Urn…` schema names consistent with the names already
336
+ * exposed by the published SDKs.
337
+ */
338
+ const COLLISION_RENAMES = {
339
+ Error: "ErrorResponse",
340
+ Object: "VaultObject",
341
+ OrganizationDto: "OrganizationInput",
342
+ RedirectUriDto: "RedirectUriInput",
343
+ AuditLogSchemaDto: "AuditLogSchemaInput",
344
+ AuditLogSchemaActorDto: "AuditLogSchemaActorInput",
345
+ AuditLogSchemaTargetDto: "AuditLogSchemaTargetInput",
346
+ ListData: "Role",
347
+ ListModel: "RoleList",
348
+ EventListListMetadata: "EventListMetadata",
349
+ RadarAction: "RadarListAction",
350
+ RadarType: "RadarListType"
351
+ };
352
+ function schemaNameTransform(name) {
353
+ if (COLLISION_RENAMES[name]) return COLLISION_RENAMES[name];
354
+ return name.replace(/Dto/g, "").replace(/DTO/g, "").replace(/Json$/, "").replace(/^Urn(?:IetfParams|Workos)O[Aa]uthGrantType/, "");
355
+ }
356
+ /**
357
+ * Pre-IR spec overlay — patch around upstream spec quirks that would otherwise
358
+ * emit breaking SDK changes. See docs/breaking-change-playbook.md and the
359
+ * oagen `transformSpec` docs for usage. Reach for this only when the upstream
360
+ * fix can't land in time AND the change is genuinely additive.
361
+ */
362
+ function transformSpec(spec) {
363
+ const schemas = spec.components?.schemas;
364
+ const paths = spec.paths;
365
+ if (!schemas || !paths) return spec;
366
+ const forkedListRef = "#/components/schemas/UserlandUserOrganizationMembershipBaseWithUserList";
367
+ const originalListRef = "#/components/schemas/UserlandUserOrganizationMembershipBaseList";
368
+ for (const pathItem of Object.values(paths)) for (const op of Object.values(pathItem)) {
369
+ const schema = op.responses?.["200"]?.content?.["application/json"]?.schema;
370
+ if (schema?.$ref === forkedListRef) schema.$ref = originalListRef;
371
+ }
372
+ const itemProps = schemas["UserlandUserOrganizationMembershipBaseList"]?.properties?.data?.items;
373
+ if (itemProps?.properties && !itemProps.properties.user) {
374
+ itemProps.properties.user = {
375
+ $ref: "#/components/schemas/UserlandUser",
376
+ description: "The user that belongs to the organization through this membership."
377
+ };
378
+ if (itemProps.required && !itemProps.required.includes("user")) itemProps.required.push("user");
379
+ }
380
+ delete schemas["UserlandUserOrganizationMembershipBaseWithUser"];
381
+ delete schemas["UserlandUserOrganizationMembershipBaseWithUserList"];
382
+ if (schemas["JwtTemplate"] && !schemas["JwtTemplateResponse"]) {
383
+ schemas["JwtTemplateResponse"] = schemas["JwtTemplate"];
384
+ delete schemas["JwtTemplate"];
385
+ const oldRef = "#/components/schemas/JwtTemplate";
386
+ const newRef = "#/components/schemas/JwtTemplateResponse";
387
+ for (const pathItem of Object.values(paths)) for (const op of Object.values(pathItem)) {
388
+ const responses = op.responses;
389
+ for (const response of Object.values(responses ?? {})) {
390
+ const schema = response.content?.["application/json"]?.schema;
391
+ if (schema?.$ref === oldRef) schema.$ref = newRef;
392
+ }
393
+ }
394
+ }
395
+ return spec;
396
+ }
397
+ //#endregion
398
+ export { modelHints, mountRules, nestjsOperationIdTransform, operationHints, schemaNameTransform, transformSpec };