import { z } from 'zod'; import { APIResponseSchema } from '@agentuity/api'; export const OAuthClientSchema = z.object({ id: z.string(), name: z.string(), description: z.string(), homepage_url: z.string(), icon: z.string().nullable().optional(), client_type: z.enum(['public', 'confidential']), redirect_uris: z.array(z.string()), post_logout_redirect_uris: z.array(z.string()), grant_types: z.array(z.string()), response_types: z.array(z.string()), scopes: z.array(z.string()), org_id: z.string().optional(), project_id: z.string().optional(), access_token_lifetime_seconds: z.number().optional(), refresh_token_lifetime_seconds: z.number().optional(), id_token_lifetime_seconds: z.number().optional(), allowed_user_ids: z.array(z.string()), internal: z.boolean().optional().default(false), is_public: z.boolean().default(true), created_at: z.string(), updated_at: z.string(), }); export type OAuthClient = z.infer; export const OAuthClientListItemSchema = OAuthClientSchema.extend({ user_count: z.number(), last_activity: z.string().nullable().optional(), link: z.string(), }); export type OAuthClientListItem = z.infer; export const OAuthClientCreateRequestSchema = z.object({ name: z.string(), description: z.string(), homepage_url: z.string(), icon: z.string().nullable().optional(), client_type: z.enum(['public', 'confidential']).optional(), redirect_uris: z.array(z.string()).optional(), post_logout_redirect_uris: z.array(z.string()).optional(), grant_types: z.array(z.string()).optional(), response_types: z.array(z.string()).optional(), scopes: z.array(z.string()).optional(), project_id: z.string().optional(), access_token_lifetime_seconds: z.number().optional(), refresh_token_lifetime_seconds: z.number().optional(), id_token_lifetime_seconds: z.number().optional(), allowed_user_ids: z.array(z.string()).optional(), is_public: z.boolean().optional(), }); export type OAuthClientCreateRequest = z.infer; export const OAuthClientCreateDataSchema = z.object({ client: OAuthClientSchema, client_secret: z.string(), }); export type OAuthClientCreateData = z.infer; export const OAuthClientUpdateRequestSchema = z.object({ name: z.string().optional(), description: z.string().optional(), homepage_url: z.string().optional(), icon: z.string().nullable().optional(), client_type: z.enum(['public', 'confidential']).optional(), redirect_uris: z.array(z.string()).optional(), post_logout_redirect_uris: z.array(z.string()).optional(), grant_types: z.array(z.string()).optional(), response_types: z.array(z.string()).optional(), scopes: z.array(z.string()).optional(), project_id: z.string().optional(), access_token_lifetime_seconds: z.number().optional(), refresh_token_lifetime_seconds: z.number().optional(), id_token_lifetime_seconds: z.number().optional(), allowed_user_ids: z.array(z.string()).optional(), is_public: z.boolean().optional(), }); export type OAuthClientUpdateRequest = z.infer; export const OAuthClientUpdateDataSchema = z.object({ client: OAuthClientSchema, client_secret: z.string().optional(), }); export type OAuthClientUpdateData = z.infer; export const OAuthRotateSecretDataSchema = z.object({ client_id: z.string(), client_secret: z.string(), }); export type OAuthRotateSecretData = z.infer; export const OAuthDeletedDataSchema = z.object({ deleted: z.literal(true), }); export type OAuthDeletedData = z.infer; export const OAuthClientActivityItemSchema = z.object({ activity_date: z.string(), total_access: z.number(), unique_users: z.number(), }); export type OAuthClientActivityItem = z.infer; export const OAuthBulkActivityItemSchema = z.object({ client_id: z.string(), activity_date: z.string(), unique_users: z.number(), }); export type OAuthBulkActivityItem = z.infer; export const OAuthConsentGrantSchema = z.object({ user_id: z.string(), scopes: z.array(z.string()), created_at: z.string(), updated_at: z.string(), }); export type OAuthConsentGrant = z.infer; export const OAuthUserConsentSchema = z.object({ client_id: z.string(), scopes: z.array(z.string()), created_at: z.string(), updated_at: z.string(), client_name: z.string(), client_description: z.string(), client_icon: z.string().nullable(), client_homepage_url: z.string(), }); export type OAuthUserConsent = z.infer; export const OAuthScopeSchema = z.object({ name: z.string(), description: z.string(), consent_title: z.string(), consent_description: z.string(), sensitive: z.boolean(), required: z.boolean(), default: z.boolean(), }); export type OAuthScope = z.infer; export const OAuthPermissionLevelSchema = z.object({ label: z.string(), value: z.string(), scopes: z.array(z.string()), warning: z.boolean().optional(), warningTitle: z.string().optional(), }); export type OAuthPermissionLevel = z.infer; export const OAuthPermissionGroupSchema = z.object({ id: z.string(), name: z.string(), description: z.string(), levels: z.array(OAuthPermissionLevelSchema), }); export type OAuthPermissionGroup = z.infer; export const OAuthPermissionCategorySchema = z.object({ id: z.string(), label: z.string(), groups: z.array(OAuthPermissionGroupSchema), }); export type OAuthPermissionCategory = z.infer; export const OAuthScopesDataSchema = z.object({ scopes: z.array(OAuthScopeSchema), permissions: z.array(OAuthPermissionCategorySchema), }); export type OAuthScopesData = z.infer; export const OAuthOrgMemberSchema = z.object({ id: z.string(), first_name: z.string().nullable(), last_name: z.string().nullable(), email: z.string().nullable(), photo_url: z.string().nullable(), role: z.string(), }); export type OAuthOrgMember = z.infer; export const OAuthKeyRotatedDataSchema = z.object({ rotated: z.literal(true), }); export type OAuthKeyRotatedData = z.infer; export const OAuthClientListResponseSchema = APIResponseSchema(z.array(OAuthClientListItemSchema)); export const OAuthClientGetResponseSchema = APIResponseSchema(OAuthClientListItemSchema); export const OAuthClientCreateResponseSchema = APIResponseSchema(OAuthClientCreateDataSchema); export const OAuthClientUpdateResponseSchema = APIResponseSchema(OAuthClientUpdateDataSchema); export const OAuthClientDeleteResponseSchema = APIResponseSchema(OAuthDeletedDataSchema); export const OAuthClientRotateSecretResponseSchema = APIResponseSchema(OAuthRotateSecretDataSchema); export const OAuthClientUsersResponseSchema = APIResponseSchema(z.array(OAuthConsentGrantSchema)); export const OAuthClientRevokeAllUsersResponseSchema = APIResponseSchema(OAuthDeletedDataSchema); export const OAuthClientRevokeUserResponseSchema = APIResponseSchema(OAuthDeletedDataSchema); export const OAuthClientActivityResponseSchema = APIResponseSchema( z.array(OAuthClientActivityItemSchema) ); export const OAuthBulkActivityResponseSchema = APIResponseSchema( z.array(OAuthBulkActivityItemSchema) ); export const OAuthUserConsentResponseSchema = APIResponseSchema(z.array(OAuthUserConsentSchema)); export const OAuthUserConsentRevokeResponseSchema = APIResponseSchema(OAuthDeletedDataSchema); export const OAuthScopesResponseSchema = APIResponseSchema(OAuthScopesDataSchema); export const OAuthOrgMembersResponseSchema = APIResponseSchema(z.array(OAuthOrgMemberSchema)); export const OAuthKeysRotateResponseSchema = APIResponseSchema(OAuthKeyRotatedDataSchema); export type OAuthClientListResponse = z.infer; export type OAuthClientGetResponse = z.infer; export type OAuthClientCreateResponse = z.infer; export type OAuthClientUpdateResponse = z.infer; export type OAuthClientDeleteResponse = z.infer; export type OAuthClientRotateSecretResponse = z.infer; export type OAuthClientUsersResponse = z.infer; export type OAuthClientRevokeAllUsersResponse = z.infer< typeof OAuthClientRevokeAllUsersResponseSchema >; export type OAuthClientRevokeUserResponse = z.infer; export type OAuthClientActivityResponse = z.infer; export type OAuthBulkActivityResponse = z.infer; export type OAuthUserConsentResponse = z.infer; export type OAuthUserConsentRevokeResponse = z.infer; export type OAuthScopesResponse = z.infer; export type OAuthOrgMembersResponse = z.infer; export type OAuthKeysRotateResponse = z.infer; // ============================================================================ // OAuth 2.0 Authorization Code Flow Types // ============================================================================ export const OAuthFlowConfigSchema = z.object({ clientId: z.string().optional().describe('OAuth client ID. Defaults to OAUTH_CLIENT_ID env var'), clientSecret: z .string() .optional() .describe('OAuth client secret. Defaults to OAUTH_CLIENT_SECRET env var'), issuer: z .string() .optional() .describe( 'OIDC issuer base URL. Defaults to OAUTH_ISSUER env var. Used to derive authorize/token/userinfo URLs' ), authorizeUrl: z .string() .optional() .describe('Authorization endpoint. Defaults to OAUTH_AUTHORIZE_URL or {issuer}/authorize'), tokenUrl: z .string() .optional() .describe('Token endpoint. Defaults to OAUTH_TOKEN_URL or {issuer}/oauth/token'), userinfoUrl: z .string() .optional() .describe('UserInfo endpoint. Defaults to OAUTH_USERINFO_URL or {issuer}/userinfo'), revokeUrl: z .string() .optional() .describe( 'Token revocation endpoint (RFC 7009). Defaults to OAUTH_REVOKE_URL or {issuer}/revoke' ), endSessionUrl: z .string() .optional() .describe( 'OIDC end session endpoint. Defaults to OAUTH_END_SESSION_URL or {issuer}/end_session' ), scopes: z .string() .optional() .describe('Space-separated scopes. Defaults to OAUTH_SCOPES or "openid profile email"'), prompt: z .enum(['none', 'login', 'consent', 'select_account']) .optional() .describe( 'OIDC prompt parameter. Controls authentication UX: "login" forces re-auth, "consent" forces consent screen, "none" fails if not authenticated, "select_account" lets user pick an account' ), }); export type OAuthFlowConfig = z.infer; export const OAuthTokenResponseSchema = z.object({ access_token: z.string(), token_type: z.string().optional(), expires_in: z.number().optional(), refresh_token: z.string().optional(), scope: z.string().optional(), id_token: z.string().optional(), }); export type OAuthTokenResponse = z.infer; export const OAuthUserInfoSchema = z .object({ sub: z.string(), name: z.string().optional(), given_name: z.string().optional(), family_name: z.string().optional(), picture: z.string().optional(), email: z.string().optional(), email_verified: z.boolean().optional(), }) .catchall(z.unknown()); export type OAuthUserInfo = z.infer; export const StoredTokenSchema = z.object({ access_token: z.string(), token_type: z.string().optional(), refresh_token: z.string().optional(), scope: z.string().optional(), id_token: z.string().optional(), expires_at: z .number() .optional() .describe('Unix timestamp (seconds) when the access token expires'), }); export type StoredToken = z.infer;