@contember/engine-tenant-api 2.2.0-alpha.5 → 2.2.0-alpha.6
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.
- package/CLAUDE.md +1 -0
- package/dist/development/index.cjs +2 -0
- package/dist/development/index.cjs.map +1 -1
- package/dist/development/index.js +2 -0
- package/dist/development/index.js.map +1 -1
- package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs +18 -0
- package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs.map +1 -0
- package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js +19 -0
- package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js.map +1 -0
- package/dist/development/src/migrations/runner.cjs +3 -1
- package/dist/development/src/migrations/runner.cjs.map +1 -1
- package/dist/development/src/migrations/runner.js +3 -1
- package/dist/development/src/migrations/runner.js.map +1 -1
- package/dist/development/src/migrations/snapshot.cjs +2 -1
- package/dist/development/src/migrations/snapshot.cjs.map +1 -1
- package/dist/development/src/migrations/snapshot.js +2 -1
- package/dist/development/src/migrations/snapshot.js.map +1 -1
- package/dist/development/src/model/commands/idp/CreateIdpCommand.cjs +8 -2
- package/dist/development/src/model/commands/idp/CreateIdpCommand.cjs.map +1 -1
- package/dist/development/src/model/commands/idp/CreateIdpCommand.js +8 -2
- package/dist/development/src/model/commands/idp/CreateIdpCommand.js.map +1 -1
- package/dist/development/src/model/commands/idp/UpdateIdpCommand.cjs +6 -2
- package/dist/development/src/model/commands/idp/UpdateIdpCommand.cjs.map +1 -1
- package/dist/development/src/model/commands/idp/UpdateIdpCommand.js +6 -2
- package/dist/development/src/model/commands/idp/UpdateIdpCommand.js.map +1 -1
- package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs +21 -0
- package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs.map +1 -0
- package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js +21 -0
- package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js.map +1 -0
- package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.cjs +1 -1
- package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.cjs.map +1 -1
- package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.js +1 -1
- package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.js.map +1 -1
- package/dist/development/src/model/queries/idp/helpers.cjs +3 -3
- package/dist/development/src/model/queries/idp/helpers.cjs.map +1 -1
- package/dist/development/src/model/queries/idp/helpers.js +3 -3
- package/dist/development/src/model/queries/idp/helpers.js.map +1 -1
- package/dist/development/src/model/service/PasswordResetManager.cjs +5 -0
- package/dist/development/src/model/service/PasswordResetManager.cjs.map +1 -1
- package/dist/development/src/model/service/PasswordResetManager.js +5 -0
- package/dist/development/src/model/service/PasswordResetManager.js.map +1 -1
- package/dist/development/src/model/service/PasswordlessSignInManager.cjs +19 -0
- package/dist/development/src/model/service/PasswordlessSignInManager.cjs.map +1 -1
- package/dist/development/src/model/service/PasswordlessSignInManager.js +19 -0
- package/dist/development/src/model/service/PasswordlessSignInManager.js.map +1 -1
- package/dist/development/src/model/service/SignInManager.cjs +5 -0
- package/dist/development/src/model/service/SignInManager.cjs.map +1 -1
- package/dist/development/src/model/service/SignInManager.js +5 -0
- package/dist/development/src/model/service/SignInManager.js.map +1 -1
- package/dist/development/src/model/service/idp/PersonIdentityProviderManager.cjs +6 -0
- package/dist/development/src/model/service/idp/PersonIdentityProviderManager.cjs.map +1 -1
- package/dist/development/src/model/service/idp/PersonIdentityProviderManager.js +6 -0
- package/dist/development/src/model/service/idp/PersonIdentityProviderManager.js.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs +2 -1
- package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.js +2 -1
- package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.js.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs +2 -1
- package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js +2 -1
- package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/audit.cjs +1 -0
- package/dist/development/src/resolvers/mutation/idp/audit.cjs.map +1 -1
- package/dist/development/src/resolvers/mutation/idp/audit.js +1 -0
- package/dist/development/src/resolvers/mutation/idp/audit.js.map +1 -1
- package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs +4 -0
- package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs.map +1 -1
- package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.js +4 -0
- package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.js.map +1 -1
- package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.cjs +2 -2
- package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.cjs.map +1 -1
- package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.js +2 -2
- package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.js.map +1 -1
- package/dist/development/src/schema/tenant.graphql.cjs +28 -0
- package/dist/development/src/schema/tenant.graphql.cjs.map +1 -1
- package/dist/development/src/schema/tenant.graphql.js +28 -0
- package/dist/development/src/schema/tenant.graphql.js.map +1 -1
- package/dist/production/index.cjs +2 -0
- package/dist/production/index.cjs.map +1 -1
- package/dist/production/index.js +2 -0
- package/dist/production/index.js.map +1 -1
- package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs +18 -0
- package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs.map +1 -0
- package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js +19 -0
- package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js.map +1 -0
- package/dist/production/src/migrations/runner.cjs +3 -1
- package/dist/production/src/migrations/runner.cjs.map +1 -1
- package/dist/production/src/migrations/runner.js +3 -1
- package/dist/production/src/migrations/runner.js.map +1 -1
- package/dist/production/src/migrations/snapshot.cjs +2 -1
- package/dist/production/src/migrations/snapshot.cjs.map +1 -1
- package/dist/production/src/migrations/snapshot.js +2 -1
- package/dist/production/src/migrations/snapshot.js.map +1 -1
- package/dist/production/src/model/commands/idp/CreateIdpCommand.cjs +8 -2
- package/dist/production/src/model/commands/idp/CreateIdpCommand.cjs.map +1 -1
- package/dist/production/src/model/commands/idp/CreateIdpCommand.js +8 -2
- package/dist/production/src/model/commands/idp/CreateIdpCommand.js.map +1 -1
- package/dist/production/src/model/commands/idp/UpdateIdpCommand.cjs +6 -2
- package/dist/production/src/model/commands/idp/UpdateIdpCommand.cjs.map +1 -1
- package/dist/production/src/model/commands/idp/UpdateIdpCommand.js +6 -2
- package/dist/production/src/model/commands/idp/UpdateIdpCommand.js.map +1 -1
- package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs +21 -0
- package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs.map +1 -0
- package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js +21 -0
- package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js.map +1 -0
- package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.cjs +1 -1
- package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.cjs.map +1 -1
- package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.js +1 -1
- package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.js.map +1 -1
- package/dist/production/src/model/queries/idp/helpers.cjs +3 -3
- package/dist/production/src/model/queries/idp/helpers.cjs.map +1 -1
- package/dist/production/src/model/queries/idp/helpers.js +3 -3
- package/dist/production/src/model/queries/idp/helpers.js.map +1 -1
- package/dist/production/src/model/service/PasswordResetManager.cjs +5 -0
- package/dist/production/src/model/service/PasswordResetManager.cjs.map +1 -1
- package/dist/production/src/model/service/PasswordResetManager.js +5 -0
- package/dist/production/src/model/service/PasswordResetManager.js.map +1 -1
- package/dist/production/src/model/service/PasswordlessSignInManager.cjs +19 -0
- package/dist/production/src/model/service/PasswordlessSignInManager.cjs.map +1 -1
- package/dist/production/src/model/service/PasswordlessSignInManager.js +19 -0
- package/dist/production/src/model/service/PasswordlessSignInManager.js.map +1 -1
- package/dist/production/src/model/service/SignInManager.cjs +5 -0
- package/dist/production/src/model/service/SignInManager.cjs.map +1 -1
- package/dist/production/src/model/service/SignInManager.js +5 -0
- package/dist/production/src/model/service/SignInManager.js.map +1 -1
- package/dist/production/src/model/service/idp/PersonIdentityProviderManager.cjs +6 -0
- package/dist/production/src/model/service/idp/PersonIdentityProviderManager.cjs.map +1 -1
- package/dist/production/src/model/service/idp/PersonIdentityProviderManager.js +6 -0
- package/dist/production/src/model/service/idp/PersonIdentityProviderManager.js.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs +2 -1
- package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.js +2 -1
- package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.js.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs +2 -1
- package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js +2 -1
- package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/audit.cjs +1 -0
- package/dist/production/src/resolvers/mutation/idp/audit.cjs.map +1 -1
- package/dist/production/src/resolvers/mutation/idp/audit.js +1 -0
- package/dist/production/src/resolvers/mutation/idp/audit.js.map +1 -1
- package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs +4 -0
- package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs.map +1 -1
- package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.js +4 -0
- package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.js.map +1 -1
- package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.cjs +2 -2
- package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.cjs.map +1 -1
- package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.js +2 -2
- package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.js.map +1 -1
- package/dist/production/src/schema/tenant.graphql.cjs +28 -0
- package/dist/production/src/schema/tenant.graphql.cjs.map +1 -1
- package/dist/production/src/schema/tenant.graphql.js +28 -0
- package/dist/production/src/schema/tenant.graphql.js.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/passwordless.d.ts +3 -0
- package/dist/tests/cases/integration/mocked/gql/passwordless.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/localAuthenticationDisabled.test.d.ts +2 -0
- package/dist/tests/cases/integration/mocked/localAuthenticationDisabled.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.d.ts +10 -0
- package/dist/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.d.ts.map +1 -0
- package/dist/tests/cases/integration/mocked/sql/personIdentityProvidersSql.d.ts +1 -0
- package/dist/tests/cases/integration/mocked/sql/personIdentityProvidersSql.d.ts.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/dist/types/migrations/2026-09-04-120000-idp-disable-local-authentication.d.ts +3 -0
- package/dist/types/migrations/2026-09-04-120000-idp-disable-local-authentication.d.ts.map +1 -0
- package/dist/types/migrations/runner.d.ts.map +1 -1
- package/dist/types/migrations/snapshot.d.ts.map +1 -1
- package/dist/types/model/commands/idp/CreateIdpCommand.d.ts.map +1 -1
- package/dist/types/model/commands/idp/UpdateIdpCommand.d.ts.map +1 -1
- package/dist/types/model/queries/idp/LocalAuthDisablingIdpsQuery.d.ts +18 -0
- package/dist/types/model/queries/idp/LocalAuthDisablingIdpsQuery.d.ts.map +1 -0
- package/dist/types/model/queries/idp/PersonIdentityProvidersQuery.d.ts +1 -0
- package/dist/types/model/queries/idp/PersonIdentityProvidersQuery.d.ts.map +1 -1
- package/dist/types/model/queries/idp/helpers.d.ts +1 -1
- package/dist/types/model/queries/idp/helpers.d.ts.map +1 -1
- package/dist/types/model/queries/idp/index.d.ts +1 -0
- package/dist/types/model/queries/idp/index.d.ts.map +1 -1
- package/dist/types/model/queries/idp/types.d.ts +1 -0
- package/dist/types/model/queries/idp/types.d.ts.map +1 -1
- package/dist/types/model/service/PasswordResetManager.d.ts.map +1 -1
- package/dist/types/model/service/PasswordlessSignInManager.d.ts.map +1 -1
- package/dist/types/model/service/SignInManager.d.ts.map +1 -1
- package/dist/types/model/service/idp/PersonIdentityProviderManager.d.ts.map +1 -1
- package/dist/types/model/type/IdentityProvider.d.ts +2 -0
- package/dist/types/model/type/IdentityProvider.d.ts.map +1 -1
- package/dist/types/resolvers/mutation/idp/AddIDPMutationResolver.d.ts.map +1 -1
- package/dist/types/resolvers/mutation/idp/UpdateIDPMutationResolver.d.ts.map +1 -1
- package/dist/types/resolvers/mutation/idp/audit.d.ts.map +1 -1
- package/dist/types/resolvers/mutation/person/PasswordlessMutationResolver.d.ts.map +1 -1
- package/dist/types/schema/index.d.ts +33 -4
- package/dist/types/schema/index.d.ts.map +1 -1
- package/dist/types/schema/tenant.graphql.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/src/migrations/2026-09-04-120000-idp-disable-local-authentication.ts +18 -0
- package/src/migrations/runner.ts +2 -0
- package/src/migrations/snapshot.ts +2 -1
- package/src/model/commands/idp/CreateIdpCommand.ts +7 -1
- package/src/model/commands/idp/UpdateIdpCommand.ts +5 -1
- package/src/model/queries/idp/LocalAuthDisablingIdpsQuery.ts +41 -0
- package/src/model/queries/idp/PersonIdentityProvidersQuery.ts +2 -0
- package/src/model/queries/idp/helpers.ts +3 -2
- package/src/model/queries/idp/index.ts +1 -0
- package/src/model/queries/idp/types.ts +1 -0
- package/src/model/service/PasswordResetManager.ts +9 -1
- package/src/model/service/PasswordlessSignInManager.ts +23 -1
- package/src/model/service/SignInManager.ts +9 -1
- package/src/model/service/idp/PersonIdentityProviderManager.ts +8 -0
- package/src/model/type/IdentityProvider.ts +2 -0
- package/src/resolvers/mutation/idp/AddIDPMutationResolver.ts +1 -0
- package/src/resolvers/mutation/idp/UpdateIDPMutationResolver.ts +1 -0
- package/src/resolvers/mutation/idp/audit.ts +1 -0
- package/src/resolvers/mutation/person/PasswordlessMutationResolver.ts +7 -0
- package/src/resolvers/mutation/person/SignInMutationResolver.ts +2 -2
- package/src/schema/index.ts +29 -0
- package/src/schema/tenant.graphql.ts +28 -0
- package/tests/cases/integration/mocked/gql/passwordless.ts +10 -0
- package/tests/cases/integration/mocked/idpClaimMappingConfig.test.ts +4 -4
- package/tests/cases/integration/mocked/localAuthenticationDisabled.test.ts +182 -0
- package/tests/cases/integration/mocked/personIdentityProviders.test.ts +67 -0
- package/tests/cases/integration/mocked/signInAnomalyDetection.test.ts +11 -0
- package/tests/cases/integration/mocked/signInIdpClaimMapping.test.ts +14 -0
- package/tests/cases/integration/mocked/signInIdpClaimMappingFixes.test.ts +4 -0
- package/tests/cases/integration/mocked/signInIdpClaimMappingSafety.test.ts +6 -0
- package/tests/cases/integration/mocked/signInIdpMutation.test.ts +5 -0
- package/tests/cases/integration/mocked/signInMfaEnforcement.test.ts +7 -0
- package/tests/cases/integration/mocked/signInMutation.test.ts +14 -0
- package/tests/cases/integration/mocked/signInPasswordlessMutation.test.ts +36 -0
- package/tests/cases/integration/mocked/sql/getIdpBySlugSql.ts +1 -1
- package/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.ts +21 -0
- package/tests/cases/integration/mocked/sql/personIdentityProvidersSql.ts +3 -1
- package/tests/cases/integration/mocked/trustForwardedClientInfo.test.ts +3 -0
- package/tests/cases/unit/idp/idpManagerUnknownConfigKeys.test.ts +8 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.graphql.js","sources":["../../../../../packages/engine-tenant-api/src/schema/tenant.graphql.ts"],"sourcesContent":["import { gql } from 'graphql-tag'\nimport { DocumentNode } from 'graphql'\n\nconst schema: DocumentNode = gql`\n\tscalar Json\n\tscalar DateTime\n\t\n\t\"\"\" Interval is a string in the format ISO 8601, e.g. \"PT1H\" for 1 hour \"\"\"\n\tscalar Interval\n\n\tschema {\n\t\tquery: Query\n\t\tmutation: Mutation\n\t}\n\n\ttype Query {\n\t\tme: Identity!\n\t\tpersonById(id: String!): Person\n\t\t\"\"\"\n\t\tList persons across the tenant. SUPER_ADMIN sees every person; otherwise\n\t\tthe result is scoped to persons who are members of a project the caller may\n\t\tview members of (i.e. the same persons reachable via \\`project.members\\`),\n\t\tso a PROJECT_ADMIN sees only their projects' members. \\`filter\\` matches by\n\t\te-mail (case-insensitive), \\`personId\\`, or \\`identityId\\`; \\`limit\\`/\\`offset\\`\n\t\tpaginate. Returns an empty list when the caller may not list anyone.\n\t\t\"\"\"\n\t\tpersons(filter: PersonsFilter, limit: Int, offset: Int): [Person!]!\n\t\tprojects: [Project!]!\n\t\tprojectBySlug(slug: String!): Project\n\t\tprojectMemberships(projectSlug: String!, identityId: String!): [Membership!]!\n\t\t\"\"\"\n\t\tList global (project-independent) permanent API keys — those created via\n\t\t\\`createGlobalApiKey\\`, whose identity carries global roles and no project\n\t\tmembership. Requires the \\`apiKey:list\\` permission — by default granted\n\t\tonly to SUPER_ADMIN via the wildcard ALL-resource/ALL-privilege grant.\n\t\tReturns an empty list when the caller may not list them. To list a\n\t\tproject's keys use \\`project.apiKeys\\`.\n\t\t\"\"\"\n\t\tglobalApiKeys: [ApiKey!]!\n\t\tcheckResetPasswordToken(requestId: String!, token: String!): CheckResetPasswordTokenCode!\n\n\t\tidentityProviders: [IdentityProvider!]!\n\n\t\tmailTemplates: [MailTemplateData!]!\n\n\t\tconfiguration: Config!\n\n\t\t\"\"\"\n\t\tList configured auth policies (per-role MFA / session policy). Requires the\n\t\t\\`system:configure\\` permission — by default granted only to SUPER_ADMIN\n\t\t(and PROJECT_ADMIN, like \\`configure\\`). With no rows configured, MFA\n\t\tenforcement is inert and sign-in behaves exactly as today.\n\t\t\"\"\"\n\t\tauthPolicies: [AuthPolicy!]!\n\n\t\t\"\"\"\n\t\tRead the tenant audit log (\\`person_auth_log\\`). Requires the\n\t\t\\`system:viewAuthLog\\` permission — by default granted only to\n\t\tSUPER_ADMIN via the wildcard ALL-resource/ALL-privilege grant.\n\t\tOrdered by created_at DESC. Page size is capped server-side\n\t\t(default 100, max 500); \\`hasMore\\` indicates a further page exists.\n\t\t\"\"\"\n\t\tauthLog(filter: AuthLogFilter, limit: Int, offset: Int): AuthLogPage!\n\t}\n\n\ttype Mutation {\n\t\tsignUp(email: String!, password: String, passwordHash: String, roles: [String!], name: String, captchaToken: String): SignUpResponse\n\t\tsignIn(email: String!, password: String!, expiration: Int, otpToken: String, backupCode: String, options: SignInOptions): SignInResponse\n\t\tcreateSessionToken(email: String, personId: String, expiration: Int, options: SignInOptions): CreateSessionTokenResponse\n\t\tsignOut(all: Boolean): SignOutResponse\n\t\tchangeProfile(personId: String!, email: String, name: String): ChangeProfileResponse\n\t\tchangeMyProfile(email: String, name: String): ChangeMyProfileResponse\n\t\tchangePassword(personId: String!, password: String!): ChangePasswordResponse\n\t\tchangeMyPassword(currentPassword: String!, newPassword: String!): ChangeMyPasswordResponse\n\n\t\tinitSignInIDP(\n\t\t\tidentityProvider: String!,\n\t\t\tdata: Json\n\t\t\tredirectUrl: String @deprecated(reason: \"use data.redirectUrl\")\n\t\t): InitSignInIDPResponse\n\t\tsignInIDP(\n\t\t\tidentityProvider: String!,\n\t\t\tdata: Json,\n\t\t\texpiration: Int\n\t\t\toptions: SignInOptions\n\t\t\tidpResponse: IDPResponseInput, @deprecated(reason: \"pass idpResponse.url as data.url\")\n\t\t\tredirectUrl: String @deprecated(reason: \"use data.redirectUrl\"),\n\t\t\tsessionData: Json @deprecated(reason: \"use data.sessionData\"),\n\t\t): SignInIDPResponse\n\t\t\n\t\t# passwordless sign in\n\t\tinitSignInPasswordless(email: String!, options: InitSignInPasswordlessOptions, captchaToken: String): InitSignInPasswordlessResponse\n\t\tsignInPasswordless(requestId: String!, validationType: PasswordlessValidationType!, token: String!, expiration: Int, mfaOtp: String, backupCode: String, options: SignInOptions): SignInPasswordlessResponse\n\t\tactivatePasswordlessOtp(requestId: String!, token: String!, otpHash: String!): ActivatePasswordlessOtpResponse\n\n enableMyPasswordless: ToggleMyPasswordlessResponse\n disableMyPasswordless: ToggleMyPasswordlessResponse\n\n\t\t# IDP management\n\t\taddIDP(identityProvider: String!, type: String!, configuration: Json!, options: IDPOptions): AddIDPResponse\n\t\tupdateIDP(identityProvider: String!, type: String, configuration: Json, options: IDPOptions, mergeConfiguration: Boolean): UpdateIDPResponse\n\t\tdisableIDP(identityProvider: String!): DisableIDPResponse\n\t\tenableIDP(identityProvider: String!): EnableIDPResponse\n\n\t\t\"\"\"\n\t\tDisconnect one of the authenticated person's own external IdP connections,\n\t\taddressed by the connection id (see PersonIdentityProvider.id) so a specific\n\t\tconnection can be removed even when the person has several to one provider.\n\t\t\"\"\"\n\t\tdisconnectMyIdentityProvider(id: String!): DisconnectIDPResponse\n\n\t\tprepareOtp(label: String): PrepareOtpResponse\n\t\tconfirmOtp(otpToken: String!): ConfirmOtpResponse\n\t\tdisableOtp: DisableOtpResponse\n\t\tregenerateBackupCodes: RegenerateBackupCodesResponse\n\n\t\tinitEmailOtp: InitEmailOtpResponse\n\t\tconfirmEmailOtp(otpToken: String!): ConfirmEmailOtpResponse\n\t\tdisableEmailOtp: DisableEmailOtpResponse\n\n\t\tdisablePerson(personId: String!): DisablePersonResponse\n\t\tenablePerson(personId: String!): EnablePersonResponse\n\t\tforceSignOutPerson(personId: String!, reason: String): ForceSignOutPersonResponse\n\t\tresetPersonMfa(personId: String!): ResetPersonMfaResponse\n\t\trevokeSession(sessionId: String!): RevokeSessionResponse\n\n\t\tcreateResetPasswordRequest(email: String!, options: CreateResetPasswordRequestOptions, captchaToken: String): CreatePasswordResetRequestResponse\n\t\tresetPassword(token: String!, password: String!): ResetPasswordResponse\n\n\t\t\"\"\"\n\t\t(Re)send the e-mail verification link for the given address. Always\n\t\treports ok regardless of whether the address exists or is already\n\t\tverified, to avoid leaking account existence.\n\t\t\"\"\"\n\t\trequestEmailVerification(email: String!, options: EmailVerificationOptions, captchaToken: String): RequestEmailVerificationResponse\n\t\tverifyEmail(token: String!): VerifyEmailResponse\n\t\t\"\"\"\n\t\tConfirm a pending e-mail change (see changeMyProfile when\n\t\tconfig.signup.requireEmailVerification is enabled). Consumes the token\n\t\tthat was mailed to the new address, swaps the address, and signs out all\n\t\texisting sessions.\n\t\t\"\"\"\n\t\tconfirmEmailChange(token: String!): ConfirmEmailChangeResponse\n\n\t\tinvite(email: String!, name: String, projectSlug: String!, memberships: [MembershipInput!]!, options: InviteOptions): InviteResponse\n\t\tunmanagedInvite(\n\t\t\temail: String!,\n\t\t\tname: String,\n\t\t\tprojectSlug: String!,\n\t\t\tmemberships: [MembershipInput!]!,\n\t\t\toptions: UnmanagedInviteOptions,\n\t\t\tpassword: String @deprecated(reason: \"Use options\")\n\t\t): InviteResponse\n\n\t\taddProjectMember(projectSlug: String!, identityId: String!, memberships: [MembershipInput!]!): AddProjectMemberResponse\n\t\tremoveProjectMember(projectSlug: String!, identityId: String!): RemoveProjectMemberResponse\n\n\t\tupdateProjectMember(projectSlug: String!, identityId: String!, memberships: [MembershipInput!]!): UpdateProjectMemberResponse\n\n\t\tcreateApiKey(projectSlug: String!, memberships: [MembershipInput!]!, description: String!, tokenHash: String, options: CreateApiKeyOptions): CreateApiKeyResponse\n\t\tcreateGlobalApiKey(description: String!, roles: [String!], tokenHash: String, options: CreateApiKeyOptions): CreateApiKeyResponse\n\t\tdisableApiKey(id: String!): DisableApiKeyResponse\n\t\taddGlobalIdentityRoles(identityId: String!, roles: [String!]!): AddGlobalIdentityRolesResponse\n\t\tremoveGlobalIdentityRoles(identityId: String!, roles: [String!]!): RemoveGlobalIdentityRolesResponse\n\n\t\taddMailTemplate(template: MailTemplate!): AddMailTemplateResponse\n\t\tremoveMailTemplate(templateIdentifier: MailTemplateIdentifier!): RemoveMailTemplateResponse\n\n\t\tcreateProject(\n\t\t\tprojectSlug: String!,\n\t\t\tname: String,\n\t\t\tconfig: Json,\n\t\t\tsecrets: [ProjectSecret!],\n\t\t\toptions: CreateProjectOptions,\n\t\t\tdeployTokenHash: String @deprecated(reason: \"Use options\")\n\t\t): CreateProjectResponse\n\t\tsetProjectSecret(projectSlug: String!, key: String!, value: String!): SetProjectSecretResponse\n\t\tupdateProject(projectSlug: String!, name: String, config: Json, mergeConfig: Boolean): UpdateProjectResponse\n\t\t\n\t\tconfigure(config: ConfigInput!): ConfigureResponse\n\n\t\t# === auth policy (per-role MFA / session policy) ===\n\t\tcreateAuthPolicy(policy: AuthPolicyInput!): CreateAuthPolicyResponse\n\t\tupdateAuthPolicy(id: String!, policy: AuthPolicyInput!): UpdateAuthPolicyResponse\n\t\tdeleteAuthPolicy(id: String!): DeleteAuthPolicyResponse\n\n\t\taddProjectMailTemplate(template: MailTemplate!): AddMailTemplateResponse\n\t\t@deprecated(reason: \"use addMailTemplate\")\n\n\t\tremoveProjectMailTemplate(templateIdentifier: MailTemplateIdentifier!): RemoveMailTemplateResponse\n\t\t@deprecated(reason: \"use removeMailTemplate\")\n\n\t}\n\t\n\t# === configure ===\n\t\n\ttype Config {\n\t\tsignup: ConfigSignup!\n\t\temailChange: ConfigEmailChange!\n\t\tpasswordless: ConfigPasswordless!\n\t\tpassword: ConfigPassword!\n\t\tlogin: ConfigLogin!\n\t\tcaptcha: ConfigCaptcha!\n\t\trateLimits: ConfigRateLimits!\n\t\tpanel: ConfigPanel!\n\t}\n\n\ttype ConfigSignup {\n\t\t\"\"\"\n\t\tWhen true, new accounts must verify their e-mail address before they can\n\t\tsign in. The requirement is captured per account at sign-up, so toggling\n\t\tthis only affects accounts created afterwards. Defaults to false (no\n\t\tchange vs. previous behavior). E-mail changes are governed separately by\n\t\tConfigEmailChange.requireVerification.\n\t\t\"\"\"\n\t\trequireEmailVerification: Boolean!\n\t}\n\n\ttype ConfigEmailChange {\n\t\t\"\"\"\n\t\tWhen true, a user-initiated changeMyProfile e-mail change does not swap\n\t\tthe address immediately: it goes through a confirmation flow\n\t\t(confirmEmailChange) against a token mailed to the new address, and the\n\t\told address stays active until the new one is confirmed. Independent of\n\t\tConfigSignup.requireEmailVerification. Defaults to false.\n\t\t\"\"\"\n\t\trequireVerification: Boolean!\n\t}\n\n\ttype ConfigPasswordless {\n\t\tenabled: ConfigPolicy!\n\t\turl: String\n\t\texpiration: Interval!\n\t}\n\n\ttype ConfigPassword {\n\t\tminLength: Int!\n\t\trequireUppercase: Int!\n\t\trequireLowercase: Int!\n\t\trequireDigit: Int!\n\t\trequireSpecial: Int!\n\t\tpattern: String\n\t\tcheckBlacklist: Boolean!\n\t\tcheckHibp: Boolean!\n }\n\n\ttype ConfigLogin {\n\t\tbaseBackoff: Interval!\n\t\tmaxBackoff: Interval!\n\t\tattemptWindow: Interval!\n\t\trevealUserExists: Boolean!\n\t\t\"\"\"\n\t\tIf false, signIn collapses NO_PASSWORD_SET / INVALID_PASSWORD into a\n\t\tgeneric INVALID_CREDENTIALS and signUp omits the recommendedAction\n\t\thint on EMAIL_ALREADY_EXISTS errors. UNKNOWN_EMAIL and existence-level\n\t\tsignals are still controlled by revealUserExists. Defaults to true\n\t\t(no change vs. previous behavior).\n\t\t\"\"\"\n\t\trevealLoginMethod: Boolean!\n\t\tdefaultTokenExpiration: Interval!\n\t\tmaxTokenExpiration: Interval\n\t\tmfaGraceDuration: Interval!\n\t\tanomalyDetection: ConfigLoginAnomalyDetection!\n }\n\n\t\"\"\"\n\tSign-in anomaly detection (A03). Opt-in, disabled by default. When enabled,\n\teach successful password verification is scored against the person's last\n\thistorySize successful logins using signals derived from the trusted client\n\tinfo (country from a reverse-proxy geo header, a user-agent fingerprint, and\n\tthe IP / IP prefix). The cumulative score then drives an action:\n\t - score >= emailThreshold → an informational UNUSUAL_LOGIN email is sent.\n\t - score >= stepUpThreshold → a second factor (email OTP) is additionally\n\t required before a session is issued (reuses the existing step-up flow).\n\tCountry is only ever read through the same trusted-proxy gate as the\n\tforwarded IP / User-Agent — never from an untrusted client.\n\t\"\"\"\n\ttype ConfigLoginAnomalyDetection {\n\t\tenabled: Boolean!\n\t\thistorySize: Int!\n\t\temailThreshold: Int!\n\t\tstepUpThreshold: Int!\n\t}\n\n\t\"\"\"\n\tCaptcha config. The secret is never exposed; only the provider and (where\n\tapplicable) the threshold are readable.\n\t\"\"\"\n\ttype ConfigCaptcha {\n\t\tprovider: CaptchaProvider\n\t\tthreshold: Float\n\t\tprotect: ConfigCaptchaProtect!\n\t}\n\n\t\"\"\"\n\tPer-flow captcha enforcement. The captcha provider/secret is shared; these\n\tflags decide which mutations actually require a captcha token when a provider\n\tis configured.\n\t\"\"\"\n\ttype ConfigCaptchaProtect {\n\t\tsignUp: Boolean!\n\t\tpasswordReset: Boolean!\n\t\tpasswordlessInit: Boolean!\n\t\temailVerification: Boolean!\n\t}\n\n\tenum CaptchaProvider {\n\t\tturnstile\n\t\thcaptcha\n\t\trecaptchaV3\n\t}\n\n\t\"\"\"\n\tConfigurable per-IP rate-limit windows. Each value bounds the number of\n\tattempts allowed from the same client IP in the configured window. Per-email\n\tthrottling for password-reset and passwordless-init flows reuses the\n\texponential backoff from ConfigLogin (baseBackoff / maxBackoff /\n\tattemptWindow) against person_auth_log entries.\n\t\"\"\"\n\ttype ConfigRateLimits {\n\t\tsignUpPerIp: ConfigRateLimitWindow!\n\t\tloginPerIp: ConfigRateLimitWindow!\n\t\tpasswordResetPerIp: ConfigRateLimitWindow!\n\t\tpasswordlessInitPerIp: ConfigRateLimitWindow!\n\t\t\"\"\"\n\t\tCaps how many email-OTP codes may be dispatched per person within the\n\t\twindow (a brute-force / email-bomb backstop). Unlike the per-IP limits it\n\t\tships enabled by default. Set limit to 0 to disable.\n\t\t\"\"\"\n\t\temailOtpPerPerson: ConfigRateLimitWindow!\n\t\temailVerificationPerIp: ConfigRateLimitWindow!\n\t}\n\n\ttype ConfigRateLimitWindow {\n\t\tlimit: Int!\n\t\twindow: Interval!\n\t}\n\n\t\"\"\"\n\tWho may enter the management panel. This is an entry gate for the console\n\tonly, not an authorization system: everything done inside the panel still\n\tgoes through the tenant ACL, so being allowed in grants no extra rights.\n\tAn identity may enter when its global roles intersect globalRoles, or when\n\tit holds a membership with one of projectRoles in at least one project.\n\tBoth lists empty means nobody can enter.\n\t\"\"\"\n\ttype ConfigPanel {\n\t\t\"\"\"Global roles (identity.roles) that may use the management panel.\"\"\"\n\t\tglobalRoles: [String!]!\n\t\t\"\"\"Project membership roles that may use the management panel, in any project.\"\"\"\n\t\tprojectRoles: [String!]!\n\t}\n\n\tinput ConfigInput {\n\t\tsignup: ConfigSignupInput\n\t\temailChange: ConfigEmailChangeInput\n\t\tpasswordless: ConfigPasswordlessInput\n\t\tpassword: ConfigPasswordInput\n\t\tlogin: ConfigLoginInput\n\t\tcaptcha: ConfigCaptchaInput\n\t\trateLimits: ConfigRateLimitsInput\n\t\tpanel: ConfigPanelInput\n\t}\n\n\tinput ConfigSignupInput {\n\t\trequireEmailVerification: Boolean\n\t}\n\n\tinput ConfigEmailChangeInput {\n\t\trequireVerification: Boolean\n\t}\n\n\tenum ConfigPolicy {\n\t\talways\n\t\tnever\n\t\toptIn\n\t\toptOut\n\t}\n\n\tinput ConfigPasswordlessInput {\n\t\tenabled: ConfigPolicy\n\t\turl: String\n\t\texpiration: Interval\n\t}\n\n\tinput ConfigPasswordInput {\n\t\tminLength: Int\n\t\trequireUppercase: Int\n\t\trequireLowercase: Int\n\t\trequireDigit: Int\n\t\trequireSpecial: Int\n\t\tpattern: String\n\t\tcheckBlacklist: Boolean\n\t\tcheckHibp: Boolean\n }\n\n\tinput ConfigLoginInput {\n\t\tbaseBackoff: Interval\n\t\tmaxBackoff: Interval\n\t\tattemptWindow: Interval\n\t\trevealUserExists: Boolean\n\t\trevealLoginMethod: Boolean\n\t\tdefaultTokenExpiration: Interval\n\t\tmaxTokenExpiration: Interval\n\t\tmfaGraceDuration: Interval\n\t\tanomalyDetection: ConfigLoginAnomalyDetectionInput\n }\n\n\tinput ConfigLoginAnomalyDetectionInput {\n\t\tenabled: Boolean\n\t\thistorySize: Int\n\t\temailThreshold: Int\n\t\tstepUpThreshold: Int\n\t}\n\n\t\"\"\"\n\tProvider null disables captcha verification. Secret is write-only.\n\tPass null secret to leave the stored value unchanged; pass empty string to clear.\n\t\"\"\"\n\tinput ConfigCaptchaInput {\n\t\tprovider: CaptchaProvider\n\t\tsecret: String\n\t\tthreshold: Float\n\t\tprotect: ConfigCaptchaProtectInput\n\t}\n\n\tinput ConfigCaptchaProtectInput {\n\t\tsignUp: Boolean\n\t\tpasswordReset: Boolean\n\t\tpasswordlessInit: Boolean\n\t\temailVerification: Boolean\n\t}\n\n\tinput ConfigRateLimitsInput {\n\t\tsignUpPerIp: ConfigRateLimitWindowInput\n\t\tloginPerIp: ConfigRateLimitWindowInput\n\t\tpasswordResetPerIp: ConfigRateLimitWindowInput\n\t\tpasswordlessInitPerIp: ConfigRateLimitWindowInput\n\t\temailOtpPerPerson: ConfigRateLimitWindowInput\n\t\temailVerificationPerIp: ConfigRateLimitWindowInput\n\t}\n\n\tinput ConfigRateLimitWindowInput {\n\t\tlimit: Int\n\t\twindow: Interval\n\t}\n\n\t\"\"\"\n\tEach list is replaced as a whole; omitting one leaves it unchanged. An empty\n\tlist closes the panel for that dimension.\n\t\"\"\"\n\tinput ConfigPanelInput {\n\t\tglobalRoles: [String!]\n\t\tprojectRoles: [String!]\n\t}\n\t\n\ttype ConfigureResponse {\n\t\tok: Boolean!\n\t\terror: ConfigureError\n\t}\n\t\n\ttype ConfigureError {\n\t\tcode: ConfigureErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ConfigureErrorCode {\n\t\tINVALID_CONFIG\n\t}\n\n\t# === signUp ===\n\ttype SignUpResponse {\n\t\tok: Boolean!\n\t\terrors: [SignUpError!]! @deprecated\n\t\terror: SignUpError\n\t\tresult: SignUpResult\n\t}\n\n\ttype SignUpError {\n\t\tcode: SignUpErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\t\"\"\"\n\t\tFor EMAIL_ALREADY_EXISTS, the recommended next action client UIs should\n\t\toffer to the visitor. Null for unrelated error codes.\n\t\t\"\"\"\n\t\trecommendedAction: SignUpRecommendedAction\n\t\tdeveloperMessage: String!\n\t\tendPersonMessage: String @deprecated\n\t}\n\n\tenum SignUpErrorCode {\n\t\tEMAIL_ALREADY_EXISTS\n\t\tINVALID_EMAIL_FORMAT\n\t\tTOO_WEAK\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\tenum SignUpRecommendedAction {\n\t\tSIGN_IN\n\t\tRESET_PASSWORD\n\t}\n\n\ttype SignUpResult {\n\t\tperson: Person!\n\t}\n\n\t# === signInCommon ==\n\n\tinterface CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\n\t# === signIn ===\n\tinput SignInOptions {\n\t\t\"\"\"\n\t\tIf true, and the calling api_key has trust_forwarded_info=true,\n\t\tthe resulting session token will trust X-Contember-Client-IP and\n\t\tX-Contember-Client-User-Agent headers on subsequent requests.\n\t\tSilently ignored when the caller's api_key does not have the flag.\n\n\t\tSecurity: a proxy that sets these headers MUST strip any\n\t\tincoming X-Contember-Client-IP / X-Contember-Client-User-Agent\n\t\tfrom upstream traffic and re-inject values it trusts. Without\n\t\tthat, any client holding a session token minted with this flag\n\t\tcould spoof its own IP/User-Agent.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean\n\t}\n\n\ttype SignInResponse {\n\t\tok: Boolean!\n\t\terrors: [SignInError!]! @deprecated\n\t\terror: SignInError\n\t\tresult: SignInResult\n\t}\n\n\ttype SignInError {\n\t\tcode: SignInErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t\tretryAfter: Int\n\t\t\"\"\"\n\t\tSet only on a MFA_ENROLLMENT_REQUIRED error: the freshly provisioned\n\t\tpending TOTP secret the client must enroll (show the QR / secret, then\n\t\tretry signIn with otpToken). Additive — clients that don't read it are\n\t\tunaffected.\n\t\t\"\"\"\n\t\tmfaEnrollment: MfaEnrollment\n\t}\n\n\ttype MfaEnrollment {\n\t\totpUri: String!\n\t\totpSecret: String!\n\t}\n\n\tenum SignInErrorCode {\n\t\tINVALID_CREDENTIALS\n\t\tUNKNOWN_EMAIL\n\t\tINVALID_PASSWORD\n\t\tPERSON_DISABLED\n\t\tNO_PASSWORD_SET\n\t\tOTP_REQUIRED\n\t\tINVALID_OTP_TOKEN\n\t\tMFA_ENROLLMENT_REQUIRED\n\t\tEMAIL_NOT_VERIFIED\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\ttype SignInResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t\t\"\"\"\n\t\tSet only when this sign-in completed an MFA enrollment (A06): the freshly\n\t\tgenerated backup codes, shown exactly once. Null on a normal sign-in.\n\t\t\"\"\"\n\t\tbackupCodes: [String!]\n\t}\n\n\t# == createSessionToken ==\n\n\ttype CreateSessionTokenResponse {\n\t\tok: Boolean!\n\t\terror: CreateSessionTokenError\n\t\tresult: CreateSessionTokenResult\n\t}\n\n\ttype CreateSessionTokenError {\n\t\tcode: CreateSessionTokenErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum CreateSessionTokenErrorCode {\n\t\tUNKNOWN_EMAIL\n\t\tUNKNOWN_PERSON_ID\n\t\tPERSON_DISABLED\n\t}\n\n\ttype CreateSessionTokenResult implements CommonSignInResult{\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\n\t# === signOut ===\n\n\ttype SignOutResponse {\n\t\tok: Boolean!\n\t\terrors: [SignOutError!]! @deprecated\n\t\terror: SignOutError\n\t\t\"\"\"\n\t\tWhen the session was federated via an OIDC identity provider that supports RP-initiated\n\t\t(front-channel) logout, the URL the client should redirect the browser to so the user is\n\t\talso signed out at the IdP (Single Logout). Null for plain sessions or legacy IdPs without\n\t\tan end-session endpoint, in which case only a local logout happened.\n\t\t\"\"\"\n\t\tlogoutUrl: String\n\t}\n\n\ttype SignOutError {\n\t\tcode: SignOutErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum SignOutErrorCode {\n\t\tNOT_A_PERSON,\n\t\tNOT_POSSIBLE_SIGN_OUT_WITH_PERMANENT_API_KEY\n\t}\n\n\t# === changeProfile ===\n\t\n\ttype ChangeProfileResponse {\n\t\tok: Boolean!\n\t\terror: ChangeProfileError\n\t}\n\t\n\ttype ChangeProfileError {\n\t\tcode: ChangeProfileErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ChangeProfileErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tINVALID_EMAIL_FORMAT\n\t\tEMAIL_ALREADY_EXISTS\n\t}\n\t\n\t# === changeMyProfile ===\n\n\ttype ChangeMyProfileResponse {\n\t\tok: Boolean!\n\t\terror: ChangeMyProfileError\n\t}\n\n\ttype ChangeMyProfileError {\n\t\tcode: ChangeMyProfileErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ChangeMyProfileErrorCode {\n\t\tNOT_A_PERSON\n\t\tINVALID_EMAIL_FORMAT\n\t\tEMAIL_ALREADY_EXISTS\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\t# === changePassword ===\n\n\ttype ChangePasswordResponse {\n\t\tok: Boolean!\n\t\terrors: [ChangePasswordError!]! @deprecated\n\t\terror: ChangePasswordError\n\t}\n\n\ttype ChangePasswordError {\n\t\tcode: ChangePasswordErrorCode!\n\t\tweakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ChangePasswordErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tTOO_WEAK\n\t}\n\t\n\tenum WeakPasswordReason {\n\t\tTOO_SHORT\n\t\tMISSING_UPPERCASE\n\t\tMISSING_LOWERCASE\n\t\tMISSING_DIGIT\n\t\tMISSING_SPECIAL\n\t\tINVALID_PATTERN\n\t\tBLACKLISTED\n\t\tCOMPROMISED\n }\n\n\n\t# === changeMyPassword ===\n\t\n\ttype ChangeMyPasswordResponse {\n\t\tok: Boolean!\n\t\terror: ChangeMyPasswordError\n\t}\n\n\ttype ChangeMyPasswordError {\n\t\tcode: ChangeMyPasswordErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ChangeMyPasswordErrorCode {\n\t\tTOO_WEAK\n\t\tNOT_A_PERSON\n\t\tINVALID_PASSWORD\n\t\tNO_PASSWORD_SET\n\t}\n\n\t# === IDP ===\n\n\ttype InitSignInIDPResponse {\n\t\tok: Boolean!\n\t\terrors: [InitSignInIDPError!]! @deprecated\n\t\terror: InitSignInIDPError\n\t\tresult: InitSignInIDPResult\n\t}\n\n\ttype InitSignInIDPResult {\n\t\tauthUrl: String!\n\t\tsessionData: Json!\n\t\tidpConfiguration: Json\n\t}\n\n\ttype InitSignInIDPError {\n\t\tcode: InitSignInIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum InitSignInIDPErrorCode {\n\t\tPROVIDER_NOT_FOUND\n\t\tIDP_VALIDATION_FAILED\n\t}\n\n\tinput IDPResponseInput {\n\t\turl: String!\n\t}\n\n\ttype SignInIDPResponse {\n\t\tok: Boolean!\n\t\terrors: [SignInIDPError!]! @deprecated\n\t\terror: SignInIDPError\n\t\tresult: SignInIDPResult\n\t}\n\n\ttype SignInIDPError {\n\t\tcode: SignInIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum SignInIDPErrorCode {\n\t\tINVALID_IDP_RESPONSE\n\t\tIDP_VALIDATION_FAILED\n\n\t\tPERSON_NOT_FOUND\n\t\tPERSON_DISABLED\n\t\tPERSON_ALREADY_EXISTS\n\t}\n\n\ttype SignInIDPResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t\tidpResponse: Json\n\t}\n\n\ttype AddIDPResponse {\n\t\terror: AddIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype AddIDPError {\n\t\tcode: AddIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum AddIDPErrorCode {\n\t\tALREADY_EXISTS\n\t\tUNKNOWN_TYPE\n\t\tINVALID_CONFIGURATION\n\t}\n\n\ttype UpdateIDPResponse {\n\t\terror: UpdateIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype UpdateIDPError {\n\t\tcode: UpdateIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateIDPErrorCode {\n\t\tNOT_FOUND\n\t\tINVALID_CONFIGURATION\n\t}\n\n\n\ttype DisableIDPResponse {\n\t\terror: DisableIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype DisableIDPError {\n\t\tcode: DisableIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisableIDPErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\ttype EnableIDPResponse {\n\t\terror: EnableIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype EnableIDPError {\n\t\tcode: EnableIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum EnableIDPErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\t\"\"\" A single external IdP connection of the currently authenticated person. \"\"\"\n\ttype PersonIdentityProvider {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\texternalIdentifier: String!\n\t\tidentityProvider: IdentityProviderListItem!\n\t}\n\n\t\"\"\" Public view of an identity provider, exposed in personal IdP connection listings. \"\"\"\n\ttype IdentityProviderListItem {\n\t\tslug: String!\n\t\ttype: String!\n\t\tdisabledAt: DateTime\n\t}\n\n\ttype DisconnectIDPResponse {\n\t\terror: DisconnectIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype DisconnectIDPError {\n\t\tcode: DisconnectIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisconnectIDPErrorCode {\n\t\t\"\"\" The authenticated person has no IdP connection with the given id. \"\"\"\n\t\tNOT_FOUND\n\t\t\"\"\" The caller is not a person (e.g. an API key) and so has no IdP connections to disconnect. \"\"\"\n\t\tNOT_A_PERSON\n\t\t\"\"\" The person is not allowed to disconnect their last remaining sign-in method. \"\"\"\n\t\tLAST_AUTH_METHOD\n\t}\n\n\ttype IdentityProvider {\n\t\tslug: String!\n\t\ttype: String!\n\t\tconfiguration: Json!\n\t\tdisabledAt: DateTime\n\t\toptions: IDPOptionsOutput!\n\t}\n\n\ttype IDPOptionsOutput {\n\t\tautoSignUp: Boolean!\n\t\texclusive: Boolean!\n\t\tinitReturnsConfig: Boolean!\n\t\t\"\"\"\n\t\tWhen true, a non-exclusive provider may only auto-link to / sign in an\n\t\texisting account by e-mail if the provider asserts the e-mail is verified.\n\t\tDefaults to false.\n\t\t\"\"\"\n\t\trequireVerifiedEmail: Boolean!\n\t\t\"\"\"\n\t\tWhen true, e-mail addresses asserted by this provider are treated as verified\n\t\teven without an \"email_verified\" claim. Use only for trusted providers.\n\t\tDefaults to false.\n\t\t\"\"\"\n\t\tassumeEmailVerified: Boolean!\n\t}\n\n\tinput IDPOptions {\n\t\tautoSignUp: Boolean\n\t\texclusive: Boolean\n\t\tinitReturnsConfig: Boolean\n\t\trequireVerifiedEmail: Boolean\n\t\tassumeEmailVerified: Boolean\n\t}\n\n\t# === passwordless sign in ===\n\t\n\ttype InitSignInPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: InitSignInPasswordlessError\n\t\tresult: InitSignInPasswordlessResult\n\t}\n\t\n\ttype InitSignInPasswordlessError {\n\t\tcode: InitSignInPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum InitSignInPasswordlessErrorCode {\n\t\tPERSON_NOT_FOUND\n\n\t\tPASSWORDLESS_DISABLED\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\t\n\ttype InitSignInPasswordlessResult {\n\t\trequestId: String!\n\t\texpiresAt: DateTime!\n\t}\n\n\tinput InitSignInPasswordlessOptions {\n\t\tmailVariant: String\n\t\tmailProject: String\n\t}\n\t\n\ttype SignInPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: SignInPasswordlessError\n\t\tresult: SignInPasswordlessResult\n\t}\n\t\n\tenum PasswordlessValidationType {\n\t\totp\n\t\ttoken\n\t}\n\t\n\ttype SignInPasswordlessError {\n\t\tcode: SignInPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum SignInPasswordlessErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_EXPIRED\n\t\tTOKEN_USED\n\t\tPERSON_DISABLED\n\t\tOTP_REQUIRED\n\t\tINVALID_OTP_TOKEN\n\t\tMFA_ENROLLMENT_REQUIRED\n\t}\n\n\ttype SignInPasswordlessResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\t\n\ttype ActivatePasswordlessOtpResponse {\n\t\tok: Boolean!\n\t\terror: ActivatePasswordlessOtpError\n\t}\n\t\n\ttype ActivatePasswordlessOtpError {\n\t\tcode: ActivatePasswordlessOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ActivatePasswordlessOtpErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_EXPIRED\n\t\tTOKEN_USED\n\t}\n\t\n\ttype ToggleMyPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: ToggleMyPasswordlessError\n\t}\n\t\n\ttype ToggleMyPasswordlessError {\n\t\tcode: ToggleMyPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ToggleMyPasswordlessErrorCode {\n\t\tCANNOT_TOGGLE\n NOT_A_PERSON\n\t}\n\t\n\n\t# === invite ===\n\n\ttype InviteResponse {\n\t\tok: Boolean!\n\t\terrors: [InviteError!]! @deprecated\n\t\terror: InviteError\n\t\tresult: InviteResult\n\t}\n\n\ttype InviteError {\n\t\tcode: InviteErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum InviteErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tALREADY_MEMBER\n\t\tINVALID_MEMBERSHIP\n\t\tINVALID_EMAIL_FORMAT\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t}\n\n\ttype InviteResult {\n\t\tperson: Person!\n\t\tisNew: Boolean!\n\t}\n\n\tenum InviteMethod {\n\t\tCREATE_PASSWORD\n\t\tRESET_PASSWORD\n\t}\n\n\tinput InviteOptions {\n\t\tmethod: InviteMethod\n\t\tmailVariant: String\n\t}\n\n\tinput UnmanagedInviteOptions {\n\t\tpassword: String\n\t\tresetTokenHash: String\n\t}\n\n\t# === addProjectMember ===\n\n\ttype AddProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [AddProjectMemberError!]!\n\t\terror: AddProjectMemberError\n\t}\n\n\ttype AddProjectMemberError {\n\t\tcode: AddProjectMemberErrorCode!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum AddProjectMemberErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tIDENTITY_NOT_FOUND\n\t\tALREADY_MEMBER\n\t\tINVALID_MEMBERSHIP\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t}\n\n\t# === updateProjectMember ===\n\n\ttype UpdateProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [UpdateProjectMemberError!]! @deprecated\n\t\terror: UpdateProjectMemberError\n\t}\n\n\ttype UpdateProjectMemberError {\n\t\tcode: UpdateProjectMemberErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum UpdateProjectMemberErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tNOT_MEMBER\n\t\tINVALID_MEMBERSHIP\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t}\n\n\t# === removeProjectMember ===\n\n\ttype RemoveProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [RemoveProjectMemberError!]!\n\t\terror: RemoveProjectMemberError\n\t}\n\n\ttype RemoveProjectMemberError {\n\t\tcode: RemoveProjectMemberErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum RemoveProjectMemberErrorCode {\n\t\tNOT_MEMBER\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\t# === createApiKey ===\n\n\tinput CreateApiKeyOptions {\n\t\t\"\"\"\n\t\tIf true, the created api_key trusts X-Contember-Client-IP and\n\t\tX-Contember-Client-User-Agent headers on subsequent requests.\n\t\tIntended for backend services that proxy user requests; the customer's\n\t\tproxy must strip these headers from incoming traffic and re-inject\n\t\tthem with the real user values.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean\n\t}\n\n\ttype CreateApiKeyResponse {\n\t\tok: Boolean!\n\t\terrors: [CreateApiKeyError!]! @deprecated\n\t\terror: CreateApiKeyError\n\t\tresult: CreateApiKeyResult\n\t}\n\n\ttype CreateApiKeyError {\n\t\tcode: CreateApiKeyErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum CreateApiKeyErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tINVALID_MEMBERSHIP\n\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t}\n\n\ttype CreateApiKeyResult {\n\t\tapiKey: ApiKeyWithToken!\n\t}\n\n\t# === disableApiKey ===\n\n\ttype DisableApiKeyResponse {\n\t\tok: Boolean!\n\t\terrors: [DisableApiKeyError!]! @deprecated\n\t\terror: DisableApiKeyError\n\t}\n\n\ttype DisableApiKeyError {\n\t\tcode: DisableApiKeyErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum DisableApiKeyErrorCode {\n\t\tKEY_NOT_FOUND\n\t}\n\t# === addGlobalIdentityRoles ===\n\n\ttype AddGlobalIdentityRolesResponse {\n\t\tok: Boolean!\n\t\terror: AddGlobalIdentityRolesError\n\t\tresult: AddGlobalIdentityRolesResult\n\t}\n\n\ttype AddGlobalIdentityRolesResult {\n\t\tidentity: Identity!\n\t}\n\ttype AddGlobalIdentityRolesError {\n\t\tcode: AddGlobalIdentityRolesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum AddGlobalIdentityRolesErrorCode {\n\t\tIDENTITY_NOT_FOUND\n\t\tINVALID_ROLE\n\t}\n\n\n\t# === removeGlobalIdentityRoles ===\n\n\ttype RemoveGlobalIdentityRolesResponse {\n\t\tok: Boolean!\n\t\terror: RemoveGlobalIdentityRolesError\n\t\tresult: RemoveGlobalIdentityRolesResult\n\t}\n\n\ttype RemoveGlobalIdentityRolesError {\n\t\tcode: RemoveGlobalIdentityRolesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\ttype RemoveGlobalIdentityRolesResult {\n\t\tidentity: Identity!\n\t}\n\n\tenum RemoveGlobalIdentityRolesErrorCode {\n\t\tIDENTITY_NOT_FOUND\n\t\tINVALID_ROLE\n\t}\n\t# === common ===\n\n\t# === variables ===\n\n\tinput VariableEntryInput {\n\t\tname: String!\n\t\tvalues: [String!]!\n\t}\n\n\ttype VariableEntry {\n\t\tname: String!\n\t\tvalues: [String!]!\n\t}\n\n\t# === membership ===\n\n\tinput MembershipInput {\n\t\trole: String!\n\t\tvariables: [VariableEntryInput!]!\n\t}\n\n\ttype Membership {\n\t\trole: String!\n\t\tvariables: [VariableEntry!]!\n\t}\n\n\ttype MembershipValidationError {\n\t\tcode: MembershipValidationErrorCode!\n\t\trole: String!\n\t\tvariable: String\n\t}\n\n\tenum MembershipValidationErrorCode {\n\t\tROLE_NOT_FOUND\n\t\tVARIABLE_NOT_FOUND\n\t\tVARIABLE_EMPTY\n\t\tVARIABLE_INVALID\n\t}\n\n\t# === person ====\n\n\ttype Person {\n\t\tid: String!\n\t\temail: String\n\t\tname: String\n\t\totpEnabled: Boolean!\n\t\t\"\"\" The person's own opt-in flag; \\`null\\` means \"follow the tenant policy\". On its own it does not say whether passwordless sign-in works — see \\`passwordlessAvailable\\`. \"\"\"\n\t\tpasswordlessEnabled: Boolean\n\t\t\"\"\"\n\t\tWhether passwordless sign-in is actually usable for this person right now: the tenant-wide\n\t\tpolicy resolved against \\`passwordlessEnabled\\`, i.e. the very same decision \\`signIn\\` makes. A UI\n\t\toffering an enable/disable toggle must branch on this — under an \\`always\\` or \\`never\\` policy the\n\t\traw opt-in flag says nothing about what will happen.\n\t\t\"\"\"\n\t\tpasswordlessAvailable: Boolean!\n\t\t\"\"\"\n\t\tWhether \\`passwordlessEnabled\\` is what decides \\`passwordlessAvailable\\`. False under an \\`always\\`\n\t\tor \\`never\\` policy, where the person's own flag is ignored — a UI should then report the state\n\t\trather than offer a toggle that changes nothing.\n\t\t\"\"\"\n\t\tpasswordlessSelfManaged: Boolean!\n\t\t\"\"\"\n\t\tWhether e-mail based one-time-password 2FA is enabled for this person\n\t\t(see \\`initEmailOtp\\` / \\`confirmEmailOtp\\` / \\`disableEmailOtp\\`). Independent\n\t\tof \\`otpEnabled\\` (TOTP authenticator), so a UI can show each MFA method's\n\t\tstate separately.\n\t\t\"\"\"\n\t\temailOtpEnabled: Boolean!\n\t\temailVerified: Boolean!\n\t\t\"\"\"\n\t\tWhen the account was disabled (see \\`disablePerson\\`), null while the person\n\t\tis active. Read-only — flip it with \\`disablePerson\\` / \\`enablePerson\\`.\n\t\t\"\"\"\n\t\tdisabledAt: DateTime\n\t\tidentity: Identity!\n\n\t\t\"\"\"\n\t\tExternal IdP connections of this person. Always visible for the calling\n\t\tperson (e.g. via \\`me { person { identityProviders } }\\`). For other\n\t\tpersons, visible to callers holding the \\`person:viewIdp\\` permission\n\t\tagainst the target's roles — SUPER_ADMIN sees everyone; PROJECT_ADMIN\n\t\tsees members whose roles fall within their allowed-input-roles. Returns\n\t\tan empty list rather than throwing when the viewer lacks visibility.\n\t\t\"\"\"\n\t\tidentityProviders: [PersonIdentityProvider!]!\n\t}\n\n\t\"\"\" Filter for the \\`persons\\` query. Fields are combined with AND. \"\"\"\n\tinput PersonsFilter {\n\t\temail: String\n\t\tpersonId: String\n\t\tidentityId: String\n\t}\n\n\t# === api key ===\n\n\tenum ApiKeyType {\n\t\tSESSION\n\t\tPERMANENT\n\t\tONE_OFF\n\t}\n\n\ttype ApiKey {\n\t\tid: String!\n\t\tidentity: Identity!\n\t\t\"\"\" Human-readable label, stored on the key's identity (\\`identity.description\\`). \"\"\"\n\t\tdescription: String\n\t\ttype: ApiKeyType\n\t\t\"\"\" False once the key has been disabled (\\`disableApiKey\\`). \"\"\"\n\t\tenabled: Boolean\n\t\tcreatedAt: DateTime\n\t\tlastUsedAt: DateTime\n\t\texpiresAt: DateTime\n\t}\n\n\ttype ApiKeyWithToken {\n\t\tid: String!\n\t\ttoken: String\n\t\tidentity: Identity!\n\t}\n\n\t# === identity ===\n\n\ttype Identity {\n\t\tid: String!\n\t\tdescription: String\n\t\tperson: Person\n\t\tapiKey: ApiKey\n\t\tprojects: [IdentityProjectRelation!]!\n\t\tpermissions: IdentityGlobalPermissions\n\t\troles: [String!]\n\t\t\"\"\"\n\t\tActive SESSION-type api keys for this identity. Always visible for\n\t\tthe calling identity (e.g. via \\`me { sessions }\\`). For other identities,\n\t\tvisible to callers holding the \\`person:viewSessions\\` permission against\n\t\tthe target's roles — SUPER_ADMIN sees everyone; PROJECT_ADMIN sees\n\t\tmembers whose roles fall within their allowed-input-roles. Returns an\n\t\tempty list rather than throwing when the viewer lacks visibility, so\n\t\tbatched identity queries do not abort on a single forbidden target.\n\t\t\"\"\"\n\t\tsessions: [SessionInfo!]!\n\t}\n\n\t\"\"\"\n\tWhat the identity may do tenant-wide, evaluated against the same ACL the resolvers enforce.\n\n\tThis is for building a UI that does not offer what it cannot deliver — it is **not** a security\n\tboundary, and answering \\`true\\` here grants nothing. Every operation is still checked when it is\n\tcalled. The distinction matters because permission failure is not uniform across this API: some\n\tqueries answer an empty list, others throw, and every mutation throws, so a client cannot tell\n\t\"nothing to show\" from \"not yours to see\" by trying.\n\t\"\"\"\n\ttype IdentityGlobalPermissions {\n\t\tcanCreateProject: Boolean!\n\t\tcanDeployEntrypoint: Boolean!\n\t\t\"\"\" Read \\`configuration\\`, which throws otherwise. The other configuration queries gate on their own actions. \"\"\"\n\t\tcanViewConfiguration: Boolean!\n\t\t\"\"\" Read \\`identityProviders\\`. \"\"\"\n\t\tcanListIdentityProviders: Boolean!\n\t\t\"\"\" Read \\`mailTemplates\\`. \"\"\"\n\t\tcanListMailTemplates: Boolean!\n\t\t\"\"\"\n\t\tWrite the tenant configuration (\\`configure\\`) and read \\`authPolicies\\`. The CLI is the usual write path.\n\t\t\"\"\"\n\t\tcanManageConfiguration: Boolean!\n\t\t\"\"\" Read \\`authLog\\`, which throws otherwise. \"\"\"\n\t\tcanViewAuthLog: Boolean!\n\t\t\"\"\"\n\t\tList every person in the tenant. Without it \\`persons\\` still answers, narrowed to the members\n\t\tof the projects the caller administers — so this marks a full listing, not access to one.\n\t\t\"\"\"\n\t\tcanListPersons: Boolean!\n\t\t\"\"\" Read \\`globalApiKeys\\`, which answers an empty list otherwise. \"\"\"\n\t\tcanListGlobalApiKeys: Boolean!\n\t\tcanCreateGlobalApiKey: Boolean!\n\t}\n\n\t\"\"\"\n\tWhat the calling identity may do in this project. Same contract as\n\t\\`IdentityGlobalPermissions\\`: advisory, evaluated per caller, never a substitute for the checks in\n\tthe resolvers.\n\t\"\"\"\n\ttype ProjectPermissions {\n\t\t\"\"\" Read \\`members\\` and \\`apiKeys\\`; both answer an empty list otherwise. \"\"\"\n\t\tcanViewMembers: Boolean!\n\t\t\"\"\" Invite or add a member (\\`invite\\`, \\`addProjectMember\\`). Which roles may be granted is checked per membership. \"\"\"\n\t\tcanAddMember: Boolean!\n\t\tcanUpdateMember: Boolean!\n\t\tcanRemoveMember: Boolean!\n\t\t\"\"\" Read \\`secrets\\` (their names, never values); answers an empty list otherwise. \"\"\"\n\t\tcanViewSecrets: Boolean!\n\t\t\"\"\" Write a project secret (\\`setProjectSecret\\`). Distinct from viewing: a project admin commonly has one and not the other. \"\"\"\n\t\tcanSetSecret: Boolean!\n\t\t\"\"\" Create an API key scoped to this project. \"\"\"\n\t\tcanCreateApiKey: Boolean!\n\t\t\"\"\" Update the project itself (\\`updateProject\\`). \"\"\"\n\t\tcanUpdate: Boolean!\n\t}\n\n\ttype IdentityProjectRelation {\n\t\tproject: Project!\n\t\tmemberships: [Membership!]!\n\t}\n\n\t# === project ===\n\n\ttype Project {\n\t\tid: String!\n\t\tname: String!\n\t\tslug: String!\n\t\tconfig: Json!\n\t\troles: [RoleDefinition!]!\n\t\tmembers(\n\t\t\tinput: ProjectMembersInput,\n\t\t\tmemberType: MemberType @deprecated(reason: \"Use args\")\n\t\t): [ProjectIdentityRelation!]!\n\t\t\"\"\"\n\t\tPermanent API keys scoped to this project — keys whose identity is a member\n\t\tof the project (excludes SESSION tokens and global keys). Each key's\n\t\tproject memberships are reachable via \\`apiKey.identity.projects\\` for\n\t\tcloning when (re)issuing a key. Requires \\`project.view members\\` permission;\n\t\treturns an empty list otherwise.\n\t\t\"\"\"\n\t\tapiKeys: [ApiKey!]!\n\t\t\"\"\"\n\t\tNames of the project's secrets (see \\`setProjectSecret\\`). Secret VALUES are\n\t\tnever returned — only the keys and their timestamps — so a UI can show which\n\t\tsecrets exist. Requires the \\`project:viewSecrets\\` permission (project admins\n\t\t+ SUPER_ADMIN by default); returns an empty list otherwise.\n\t\t\"\"\"\n\t\tsecrets: [ProjectSecretInfo!]!\n\t\t\"\"\" What the calling identity may do here. Advisory — for building the UI, not for enforcing it. \"\"\"\n\t\tpermissions: ProjectPermissions!\n\t}\n\n\t\"\"\" Metadata about a project secret — never its value. \"\"\"\n\ttype ProjectSecretInfo {\n\t\tkey: String!\n\t\tcreatedAt: DateTime!\n\t\tupdatedAt: DateTime!\n\t}\n\n\tinput ProjectMembersInput {\n\t\tlimit: Int\n\t\toffset: Int\n\t\tfilter: ProjectMembersFilter\n\t}\n\n\tinput ProjectMembersFilter {\n\t\tmemberType: MemberType\n\t\temail: [String!]\n\t\tidentityId: [String!]\n\t\tpersonId: [String!]\n\t}\n\n\tenum MemberType {\n\t\tAPI_KEY\n\t\tPERSON\n\t}\n\n\ttype ProjectIdentityRelation {\n\t\tidentity: Identity!\n\t\tmemberships: [Membership!]!\n\t}\n\n\ttype RoleDefinition {\n\t\tname: String!\n\t\tvariables: [RoleVariableDefinition!]!\n\t}\n\n\tinterface RoleVariableDefinition {\n\t\tname: String!\n\t}\n\n\ttype RoleEntityVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t\tentityName: String!\n\t}\n\n\ttype RolePredefinedVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t\tvalue: String!\n\t}\n\n\ttype RoleConditionVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t}\n\n\t# ==== 2fa ====\n\n\ttype PrepareOtpResponse {\n\t\tok: Boolean!\n\t\tresult: PrepareOtpResult\n\t}\n\n\ttype PrepareOtpResult {\n\t\totpUri: String!\n\t\totpSecret: String!\n\t}\n\n\ttype ConfirmOtpResponse {\n\t\tok: Boolean!\n\t\terrors: [ConfirmOtpError!]! @deprecated\n\t\terror: ConfirmOtpError\n\t\tresult: ConfirmOtpResult\n\t}\n\n\ttype ConfirmOtpResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\ttype ConfirmOtpError {\n\t\tcode: ConfirmOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ConfirmOtpErrorCode {\n\t\tINVALID_OTP_TOKEN\n\t\tNOT_PREPARED\n\t}\n\n\ttype DisableOtpResponse {\n\t\tok: Boolean!\n\t\terrors: [DisableOtpError!]! @deprecated\n\t\terror: DisableOtpError\n\t}\n\n\ttype DisableOtpError {\n\t\tcode: DisableOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum DisableOtpErrorCode {\n\t\tOTP_NOT_ACTIVE\n\t\tMFA_REQUIRED\n\t}\n\n\ttype RegenerateBackupCodesResponse {\n\t\tok: Boolean!\n\t\terror: RegenerateBackupCodesError\n\t\tresult: RegenerateBackupCodesResult\n\t}\n\n\ttype RegenerateBackupCodesError {\n\t\tcode: RegenerateBackupCodesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RegenerateBackupCodesErrorCode {\n\t\tOTP_NOT_ACTIVE\n\t}\n\n\ttype RegenerateBackupCodesResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\t# ==== email otp (A05) ====\n\n\ttype InitEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: InitEmailOtpError\n\t}\n\n\ttype InitEmailOtpError {\n\t\tcode: InitEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum InitEmailOtpErrorCode {\n\t\tNO_EMAIL\n\t\tRATE_LIMITED\n\t}\n\n\ttype ConfirmEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: ConfirmEmailOtpError\n\t\tresult: ConfirmEmailOtpResult\n\t}\n\n\ttype ConfirmEmailOtpResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\ttype ConfirmEmailOtpError {\n\t\tcode: ConfirmEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ConfirmEmailOtpErrorCode {\n\t\tINVALID_OTP_TOKEN\n\t}\n\n\ttype DisableEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: DisableEmailOtpError\n\t}\n\n\ttype DisableEmailOtpError {\n\t\tcode: DisableEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisableEmailOtpErrorCode {\n\t\tEMAIL_OTP_NOT_ACTIVE\n\t\tMFA_REQUIRED\n\t}\n\n\ttype DisablePersonResponse {\n\t\tok: Boolean!\n\t\terror: DisablePersonError\n\t}\n\n\ttype DisablePersonError {\n\t\tcode: DisablePersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisablePersonErrorCode {\n\t\tPERSON_ALREADY_DISABLED\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === enablePerson ===\n\n\ttype EnablePersonResponse {\n\t\tok: Boolean!\n\t\terror: EnablePersonError\n\t}\n\n\ttype EnablePersonError {\n\t\tcode: EnablePersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum EnablePersonErrorCode {\n\t\tPERSON_ALREADY_ENABLED\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === forceSignOutPerson ===\n\n\ttype ForceSignOutPersonResponse {\n\t\tok: Boolean!\n\t\terror: ForceSignOutPersonError\n\t}\n\n\ttype ForceSignOutPersonError {\n\t\tcode: ForceSignOutPersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ForceSignOutPersonErrorCode {\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === resetPersonMfa ===\n\n\ttype ResetPersonMfaResponse {\n\t\tok: Boolean!\n\t\terror: ResetPersonMfaError\n\t}\n\n\ttype ResetPersonMfaError {\n\t\tcode: ResetPersonMfaErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ResetPersonMfaErrorCode {\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === auth policy (per-role MFA / session policy) ===\n\n\ttype AuthPolicy {\n\t\tid: String!\n\t\tscope: AuthPolicyScope!\n\t\t\"\"\"Project slug, present only for project-scoped policies.\"\"\"\n\t\tproject: String\n\t\troles: [String!]!\n\t\tmfaRequired: Boolean\n\t\ttokenExpiration: Interval\n\t\tidleTimeout: Interval\n\t\tmfaGraceDuration: Interval\n\t\trememberMeAllowed: Boolean\n\t}\n\n\tenum AuthPolicyScope {\n\t\tglobal\n\t\tproject\n\t}\n\n\tinput AuthPolicyInput {\n\t\tscope: AuthPolicyScope!\n\t\t\"\"\"Project slug. Required for scope=project, forbidden for scope=global.\"\"\"\n\t\tproject: String\n\t\troles: [String!]!\n\t\tmfaRequired: Boolean\n\t\ttokenExpiration: Interval\n\t\tidleTimeout: Interval\n\t\tmfaGraceDuration: Interval\n\t\trememberMeAllowed: Boolean\n\t}\n\n\ttype CreateAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: CreateAuthPolicyError\n\t\tresult: CreateAuthPolicyResult\n\t}\n\n\ttype CreateAuthPolicyResult {\n\t\tid: String!\n\t}\n\n\ttype CreateAuthPolicyError {\n\t\tcode: CreateAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum CreateAuthPolicyErrorCode {\n\t\tPROJECT_REQUIRED\n\t\tPROJECT_NOT_ALLOWED\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype UpdateAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: UpdateAuthPolicyError\n\t}\n\n\ttype UpdateAuthPolicyError {\n\t\tcode: UpdateAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateAuthPolicyErrorCode {\n\t\tNOT_FOUND\n\t\tPROJECT_REQUIRED\n\t\tPROJECT_NOT_ALLOWED\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype DeleteAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: DeleteAuthPolicyError\n\t}\n\n\ttype DeleteAuthPolicyError {\n\t\tcode: DeleteAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DeleteAuthPolicyErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\t# === sessions ===\n\n\ttype SessionInfo {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\texpiresAt: DateTime\n\t\tlastUsedAt: DateTime\n\t\tlastIp: String\n\t\tlastUserAgent: String\n\t\tcreatedIp: String\n\t\tcreatedUserAgent: String\n\t\tisCurrent: Boolean!\n\t\t\"\"\"\n\t\tWhether this session honors X-Contember-Client-IP /\n\t\tX-Contember-Client-User-Agent headers on subsequent requests. Set when\n\t\tthe session was minted via \\`SignInOptions.trustForwardedClientInfo\\`\n\t\tfrom an api_key that was itself created with the flag.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean!\n\t}\n\n\ttype RevokeSessionResponse {\n\t\tok: Boolean!\n\t\terror: RevokeSessionError\n\t}\n\n\ttype RevokeSessionError {\n\t\tcode: RevokeSessionErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RevokeSessionErrorCode {\n\t\tSESSION_NOT_FOUND\n\t\tNOT_A_PERSON\n\t}\n\n\t# === mails ===\n\t\n\ttype MailTemplateData {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\tvariant: String\n\t\tsubject: String!\n\t\tcontent: String!\n\t\tuseLayout: Boolean!\n\t\treplyTo: String\n\t}\n\t\n\tinput MailTemplate {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\t\"Custom mail variant identifier, e.g. a locale.\"\n\t\tvariant: String\n\t\tsubject: String!\n\t\tcontent: String!\n\t\tuseLayout: Boolean\n\t\treplyTo: String\n\t}\n\n\tenum MailType {\n\t\tEXISTING_USER_INVITED\n\t\tNEW_USER_INVITED\n\t\tRESET_PASSWORD_REQUEST\n\t\tPASSWORDLESS_SIGN_IN\n\t\tFORCED_SIGN_OUT\n\t\tEMAIL_OTP\n\t\tBACKUP_CODES_EXHAUSTED\n\t\tEMAIL_VERIFICATION\n\t\tEMAIL_CHANGE_VERIFY\n\t\tEMAIL_CHANGE_NOTIFY\n\t\tUNUSUAL_LOGIN\n\t}\n\n\tinput MailTemplateIdentifier {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\tvariant: String\n\t}\n\n\ttype AddMailTemplateResponse {\n\t\tok: Boolean!\n\t\terrors: [AddMailTemplateError!]! @deprecated\n\t\terror: AddMailTemplateError\n\t}\n\n\ttype AddMailTemplateError {\n\t\tcode: AddMailTemplateErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum AddMailTemplateErrorCode {\n\t\tMISSING_VARIABLE\n\t\tPROJECT_NOT_FOUND\n\t\tINVALID_REPLY_EMAIL_FORMAT\n\t}\n\n\ttype RemoveMailTemplateResponse {\n\t\tok: Boolean!\n\t\terrors: [RemoveMailTemplateError!]!\n\t\terror: RemoveMailTemplateError\n\t}\n\n\ttype RemoveMailTemplateError {\n\t\tcode: RemoveMailTemplateErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum RemoveMailTemplateErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tTEMPLATE_NOT_FOUND\n\t}\n\n\t# === password reset ===\n\n\ttype CheckResetPasswordTokenResult {\n\t\tcode: CheckResetPasswordTokenCode!\n\t}\n\n\tenum CheckResetPasswordTokenCode {\n\t\tREQUEST_NOT_FOUND\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t}\n\n\ttype CreatePasswordResetRequestResponse {\n\t\tok: Boolean!\n\t\terrors: [CreatePasswordResetRequestError!]! @deprecated\n\t\terror: CreatePasswordResetRequestError\n\t}\n\n\ttype CreatePasswordResetRequestError {\n\t\tcode: CreatePasswordResetRequestErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum CreatePasswordResetRequestErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\ttype ResetPasswordResponse {\n\t\tok: Boolean!\n\t\terrors: [ResetPasswordError!]! @deprecated\n\t\terror: ResetPasswordError\n\t}\n\ttype ResetPasswordError {\n\t\tcode: ResetPasswordErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ResetPasswordErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\n\t\tPASSWORD_TOO_WEAK\n\t}\n\n\tinput CreateResetPasswordRequestOptions {\n\t\tmailProject: String\n\t\tmailVariant: String\n\t}\n\n\t# === email verification ===\n\n\tinput EmailVerificationOptions {\n\t\tmailProject: String\n\t\tmailVariant: String\n\t}\n\n\ttype RequestEmailVerificationResponse {\n\t\tok: Boolean!\n\t\terror: RequestEmailVerificationError\n\t}\n\n\ttype RequestEmailVerificationError {\n\t\tcode: RequestEmailVerificationErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RequestEmailVerificationErrorCode {\n\t\tRATE_LIMIT_EXCEEDED\n\t\tINVALID_CAPTCHA\n\t}\n\n\ttype VerifyEmailResponse {\n\t\tok: Boolean!\n\t\terror: VerifyEmailError\n\t}\n\n\ttype VerifyEmailError {\n\t\tcode: VerifyEmailErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum VerifyEmailErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t}\n\n\ttype ConfirmEmailChangeResponse {\n\t\tok: Boolean!\n\t\terror: ConfirmEmailChangeError\n\t}\n\n\ttype ConfirmEmailChangeError {\n\t\tcode: ConfirmEmailChangeErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ConfirmEmailChangeErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t\tEMAIL_ALREADY_EXISTS\n\t\tINVALID_EMAIL_FORMAT\n\t}\n\n\t# === project ===\n\n\tinput ProjectSecret {\n\t\tkey: String!\n\t\tvalue: String!\n\t}\n\n\tinput CreateProjectOptions {\n\t\tdeployTokenHash: String\n\t\tnoDeployToken: Boolean\n\t}\n\n\ttype CreateProjectResponse {\n\t\tok: Boolean!\n\t\terror: CreateProjectResponseError\n\t\tresult: CreateProjectResult\n\t}\n\n\ttype CreateProjectResponseError {\n\t\tcode: CreateProjectResponseErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\ttype CreateProjectResult {\n\t\tdeployerApiKey: ApiKeyWithToken\n\t}\n\n\tenum CreateProjectResponseErrorCode {\n\t\tALREADY_EXISTS\n\t\tINIT_ERROR\n\t}\n\n\ttype SetProjectSecretResponse {\n\t\tok: Boolean!\n\t\terror: SetProjectSecretError\n\t}\n\n\ttype SetProjectSecretError {\n\t\tcode: SetProjectSecretErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum SetProjectSecretErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype UpdateProjectResponse {\n\t\tok: Boolean!\n\t\terror: UpdateProjectError\n\t}\n\n\ttype UpdateProjectError {\n\t\tcode: UpdateProjectErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateProjectErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\t# === auth log ===\n\n\t\"\"\"\n\tA single \\`person_auth_log\\` row. Mirrors the columns described in\n\tdocs/.../audit-log.md.\n\t\"\"\"\n\ttype AuthLogEntry {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\t\"\"\"\n\t\tOne of the values listed in \\`auth_log_type\\` (see audit-log docs).\n\t\tKept as String rather than a GraphQL enum because a few legacy values\n\t\t(\\`2fa_enable\\`, \\`2fa_disable\\`) start with a digit and aren't valid\n\t\tenum names, and the set is expected to keep growing.\n\t\t\"\"\"\n\t\ttype: String!\n\t\tsuccess: Boolean!\n\t\t\"\"\"\n\t\tIdentity that performed the action. May be null for entries created\n\t\tbefore this column was populated, or when the actor's identity was\n\t\tlater deleted (FK is ON DELETE SET NULL semantics-wise).\n\t\t\"\"\"\n\t\tinvokedByIdentityId: String\n\t\t\"\"\"\n\t\tThe actor's person (if the actor was a person, not a bare api_key).\n\t\t\"\"\"\n\t\tpersonId: String\n\t\t\"\"\"\n\t\tThe subject of the action when different from the actor (e.g. force\n\t\tsign-out, role grant, membership change). Resolved from the affected\n\t\tidentity so the trail points at the right person even when the actor\n\t\tacts on someone else's identity.\n\t\t\"\"\"\n\t\ttargetPersonId: String\n\t\t\"\"\"\n\t\tFree-form input string — typically the email submitted on a failed\n\t\tlogin, before any person record was looked up.\n\t\t\"\"\"\n\t\tpersonInputIdentifier: String\n\t\terrorCode: String\n\t\terrorMessage: String\n\t\t\"\"\"\n\t\tEffective client IP after \\`trust-forwarded-info\\` is applied. The\n\t\traw socket peer is preserved in \\`metadata.forwarderIp\\` when a\n\t\ttrusted proxy was involved.\n\t\t\"\"\"\n\t\tipAddress: String\n\t\tuserAgent: String\n\t\tidentityProviderId: String\n\t\t\"\"\"\n\t\tJSONB — forensic context. Common keys: \\`forwarderIp\\`,\n\t\t\\`forwarderUserAgent\\`, \\`sessionId\\`, \\`reason\\`.\n\t\t\"\"\"\n\t\tmetadata: Json\n\t\t\"\"\"\n\t\tJSONB — domain payload. For change events this is typically\n\t\t\\`{before, after}\\`; for creation events it's the snapshot.\n\t\tSecret-bearing inputs are redacted before being stored.\n\t\t\"\"\"\n\t\teventData: Json\n\t}\n\n\t\"\"\"\n\tAll fields are AND-combined. Omitted fields are unconstrained.\n\t\"\"\"\n\tinput AuthLogFilter {\n\t\t\"OR-combined: any of the listed \\`auth_log_type\\` values matches.\"\n\t\ttypes: [String!]\n\t\tsuccess: Boolean\n\t\tinvokedByIdentityId: String\n\t\tpersonId: String\n\t\ttargetPersonId: String\n\t\tpersonInputIdentifier: String\n\t\t\"Inclusive lower bound (\\`created_at >= createdAfter\\`).\"\n\t\tcreatedAfter: DateTime\n\t\t\"Exclusive upper bound (\\`created_at < createdBefore\\`).\"\n\t\tcreatedBefore: DateTime\n\t}\n\n\ttype AuthLogPage {\n\t\tentries: [AuthLogEntry!]!\n\t\t\"True when more rows exist past \\`offset + limit\\`.\"\n\t\thasMore: Boolean!\n\t}\n`\n\nexport default schema\n"],"names":[],"mappings":";AAGA,MAAM,SAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
|
|
1
|
+
{"version":3,"file":"tenant.graphql.js","sources":["../../../../../packages/engine-tenant-api/src/schema/tenant.graphql.ts"],"sourcesContent":["import { gql } from 'graphql-tag'\nimport { DocumentNode } from 'graphql'\n\nconst schema: DocumentNode = gql`\n\tscalar Json\n\tscalar DateTime\n\t\n\t\"\"\" Interval is a string in the format ISO 8601, e.g. \"PT1H\" for 1 hour \"\"\"\n\tscalar Interval\n\n\tschema {\n\t\tquery: Query\n\t\tmutation: Mutation\n\t}\n\n\ttype Query {\n\t\tme: Identity!\n\t\tpersonById(id: String!): Person\n\t\t\"\"\"\n\t\tList persons across the tenant. SUPER_ADMIN sees every person; otherwise\n\t\tthe result is scoped to persons who are members of a project the caller may\n\t\tview members of (i.e. the same persons reachable via \\`project.members\\`),\n\t\tso a PROJECT_ADMIN sees only their projects' members. \\`filter\\` matches by\n\t\te-mail (case-insensitive), \\`personId\\`, or \\`identityId\\`; \\`limit\\`/\\`offset\\`\n\t\tpaginate. Returns an empty list when the caller may not list anyone.\n\t\t\"\"\"\n\t\tpersons(filter: PersonsFilter, limit: Int, offset: Int): [Person!]!\n\t\tprojects: [Project!]!\n\t\tprojectBySlug(slug: String!): Project\n\t\tprojectMemberships(projectSlug: String!, identityId: String!): [Membership!]!\n\t\t\"\"\"\n\t\tList global (project-independent) permanent API keys — those created via\n\t\t\\`createGlobalApiKey\\`, whose identity carries global roles and no project\n\t\tmembership. Requires the \\`apiKey:list\\` permission — by default granted\n\t\tonly to SUPER_ADMIN via the wildcard ALL-resource/ALL-privilege grant.\n\t\tReturns an empty list when the caller may not list them. To list a\n\t\tproject's keys use \\`project.apiKeys\\`.\n\t\t\"\"\"\n\t\tglobalApiKeys: [ApiKey!]!\n\t\tcheckResetPasswordToken(requestId: String!, token: String!): CheckResetPasswordTokenCode!\n\n\t\tidentityProviders: [IdentityProvider!]!\n\n\t\tmailTemplates: [MailTemplateData!]!\n\n\t\tconfiguration: Config!\n\n\t\t\"\"\"\n\t\tList configured auth policies (per-role MFA / session policy). Requires the\n\t\t\\`system:configure\\` permission — by default granted only to SUPER_ADMIN\n\t\t(and PROJECT_ADMIN, like \\`configure\\`). With no rows configured, MFA\n\t\tenforcement is inert and sign-in behaves exactly as today.\n\t\t\"\"\"\n\t\tauthPolicies: [AuthPolicy!]!\n\n\t\t\"\"\"\n\t\tRead the tenant audit log (\\`person_auth_log\\`). Requires the\n\t\t\\`system:viewAuthLog\\` permission — by default granted only to\n\t\tSUPER_ADMIN via the wildcard ALL-resource/ALL-privilege grant.\n\t\tOrdered by created_at DESC. Page size is capped server-side\n\t\t(default 100, max 500); \\`hasMore\\` indicates a further page exists.\n\t\t\"\"\"\n\t\tauthLog(filter: AuthLogFilter, limit: Int, offset: Int): AuthLogPage!\n\t}\n\n\ttype Mutation {\n\t\tsignUp(email: String!, password: String, passwordHash: String, roles: [String!], name: String, captchaToken: String): SignUpResponse\n\t\tsignIn(email: String!, password: String!, expiration: Int, otpToken: String, backupCode: String, options: SignInOptions): SignInResponse\n\t\tcreateSessionToken(email: String, personId: String, expiration: Int, options: SignInOptions): CreateSessionTokenResponse\n\t\tsignOut(all: Boolean): SignOutResponse\n\t\tchangeProfile(personId: String!, email: String, name: String): ChangeProfileResponse\n\t\tchangeMyProfile(email: String, name: String): ChangeMyProfileResponse\n\t\tchangePassword(personId: String!, password: String!): ChangePasswordResponse\n\t\tchangeMyPassword(currentPassword: String!, newPassword: String!): ChangeMyPasswordResponse\n\n\t\tinitSignInIDP(\n\t\t\tidentityProvider: String!,\n\t\t\tdata: Json\n\t\t\tredirectUrl: String @deprecated(reason: \"use data.redirectUrl\")\n\t\t): InitSignInIDPResponse\n\t\tsignInIDP(\n\t\t\tidentityProvider: String!,\n\t\t\tdata: Json,\n\t\t\texpiration: Int\n\t\t\toptions: SignInOptions\n\t\t\tidpResponse: IDPResponseInput, @deprecated(reason: \"pass idpResponse.url as data.url\")\n\t\t\tredirectUrl: String @deprecated(reason: \"use data.redirectUrl\"),\n\t\t\tsessionData: Json @deprecated(reason: \"use data.sessionData\"),\n\t\t): SignInIDPResponse\n\t\t\n\t\t# passwordless sign in\n\t\tinitSignInPasswordless(email: String!, options: InitSignInPasswordlessOptions, captchaToken: String): InitSignInPasswordlessResponse\n\t\tsignInPasswordless(requestId: String!, validationType: PasswordlessValidationType!, token: String!, expiration: Int, mfaOtp: String, backupCode: String, options: SignInOptions): SignInPasswordlessResponse\n\t\tactivatePasswordlessOtp(requestId: String!, token: String!, otpHash: String!): ActivatePasswordlessOtpResponse\n\n enableMyPasswordless: ToggleMyPasswordlessResponse\n disableMyPasswordless: ToggleMyPasswordlessResponse\n\n\t\t# IDP management\n\t\taddIDP(identityProvider: String!, type: String!, configuration: Json!, options: IDPOptions): AddIDPResponse\n\t\tupdateIDP(identityProvider: String!, type: String, configuration: Json, options: IDPOptions, mergeConfiguration: Boolean): UpdateIDPResponse\n\t\tdisableIDP(identityProvider: String!): DisableIDPResponse\n\t\tenableIDP(identityProvider: String!): EnableIDPResponse\n\n\t\t\"\"\"\n\t\tDisconnect one of the authenticated person's own external IdP connections,\n\t\taddressed by the connection id (see PersonIdentityProvider.id) so a specific\n\t\tconnection can be removed even when the person has several to one provider.\n\t\t\"\"\"\n\t\tdisconnectMyIdentityProvider(id: String!): DisconnectIDPResponse\n\n\t\tprepareOtp(label: String): PrepareOtpResponse\n\t\tconfirmOtp(otpToken: String!): ConfirmOtpResponse\n\t\tdisableOtp: DisableOtpResponse\n\t\tregenerateBackupCodes: RegenerateBackupCodesResponse\n\n\t\tinitEmailOtp: InitEmailOtpResponse\n\t\tconfirmEmailOtp(otpToken: String!): ConfirmEmailOtpResponse\n\t\tdisableEmailOtp: DisableEmailOtpResponse\n\n\t\tdisablePerson(personId: String!): DisablePersonResponse\n\t\tenablePerson(personId: String!): EnablePersonResponse\n\t\tforceSignOutPerson(personId: String!, reason: String): ForceSignOutPersonResponse\n\t\tresetPersonMfa(personId: String!): ResetPersonMfaResponse\n\t\trevokeSession(sessionId: String!): RevokeSessionResponse\n\n\t\tcreateResetPasswordRequest(email: String!, options: CreateResetPasswordRequestOptions, captchaToken: String): CreatePasswordResetRequestResponse\n\t\tresetPassword(token: String!, password: String!): ResetPasswordResponse\n\n\t\t\"\"\"\n\t\t(Re)send the e-mail verification link for the given address. Always\n\t\treports ok regardless of whether the address exists or is already\n\t\tverified, to avoid leaking account existence.\n\t\t\"\"\"\n\t\trequestEmailVerification(email: String!, options: EmailVerificationOptions, captchaToken: String): RequestEmailVerificationResponse\n\t\tverifyEmail(token: String!): VerifyEmailResponse\n\t\t\"\"\"\n\t\tConfirm a pending e-mail change (see changeMyProfile when\n\t\tconfig.signup.requireEmailVerification is enabled). Consumes the token\n\t\tthat was mailed to the new address, swaps the address, and signs out all\n\t\texisting sessions.\n\t\t\"\"\"\n\t\tconfirmEmailChange(token: String!): ConfirmEmailChangeResponse\n\n\t\tinvite(email: String!, name: String, projectSlug: String!, memberships: [MembershipInput!]!, options: InviteOptions): InviteResponse\n\t\tunmanagedInvite(\n\t\t\temail: String!,\n\t\t\tname: String,\n\t\t\tprojectSlug: String!,\n\t\t\tmemberships: [MembershipInput!]!,\n\t\t\toptions: UnmanagedInviteOptions,\n\t\t\tpassword: String @deprecated(reason: \"Use options\")\n\t\t): InviteResponse\n\n\t\taddProjectMember(projectSlug: String!, identityId: String!, memberships: [MembershipInput!]!): AddProjectMemberResponse\n\t\tremoveProjectMember(projectSlug: String!, identityId: String!): RemoveProjectMemberResponse\n\n\t\tupdateProjectMember(projectSlug: String!, identityId: String!, memberships: [MembershipInput!]!): UpdateProjectMemberResponse\n\n\t\tcreateApiKey(projectSlug: String!, memberships: [MembershipInput!]!, description: String!, tokenHash: String, options: CreateApiKeyOptions): CreateApiKeyResponse\n\t\tcreateGlobalApiKey(description: String!, roles: [String!], tokenHash: String, options: CreateApiKeyOptions): CreateApiKeyResponse\n\t\tdisableApiKey(id: String!): DisableApiKeyResponse\n\t\taddGlobalIdentityRoles(identityId: String!, roles: [String!]!): AddGlobalIdentityRolesResponse\n\t\tremoveGlobalIdentityRoles(identityId: String!, roles: [String!]!): RemoveGlobalIdentityRolesResponse\n\n\t\taddMailTemplate(template: MailTemplate!): AddMailTemplateResponse\n\t\tremoveMailTemplate(templateIdentifier: MailTemplateIdentifier!): RemoveMailTemplateResponse\n\n\t\tcreateProject(\n\t\t\tprojectSlug: String!,\n\t\t\tname: String,\n\t\t\tconfig: Json,\n\t\t\tsecrets: [ProjectSecret!],\n\t\t\toptions: CreateProjectOptions,\n\t\t\tdeployTokenHash: String @deprecated(reason: \"Use options\")\n\t\t): CreateProjectResponse\n\t\tsetProjectSecret(projectSlug: String!, key: String!, value: String!): SetProjectSecretResponse\n\t\tupdateProject(projectSlug: String!, name: String, config: Json, mergeConfig: Boolean): UpdateProjectResponse\n\t\t\n\t\tconfigure(config: ConfigInput!): ConfigureResponse\n\n\t\t# === auth policy (per-role MFA / session policy) ===\n\t\tcreateAuthPolicy(policy: AuthPolicyInput!): CreateAuthPolicyResponse\n\t\tupdateAuthPolicy(id: String!, policy: AuthPolicyInput!): UpdateAuthPolicyResponse\n\t\tdeleteAuthPolicy(id: String!): DeleteAuthPolicyResponse\n\n\t\taddProjectMailTemplate(template: MailTemplate!): AddMailTemplateResponse\n\t\t@deprecated(reason: \"use addMailTemplate\")\n\n\t\tremoveProjectMailTemplate(templateIdentifier: MailTemplateIdentifier!): RemoveMailTemplateResponse\n\t\t@deprecated(reason: \"use removeMailTemplate\")\n\n\t}\n\t\n\t# === configure ===\n\t\n\ttype Config {\n\t\tsignup: ConfigSignup!\n\t\temailChange: ConfigEmailChange!\n\t\tpasswordless: ConfigPasswordless!\n\t\tpassword: ConfigPassword!\n\t\tlogin: ConfigLogin!\n\t\tcaptcha: ConfigCaptcha!\n\t\trateLimits: ConfigRateLimits!\n\t\tpanel: ConfigPanel!\n\t}\n\n\ttype ConfigSignup {\n\t\t\"\"\"\n\t\tWhen true, new accounts must verify their e-mail address before they can\n\t\tsign in. The requirement is captured per account at sign-up, so toggling\n\t\tthis only affects accounts created afterwards. Defaults to false (no\n\t\tchange vs. previous behavior). E-mail changes are governed separately by\n\t\tConfigEmailChange.requireVerification.\n\t\t\"\"\"\n\t\trequireEmailVerification: Boolean!\n\t}\n\n\ttype ConfigEmailChange {\n\t\t\"\"\"\n\t\tWhen true, a user-initiated changeMyProfile e-mail change does not swap\n\t\tthe address immediately: it goes through a confirmation flow\n\t\t(confirmEmailChange) against a token mailed to the new address, and the\n\t\told address stays active until the new one is confirmed. Independent of\n\t\tConfigSignup.requireEmailVerification. Defaults to false.\n\t\t\"\"\"\n\t\trequireVerification: Boolean!\n\t}\n\n\ttype ConfigPasswordless {\n\t\tenabled: ConfigPolicy!\n\t\turl: String\n\t\texpiration: Interval!\n\t}\n\n\ttype ConfigPassword {\n\t\tminLength: Int!\n\t\trequireUppercase: Int!\n\t\trequireLowercase: Int!\n\t\trequireDigit: Int!\n\t\trequireSpecial: Int!\n\t\tpattern: String\n\t\tcheckBlacklist: Boolean!\n\t\tcheckHibp: Boolean!\n }\n\n\ttype ConfigLogin {\n\t\tbaseBackoff: Interval!\n\t\tmaxBackoff: Interval!\n\t\tattemptWindow: Interval!\n\t\trevealUserExists: Boolean!\n\t\t\"\"\"\n\t\tIf false, signIn collapses NO_PASSWORD_SET / INVALID_PASSWORD into a\n\t\tgeneric INVALID_CREDENTIALS and signUp omits the recommendedAction\n\t\thint on EMAIL_ALREADY_EXISTS errors. UNKNOWN_EMAIL and existence-level\n\t\tsignals are still controlled by revealUserExists. Defaults to true\n\t\t(no change vs. previous behavior).\n\t\t\"\"\"\n\t\trevealLoginMethod: Boolean!\n\t\tdefaultTokenExpiration: Interval!\n\t\tmaxTokenExpiration: Interval\n\t\tmfaGraceDuration: Interval!\n\t\tanomalyDetection: ConfigLoginAnomalyDetection!\n }\n\n\t\"\"\"\n\tSign-in anomaly detection (A03). Opt-in, disabled by default. When enabled,\n\teach successful password verification is scored against the person's last\n\thistorySize successful logins using signals derived from the trusted client\n\tinfo (country from a reverse-proxy geo header, a user-agent fingerprint, and\n\tthe IP / IP prefix). The cumulative score then drives an action:\n\t - score >= emailThreshold → an informational UNUSUAL_LOGIN email is sent.\n\t - score >= stepUpThreshold → a second factor (email OTP) is additionally\n\t required before a session is issued (reuses the existing step-up flow).\n\tCountry is only ever read through the same trusted-proxy gate as the\n\tforwarded IP / User-Agent — never from an untrusted client.\n\t\"\"\"\n\ttype ConfigLoginAnomalyDetection {\n\t\tenabled: Boolean!\n\t\thistorySize: Int!\n\t\temailThreshold: Int!\n\t\tstepUpThreshold: Int!\n\t}\n\n\t\"\"\"\n\tCaptcha config. The secret is never exposed; only the provider and (where\n\tapplicable) the threshold are readable.\n\t\"\"\"\n\ttype ConfigCaptcha {\n\t\tprovider: CaptchaProvider\n\t\tthreshold: Float\n\t\tprotect: ConfigCaptchaProtect!\n\t}\n\n\t\"\"\"\n\tPer-flow captcha enforcement. The captcha provider/secret is shared; these\n\tflags decide which mutations actually require a captcha token when a provider\n\tis configured.\n\t\"\"\"\n\ttype ConfigCaptchaProtect {\n\t\tsignUp: Boolean!\n\t\tpasswordReset: Boolean!\n\t\tpasswordlessInit: Boolean!\n\t\temailVerification: Boolean!\n\t}\n\n\tenum CaptchaProvider {\n\t\tturnstile\n\t\thcaptcha\n\t\trecaptchaV3\n\t}\n\n\t\"\"\"\n\tConfigurable per-IP rate-limit windows. Each value bounds the number of\n\tattempts allowed from the same client IP in the configured window. Per-email\n\tthrottling for password-reset and passwordless-init flows reuses the\n\texponential backoff from ConfigLogin (baseBackoff / maxBackoff /\n\tattemptWindow) against person_auth_log entries.\n\t\"\"\"\n\ttype ConfigRateLimits {\n\t\tsignUpPerIp: ConfigRateLimitWindow!\n\t\tloginPerIp: ConfigRateLimitWindow!\n\t\tpasswordResetPerIp: ConfigRateLimitWindow!\n\t\tpasswordlessInitPerIp: ConfigRateLimitWindow!\n\t\t\"\"\"\n\t\tCaps how many email-OTP codes may be dispatched per person within the\n\t\twindow (a brute-force / email-bomb backstop). Unlike the per-IP limits it\n\t\tships enabled by default. Set limit to 0 to disable.\n\t\t\"\"\"\n\t\temailOtpPerPerson: ConfigRateLimitWindow!\n\t\temailVerificationPerIp: ConfigRateLimitWindow!\n\t}\n\n\ttype ConfigRateLimitWindow {\n\t\tlimit: Int!\n\t\twindow: Interval!\n\t}\n\n\t\"\"\"\n\tWho may enter the management panel. This is an entry gate for the console\n\tonly, not an authorization system: everything done inside the panel still\n\tgoes through the tenant ACL, so being allowed in grants no extra rights.\n\tAn identity may enter when its global roles intersect globalRoles, or when\n\tit holds a membership with one of projectRoles in at least one project.\n\tBoth lists empty means nobody can enter.\n\t\"\"\"\n\ttype ConfigPanel {\n\t\t\"\"\"Global roles (identity.roles) that may use the management panel.\"\"\"\n\t\tglobalRoles: [String!]!\n\t\t\"\"\"Project membership roles that may use the management panel, in any project.\"\"\"\n\t\tprojectRoles: [String!]!\n\t}\n\n\tinput ConfigInput {\n\t\tsignup: ConfigSignupInput\n\t\temailChange: ConfigEmailChangeInput\n\t\tpasswordless: ConfigPasswordlessInput\n\t\tpassword: ConfigPasswordInput\n\t\tlogin: ConfigLoginInput\n\t\tcaptcha: ConfigCaptchaInput\n\t\trateLimits: ConfigRateLimitsInput\n\t\tpanel: ConfigPanelInput\n\t}\n\n\tinput ConfigSignupInput {\n\t\trequireEmailVerification: Boolean\n\t}\n\n\tinput ConfigEmailChangeInput {\n\t\trequireVerification: Boolean\n\t}\n\n\tenum ConfigPolicy {\n\t\talways\n\t\tnever\n\t\toptIn\n\t\toptOut\n\t}\n\n\tinput ConfigPasswordlessInput {\n\t\tenabled: ConfigPolicy\n\t\turl: String\n\t\texpiration: Interval\n\t}\n\n\tinput ConfigPasswordInput {\n\t\tminLength: Int\n\t\trequireUppercase: Int\n\t\trequireLowercase: Int\n\t\trequireDigit: Int\n\t\trequireSpecial: Int\n\t\tpattern: String\n\t\tcheckBlacklist: Boolean\n\t\tcheckHibp: Boolean\n }\n\n\tinput ConfigLoginInput {\n\t\tbaseBackoff: Interval\n\t\tmaxBackoff: Interval\n\t\tattemptWindow: Interval\n\t\trevealUserExists: Boolean\n\t\trevealLoginMethod: Boolean\n\t\tdefaultTokenExpiration: Interval\n\t\tmaxTokenExpiration: Interval\n\t\tmfaGraceDuration: Interval\n\t\tanomalyDetection: ConfigLoginAnomalyDetectionInput\n }\n\n\tinput ConfigLoginAnomalyDetectionInput {\n\t\tenabled: Boolean\n\t\thistorySize: Int\n\t\temailThreshold: Int\n\t\tstepUpThreshold: Int\n\t}\n\n\t\"\"\"\n\tProvider null disables captcha verification. Secret is write-only.\n\tPass null secret to leave the stored value unchanged; pass empty string to clear.\n\t\"\"\"\n\tinput ConfigCaptchaInput {\n\t\tprovider: CaptchaProvider\n\t\tsecret: String\n\t\tthreshold: Float\n\t\tprotect: ConfigCaptchaProtectInput\n\t}\n\n\tinput ConfigCaptchaProtectInput {\n\t\tsignUp: Boolean\n\t\tpasswordReset: Boolean\n\t\tpasswordlessInit: Boolean\n\t\temailVerification: Boolean\n\t}\n\n\tinput ConfigRateLimitsInput {\n\t\tsignUpPerIp: ConfigRateLimitWindowInput\n\t\tloginPerIp: ConfigRateLimitWindowInput\n\t\tpasswordResetPerIp: ConfigRateLimitWindowInput\n\t\tpasswordlessInitPerIp: ConfigRateLimitWindowInput\n\t\temailOtpPerPerson: ConfigRateLimitWindowInput\n\t\temailVerificationPerIp: ConfigRateLimitWindowInput\n\t}\n\n\tinput ConfigRateLimitWindowInput {\n\t\tlimit: Int\n\t\twindow: Interval\n\t}\n\n\t\"\"\"\n\tEach list is replaced as a whole; omitting one leaves it unchanged. An empty\n\tlist closes the panel for that dimension.\n\t\"\"\"\n\tinput ConfigPanelInput {\n\t\tglobalRoles: [String!]\n\t\tprojectRoles: [String!]\n\t}\n\t\n\ttype ConfigureResponse {\n\t\tok: Boolean!\n\t\terror: ConfigureError\n\t}\n\t\n\ttype ConfigureError {\n\t\tcode: ConfigureErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ConfigureErrorCode {\n\t\tINVALID_CONFIG\n\t}\n\n\t# === signUp ===\n\ttype SignUpResponse {\n\t\tok: Boolean!\n\t\terrors: [SignUpError!]! @deprecated\n\t\terror: SignUpError\n\t\tresult: SignUpResult\n\t}\n\n\ttype SignUpError {\n\t\tcode: SignUpErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\t\"\"\"\n\t\tFor EMAIL_ALREADY_EXISTS, the recommended next action client UIs should\n\t\toffer to the visitor. Null for unrelated error codes.\n\t\t\"\"\"\n\t\trecommendedAction: SignUpRecommendedAction\n\t\tdeveloperMessage: String!\n\t\tendPersonMessage: String @deprecated\n\t}\n\n\tenum SignUpErrorCode {\n\t\tEMAIL_ALREADY_EXISTS\n\t\tINVALID_EMAIL_FORMAT\n\t\tTOO_WEAK\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\tenum SignUpRecommendedAction {\n\t\tSIGN_IN\n\t\tRESET_PASSWORD\n\t}\n\n\ttype SignUpResult {\n\t\tperson: Person!\n\t}\n\n\t# === signInCommon ==\n\n\tinterface CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\n\t# === signIn ===\n\tinput SignInOptions {\n\t\t\"\"\"\n\t\tIf true, and the calling api_key has trust_forwarded_info=true,\n\t\tthe resulting session token will trust X-Contember-Client-IP and\n\t\tX-Contember-Client-User-Agent headers on subsequent requests.\n\t\tSilently ignored when the caller's api_key does not have the flag.\n\n\t\tSecurity: a proxy that sets these headers MUST strip any\n\t\tincoming X-Contember-Client-IP / X-Contember-Client-User-Agent\n\t\tfrom upstream traffic and re-inject values it trusts. Without\n\t\tthat, any client holding a session token minted with this flag\n\t\tcould spoof its own IP/User-Agent.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean\n\t}\n\n\ttype SignInResponse {\n\t\tok: Boolean!\n\t\terrors: [SignInError!]! @deprecated\n\t\terror: SignInError\n\t\tresult: SignInResult\n\t}\n\n\ttype SignInError {\n\t\tcode: SignInErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t\tretryAfter: Int\n\t\t\"\"\"\n\t\tSet only on a MFA_ENROLLMENT_REQUIRED error: the freshly provisioned\n\t\tpending TOTP secret the client must enroll (show the QR / secret, then\n\t\tretry signIn with otpToken). Additive — clients that don't read it are\n\t\tunaffected.\n\t\t\"\"\"\n\t\tmfaEnrollment: MfaEnrollment\n\t}\n\n\ttype MfaEnrollment {\n\t\totpUri: String!\n\t\totpSecret: String!\n\t}\n\n\tenum SignInErrorCode {\n\t\tINVALID_CREDENTIALS\n\t\tUNKNOWN_EMAIL\n\t\tINVALID_PASSWORD\n\t\tPERSON_DISABLED\n\t\tNO_PASSWORD_SET\n\t\tOTP_REQUIRED\n\t\tINVALID_OTP_TOKEN\n\t\tMFA_ENROLLMENT_REQUIRED\n\t\tEMAIL_NOT_VERIFIED\n\t\tRATE_LIMIT_EXCEEDED\n\t\t\"\"\"\n\t\tThe person is linked to an identity provider with\n\t\t\\`disableLocalAuthentication\\`, so password sign-in is not available to them.\n\t\t\"\"\"\n\t\tIDP_REQUIRED\n\t}\n\n\ttype SignInResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t\t\"\"\"\n\t\tSet only when this sign-in completed an MFA enrollment (A06): the freshly\n\t\tgenerated backup codes, shown exactly once. Null on a normal sign-in.\n\t\t\"\"\"\n\t\tbackupCodes: [String!]\n\t}\n\n\t# == createSessionToken ==\n\n\ttype CreateSessionTokenResponse {\n\t\tok: Boolean!\n\t\terror: CreateSessionTokenError\n\t\tresult: CreateSessionTokenResult\n\t}\n\n\ttype CreateSessionTokenError {\n\t\tcode: CreateSessionTokenErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum CreateSessionTokenErrorCode {\n\t\tUNKNOWN_EMAIL\n\t\tUNKNOWN_PERSON_ID\n\t\tPERSON_DISABLED\n\t}\n\n\ttype CreateSessionTokenResult implements CommonSignInResult{\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\n\t# === signOut ===\n\n\ttype SignOutResponse {\n\t\tok: Boolean!\n\t\terrors: [SignOutError!]! @deprecated\n\t\terror: SignOutError\n\t\t\"\"\"\n\t\tWhen the session was federated via an OIDC identity provider that supports RP-initiated\n\t\t(front-channel) logout, the URL the client should redirect the browser to so the user is\n\t\talso signed out at the IdP (Single Logout). Null for plain sessions or legacy IdPs without\n\t\tan end-session endpoint, in which case only a local logout happened.\n\t\t\"\"\"\n\t\tlogoutUrl: String\n\t}\n\n\ttype SignOutError {\n\t\tcode: SignOutErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum SignOutErrorCode {\n\t\tNOT_A_PERSON,\n\t\tNOT_POSSIBLE_SIGN_OUT_WITH_PERMANENT_API_KEY\n\t}\n\n\t# === changeProfile ===\n\t\n\ttype ChangeProfileResponse {\n\t\tok: Boolean!\n\t\terror: ChangeProfileError\n\t}\n\t\n\ttype ChangeProfileError {\n\t\tcode: ChangeProfileErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ChangeProfileErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tINVALID_EMAIL_FORMAT\n\t\tEMAIL_ALREADY_EXISTS\n\t}\n\t\n\t# === changeMyProfile ===\n\n\ttype ChangeMyProfileResponse {\n\t\tok: Boolean!\n\t\terror: ChangeMyProfileError\n\t}\n\n\ttype ChangeMyProfileError {\n\t\tcode: ChangeMyProfileErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ChangeMyProfileErrorCode {\n\t\tNOT_A_PERSON\n\t\tINVALID_EMAIL_FORMAT\n\t\tEMAIL_ALREADY_EXISTS\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\t# === changePassword ===\n\n\ttype ChangePasswordResponse {\n\t\tok: Boolean!\n\t\terrors: [ChangePasswordError!]! @deprecated\n\t\terror: ChangePasswordError\n\t}\n\n\ttype ChangePasswordError {\n\t\tcode: ChangePasswordErrorCode!\n\t\tweakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ChangePasswordErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tTOO_WEAK\n\t}\n\t\n\tenum WeakPasswordReason {\n\t\tTOO_SHORT\n\t\tMISSING_UPPERCASE\n\t\tMISSING_LOWERCASE\n\t\tMISSING_DIGIT\n\t\tMISSING_SPECIAL\n\t\tINVALID_PATTERN\n\t\tBLACKLISTED\n\t\tCOMPROMISED\n }\n\n\n\t# === changeMyPassword ===\n\t\n\ttype ChangeMyPasswordResponse {\n\t\tok: Boolean!\n\t\terror: ChangeMyPasswordError\n\t}\n\n\ttype ChangeMyPasswordError {\n\t\tcode: ChangeMyPasswordErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ChangeMyPasswordErrorCode {\n\t\tTOO_WEAK\n\t\tNOT_A_PERSON\n\t\tINVALID_PASSWORD\n\t\tNO_PASSWORD_SET\n\t}\n\n\t# === IDP ===\n\n\ttype InitSignInIDPResponse {\n\t\tok: Boolean!\n\t\terrors: [InitSignInIDPError!]! @deprecated\n\t\terror: InitSignInIDPError\n\t\tresult: InitSignInIDPResult\n\t}\n\n\ttype InitSignInIDPResult {\n\t\tauthUrl: String!\n\t\tsessionData: Json!\n\t\tidpConfiguration: Json\n\t}\n\n\ttype InitSignInIDPError {\n\t\tcode: InitSignInIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum InitSignInIDPErrorCode {\n\t\tPROVIDER_NOT_FOUND\n\t\tIDP_VALIDATION_FAILED\n\t}\n\n\tinput IDPResponseInput {\n\t\turl: String!\n\t}\n\n\ttype SignInIDPResponse {\n\t\tok: Boolean!\n\t\terrors: [SignInIDPError!]! @deprecated\n\t\terror: SignInIDPError\n\t\tresult: SignInIDPResult\n\t}\n\n\ttype SignInIDPError {\n\t\tcode: SignInIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum SignInIDPErrorCode {\n\t\tINVALID_IDP_RESPONSE\n\t\tIDP_VALIDATION_FAILED\n\n\t\tPERSON_NOT_FOUND\n\t\tPERSON_DISABLED\n\t\tPERSON_ALREADY_EXISTS\n\t}\n\n\ttype SignInIDPResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t\tidpResponse: Json\n\t}\n\n\ttype AddIDPResponse {\n\t\terror: AddIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype AddIDPError {\n\t\tcode: AddIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum AddIDPErrorCode {\n\t\tALREADY_EXISTS\n\t\tUNKNOWN_TYPE\n\t\tINVALID_CONFIGURATION\n\t}\n\n\ttype UpdateIDPResponse {\n\t\terror: UpdateIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype UpdateIDPError {\n\t\tcode: UpdateIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateIDPErrorCode {\n\t\tNOT_FOUND\n\t\tINVALID_CONFIGURATION\n\t}\n\n\n\ttype DisableIDPResponse {\n\t\terror: DisableIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype DisableIDPError {\n\t\tcode: DisableIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisableIDPErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\ttype EnableIDPResponse {\n\t\terror: EnableIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype EnableIDPError {\n\t\tcode: EnableIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum EnableIDPErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\t\"\"\" A single external IdP connection of the currently authenticated person. \"\"\"\n\ttype PersonIdentityProvider {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\texternalIdentifier: String!\n\t\tidentityProvider: IdentityProviderListItem!\n\t}\n\n\t\"\"\" Public view of an identity provider, exposed in personal IdP connection listings. \"\"\"\n\ttype IdentityProviderListItem {\n\t\tslug: String!\n\t\ttype: String!\n\t\tdisabledAt: DateTime\n\t}\n\n\ttype DisconnectIDPResponse {\n\t\terror: DisconnectIDPError\n\t\tok: Boolean!\n\t}\n\n\ttype DisconnectIDPError {\n\t\tcode: DisconnectIDPErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisconnectIDPErrorCode {\n\t\t\"\"\" The authenticated person has no IdP connection with the given id. \"\"\"\n\t\tNOT_FOUND\n\t\t\"\"\" The caller is not a person (e.g. an API key) and so has no IdP connections to disconnect. \"\"\"\n\t\tNOT_A_PERSON\n\t\t\"\"\" The person is not allowed to disconnect their last remaining sign-in method. \"\"\"\n\t\tLAST_AUTH_METHOD\n\t\t\"\"\"\n\t\tThe provider has \\`disableLocalAuthentication\\`, so this connection is the only way\n\t\tthe person may sign in and cannot be removed by them — not even while the provider is disabled.\n\t\t\"\"\"\n\t\tIDP_REQUIRED\n\t}\n\n\ttype IdentityProvider {\n\t\tslug: String!\n\t\ttype: String!\n\t\tconfiguration: Json!\n\t\tdisabledAt: DateTime\n\t\toptions: IDPOptionsOutput!\n\t}\n\n\ttype IDPOptionsOutput {\n\t\tautoSignUp: Boolean!\n\t\texclusive: Boolean!\n\t\tinitReturnsConfig: Boolean!\n\t\t\"\"\"\n\t\tWhen true, a non-exclusive provider may only auto-link to / sign in an\n\t\texisting account by e-mail if the provider asserts the e-mail is verified.\n\t\tDefaults to false.\n\t\t\"\"\"\n\t\trequireVerifiedEmail: Boolean!\n\t\t\"\"\"\n\t\tWhen true, e-mail addresses asserted by this provider are treated as verified\n\t\teven without an \"email_verified\" claim. Use only for trusted providers.\n\t\tDefaults to false.\n\t\t\"\"\"\n\t\tassumeEmailVerified: Boolean!\n\t\t\"\"\"\n\t\tWhen true, a person linked to this provider may authenticate ONLY through it:\n\t\tpassword sign-in and passwordless sign-in are refused and no password-reset\n\t\tmail is sent. Disabling the provider lifts the restriction, which is the\n\t\tbreak-glass for an IdP outage. Defaults to false.\n\t\t\"\"\"\n\t\tdisableLocalAuthentication: Boolean!\n\t}\n\n\tinput IDPOptions {\n\t\tautoSignUp: Boolean\n\t\texclusive: Boolean\n\t\tinitReturnsConfig: Boolean\n\t\trequireVerifiedEmail: Boolean\n\t\tassumeEmailVerified: Boolean\n\t\tdisableLocalAuthentication: Boolean\n\t}\n\n\t# === passwordless sign in ===\n\t\n\ttype InitSignInPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: InitSignInPasswordlessError\n\t\tresult: InitSignInPasswordlessResult\n\t}\n\t\n\ttype InitSignInPasswordlessError {\n\t\tcode: InitSignInPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum InitSignInPasswordlessErrorCode {\n\t\tPERSON_NOT_FOUND\n\n\t\tPASSWORDLESS_DISABLED\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t\t\"\"\"\n\t\tThe person is linked to an identity provider with\n\t\t\\`disableLocalAuthentication\\`, so passwordless sign-in is not available to them.\n\t\t\"\"\"\n\t\tIDP_REQUIRED\n\t}\n\t\n\ttype InitSignInPasswordlessResult {\n\t\trequestId: String!\n\t\texpiresAt: DateTime!\n\t}\n\n\tinput InitSignInPasswordlessOptions {\n\t\tmailVariant: String\n\t\tmailProject: String\n\t}\n\t\n\ttype SignInPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: SignInPasswordlessError\n\t\tresult: SignInPasswordlessResult\n\t}\n\t\n\tenum PasswordlessValidationType {\n\t\totp\n\t\ttoken\n\t}\n\t\n\ttype SignInPasswordlessError {\n\t\tcode: SignInPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum SignInPasswordlessErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_EXPIRED\n\t\tTOKEN_USED\n\t\tPERSON_DISABLED\n\t\tOTP_REQUIRED\n\t\tINVALID_OTP_TOKEN\n\t\tMFA_ENROLLMENT_REQUIRED\n\t\t\"\"\"\n\t\tThe person became linked to an identity provider with\n\t\t\\`disableLocalAuthentication\\` after this magic link was issued.\n\t\t\"\"\"\n\t\tIDP_REQUIRED\n\t}\n\n\ttype SignInPasswordlessResult implements CommonSignInResult {\n\t\ttoken: String!\n\t\tperson: Person!\n\t}\n\t\n\ttype ActivatePasswordlessOtpResponse {\n\t\tok: Boolean!\n\t\terror: ActivatePasswordlessOtpError\n\t}\n\t\n\ttype ActivatePasswordlessOtpError {\n\t\tcode: ActivatePasswordlessOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ActivatePasswordlessOtpErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_EXPIRED\n\t\tTOKEN_USED\n\t}\n\t\n\ttype ToggleMyPasswordlessResponse {\n\t\tok: Boolean!\n\t\terror: ToggleMyPasswordlessError\n\t}\n\t\n\ttype ToggleMyPasswordlessError {\n\t\tcode: ToggleMyPasswordlessErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\t\n\tenum ToggleMyPasswordlessErrorCode {\n\t\tCANNOT_TOGGLE\n NOT_A_PERSON\n\t}\n\t\n\n\t# === invite ===\n\n\ttype InviteResponse {\n\t\tok: Boolean!\n\t\terrors: [InviteError!]! @deprecated\n\t\terror: InviteError\n\t\tresult: InviteResult\n\t}\n\n\ttype InviteError {\n\t\tcode: InviteErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum InviteErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tALREADY_MEMBER\n\t\tINVALID_MEMBERSHIP\n\t\tINVALID_EMAIL_FORMAT\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t}\n\n\ttype InviteResult {\n\t\tperson: Person!\n\t\tisNew: Boolean!\n\t}\n\n\tenum InviteMethod {\n\t\tCREATE_PASSWORD\n\t\tRESET_PASSWORD\n\t}\n\n\tinput InviteOptions {\n\t\tmethod: InviteMethod\n\t\tmailVariant: String\n\t}\n\n\tinput UnmanagedInviteOptions {\n\t\tpassword: String\n\t\tresetTokenHash: String\n\t}\n\n\t# === addProjectMember ===\n\n\ttype AddProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [AddProjectMemberError!]!\n\t\terror: AddProjectMemberError\n\t}\n\n\ttype AddProjectMemberError {\n\t\tcode: AddProjectMemberErrorCode!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum AddProjectMemberErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tIDENTITY_NOT_FOUND\n\t\tALREADY_MEMBER\n\t\tINVALID_MEMBERSHIP\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t}\n\n\t# === updateProjectMember ===\n\n\ttype UpdateProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [UpdateProjectMemberError!]! @deprecated\n\t\terror: UpdateProjectMemberError\n\t}\n\n\ttype UpdateProjectMemberError {\n\t\tcode: UpdateProjectMemberErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum UpdateProjectMemberErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tNOT_MEMBER\n\t\tINVALID_MEMBERSHIP\n\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t}\n\n\t# === removeProjectMember ===\n\n\ttype RemoveProjectMemberResponse {\n\t\tok: Boolean!\n\t\terrors: [RemoveProjectMemberError!]!\n\t\terror: RemoveProjectMemberError\n\t}\n\n\ttype RemoveProjectMemberError {\n\t\tcode: RemoveProjectMemberErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum RemoveProjectMemberErrorCode {\n\t\tNOT_MEMBER\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\t# === createApiKey ===\n\n\tinput CreateApiKeyOptions {\n\t\t\"\"\"\n\t\tIf true, the created api_key trusts X-Contember-Client-IP and\n\t\tX-Contember-Client-User-Agent headers on subsequent requests.\n\t\tIntended for backend services that proxy user requests; the customer's\n\t\tproxy must strip these headers from incoming traffic and re-inject\n\t\tthem with the real user values.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean\n\t}\n\n\ttype CreateApiKeyResponse {\n\t\tok: Boolean!\n\t\terrors: [CreateApiKeyError!]! @deprecated\n\t\terror: CreateApiKeyError\n\t\tresult: CreateApiKeyResult\n\t}\n\n\ttype CreateApiKeyError {\n\t\tcode: CreateApiKeyErrorCode!\n\t\tdeveloperMessage: String!\n\t\tmembershipValidation: [MembershipValidationError!]\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum CreateApiKeyErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tINVALID_MEMBERSHIP\n\n\t\tVARIABLE_NOT_FOUND @deprecated\n\t\tROLE_NOT_FOUND @deprecated\n\t\tVARIABLE_EMPTY @deprecated\n\t}\n\n\ttype CreateApiKeyResult {\n\t\tapiKey: ApiKeyWithToken!\n\t}\n\n\t# === disableApiKey ===\n\n\ttype DisableApiKeyResponse {\n\t\tok: Boolean!\n\t\terrors: [DisableApiKeyError!]! @deprecated\n\t\terror: DisableApiKeyError\n\t}\n\n\ttype DisableApiKeyError {\n\t\tcode: DisableApiKeyErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum DisableApiKeyErrorCode {\n\t\tKEY_NOT_FOUND\n\t}\n\t# === addGlobalIdentityRoles ===\n\n\ttype AddGlobalIdentityRolesResponse {\n\t\tok: Boolean!\n\t\terror: AddGlobalIdentityRolesError\n\t\tresult: AddGlobalIdentityRolesResult\n\t}\n\n\ttype AddGlobalIdentityRolesResult {\n\t\tidentity: Identity!\n\t}\n\ttype AddGlobalIdentityRolesError {\n\t\tcode: AddGlobalIdentityRolesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum AddGlobalIdentityRolesErrorCode {\n\t\tIDENTITY_NOT_FOUND\n\t\tINVALID_ROLE\n\t}\n\n\n\t# === removeGlobalIdentityRoles ===\n\n\ttype RemoveGlobalIdentityRolesResponse {\n\t\tok: Boolean!\n\t\terror: RemoveGlobalIdentityRolesError\n\t\tresult: RemoveGlobalIdentityRolesResult\n\t}\n\n\ttype RemoveGlobalIdentityRolesError {\n\t\tcode: RemoveGlobalIdentityRolesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\ttype RemoveGlobalIdentityRolesResult {\n\t\tidentity: Identity!\n\t}\n\n\tenum RemoveGlobalIdentityRolesErrorCode {\n\t\tIDENTITY_NOT_FOUND\n\t\tINVALID_ROLE\n\t}\n\t# === common ===\n\n\t# === variables ===\n\n\tinput VariableEntryInput {\n\t\tname: String!\n\t\tvalues: [String!]!\n\t}\n\n\ttype VariableEntry {\n\t\tname: String!\n\t\tvalues: [String!]!\n\t}\n\n\t# === membership ===\n\n\tinput MembershipInput {\n\t\trole: String!\n\t\tvariables: [VariableEntryInput!]!\n\t}\n\n\ttype Membership {\n\t\trole: String!\n\t\tvariables: [VariableEntry!]!\n\t}\n\n\ttype MembershipValidationError {\n\t\tcode: MembershipValidationErrorCode!\n\t\trole: String!\n\t\tvariable: String\n\t}\n\n\tenum MembershipValidationErrorCode {\n\t\tROLE_NOT_FOUND\n\t\tVARIABLE_NOT_FOUND\n\t\tVARIABLE_EMPTY\n\t\tVARIABLE_INVALID\n\t}\n\n\t# === person ====\n\n\ttype Person {\n\t\tid: String!\n\t\temail: String\n\t\tname: String\n\t\totpEnabled: Boolean!\n\t\t\"\"\" The person's own opt-in flag; \\`null\\` means \"follow the tenant policy\". On its own it does not say whether passwordless sign-in works — see \\`passwordlessAvailable\\`. \"\"\"\n\t\tpasswordlessEnabled: Boolean\n\t\t\"\"\"\n\t\tWhether passwordless sign-in is actually usable for this person right now: the tenant-wide\n\t\tpolicy resolved against \\`passwordlessEnabled\\`, i.e. the very same decision \\`signIn\\` makes. A UI\n\t\toffering an enable/disable toggle must branch on this — under an \\`always\\` or \\`never\\` policy the\n\t\traw opt-in flag says nothing about what will happen.\n\t\t\"\"\"\n\t\tpasswordlessAvailable: Boolean!\n\t\t\"\"\"\n\t\tWhether \\`passwordlessEnabled\\` is what decides \\`passwordlessAvailable\\`. False under an \\`always\\`\n\t\tor \\`never\\` policy, where the person's own flag is ignored — a UI should then report the state\n\t\trather than offer a toggle that changes nothing.\n\t\t\"\"\"\n\t\tpasswordlessSelfManaged: Boolean!\n\t\t\"\"\"\n\t\tWhether e-mail based one-time-password 2FA is enabled for this person\n\t\t(see \\`initEmailOtp\\` / \\`confirmEmailOtp\\` / \\`disableEmailOtp\\`). Independent\n\t\tof \\`otpEnabled\\` (TOTP authenticator), so a UI can show each MFA method's\n\t\tstate separately.\n\t\t\"\"\"\n\t\temailOtpEnabled: Boolean!\n\t\temailVerified: Boolean!\n\t\t\"\"\"\n\t\tWhen the account was disabled (see \\`disablePerson\\`), null while the person\n\t\tis active. Read-only — flip it with \\`disablePerson\\` / \\`enablePerson\\`.\n\t\t\"\"\"\n\t\tdisabledAt: DateTime\n\t\tidentity: Identity!\n\n\t\t\"\"\"\n\t\tExternal IdP connections of this person. Always visible for the calling\n\t\tperson (e.g. via \\`me { person { identityProviders } }\\`). For other\n\t\tpersons, visible to callers holding the \\`person:viewIdp\\` permission\n\t\tagainst the target's roles — SUPER_ADMIN sees everyone; PROJECT_ADMIN\n\t\tsees members whose roles fall within their allowed-input-roles. Returns\n\t\tan empty list rather than throwing when the viewer lacks visibility.\n\t\t\"\"\"\n\t\tidentityProviders: [PersonIdentityProvider!]!\n\t}\n\n\t\"\"\" Filter for the \\`persons\\` query. Fields are combined with AND. \"\"\"\n\tinput PersonsFilter {\n\t\temail: String\n\t\tpersonId: String\n\t\tidentityId: String\n\t}\n\n\t# === api key ===\n\n\tenum ApiKeyType {\n\t\tSESSION\n\t\tPERMANENT\n\t\tONE_OFF\n\t}\n\n\ttype ApiKey {\n\t\tid: String!\n\t\tidentity: Identity!\n\t\t\"\"\" Human-readable label, stored on the key's identity (\\`identity.description\\`). \"\"\"\n\t\tdescription: String\n\t\ttype: ApiKeyType\n\t\t\"\"\" False once the key has been disabled (\\`disableApiKey\\`). \"\"\"\n\t\tenabled: Boolean\n\t\tcreatedAt: DateTime\n\t\tlastUsedAt: DateTime\n\t\texpiresAt: DateTime\n\t}\n\n\ttype ApiKeyWithToken {\n\t\tid: String!\n\t\ttoken: String\n\t\tidentity: Identity!\n\t}\n\n\t# === identity ===\n\n\ttype Identity {\n\t\tid: String!\n\t\tdescription: String\n\t\tperson: Person\n\t\tapiKey: ApiKey\n\t\tprojects: [IdentityProjectRelation!]!\n\t\tpermissions: IdentityGlobalPermissions\n\t\troles: [String!]\n\t\t\"\"\"\n\t\tActive SESSION-type api keys for this identity. Always visible for\n\t\tthe calling identity (e.g. via \\`me { sessions }\\`). For other identities,\n\t\tvisible to callers holding the \\`person:viewSessions\\` permission against\n\t\tthe target's roles — SUPER_ADMIN sees everyone; PROJECT_ADMIN sees\n\t\tmembers whose roles fall within their allowed-input-roles. Returns an\n\t\tempty list rather than throwing when the viewer lacks visibility, so\n\t\tbatched identity queries do not abort on a single forbidden target.\n\t\t\"\"\"\n\t\tsessions: [SessionInfo!]!\n\t}\n\n\t\"\"\"\n\tWhat the identity may do tenant-wide, evaluated against the same ACL the resolvers enforce.\n\n\tThis is for building a UI that does not offer what it cannot deliver — it is **not** a security\n\tboundary, and answering \\`true\\` here grants nothing. Every operation is still checked when it is\n\tcalled. The distinction matters because permission failure is not uniform across this API: some\n\tqueries answer an empty list, others throw, and every mutation throws, so a client cannot tell\n\t\"nothing to show\" from \"not yours to see\" by trying.\n\t\"\"\"\n\ttype IdentityGlobalPermissions {\n\t\tcanCreateProject: Boolean!\n\t\tcanDeployEntrypoint: Boolean!\n\t\t\"\"\" Read \\`configuration\\`, which throws otherwise. The other configuration queries gate on their own actions. \"\"\"\n\t\tcanViewConfiguration: Boolean!\n\t\t\"\"\" Read \\`identityProviders\\`. \"\"\"\n\t\tcanListIdentityProviders: Boolean!\n\t\t\"\"\" Read \\`mailTemplates\\`. \"\"\"\n\t\tcanListMailTemplates: Boolean!\n\t\t\"\"\"\n\t\tWrite the tenant configuration (\\`configure\\`) and read \\`authPolicies\\`. The CLI is the usual write path.\n\t\t\"\"\"\n\t\tcanManageConfiguration: Boolean!\n\t\t\"\"\" Read \\`authLog\\`, which throws otherwise. \"\"\"\n\t\tcanViewAuthLog: Boolean!\n\t\t\"\"\"\n\t\tList every person in the tenant. Without it \\`persons\\` still answers, narrowed to the members\n\t\tof the projects the caller administers — so this marks a full listing, not access to one.\n\t\t\"\"\"\n\t\tcanListPersons: Boolean!\n\t\t\"\"\" Read \\`globalApiKeys\\`, which answers an empty list otherwise. \"\"\"\n\t\tcanListGlobalApiKeys: Boolean!\n\t\tcanCreateGlobalApiKey: Boolean!\n\t}\n\n\t\"\"\"\n\tWhat the calling identity may do in this project. Same contract as\n\t\\`IdentityGlobalPermissions\\`: advisory, evaluated per caller, never a substitute for the checks in\n\tthe resolvers.\n\t\"\"\"\n\ttype ProjectPermissions {\n\t\t\"\"\" Read \\`members\\` and \\`apiKeys\\`; both answer an empty list otherwise. \"\"\"\n\t\tcanViewMembers: Boolean!\n\t\t\"\"\" Invite or add a member (\\`invite\\`, \\`addProjectMember\\`). Which roles may be granted is checked per membership. \"\"\"\n\t\tcanAddMember: Boolean!\n\t\tcanUpdateMember: Boolean!\n\t\tcanRemoveMember: Boolean!\n\t\t\"\"\" Read \\`secrets\\` (their names, never values); answers an empty list otherwise. \"\"\"\n\t\tcanViewSecrets: Boolean!\n\t\t\"\"\" Write a project secret (\\`setProjectSecret\\`). Distinct from viewing: a project admin commonly has one and not the other. \"\"\"\n\t\tcanSetSecret: Boolean!\n\t\t\"\"\" Create an API key scoped to this project. \"\"\"\n\t\tcanCreateApiKey: Boolean!\n\t\t\"\"\" Update the project itself (\\`updateProject\\`). \"\"\"\n\t\tcanUpdate: Boolean!\n\t}\n\n\ttype IdentityProjectRelation {\n\t\tproject: Project!\n\t\tmemberships: [Membership!]!\n\t}\n\n\t# === project ===\n\n\ttype Project {\n\t\tid: String!\n\t\tname: String!\n\t\tslug: String!\n\t\tconfig: Json!\n\t\troles: [RoleDefinition!]!\n\t\tmembers(\n\t\t\tinput: ProjectMembersInput,\n\t\t\tmemberType: MemberType @deprecated(reason: \"Use args\")\n\t\t): [ProjectIdentityRelation!]!\n\t\t\"\"\"\n\t\tPermanent API keys scoped to this project — keys whose identity is a member\n\t\tof the project (excludes SESSION tokens and global keys). Each key's\n\t\tproject memberships are reachable via \\`apiKey.identity.projects\\` for\n\t\tcloning when (re)issuing a key. Requires \\`project.view members\\` permission;\n\t\treturns an empty list otherwise.\n\t\t\"\"\"\n\t\tapiKeys: [ApiKey!]!\n\t\t\"\"\"\n\t\tNames of the project's secrets (see \\`setProjectSecret\\`). Secret VALUES are\n\t\tnever returned — only the keys and their timestamps — so a UI can show which\n\t\tsecrets exist. Requires the \\`project:viewSecrets\\` permission (project admins\n\t\t+ SUPER_ADMIN by default); returns an empty list otherwise.\n\t\t\"\"\"\n\t\tsecrets: [ProjectSecretInfo!]!\n\t\t\"\"\" What the calling identity may do here. Advisory — for building the UI, not for enforcing it. \"\"\"\n\t\tpermissions: ProjectPermissions!\n\t}\n\n\t\"\"\" Metadata about a project secret — never its value. \"\"\"\n\ttype ProjectSecretInfo {\n\t\tkey: String!\n\t\tcreatedAt: DateTime!\n\t\tupdatedAt: DateTime!\n\t}\n\n\tinput ProjectMembersInput {\n\t\tlimit: Int\n\t\toffset: Int\n\t\tfilter: ProjectMembersFilter\n\t}\n\n\tinput ProjectMembersFilter {\n\t\tmemberType: MemberType\n\t\temail: [String!]\n\t\tidentityId: [String!]\n\t\tpersonId: [String!]\n\t}\n\n\tenum MemberType {\n\t\tAPI_KEY\n\t\tPERSON\n\t}\n\n\ttype ProjectIdentityRelation {\n\t\tidentity: Identity!\n\t\tmemberships: [Membership!]!\n\t}\n\n\ttype RoleDefinition {\n\t\tname: String!\n\t\tvariables: [RoleVariableDefinition!]!\n\t}\n\n\tinterface RoleVariableDefinition {\n\t\tname: String!\n\t}\n\n\ttype RoleEntityVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t\tentityName: String!\n\t}\n\n\ttype RolePredefinedVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t\tvalue: String!\n\t}\n\n\ttype RoleConditionVariableDefinition implements RoleVariableDefinition {\n\t\tname: String!\n\t}\n\n\t# ==== 2fa ====\n\n\ttype PrepareOtpResponse {\n\t\tok: Boolean!\n\t\tresult: PrepareOtpResult\n\t}\n\n\ttype PrepareOtpResult {\n\t\totpUri: String!\n\t\totpSecret: String!\n\t}\n\n\ttype ConfirmOtpResponse {\n\t\tok: Boolean!\n\t\terrors: [ConfirmOtpError!]! @deprecated\n\t\terror: ConfirmOtpError\n\t\tresult: ConfirmOtpResult\n\t}\n\n\ttype ConfirmOtpResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\ttype ConfirmOtpError {\n\t\tcode: ConfirmOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ConfirmOtpErrorCode {\n\t\tINVALID_OTP_TOKEN\n\t\tNOT_PREPARED\n\t}\n\n\ttype DisableOtpResponse {\n\t\tok: Boolean!\n\t\terrors: [DisableOtpError!]! @deprecated\n\t\terror: DisableOtpError\n\t}\n\n\ttype DisableOtpError {\n\t\tcode: DisableOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum DisableOtpErrorCode {\n\t\tOTP_NOT_ACTIVE\n\t\tMFA_REQUIRED\n\t}\n\n\ttype RegenerateBackupCodesResponse {\n\t\tok: Boolean!\n\t\terror: RegenerateBackupCodesError\n\t\tresult: RegenerateBackupCodesResult\n\t}\n\n\ttype RegenerateBackupCodesError {\n\t\tcode: RegenerateBackupCodesErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RegenerateBackupCodesErrorCode {\n\t\tOTP_NOT_ACTIVE\n\t}\n\n\ttype RegenerateBackupCodesResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\t# ==== email otp (A05) ====\n\n\ttype InitEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: InitEmailOtpError\n\t}\n\n\ttype InitEmailOtpError {\n\t\tcode: InitEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum InitEmailOtpErrorCode {\n\t\tNO_EMAIL\n\t\tRATE_LIMITED\n\t}\n\n\ttype ConfirmEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: ConfirmEmailOtpError\n\t\tresult: ConfirmEmailOtpResult\n\t}\n\n\ttype ConfirmEmailOtpResult {\n\t\tbackupCodes: [String!]!\n\t}\n\n\ttype ConfirmEmailOtpError {\n\t\tcode: ConfirmEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ConfirmEmailOtpErrorCode {\n\t\tINVALID_OTP_TOKEN\n\t}\n\n\ttype DisableEmailOtpResponse {\n\t\tok: Boolean!\n\t\terror: DisableEmailOtpError\n\t}\n\n\ttype DisableEmailOtpError {\n\t\tcode: DisableEmailOtpErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisableEmailOtpErrorCode {\n\t\tEMAIL_OTP_NOT_ACTIVE\n\t\tMFA_REQUIRED\n\t}\n\n\ttype DisablePersonResponse {\n\t\tok: Boolean!\n\t\terror: DisablePersonError\n\t}\n\n\ttype DisablePersonError {\n\t\tcode: DisablePersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DisablePersonErrorCode {\n\t\tPERSON_ALREADY_DISABLED\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === enablePerson ===\n\n\ttype EnablePersonResponse {\n\t\tok: Boolean!\n\t\terror: EnablePersonError\n\t}\n\n\ttype EnablePersonError {\n\t\tcode: EnablePersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum EnablePersonErrorCode {\n\t\tPERSON_ALREADY_ENABLED\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === forceSignOutPerson ===\n\n\ttype ForceSignOutPersonResponse {\n\t\tok: Boolean!\n\t\terror: ForceSignOutPersonError\n\t}\n\n\ttype ForceSignOutPersonError {\n\t\tcode: ForceSignOutPersonErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ForceSignOutPersonErrorCode {\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === resetPersonMfa ===\n\n\ttype ResetPersonMfaResponse {\n\t\tok: Boolean!\n\t\terror: ResetPersonMfaError\n\t}\n\n\ttype ResetPersonMfaError {\n\t\tcode: ResetPersonMfaErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ResetPersonMfaErrorCode {\n\t\tPERSON_NOT_FOUND\n\t}\n\n\t# === auth policy (per-role MFA / session policy) ===\n\n\ttype AuthPolicy {\n\t\tid: String!\n\t\tscope: AuthPolicyScope!\n\t\t\"\"\"Project slug, present only for project-scoped policies.\"\"\"\n\t\tproject: String\n\t\troles: [String!]!\n\t\tmfaRequired: Boolean\n\t\ttokenExpiration: Interval\n\t\tidleTimeout: Interval\n\t\tmfaGraceDuration: Interval\n\t\trememberMeAllowed: Boolean\n\t}\n\n\tenum AuthPolicyScope {\n\t\tglobal\n\t\tproject\n\t}\n\n\tinput AuthPolicyInput {\n\t\tscope: AuthPolicyScope!\n\t\t\"\"\"Project slug. Required for scope=project, forbidden for scope=global.\"\"\"\n\t\tproject: String\n\t\troles: [String!]!\n\t\tmfaRequired: Boolean\n\t\ttokenExpiration: Interval\n\t\tidleTimeout: Interval\n\t\tmfaGraceDuration: Interval\n\t\trememberMeAllowed: Boolean\n\t}\n\n\ttype CreateAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: CreateAuthPolicyError\n\t\tresult: CreateAuthPolicyResult\n\t}\n\n\ttype CreateAuthPolicyResult {\n\t\tid: String!\n\t}\n\n\ttype CreateAuthPolicyError {\n\t\tcode: CreateAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum CreateAuthPolicyErrorCode {\n\t\tPROJECT_REQUIRED\n\t\tPROJECT_NOT_ALLOWED\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype UpdateAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: UpdateAuthPolicyError\n\t}\n\n\ttype UpdateAuthPolicyError {\n\t\tcode: UpdateAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateAuthPolicyErrorCode {\n\t\tNOT_FOUND\n\t\tPROJECT_REQUIRED\n\t\tPROJECT_NOT_ALLOWED\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype DeleteAuthPolicyResponse {\n\t\tok: Boolean!\n\t\terror: DeleteAuthPolicyError\n\t}\n\n\ttype DeleteAuthPolicyError {\n\t\tcode: DeleteAuthPolicyErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum DeleteAuthPolicyErrorCode {\n\t\tNOT_FOUND\n\t}\n\n\t# === sessions ===\n\n\ttype SessionInfo {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\texpiresAt: DateTime\n\t\tlastUsedAt: DateTime\n\t\tlastIp: String\n\t\tlastUserAgent: String\n\t\tcreatedIp: String\n\t\tcreatedUserAgent: String\n\t\tisCurrent: Boolean!\n\t\t\"\"\"\n\t\tWhether this session honors X-Contember-Client-IP /\n\t\tX-Contember-Client-User-Agent headers on subsequent requests. Set when\n\t\tthe session was minted via \\`SignInOptions.trustForwardedClientInfo\\`\n\t\tfrom an api_key that was itself created with the flag.\n\t\t\"\"\"\n\t\ttrustForwardedClientInfo: Boolean!\n\t}\n\n\ttype RevokeSessionResponse {\n\t\tok: Boolean!\n\t\terror: RevokeSessionError\n\t}\n\n\ttype RevokeSessionError {\n\t\tcode: RevokeSessionErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RevokeSessionErrorCode {\n\t\tSESSION_NOT_FOUND\n\t\tNOT_A_PERSON\n\t}\n\n\t# === mails ===\n\t\n\ttype MailTemplateData {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\tvariant: String\n\t\tsubject: String!\n\t\tcontent: String!\n\t\tuseLayout: Boolean!\n\t\treplyTo: String\n\t}\n\t\n\tinput MailTemplate {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\t\"Custom mail variant identifier, e.g. a locale.\"\n\t\tvariant: String\n\t\tsubject: String!\n\t\tcontent: String!\n\t\tuseLayout: Boolean\n\t\treplyTo: String\n\t}\n\n\tenum MailType {\n\t\tEXISTING_USER_INVITED\n\t\tNEW_USER_INVITED\n\t\tRESET_PASSWORD_REQUEST\n\t\tPASSWORDLESS_SIGN_IN\n\t\tFORCED_SIGN_OUT\n\t\tEMAIL_OTP\n\t\tBACKUP_CODES_EXHAUSTED\n\t\tEMAIL_VERIFICATION\n\t\tEMAIL_CHANGE_VERIFY\n\t\tEMAIL_CHANGE_NOTIFY\n\t\tUNUSUAL_LOGIN\n\t}\n\n\tinput MailTemplateIdentifier {\n\t\tprojectSlug: String\n\t\ttype: MailType!\n\t\tvariant: String\n\t}\n\n\ttype AddMailTemplateResponse {\n\t\tok: Boolean!\n\t\terrors: [AddMailTemplateError!]! @deprecated\n\t\terror: AddMailTemplateError\n\t}\n\n\ttype AddMailTemplateError {\n\t\tcode: AddMailTemplateErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum AddMailTemplateErrorCode {\n\t\tMISSING_VARIABLE\n\t\tPROJECT_NOT_FOUND\n\t\tINVALID_REPLY_EMAIL_FORMAT\n\t}\n\n\ttype RemoveMailTemplateResponse {\n\t\tok: Boolean!\n\t\terrors: [RemoveMailTemplateError!]!\n\t\terror: RemoveMailTemplateError\n\t}\n\n\ttype RemoveMailTemplateError {\n\t\tcode: RemoveMailTemplateErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum RemoveMailTemplateErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t\tTEMPLATE_NOT_FOUND\n\t}\n\n\t# === password reset ===\n\n\ttype CheckResetPasswordTokenResult {\n\t\tcode: CheckResetPasswordTokenCode!\n\t}\n\n\tenum CheckResetPasswordTokenCode {\n\t\tREQUEST_NOT_FOUND\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t}\n\n\ttype CreatePasswordResetRequestResponse {\n\t\tok: Boolean!\n\t\terrors: [CreatePasswordResetRequestError!]! @deprecated\n\t\terror: CreatePasswordResetRequestError\n\t}\n\n\ttype CreatePasswordResetRequestError {\n\t\tcode: CreatePasswordResetRequestErrorCode!\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum CreatePasswordResetRequestErrorCode {\n\t\tPERSON_NOT_FOUND\n\t\tINVALID_CAPTCHA\n\t\tRATE_LIMIT_EXCEEDED\n\t}\n\n\ttype ResetPasswordResponse {\n\t\tok: Boolean!\n\t\terrors: [ResetPasswordError!]! @deprecated\n\t\terror: ResetPasswordError\n\t}\n\ttype ResetPasswordError {\n\t\tcode: ResetPasswordErrorCode!\n weakPasswordReasons: [WeakPasswordReason!]\n\t\tdeveloperMessage: String!\n\t\tendUserMessage: String @deprecated\n\t}\n\n\tenum ResetPasswordErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\n\t\tPASSWORD_TOO_WEAK\n\t}\n\n\tinput CreateResetPasswordRequestOptions {\n\t\tmailProject: String\n\t\tmailVariant: String\n\t}\n\n\t# === email verification ===\n\n\tinput EmailVerificationOptions {\n\t\tmailProject: String\n\t\tmailVariant: String\n\t}\n\n\ttype RequestEmailVerificationResponse {\n\t\tok: Boolean!\n\t\terror: RequestEmailVerificationError\n\t}\n\n\ttype RequestEmailVerificationError {\n\t\tcode: RequestEmailVerificationErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum RequestEmailVerificationErrorCode {\n\t\tRATE_LIMIT_EXCEEDED\n\t\tINVALID_CAPTCHA\n\t}\n\n\ttype VerifyEmailResponse {\n\t\tok: Boolean!\n\t\terror: VerifyEmailError\n\t}\n\n\ttype VerifyEmailError {\n\t\tcode: VerifyEmailErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum VerifyEmailErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t}\n\n\ttype ConfirmEmailChangeResponse {\n\t\tok: Boolean!\n\t\terror: ConfirmEmailChangeError\n\t}\n\n\ttype ConfirmEmailChangeError {\n\t\tcode: ConfirmEmailChangeErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum ConfirmEmailChangeErrorCode {\n\t\tTOKEN_NOT_FOUND\n\t\tTOKEN_INVALID\n\t\tTOKEN_USED\n\t\tTOKEN_EXPIRED\n\t\tEMAIL_ALREADY_EXISTS\n\t\tINVALID_EMAIL_FORMAT\n\t}\n\n\t# === project ===\n\n\tinput ProjectSecret {\n\t\tkey: String!\n\t\tvalue: String!\n\t}\n\n\tinput CreateProjectOptions {\n\t\tdeployTokenHash: String\n\t\tnoDeployToken: Boolean\n\t}\n\n\ttype CreateProjectResponse {\n\t\tok: Boolean!\n\t\terror: CreateProjectResponseError\n\t\tresult: CreateProjectResult\n\t}\n\n\ttype CreateProjectResponseError {\n\t\tcode: CreateProjectResponseErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\ttype CreateProjectResult {\n\t\tdeployerApiKey: ApiKeyWithToken\n\t}\n\n\tenum CreateProjectResponseErrorCode {\n\t\tALREADY_EXISTS\n\t\tINIT_ERROR\n\t}\n\n\ttype SetProjectSecretResponse {\n\t\tok: Boolean!\n\t\terror: SetProjectSecretError\n\t}\n\n\ttype SetProjectSecretError {\n\t\tcode: SetProjectSecretErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum SetProjectSecretErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\ttype UpdateProjectResponse {\n\t\tok: Boolean!\n\t\terror: UpdateProjectError\n\t}\n\n\ttype UpdateProjectError {\n\t\tcode: UpdateProjectErrorCode!\n\t\tdeveloperMessage: String!\n\t}\n\n\tenum UpdateProjectErrorCode {\n\t\tPROJECT_NOT_FOUND\n\t}\n\n\t# === auth log ===\n\n\t\"\"\"\n\tA single \\`person_auth_log\\` row. Mirrors the columns described in\n\tdocs/.../audit-log.md.\n\t\"\"\"\n\ttype AuthLogEntry {\n\t\tid: String!\n\t\tcreatedAt: DateTime!\n\t\t\"\"\"\n\t\tOne of the values listed in \\`auth_log_type\\` (see audit-log docs).\n\t\tKept as String rather than a GraphQL enum because a few legacy values\n\t\t(\\`2fa_enable\\`, \\`2fa_disable\\`) start with a digit and aren't valid\n\t\tenum names, and the set is expected to keep growing.\n\t\t\"\"\"\n\t\ttype: String!\n\t\tsuccess: Boolean!\n\t\t\"\"\"\n\t\tIdentity that performed the action. May be null for entries created\n\t\tbefore this column was populated, or when the actor's identity was\n\t\tlater deleted (FK is ON DELETE SET NULL semantics-wise).\n\t\t\"\"\"\n\t\tinvokedByIdentityId: String\n\t\t\"\"\"\n\t\tThe actor's person (if the actor was a person, not a bare api_key).\n\t\t\"\"\"\n\t\tpersonId: String\n\t\t\"\"\"\n\t\tThe subject of the action when different from the actor (e.g. force\n\t\tsign-out, role grant, membership change). Resolved from the affected\n\t\tidentity so the trail points at the right person even when the actor\n\t\tacts on someone else's identity.\n\t\t\"\"\"\n\t\ttargetPersonId: String\n\t\t\"\"\"\n\t\tFree-form input string — typically the email submitted on a failed\n\t\tlogin, before any person record was looked up.\n\t\t\"\"\"\n\t\tpersonInputIdentifier: String\n\t\terrorCode: String\n\t\terrorMessage: String\n\t\t\"\"\"\n\t\tEffective client IP after \\`trust-forwarded-info\\` is applied. The\n\t\traw socket peer is preserved in \\`metadata.forwarderIp\\` when a\n\t\ttrusted proxy was involved.\n\t\t\"\"\"\n\t\tipAddress: String\n\t\tuserAgent: String\n\t\tidentityProviderId: String\n\t\t\"\"\"\n\t\tJSONB — forensic context. Common keys: \\`forwarderIp\\`,\n\t\t\\`forwarderUserAgent\\`, \\`sessionId\\`, \\`reason\\`.\n\t\t\"\"\"\n\t\tmetadata: Json\n\t\t\"\"\"\n\t\tJSONB — domain payload. For change events this is typically\n\t\t\\`{before, after}\\`; for creation events it's the snapshot.\n\t\tSecret-bearing inputs are redacted before being stored.\n\t\t\"\"\"\n\t\teventData: Json\n\t}\n\n\t\"\"\"\n\tAll fields are AND-combined. Omitted fields are unconstrained.\n\t\"\"\"\n\tinput AuthLogFilter {\n\t\t\"OR-combined: any of the listed \\`auth_log_type\\` values matches.\"\n\t\ttypes: [String!]\n\t\tsuccess: Boolean\n\t\tinvokedByIdentityId: String\n\t\tpersonId: String\n\t\ttargetPersonId: String\n\t\tpersonInputIdentifier: String\n\t\t\"Inclusive lower bound (\\`created_at >= createdAfter\\`).\"\n\t\tcreatedAfter: DateTime\n\t\t\"Exclusive upper bound (\\`created_at < createdBefore\\`).\"\n\t\tcreatedBefore: DateTime\n\t}\n\n\ttype AuthLogPage {\n\t\tentries: [AuthLogEntry!]!\n\t\t\"True when more rows exist past \\`offset + limit\\`.\"\n\t\thasMore: Boolean!\n\t}\n`\n\nexport default schema\n"],"names":[],"mappings":";AAGA,MAAM,SAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
|
|
@@ -84,6 +84,7 @@ const IdentityProvidersQuery = require("./src/model/queries/idp/IdentityProvider
|
|
|
84
84
|
const IdpSessionByApiKeyQuery = require("./src/model/queries/idp/IdpSessionByApiKeyQuery.cjs");
|
|
85
85
|
const IdpSessionsBySidQuery = require("./src/model/queries/idp/IdpSessionsBySidQuery.cjs");
|
|
86
86
|
const IdpSessionsBySubQuery = require("./src/model/queries/idp/IdpSessionsBySubQuery.cjs");
|
|
87
|
+
const LocalAuthDisablingIdpsQuery = require("./src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs");
|
|
87
88
|
const PersonIdentityProvidersQuery = require("./src/model/queries/idp/PersonIdentityProvidersQuery.cjs");
|
|
88
89
|
const ProjectSecretsQuery = require("./src/model/queries/project/ProjectSecretsQuery.cjs");
|
|
89
90
|
const ProjectSecretKeysQuery = require("./src/model/queries/project/ProjectSecretKeysQuery.cjs");
|
|
@@ -286,6 +287,7 @@ exports.IdentityProvidersQuery = IdentityProvidersQuery.IdentityProvidersQuery;
|
|
|
286
287
|
exports.IdpSessionByApiKeyQuery = IdpSessionByApiKeyQuery.IdpSessionByApiKeyQuery;
|
|
287
288
|
exports.IdpSessionsBySidQuery = IdpSessionsBySidQuery.IdpSessionsBySidQuery;
|
|
288
289
|
exports.IdpSessionsBySubQuery = IdpSessionsBySubQuery.IdpSessionsBySubQuery;
|
|
290
|
+
exports.LocalAuthDisablingIdpsQuery = LocalAuthDisablingIdpsQuery.LocalAuthDisablingIdpsQuery;
|
|
289
291
|
exports.PersonIdentityProvidersQuery = PersonIdentityProvidersQuery.PersonIdentityProvidersQuery;
|
|
290
292
|
exports.ProjectSecretsQuery = ProjectSecretsQuery.ProjectSecretsQuery;
|
|
291
293
|
exports.ProjectSecretKeysQuery = ProjectSecretKeysQuery.ProjectSecretKeysQuery;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/production/index.js
CHANGED
|
@@ -82,6 +82,7 @@ import { IdentityProvidersQuery } from "./src/model/queries/idp/IdentityProvider
|
|
|
82
82
|
import { IdpSessionByApiKeyQuery } from "./src/model/queries/idp/IdpSessionByApiKeyQuery.js";
|
|
83
83
|
import { IdpSessionsBySidQuery } from "./src/model/queries/idp/IdpSessionsBySidQuery.js";
|
|
84
84
|
import { IdpSessionsBySubQuery } from "./src/model/queries/idp/IdpSessionsBySubQuery.js";
|
|
85
|
+
import { LocalAuthDisablingIdpsQuery } from "./src/model/queries/idp/LocalAuthDisablingIdpsQuery.js";
|
|
85
86
|
import { PersonIdentityProvidersQuery } from "./src/model/queries/idp/PersonIdentityProvidersQuery.js";
|
|
86
87
|
import { ProjectSecretsQuery } from "./src/model/queries/project/ProjectSecretsQuery.js";
|
|
87
88
|
import { ProjectSecretKeysQuery } from "./src/model/queries/project/ProjectSecretKeysQuery.js";
|
|
@@ -293,6 +294,7 @@ export {
|
|
|
293
294
|
InviteManager,
|
|
294
295
|
InviteMutationResolver,
|
|
295
296
|
InviteResult,
|
|
297
|
+
LocalAuthDisablingIdpsQuery,
|
|
296
298
|
LoginRiskAnalyzer,
|
|
297
299
|
MAX_OTP_ATTEMPTS,
|
|
298
300
|
MailTemplateListQuery,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const sql = `
|
|
3
|
+
-- When TRUE, a person linked to this identity provider may authenticate ONLY through
|
|
4
|
+
-- it: password sign-in, passwordless sign-in and password-reset mails are refused for
|
|
5
|
+
-- them. The link itself is the marker, so it also covers a person who predates the
|
|
6
|
+
-- provider and got linked by e-mail matching.
|
|
7
|
+
--
|
|
8
|
+
-- Scoped to providers that are currently enabled: disabling the provider restores
|
|
9
|
+
-- local authentication for everyone linked to it, which is the break-glass for an IdP
|
|
10
|
+
-- outage. Defaults to FALSE to preserve existing behavior.
|
|
11
|
+
ALTER TABLE "identity_provider"
|
|
12
|
+
ADD COLUMN "disable_local_authentication" BOOLEAN NOT NULL DEFAULT FALSE;
|
|
13
|
+
`;
|
|
14
|
+
async function _20260904120000idpdisablelocalauthentication(builder) {
|
|
15
|
+
builder.sql(sql);
|
|
16
|
+
}
|
|
17
|
+
module.exports = _20260904120000idpdisablelocalauthentication;
|
|
18
|
+
//# sourceMappingURL=2026-09-04-120000-idp-disable-local-authentication.cjs.map
|
package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"2026-09-04-120000-idp-disable-local-authentication.cjs","sources":["../../../../../packages/engine-tenant-api/src/migrations/2026-09-04-120000-idp-disable-local-authentication.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\n\nconst sql = `\n-- When TRUE, a person linked to this identity provider may authenticate ONLY through\n-- it: password sign-in, passwordless sign-in and password-reset mails are refused for\n-- them. The link itself is the marker, so it also covers a person who predates the\n-- provider and got linked by e-mail matching.\n--\n-- Scoped to providers that are currently enabled: disabling the provider restores\n-- local authentication for everyone linked to it, which is the break-glass for an IdP\n-- outage. Defaults to FALSE to preserve existing behavior.\nALTER TABLE \"identity_provider\"\n\tADD COLUMN \"disable_local_authentication\" BOOLEAN NOT NULL DEFAULT FALSE;\n`\n\nexport default async function(builder: MigrationBuilder) {\n\tbuilder.sql(sql)\n}\n"],"names":[],"mappings":";AAEA,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaZ,eAAA,6CAA8B,SAA2B;AACxD,UAAQ,IAAI,GAAG;AAChB;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const sql = `
|
|
2
|
+
-- When TRUE, a person linked to this identity provider may authenticate ONLY through
|
|
3
|
+
-- it: password sign-in, passwordless sign-in and password-reset mails are refused for
|
|
4
|
+
-- them. The link itself is the marker, so it also covers a person who predates the
|
|
5
|
+
-- provider and got linked by e-mail matching.
|
|
6
|
+
--
|
|
7
|
+
-- Scoped to providers that are currently enabled: disabling the provider restores
|
|
8
|
+
-- local authentication for everyone linked to it, which is the break-glass for an IdP
|
|
9
|
+
-- outage. Defaults to FALSE to preserve existing behavior.
|
|
10
|
+
ALTER TABLE "identity_provider"
|
|
11
|
+
ADD COLUMN "disable_local_authentication" BOOLEAN NOT NULL DEFAULT FALSE;
|
|
12
|
+
`;
|
|
13
|
+
async function _20260904120000idpdisablelocalauthentication(builder) {
|
|
14
|
+
builder.sql(sql);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
_20260904120000idpdisablelocalauthentication as default
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=2026-09-04-120000-idp-disable-local-authentication.js.map
|
package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"2026-09-04-120000-idp-disable-local-authentication.js","sources":["../../../../../packages/engine-tenant-api/src/migrations/2026-09-04-120000-idp-disable-local-authentication.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\n\nconst sql = `\n-- When TRUE, a person linked to this identity provider may authenticate ONLY through\n-- it: password sign-in, passwordless sign-in and password-reset mails are refused for\n-- them. The link itself is the marker, so it also covers a person who predates the\n-- provider and got linked by e-mail matching.\n--\n-- Scoped to providers that are currently enabled: disabling the provider restores\n-- local authentication for everyone linked to it, which is the break-glass for an IdP\n-- outage. Defaults to FALSE to preserve existing behavior.\nALTER TABLE \"identity_provider\"\n\tADD COLUMN \"disable_local_authentication\" BOOLEAN NOT NULL DEFAULT FALSE;\n`\n\nexport default async function(builder: MigrationBuilder) {\n\tbuilder.sql(sql)\n}\n"],"names":[],"mappings":"AAEA,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaZ,eAAA,6CAA8B,SAA2B;AACxD,UAAQ,IAAI,GAAG;AAChB;"}
|
|
@@ -66,6 +66,7 @@ const _20260616130000IdpLogout = require("./2026-06-16-130000-idp-logout.cjs");
|
|
|
66
66
|
const _20260618120000IdpClaimMapping = require("./2026-06-18-120000-idp-claim-mapping.cjs");
|
|
67
67
|
const _20260803120000PersonEnableAuthLog = require("./2026-08-03-120000-person-enable-auth-log.cjs");
|
|
68
68
|
const _20260804120000ConfigPanel = require("./2026-08-04-120000-config-panel.cjs");
|
|
69
|
+
const _20260904120000IdpDisableLocalAuthentication = require("./2026-09-04-120000-idp-disable-local-authentication.cjs");
|
|
69
70
|
const snapshot = require("./snapshot.cjs");
|
|
70
71
|
require("../model/authorization/PermissionActions.cjs");
|
|
71
72
|
require("@contember/authorization");
|
|
@@ -151,7 +152,8 @@ const migrations = {
|
|
|
151
152
|
"2026-06-16-130000-idp-logout": _20260616130000IdpLogout,
|
|
152
153
|
"2026-06-18-120000-idp-claim-mapping": _20260618120000IdpClaimMapping,
|
|
153
154
|
"2026-08-03-120000-person-enable-auth-log": _20260803120000PersonEnableAuthLog,
|
|
154
|
-
"2026-08-04-120000-config-panel": _20260804120000ConfigPanel
|
|
155
|
+
"2026-08-04-120000-config-panel": _20260804120000ConfigPanel,
|
|
156
|
+
"2026-09-04-120000-idp-disable-local-authentication": _20260904120000IdpDisableLocalAuthentication
|
|
155
157
|
};
|
|
156
158
|
class TenantMigrationsRunner {
|
|
157
159
|
constructor(db, schema, tenantCredentials, providers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.cjs","sources":["../../../../../packages/engine-tenant-api/src/migrations/runner.ts"],"sourcesContent":["import { Connection, createDatabaseIfNotExists, DatabaseConfig, EventManager } from '@contember/database'\nimport { TenantMigrationArgs } from './types.js'\nimport { MigrationsRunner as DbMigrationsRunner, SnapshotMigrationResolver } from '@contember/database-migrations'\nimport _20180802174310init from './2018-08-02-174310-init.js'\nimport _20180903140621identityproject from './2018-09-03-140621-identity-project.js'\nimport _20181026165450setupapikey from './2018-10-26-165450-setup-api-key.js'\nimport _20181026175155variables from './2018-10-26-175155-variables.js'\nimport _20190218110949projectslug from './2019-02-18-110949-project-slug.js'\nimport _20190218160155sessionexpiration from './2019-02-18-160155-session-expiration.js'\nimport _20190503163729apikeydisabledat from './2019-05-03-163729-api-key-disabled-at.js'\nimport _20190814153300projectslugunique from './2019-08-14-153300-project-slug-unique.js'\nimport _20190906111000membership from './2019-09-06-111000-membership.js'\nimport _20190906111001dropoldmember from './2019-09-06-111001-drop-old-member.js'\nimport _20200129idenitynote from './2020-01-29-idenity-note.js'\nimport _20200417fixpersonindex from './2020-04-17-fix-person-index.js'\nimport _20200501170000apikeyindex from './2020-05-01-170000-api-key-index.js'\nimport _20200608134000tenantcredentials from './2020-06-08-134000-tenant-credentials.js'\nimport _20200807110000personotp from './2020-08-07-110000-person-otp.js'\nimport _20200817162200mailtemplates from './2020-08-17-162200-mail-templates.js'\nimport _20200821143400personpasswordreset from './2020-08-21-143400-person-password-reset.js'\nimport _20200907094200identityprovider from './2020-09-07-094200-identity-provider.js'\nimport _20210328134000timestamp from './2021-03-28-134000-timestamp.js'\nimport _20210726105000projectconfig from './2021-07-26-105000-project-config.js'\nimport _20210726132000projectsecrets from './2021-07-26-132000-project-secrets.js'\nimport _20210727174000projectaliasindex from './2021-07-27-174000-project-alias-index.js'\nimport _20211124130000personpasswordnull from './2021-11-24-130000-person-password-null.js'\nimport _20211124161500mailtemplateprojectnull from './2021-11-24-161500-mail-template-project-null.js'\nimport _20220104144000personuniqueidentity from './2022-01-04-144000-person-unique-identity.js'\nimport _20220209111800fixcrypted from './2022-02-09-111800-fix-crypted.js'\nimport _20220211153000idpautosignup from './2022-02-11-153000-idp-auto-sign-up.js'\nimport _20220629105000personidp from './2022-06-29-105000-person-idp.js'\nimport _20220707135000personemailoptuniq from './2022-07-07-135000-person-email-opt-uniq.js'\nimport _20220707141000persondisplayname from './2022-07-07-141000-person-display-name.js'\nimport _20220714145000personloginoptions from './2022-07-14-145000-person-login-options.js'\nimport _20221108projectupdatenotification from './2022-11-08-project-update-notification.js'\nimport _20230120135500personemailnormalize from './2023-01-20-135500-person-email-normalize.js'\nimport _20230603104000persondisabled from './2023-06-03-104000-person-disabled.js'\nimport _20230901165000idpreturnconfig from './2023-09-01-165000-idp-return-config.js'\nimport _20240620140000mailreply from './2024-06-20-140000-mail-reply.js'\nimport _20240826120000passwordless from './2024-08-26-120000-passwordless.js'\nimport _20250416180000configup from './2025-04-16-180000-config-up.js'\nimport _20250417160000authlog from './2025-04-17-160000-auth-log.js'\nimport _20260512120000apikeysessiontracking from './2026-05-12-120000-api-key-session-tracking.js'\nimport _20260512130000apikeytrustforwardedinfo from './2026-05-12-130000-api-key-trust-forwarded-info.js'\nimport _20260513120000authlogeventdata from './2026-05-13-120000-auth-log-event-data.js'\nimport _20260513130000antiabuse from './2026-05-13-130000-anti-abuse.js'\nimport _20260514100000authlogadminactions from './2026-05-14-100000-auth-log-admin-actions.js'\nimport _20260515120000configreveallogmethod from './2026-05-15-120000-config-reveal-login-method.js'\nimport _20260521100000personmfa from './2026-05-21-100000-person-mfa.js'\nimport _20260521110000mfafoundation from './2026-05-21-110000-mfa-foundation.js'\nimport _20260521120000emailotp from './2026-05-21-120000-email-otp.js'\nimport _20260521130000apikeysessionpolicy from './2026-05-21-130000-api-key-session-policy.js'\nimport _20260521140000mfagraceduration from './2026-05-21-140000-mfa-grace-duration.js'\nimport _20260521150000emailotpratelimit from './2026-05-21-150000-email-otp-rate-limit.js'\nimport _20260526120000emailverificationtypes from './2026-05-26-120000-email-verification-types.js'\nimport _20260526120010emailverification from './2026-05-26-120010-email-verification.js'\nimport _20260526130000emailchangeverificationconfig from './2026-05-26-130000-email-change-verification-config.js'\nimport _20260526130010idprequireverifiedemail from './2026-05-26-130010-idp-require-verified-email.js'\nimport _20260526130020emailverificationratelimit from './2026-05-26-130020-email-verification-rate-limit.js'\nimport _20260526130030captchaprotectflows from './2026-05-26-130030-captcha-protect-flows.js'\nimport _20260526140000idpsession from './2026-05-26-140000-idp-session.js'\nimport _20260608100000idpassumeemailverified from './2026-06-08-100000-idp-assume-email-verified.js'\nimport _20260616120000loginanomalydetection from './2026-06-16-120000-login-anomaly-detection.js'\nimport _20260616130000idplogout from './2026-06-16-130000-idp-logout.js'\nimport _20260618120000idpclaimmapping from './2026-06-18-120000-idp-claim-mapping.js'\nimport _20260803120000personenableauthlog from './2026-08-03-120000-person-enable-auth-log.js'\nimport _20260804120000configpanel from './2026-08-04-120000-config-panel.js'\nimport snapshot from './snapshot.js'\nimport { computeTokenHash, Providers } from '../model/index.js'\nimport { Logger } from '@contember/logger'\n\nexport interface TenantCredentials {\n\tloginToken?: string\n\trootEmail?: string\n\trootToken?: string\n\trootTokenHash?: string\n\trootPassword?: string\n\t/**\n\t * Unpersisted root tokens (plain values). When set, these tokens are\n\t * verified at runtime and resolve to a super-admin identity without being\n\t * stored in the database. Useful for easy rotation.\n\t */\n\trootTokens?: readonly string[]\n\t/**\n\t * Unpersisted root token hashes (sha256 hex). Same as {@link rootTokens} but\n\t * the plain token never needs to be passed to the engine.\n\t */\n\trootTokenHashes?: readonly string[]\n}\n\nconst migrations = {\n\t'2018-08-02-174310-init': _20180802174310init,\n\t'2018-09-03-140621-identity-project': _20180903140621identityproject,\n\t'2018-10-26-165450-setup-api-key': _20181026165450setupapikey,\n\t'2018-10-26-175155-variables': _20181026175155variables,\n\t'2019-02-18-110949-project-slug': _20190218110949projectslug,\n\t'2019-02-18-160155-session-expiration': _20190218160155sessionexpiration,\n\t'2019-05-03-163729-api-key-disabled-at': _20190503163729apikeydisabledat,\n\t'2019-08-14-153300-project-slug-unique': _20190814153300projectslugunique,\n\t'2019-09-06-111000-membership': _20190906111000membership,\n\t'2019-09-06-111001-drop-old-member': _20190906111001dropoldmember,\n\t'2020-01-29-idenity-note': _20200129idenitynote,\n\t'2020-04-17-fix-person-index': _20200417fixpersonindex,\n\t'2020-05-01-170000-api-key-index': _20200501170000apikeyindex,\n\t'2020-06-08-134000-tenant-credentials': _20200608134000tenantcredentials,\n\t'2020-08-07-110000-person-otp': _20200807110000personotp,\n\t'2020-08-17-162200-mail-templates': _20200817162200mailtemplates,\n\t'2020-08-21-143400-person-password-reset': _20200821143400personpasswordreset,\n\t'2020-09-07-094200-identity-provider': _20200907094200identityprovider,\n\t'2021-03-28-134000-timestamp': _20210328134000timestamp,\n\t'2021-07-26-105000-project-config': _20210726105000projectconfig,\n\t'2021-07-26-132000-project-secrets': _20210726132000projectsecrets,\n\t'2021-07-27-174000-project-alias-index': _20210727174000projectaliasindex,\n\t'2021-11-24-130000-person-password-null': _20211124130000personpasswordnull,\n\t'2021-11-24-161500-mail-template-project-null': _20211124161500mailtemplateprojectnull,\n\t'2022-01-04-144000-person-unique-identity': _20220104144000personuniqueidentity,\n\t'2022-02-09-111800-fix-crypted': _20220209111800fixcrypted,\n\t'2022-02-11-153000-idp-auto-sign-up': _20220211153000idpautosignup,\n\t'2022-06-29-105000-person-idp': _20220629105000personidp,\n\t'2022-07-07-135000-person-email-opt-uniq': _20220707135000personemailoptuniq,\n\t'2022-07-07-141000-person-display-name': _20220707141000persondisplayname,\n\t'2022-07-14-145000-person-login-options': _20220714145000personloginoptions,\n\t'2022-11-08-project-update-notification': _20221108projectupdatenotification,\n\t'2023-01-20-135500-person-email-normalize': _20230120135500personemailnormalize,\n\t'2023-06-03-104000-person-disabled': _20230603104000persondisabled,\n\t'2023-09-01-165000-idp-return-config': _20230901165000idpreturnconfig,\n\t'2024-06-20-140000-mail-reply': _20240620140000mailreply,\n\t'2024-08-26-120000-passwordless': _20240826120000passwordless,\n\t'2025-04-16-180000-config-up': _20250416180000configup,\n\t'2025-04-17-160000-auth-log': _20250417160000authlog,\n\t'2026-05-12-120000-api-key-session-tracking': _20260512120000apikeysessiontracking,\n\t'2026-05-12-130000-api-key-trust-forwarded-info': _20260512130000apikeytrustforwardedinfo,\n\t'2026-05-13-120000-auth-log-event-data': _20260513120000authlogeventdata,\n\t'2026-05-13-130000-anti-abuse': _20260513130000antiabuse,\n\t'2026-05-14-100000-auth-log-admin-actions': _20260514100000authlogadminactions,\n\t'2026-05-15-120000-config-reveal-login-method': _20260515120000configreveallogmethod,\n\t'2026-05-21-100000-person-mfa': _20260521100000personmfa,\n\t'2026-05-21-110000-mfa-foundation': _20260521110000mfafoundation,\n\t'2026-05-21-120000-email-otp': _20260521120000emailotp,\n\t'2026-05-21-130000-api-key-session-policy': _20260521130000apikeysessionpolicy,\n\t'2026-05-21-140000-mfa-grace-duration': _20260521140000mfagraceduration,\n\t'2026-05-21-150000-email-otp-rate-limit': _20260521150000emailotpratelimit,\n\t'2026-05-26-120000-email-verification-types': _20260526120000emailverificationtypes,\n\t'2026-05-26-120010-email-verification': _20260526120010emailverification,\n\t'2026-05-26-130000-email-change-verification-config': _20260526130000emailchangeverificationconfig,\n\t'2026-05-26-130010-idp-require-verified-email': _20260526130010idprequireverifiedemail,\n\t'2026-05-26-130020-email-verification-rate-limit': _20260526130020emailverificationratelimit,\n\t'2026-05-26-130030-captcha-protect-flows': _20260526130030captchaprotectflows,\n\t'2026-05-26-140000-idp-session': _20260526140000idpsession,\n\t'2026-06-08-100000-idp-assume-email-verified': _20260608100000idpassumeemailverified,\n\t'2026-06-16-120000-login-anomaly-detection': _20260616120000loginanomalydetection,\n\t'2026-06-16-130000-idp-logout': _20260616130000idplogout,\n\t'2026-06-18-120000-idp-claim-mapping': _20260618120000idpclaimmapping,\n\t'2026-08-03-120000-person-enable-auth-log': _20260803120000personenableauthlog,\n\t'2026-08-04-120000-config-panel': _20260804120000configpanel,\n}\n\nexport class TenantMigrationsRunner {\n\tconstructor(\n\t\tprivate readonly db: DatabaseConfig,\n\t\tprivate readonly schema: string,\n\t\tprivate readonly tenantCredentials: TenantCredentials,\n\t\tprivate readonly providers: Pick<Providers, 'bcrypt' | 'uuid'>,\n\t) {\n\t}\n\n\tpublic async run(logger: Logger): Promise<{ name: string }[]> {\n\t\tawait createDatabaseIfNotExists(this.db, message => typeof message === 'string' ? logger.warn(message) : logger.error(message))\n\t\tconst connection = Connection.createSingle(this.db, err => logger.error(err))\n\t\tconst result = await connection.scope(async connection => {\n\t\t\tconst migrationsResolver = new SnapshotMigrationResolver(snapshot, migrations)\n\n\t\t\tconst innerRunner = new DbMigrationsRunner<TenantMigrationArgs>(connection, this.schema, migrationsResolver)\n\t\t\treturn await innerRunner.migrate(message => logger.warn(message), {\n\t\t\t\tgetCredentials: async () => ({\n\t\t\t\t\tloginTokenHash: this.tenantCredentials.loginToken ? computeTokenHash(this.tenantCredentials.loginToken) : undefined,\n\t\t\t\t\trootTokenHash: this.tenantCredentials.rootTokenHash\n\t\t\t\t\t\t?? (this.tenantCredentials.rootToken ? computeTokenHash(this.tenantCredentials.rootToken) : undefined),\n\t\t\t\t\trootEmail: this.tenantCredentials.rootEmail,\n\t\t\t\t\trootPasswordBcrypted: this.tenantCredentials.rootPassword ? await this.providers.bcrypt(this.tenantCredentials.rootPassword) : undefined,\n\t\t\t\t}),\n\t\t\t\tproviders: this.providers,\n\t\t\t})\n\t\t})\n\t\tawait connection.end()\n\t\treturn result\n\t}\n}\n"],"names":["_20180802174310init","_20180903140621identityproject","_20181026165450setupapikey","_20181026175155variables","_20190218110949projectslug","_20190218160155sessionexpiration","_20190503163729apikeydisabledat","_20190814153300projectslugunique","_20190906111000membership","_20190906111001dropoldmember","_20200129idenitynote","_20200417fixpersonindex","_20200501170000apikeyindex","_20200608134000tenantcredentials","_20200807110000personotp","_20200817162200mailtemplates","_20200821143400personpasswordreset","_20200907094200identityprovider","_20210328134000timestamp","_20210726105000projectconfig","_20210726132000projectsecrets","_20210727174000projectaliasindex","_20211124130000personpasswordnull","_20211124161500mailtemplateprojectnull","_20220104144000personuniqueidentity","_20220209111800fixcrypted","_20220211153000idpautosignup","_20220629105000personidp","_20220707135000personemailoptuniq","_20220707141000persondisplayname","_20220714145000personloginoptions","_20221108projectupdatenotification","_20230120135500personemailnormalize","_20230603104000persondisabled","_20230901165000idpreturnconfig","_20240620140000mailreply","_20240826120000passwordless","_20250416180000configup","_20250417160000authlog","_20260512120000apikeysessiontracking","_20260512130000apikeytrustforwardedinfo","_20260513120000authlogeventdata","_20260513130000antiabuse","_20260514100000authlogadminactions","_20260515120000configreveallogmethod","_20260521100000personmfa","_20260521110000mfafoundation","_20260521120000emailotp","_20260521130000apikeysessionpolicy","_20260521140000mfagraceduration","_20260521150000emailotpratelimit","_20260526120000emailverificationtypes","_20260526120010emailverification","_20260526130000emailchangeverificationconfig","_20260526130010idprequireverifiedemail","_20260526130020emailverificationratelimit","_20260526130030captchaprotectflows","_20260526140000idpsession","_20260608100000idpassumeemailverified","_20260616120000loginanomalydetection","_20260616130000idplogout","_20260618120000idpclaimmapping","_20260803120000personenableauthlog","_20260804120000configpanel","createDatabaseIfNotExists","Connection","connection","SnapshotMigrationResolver","DbMigrationsRunner","computeTokenHash"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,MAAM,aAAa;AAAA,EAClB,0BAA0BA;AAAAA,EAC1B,sCAAsCC;AAAAA,EACtC,mCAAmCC;AAAAA,EACnC,+BAA+BC;AAAAA,EAC/B,kCAAkCC;AAAAA,EAClC,wCAAwCC;AAAAA,EACxC,yCAAyCC;AAAAA,EACzC,yCAAyCC;AAAAA,EACzC,gCAAgCC;AAAAA,EAChC,qCAAqCC;AAAAA,EACrC,2BAA2BC;AAAAA,EAC3B,+BAA+BC;AAAAA,EAC/B,mCAAmCC;AAAAA,EACnC,wCAAwCC;AAAAA,EACxC,gCAAgCC;AAAAA,EAChC,oCAAoCC;AAAAA,EACpC,2CAA2CC;AAAAA,EAC3C,uCAAuCC;AAAAA,EACvC,+BAA+BC;AAAAA,EAC/B,oCAAoCC;AAAAA,EACpC,qCAAqCC;AAAAA,EACrC,yCAAyCC;AAAAA,EACzC,0CAA0CC;AAAAA,EAC1C,gDAAgDC;AAAAA,EAChD,4CAA4CC;AAAAA,EAC5C,iCAAiCC;AAAAA,EACjC,sCAAsCC;AAAAA,EACtC,gCAAgCC;AAAAA,EAChC,2CAA2CC;AAAAA,EAC3C,yCAAyCC;AAAAA,EACzC,0CAA0CC;AAAAA,EAC1C,0CAA0CC;AAAAA,EAC1C,4CAA4CC;AAAAA,EAC5C,qCAAqCC;AAAAA,EACrC,uCAAuCC;AAAAA,EACvC,gCAAgCC;AAAAA,EAChC,kCAAkCC;AAAAA,EAClC,+BAA+BC;AAAAA,EAC/B,8BAA8BC;AAAAA,EAC9B,8CAA8CC;AAAAA,EAC9C,kDAAkDC;AAAAA,EAClD,yCAAyCC;AAAAA,EACzC,gCAAgCC;AAAAA,EAChC,4CAA4CC;AAAAA,EAC5C,gDAAgDC;AAAAA,EAChD,gCAAgCC;AAAAA,EAChC,oCAAoCC;AAAAA,EACpC,+BAA+BC;AAAAA,EAC/B,4CAA4CC;AAAAA,EAC5C,wCAAwCC;AAAAA,EACxC,0CAA0CC;AAAAA,EAC1C,8CAA8CC;AAAAA,EAC9C,wCAAwCC;AAAAA,EACxC,sDAAsDC;AAAAA,EACtD,gDAAgDC;AAAAA,EAChD,mDAAmDC;AAAAA,EACnD,2CAA2CC;AAAAA,EAC3C,iCAAiCC;AAAAA,EACjC,+CAA+CC;AAAAA,EAC/C,6CAA6CC;AAAAA,EAC7C,gCAAgCC;AAAAA,EAChC,uCAAuCC;AAAAA,EACvC,4CAA4CC;AAAAA,EAC5C,kCAAkCC;AACnC;AAEO,MAAM,uBAAuB;AAAA,EACnC,YACkB,IACA,QACA,mBACA,WAChB;AAJgB,SAAA,KAAA;AACA,SAAA,SAAA;AACA,SAAA,oBAAA;AACA,SAAA,YAAA;AAAA,EAElB;AAAA,EAEA,MAAa,IAAI,QAA6C;AAC7D,UAAMC,SAAAA,0BAA0B,KAAK,IAAI,CAAA,YAAW,OAAO,YAAY,WAAW,OAAO,KAAK,OAAO,IAAI,OAAO,MAAM,OAAO,CAAC;AAC9H,UAAM,aAAaC,SAAAA,WAAW,aAAa,KAAK,IAAI,CAAA,QAAO,OAAO,MAAM,GAAG,CAAC;AAC5E,UAAM,SAAS,MAAM,WAAW,MAAM,OAAMC,gBAAc;AACzD,YAAM,qBAAqB,IAAIC,6CAA0B,UAAU,UAAU;AAE7E,YAAM,cAAc,IAAIC,mBAAAA,iBAAwCF,aAAY,KAAK,QAAQ,kBAAkB;AAC3G,aAAO,MAAM,YAAY,QAAQ,aAAW,OAAO,KAAK,OAAO,GAAG;AAAA,QACjE,gBAAgB,aAAa;AAAA,UAC5B,gBAAgB,KAAK,kBAAkB,aAAaG,MAAAA,iBAAiB,KAAK,kBAAkB,UAAU,IAAI;AAAA,UAC1G,eAAe,KAAK,kBAAkB,kBACjC,KAAK,kBAAkB,YAAYA,MAAAA,iBAAiB,KAAK,kBAAkB,SAAS,IAAI;AAAA,UAC7F,WAAW,KAAK,kBAAkB;AAAA,UAClC,sBAAsB,KAAK,kBAAkB,eAAe,MAAM,KAAK,UAAU,OAAO,KAAK,kBAAkB,YAAY,IAAI;AAAA,QAAA;AAAA,QAEhI,WAAW,KAAK;AAAA,MAAA,CAChB;AAAA,IACF,CAAC;AACD,UAAM,WAAW,IAAA;AACjB,WAAO;AAAA,EACR;AACD;;"}
|
|
1
|
+
{"version":3,"file":"runner.cjs","sources":["../../../../../packages/engine-tenant-api/src/migrations/runner.ts"],"sourcesContent":["import { Connection, createDatabaseIfNotExists, DatabaseConfig, EventManager } from '@contember/database'\nimport { TenantMigrationArgs } from './types.js'\nimport { MigrationsRunner as DbMigrationsRunner, SnapshotMigrationResolver } from '@contember/database-migrations'\nimport _20180802174310init from './2018-08-02-174310-init.js'\nimport _20180903140621identityproject from './2018-09-03-140621-identity-project.js'\nimport _20181026165450setupapikey from './2018-10-26-165450-setup-api-key.js'\nimport _20181026175155variables from './2018-10-26-175155-variables.js'\nimport _20190218110949projectslug from './2019-02-18-110949-project-slug.js'\nimport _20190218160155sessionexpiration from './2019-02-18-160155-session-expiration.js'\nimport _20190503163729apikeydisabledat from './2019-05-03-163729-api-key-disabled-at.js'\nimport _20190814153300projectslugunique from './2019-08-14-153300-project-slug-unique.js'\nimport _20190906111000membership from './2019-09-06-111000-membership.js'\nimport _20190906111001dropoldmember from './2019-09-06-111001-drop-old-member.js'\nimport _20200129idenitynote from './2020-01-29-idenity-note.js'\nimport _20200417fixpersonindex from './2020-04-17-fix-person-index.js'\nimport _20200501170000apikeyindex from './2020-05-01-170000-api-key-index.js'\nimport _20200608134000tenantcredentials from './2020-06-08-134000-tenant-credentials.js'\nimport _20200807110000personotp from './2020-08-07-110000-person-otp.js'\nimport _20200817162200mailtemplates from './2020-08-17-162200-mail-templates.js'\nimport _20200821143400personpasswordreset from './2020-08-21-143400-person-password-reset.js'\nimport _20200907094200identityprovider from './2020-09-07-094200-identity-provider.js'\nimport _20210328134000timestamp from './2021-03-28-134000-timestamp.js'\nimport _20210726105000projectconfig from './2021-07-26-105000-project-config.js'\nimport _20210726132000projectsecrets from './2021-07-26-132000-project-secrets.js'\nimport _20210727174000projectaliasindex from './2021-07-27-174000-project-alias-index.js'\nimport _20211124130000personpasswordnull from './2021-11-24-130000-person-password-null.js'\nimport _20211124161500mailtemplateprojectnull from './2021-11-24-161500-mail-template-project-null.js'\nimport _20220104144000personuniqueidentity from './2022-01-04-144000-person-unique-identity.js'\nimport _20220209111800fixcrypted from './2022-02-09-111800-fix-crypted.js'\nimport _20220211153000idpautosignup from './2022-02-11-153000-idp-auto-sign-up.js'\nimport _20220629105000personidp from './2022-06-29-105000-person-idp.js'\nimport _20220707135000personemailoptuniq from './2022-07-07-135000-person-email-opt-uniq.js'\nimport _20220707141000persondisplayname from './2022-07-07-141000-person-display-name.js'\nimport _20220714145000personloginoptions from './2022-07-14-145000-person-login-options.js'\nimport _20221108projectupdatenotification from './2022-11-08-project-update-notification.js'\nimport _20230120135500personemailnormalize from './2023-01-20-135500-person-email-normalize.js'\nimport _20230603104000persondisabled from './2023-06-03-104000-person-disabled.js'\nimport _20230901165000idpreturnconfig from './2023-09-01-165000-idp-return-config.js'\nimport _20240620140000mailreply from './2024-06-20-140000-mail-reply.js'\nimport _20240826120000passwordless from './2024-08-26-120000-passwordless.js'\nimport _20250416180000configup from './2025-04-16-180000-config-up.js'\nimport _20250417160000authlog from './2025-04-17-160000-auth-log.js'\nimport _20260512120000apikeysessiontracking from './2026-05-12-120000-api-key-session-tracking.js'\nimport _20260512130000apikeytrustforwardedinfo from './2026-05-12-130000-api-key-trust-forwarded-info.js'\nimport _20260513120000authlogeventdata from './2026-05-13-120000-auth-log-event-data.js'\nimport _20260513130000antiabuse from './2026-05-13-130000-anti-abuse.js'\nimport _20260514100000authlogadminactions from './2026-05-14-100000-auth-log-admin-actions.js'\nimport _20260515120000configreveallogmethod from './2026-05-15-120000-config-reveal-login-method.js'\nimport _20260521100000personmfa from './2026-05-21-100000-person-mfa.js'\nimport _20260521110000mfafoundation from './2026-05-21-110000-mfa-foundation.js'\nimport _20260521120000emailotp from './2026-05-21-120000-email-otp.js'\nimport _20260521130000apikeysessionpolicy from './2026-05-21-130000-api-key-session-policy.js'\nimport _20260521140000mfagraceduration from './2026-05-21-140000-mfa-grace-duration.js'\nimport _20260521150000emailotpratelimit from './2026-05-21-150000-email-otp-rate-limit.js'\nimport _20260526120000emailverificationtypes from './2026-05-26-120000-email-verification-types.js'\nimport _20260526120010emailverification from './2026-05-26-120010-email-verification.js'\nimport _20260526130000emailchangeverificationconfig from './2026-05-26-130000-email-change-verification-config.js'\nimport _20260526130010idprequireverifiedemail from './2026-05-26-130010-idp-require-verified-email.js'\nimport _20260526130020emailverificationratelimit from './2026-05-26-130020-email-verification-rate-limit.js'\nimport _20260526130030captchaprotectflows from './2026-05-26-130030-captcha-protect-flows.js'\nimport _20260526140000idpsession from './2026-05-26-140000-idp-session.js'\nimport _20260608100000idpassumeemailverified from './2026-06-08-100000-idp-assume-email-verified.js'\nimport _20260616120000loginanomalydetection from './2026-06-16-120000-login-anomaly-detection.js'\nimport _20260616130000idplogout from './2026-06-16-130000-idp-logout.js'\nimport _20260618120000idpclaimmapping from './2026-06-18-120000-idp-claim-mapping.js'\nimport _20260803120000personenableauthlog from './2026-08-03-120000-person-enable-auth-log.js'\nimport _20260804120000configpanel from './2026-08-04-120000-config-panel.js'\nimport _20260904120000idpdisablelocalauthentication from './2026-09-04-120000-idp-disable-local-authentication.js'\nimport snapshot from './snapshot.js'\nimport { computeTokenHash, Providers } from '../model/index.js'\nimport { Logger } from '@contember/logger'\n\nexport interface TenantCredentials {\n\tloginToken?: string\n\trootEmail?: string\n\trootToken?: string\n\trootTokenHash?: string\n\trootPassword?: string\n\t/**\n\t * Unpersisted root tokens (plain values). When set, these tokens are\n\t * verified at runtime and resolve to a super-admin identity without being\n\t * stored in the database. Useful for easy rotation.\n\t */\n\trootTokens?: readonly string[]\n\t/**\n\t * Unpersisted root token hashes (sha256 hex). Same as {@link rootTokens} but\n\t * the plain token never needs to be passed to the engine.\n\t */\n\trootTokenHashes?: readonly string[]\n}\n\nconst migrations = {\n\t'2018-08-02-174310-init': _20180802174310init,\n\t'2018-09-03-140621-identity-project': _20180903140621identityproject,\n\t'2018-10-26-165450-setup-api-key': _20181026165450setupapikey,\n\t'2018-10-26-175155-variables': _20181026175155variables,\n\t'2019-02-18-110949-project-slug': _20190218110949projectslug,\n\t'2019-02-18-160155-session-expiration': _20190218160155sessionexpiration,\n\t'2019-05-03-163729-api-key-disabled-at': _20190503163729apikeydisabledat,\n\t'2019-08-14-153300-project-slug-unique': _20190814153300projectslugunique,\n\t'2019-09-06-111000-membership': _20190906111000membership,\n\t'2019-09-06-111001-drop-old-member': _20190906111001dropoldmember,\n\t'2020-01-29-idenity-note': _20200129idenitynote,\n\t'2020-04-17-fix-person-index': _20200417fixpersonindex,\n\t'2020-05-01-170000-api-key-index': _20200501170000apikeyindex,\n\t'2020-06-08-134000-tenant-credentials': _20200608134000tenantcredentials,\n\t'2020-08-07-110000-person-otp': _20200807110000personotp,\n\t'2020-08-17-162200-mail-templates': _20200817162200mailtemplates,\n\t'2020-08-21-143400-person-password-reset': _20200821143400personpasswordreset,\n\t'2020-09-07-094200-identity-provider': _20200907094200identityprovider,\n\t'2021-03-28-134000-timestamp': _20210328134000timestamp,\n\t'2021-07-26-105000-project-config': _20210726105000projectconfig,\n\t'2021-07-26-132000-project-secrets': _20210726132000projectsecrets,\n\t'2021-07-27-174000-project-alias-index': _20210727174000projectaliasindex,\n\t'2021-11-24-130000-person-password-null': _20211124130000personpasswordnull,\n\t'2021-11-24-161500-mail-template-project-null': _20211124161500mailtemplateprojectnull,\n\t'2022-01-04-144000-person-unique-identity': _20220104144000personuniqueidentity,\n\t'2022-02-09-111800-fix-crypted': _20220209111800fixcrypted,\n\t'2022-02-11-153000-idp-auto-sign-up': _20220211153000idpautosignup,\n\t'2022-06-29-105000-person-idp': _20220629105000personidp,\n\t'2022-07-07-135000-person-email-opt-uniq': _20220707135000personemailoptuniq,\n\t'2022-07-07-141000-person-display-name': _20220707141000persondisplayname,\n\t'2022-07-14-145000-person-login-options': _20220714145000personloginoptions,\n\t'2022-11-08-project-update-notification': _20221108projectupdatenotification,\n\t'2023-01-20-135500-person-email-normalize': _20230120135500personemailnormalize,\n\t'2023-06-03-104000-person-disabled': _20230603104000persondisabled,\n\t'2023-09-01-165000-idp-return-config': _20230901165000idpreturnconfig,\n\t'2024-06-20-140000-mail-reply': _20240620140000mailreply,\n\t'2024-08-26-120000-passwordless': _20240826120000passwordless,\n\t'2025-04-16-180000-config-up': _20250416180000configup,\n\t'2025-04-17-160000-auth-log': _20250417160000authlog,\n\t'2026-05-12-120000-api-key-session-tracking': _20260512120000apikeysessiontracking,\n\t'2026-05-12-130000-api-key-trust-forwarded-info': _20260512130000apikeytrustforwardedinfo,\n\t'2026-05-13-120000-auth-log-event-data': _20260513120000authlogeventdata,\n\t'2026-05-13-130000-anti-abuse': _20260513130000antiabuse,\n\t'2026-05-14-100000-auth-log-admin-actions': _20260514100000authlogadminactions,\n\t'2026-05-15-120000-config-reveal-login-method': _20260515120000configreveallogmethod,\n\t'2026-05-21-100000-person-mfa': _20260521100000personmfa,\n\t'2026-05-21-110000-mfa-foundation': _20260521110000mfafoundation,\n\t'2026-05-21-120000-email-otp': _20260521120000emailotp,\n\t'2026-05-21-130000-api-key-session-policy': _20260521130000apikeysessionpolicy,\n\t'2026-05-21-140000-mfa-grace-duration': _20260521140000mfagraceduration,\n\t'2026-05-21-150000-email-otp-rate-limit': _20260521150000emailotpratelimit,\n\t'2026-05-26-120000-email-verification-types': _20260526120000emailverificationtypes,\n\t'2026-05-26-120010-email-verification': _20260526120010emailverification,\n\t'2026-05-26-130000-email-change-verification-config': _20260526130000emailchangeverificationconfig,\n\t'2026-05-26-130010-idp-require-verified-email': _20260526130010idprequireverifiedemail,\n\t'2026-05-26-130020-email-verification-rate-limit': _20260526130020emailverificationratelimit,\n\t'2026-05-26-130030-captcha-protect-flows': _20260526130030captchaprotectflows,\n\t'2026-05-26-140000-idp-session': _20260526140000idpsession,\n\t'2026-06-08-100000-idp-assume-email-verified': _20260608100000idpassumeemailverified,\n\t'2026-06-16-120000-login-anomaly-detection': _20260616120000loginanomalydetection,\n\t'2026-06-16-130000-idp-logout': _20260616130000idplogout,\n\t'2026-06-18-120000-idp-claim-mapping': _20260618120000idpclaimmapping,\n\t'2026-08-03-120000-person-enable-auth-log': _20260803120000personenableauthlog,\n\t'2026-08-04-120000-config-panel': _20260804120000configpanel,\n\t'2026-09-04-120000-idp-disable-local-authentication': _20260904120000idpdisablelocalauthentication,\n}\n\nexport class TenantMigrationsRunner {\n\tconstructor(\n\t\tprivate readonly db: DatabaseConfig,\n\t\tprivate readonly schema: string,\n\t\tprivate readonly tenantCredentials: TenantCredentials,\n\t\tprivate readonly providers: Pick<Providers, 'bcrypt' | 'uuid'>,\n\t) {\n\t}\n\n\tpublic async run(logger: Logger): Promise<{ name: string }[]> {\n\t\tawait createDatabaseIfNotExists(this.db, message => typeof message === 'string' ? logger.warn(message) : logger.error(message))\n\t\tconst connection = Connection.createSingle(this.db, err => logger.error(err))\n\t\tconst result = await connection.scope(async connection => {\n\t\t\tconst migrationsResolver = new SnapshotMigrationResolver(snapshot, migrations)\n\n\t\t\tconst innerRunner = new DbMigrationsRunner<TenantMigrationArgs>(connection, this.schema, migrationsResolver)\n\t\t\treturn await innerRunner.migrate(message => logger.warn(message), {\n\t\t\t\tgetCredentials: async () => ({\n\t\t\t\t\tloginTokenHash: this.tenantCredentials.loginToken ? computeTokenHash(this.tenantCredentials.loginToken) : undefined,\n\t\t\t\t\trootTokenHash: this.tenantCredentials.rootTokenHash\n\t\t\t\t\t\t?? (this.tenantCredentials.rootToken ? computeTokenHash(this.tenantCredentials.rootToken) : undefined),\n\t\t\t\t\trootEmail: this.tenantCredentials.rootEmail,\n\t\t\t\t\trootPasswordBcrypted: this.tenantCredentials.rootPassword ? await this.providers.bcrypt(this.tenantCredentials.rootPassword) : undefined,\n\t\t\t\t}),\n\t\t\t\tproviders: this.providers,\n\t\t\t})\n\t\t})\n\t\tawait connection.end()\n\t\treturn result\n\t}\n}\n"],"names":["_20180802174310init","_20180903140621identityproject","_20181026165450setupapikey","_20181026175155variables","_20190218110949projectslug","_20190218160155sessionexpiration","_20190503163729apikeydisabledat","_20190814153300projectslugunique","_20190906111000membership","_20190906111001dropoldmember","_20200129idenitynote","_20200417fixpersonindex","_20200501170000apikeyindex","_20200608134000tenantcredentials","_20200807110000personotp","_20200817162200mailtemplates","_20200821143400personpasswordreset","_20200907094200identityprovider","_20210328134000timestamp","_20210726105000projectconfig","_20210726132000projectsecrets","_20210727174000projectaliasindex","_20211124130000personpasswordnull","_20211124161500mailtemplateprojectnull","_20220104144000personuniqueidentity","_20220209111800fixcrypted","_20220211153000idpautosignup","_20220629105000personidp","_20220707135000personemailoptuniq","_20220707141000persondisplayname","_20220714145000personloginoptions","_20221108projectupdatenotification","_20230120135500personemailnormalize","_20230603104000persondisabled","_20230901165000idpreturnconfig","_20240620140000mailreply","_20240826120000passwordless","_20250416180000configup","_20250417160000authlog","_20260512120000apikeysessiontracking","_20260512130000apikeytrustforwardedinfo","_20260513120000authlogeventdata","_20260513130000antiabuse","_20260514100000authlogadminactions","_20260515120000configreveallogmethod","_20260521100000personmfa","_20260521110000mfafoundation","_20260521120000emailotp","_20260521130000apikeysessionpolicy","_20260521140000mfagraceduration","_20260521150000emailotpratelimit","_20260526120000emailverificationtypes","_20260526120010emailverification","_20260526130000emailchangeverificationconfig","_20260526130010idprequireverifiedemail","_20260526130020emailverificationratelimit","_20260526130030captchaprotectflows","_20260526140000idpsession","_20260608100000idpassumeemailverified","_20260616120000loginanomalydetection","_20260616130000idplogout","_20260618120000idpclaimmapping","_20260803120000personenableauthlog","_20260804120000configpanel","_20260904120000idpdisablelocalauthentication","createDatabaseIfNotExists","Connection","connection","SnapshotMigrationResolver","DbMigrationsRunner","computeTokenHash"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,MAAM,aAAa;AAAA,EAClB,0BAA0BA;AAAAA,EAC1B,sCAAsCC;AAAAA,EACtC,mCAAmCC;AAAAA,EACnC,+BAA+BC;AAAAA,EAC/B,kCAAkCC;AAAAA,EAClC,wCAAwCC;AAAAA,EACxC,yCAAyCC;AAAAA,EACzC,yCAAyCC;AAAAA,EACzC,gCAAgCC;AAAAA,EAChC,qCAAqCC;AAAAA,EACrC,2BAA2BC;AAAAA,EAC3B,+BAA+BC;AAAAA,EAC/B,mCAAmCC;AAAAA,EACnC,wCAAwCC;AAAAA,EACxC,gCAAgCC;AAAAA,EAChC,oCAAoCC;AAAAA,EACpC,2CAA2CC;AAAAA,EAC3C,uCAAuCC;AAAAA,EACvC,+BAA+BC;AAAAA,EAC/B,oCAAoCC;AAAAA,EACpC,qCAAqCC;AAAAA,EACrC,yCAAyCC;AAAAA,EACzC,0CAA0CC;AAAAA,EAC1C,gDAAgDC;AAAAA,EAChD,4CAA4CC;AAAAA,EAC5C,iCAAiCC;AAAAA,EACjC,sCAAsCC;AAAAA,EACtC,gCAAgCC;AAAAA,EAChC,2CAA2CC;AAAAA,EAC3C,yCAAyCC;AAAAA,EACzC,0CAA0CC;AAAAA,EAC1C,0CAA0CC;AAAAA,EAC1C,4CAA4CC;AAAAA,EAC5C,qCAAqCC;AAAAA,EACrC,uCAAuCC;AAAAA,EACvC,gCAAgCC;AAAAA,EAChC,kCAAkCC;AAAAA,EAClC,+BAA+BC;AAAAA,EAC/B,8BAA8BC;AAAAA,EAC9B,8CAA8CC;AAAAA,EAC9C,kDAAkDC;AAAAA,EAClD,yCAAyCC;AAAAA,EACzC,gCAAgCC;AAAAA,EAChC,4CAA4CC;AAAAA,EAC5C,gDAAgDC;AAAAA,EAChD,gCAAgCC;AAAAA,EAChC,oCAAoCC;AAAAA,EACpC,+BAA+BC;AAAAA,EAC/B,4CAA4CC;AAAAA,EAC5C,wCAAwCC;AAAAA,EACxC,0CAA0CC;AAAAA,EAC1C,8CAA8CC;AAAAA,EAC9C,wCAAwCC;AAAAA,EACxC,sDAAsDC;AAAAA,EACtD,gDAAgDC;AAAAA,EAChD,mDAAmDC;AAAAA,EACnD,2CAA2CC;AAAAA,EAC3C,iCAAiCC;AAAAA,EACjC,+CAA+CC;AAAAA,EAC/C,6CAA6CC;AAAAA,EAC7C,gCAAgCC;AAAAA,EAChC,uCAAuCC;AAAAA,EACvC,4CAA4CC;AAAAA,EAC5C,kCAAkCC;AAAAA,EAClC,sDAAsDC;AACvD;AAEO,MAAM,uBAAuB;AAAA,EACnC,YACkB,IACA,QACA,mBACA,WAChB;AAJgB,SAAA,KAAA;AACA,SAAA,SAAA;AACA,SAAA,oBAAA;AACA,SAAA,YAAA;AAAA,EAElB;AAAA,EAEA,MAAa,IAAI,QAA6C;AAC7D,UAAMC,SAAAA,0BAA0B,KAAK,IAAI,CAAA,YAAW,OAAO,YAAY,WAAW,OAAO,KAAK,OAAO,IAAI,OAAO,MAAM,OAAO,CAAC;AAC9H,UAAM,aAAaC,SAAAA,WAAW,aAAa,KAAK,IAAI,CAAA,QAAO,OAAO,MAAM,GAAG,CAAC;AAC5E,UAAM,SAAS,MAAM,WAAW,MAAM,OAAMC,gBAAc;AACzD,YAAM,qBAAqB,IAAIC,6CAA0B,UAAU,UAAU;AAE7E,YAAM,cAAc,IAAIC,mBAAAA,iBAAwCF,aAAY,KAAK,QAAQ,kBAAkB;AAC3G,aAAO,MAAM,YAAY,QAAQ,aAAW,OAAO,KAAK,OAAO,GAAG;AAAA,QACjE,gBAAgB,aAAa;AAAA,UAC5B,gBAAgB,KAAK,kBAAkB,aAAaG,MAAAA,iBAAiB,KAAK,kBAAkB,UAAU,IAAI;AAAA,UAC1G,eAAe,KAAK,kBAAkB,kBACjC,KAAK,kBAAkB,YAAYA,MAAAA,iBAAiB,KAAK,kBAAkB,SAAS,IAAI;AAAA,UAC7F,WAAW,KAAK,kBAAkB;AAAA,UAClC,sBAAsB,KAAK,kBAAkB,eAAe,MAAM,KAAK,UAAU,OAAO,KAAK,kBAAkB,YAAY,IAAI;AAAA,QAAA;AAAA,QAEhI,WAAW,KAAK;AAAA,MAAA,CAChB;AAAA,IACF,CAAC;AACD,UAAM,WAAW,IAAA;AACjB,WAAO;AAAA,EACR;AACD;;"}
|
|
@@ -64,6 +64,7 @@ import _20260616130000idplogout from "./2026-06-16-130000-idp-logout.js";
|
|
|
64
64
|
import _20260618120000idpclaimmapping from "./2026-06-18-120000-idp-claim-mapping.js";
|
|
65
65
|
import _20260803120000personenableauthlog from "./2026-08-03-120000-person-enable-auth-log.js";
|
|
66
66
|
import _20260804120000configpanel from "./2026-08-04-120000-config-panel.js";
|
|
67
|
+
import _20260904120000idpdisablelocalauthentication from "./2026-09-04-120000-idp-disable-local-authentication.js";
|
|
67
68
|
import snapshot from "./snapshot.js";
|
|
68
69
|
import "../model/authorization/PermissionActions.js";
|
|
69
70
|
import "@contember/authorization";
|
|
@@ -149,7 +150,8 @@ const migrations = {
|
|
|
149
150
|
"2026-06-16-130000-idp-logout": _20260616130000idplogout,
|
|
150
151
|
"2026-06-18-120000-idp-claim-mapping": _20260618120000idpclaimmapping,
|
|
151
152
|
"2026-08-03-120000-person-enable-auth-log": _20260803120000personenableauthlog,
|
|
152
|
-
"2026-08-04-120000-config-panel": _20260804120000configpanel
|
|
153
|
+
"2026-08-04-120000-config-panel": _20260804120000configpanel,
|
|
154
|
+
"2026-09-04-120000-idp-disable-local-authentication": _20260904120000idpdisablelocalauthentication
|
|
153
155
|
};
|
|
154
156
|
class TenantMigrationsRunner {
|
|
155
157
|
constructor(db, schema, tenantCredentials, providers) {
|