import * as plugins from '../plugins.js'; import type * as data from '../data/index.js'; import type { IIdentity, IIdentityCredential } from '../data/user.js'; import type { IHostedAppBootstrapAction, IHostedAppBootstrapActionRequest, IHostedAppLifecycleReport, IHostedAppLifecycleState, IHostedAppUpgradeState, } from '../data/hostedapp.js'; export interface IReq_GetHostedAppAccessConfiguration extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_GetHostedAppAccessConfiguration > { method: 'getHostedAppAccessConfiguration'; request: { identity: data.IIdentity; }; response: { users: Array<{ userId: string; username: string; role: 'admin' | 'user'; platformOidcIssuer?: string; }>; assignments: data.IHostedAppRoleAssignment[]; apps: Array<{ serviceId: string; appInstanceId: string; displayName: string; roles: data.IHostedAppRoleDefinition[]; platformOidcSupported: boolean; platformOidcRegistration?: data.IHostedAppPlatformOidcRegistration; }>; }; } export interface IReq_SetHostedAppRoleAssignment extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_SetHostedAppRoleAssignment > { method: 'setHostedAppRoleAssignment'; request: { identity: data.IIdentity; userId: string; appInstanceId: string; roleIds: string[]; }; response: { assignment: data.IHostedAppRoleAssignment | null; }; } export interface IReq_SetHostedAppPlatformOidc extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_SetHostedAppPlatformOidc > { method: 'setHostedAppPlatformOidc'; request: { identity: data.IIdentity; appInstanceId: string; enabled: boolean; }; response: { registration: data.IHostedAppPlatformOidcRegistration; }; } export interface IReq_GetHostedAppOidcAuthorization extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_GetHostedAppOidcAuthorization > { method: 'getHostedAppOidcAuthorization'; request: { identity: data.IIdentity; requestId: string; }; response: { appInstanceId: string; appName: string; roleIds: string[]; expiresAt: number; }; } export interface IReq_CompleteHostedAppOidcAuthorization extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_CompleteHostedAppOidcAuthorization > { method: 'completeHostedAppOidcAuthorization'; request: { identity: data.IIdentity; requestId: string; }; response: { redirectUrl: string; }; } export interface IReq_CancelHostedAppOidcAuthorization extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_CancelHostedAppOidcAuthorization > { method: 'cancelHostedAppOidcAuthorization'; request: { identity: data.IIdentity; requestId: string; }; response: { redirectUrl: string; }; } export interface IReq_HostedApp_ReportLifecycleState extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_ReportLifecycleState > { method: 'hostedAppReportLifecycleState'; request: { identity: IIdentityCredential; report: IHostedAppLifecycleReport; }; response: { state: IHostedAppLifecycleState; }; } export interface IReq_HostedApp_GetLifecycleState extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_GetLifecycleState > { method: 'hostedAppGetLifecycleState'; request: { identity: IIdentityCredential; }; response: { state: IHostedAppLifecycleState; }; } export interface IReq_HostedApp_RequestBootstrapAction extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_RequestBootstrapAction > { method: 'hostedAppRequestBootstrapAction'; request: { identity: IIdentityCredential; action: IHostedAppBootstrapActionRequest; }; response: { action: IHostedAppBootstrapAction; state: IHostedAppLifecycleState; }; } export interface IReq_HostedApp_CompleteBootstrapAction extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_CompleteBootstrapAction > { method: 'hostedAppCompleteBootstrapAction'; request: { identity: IIdentityCredential; actionId: string; expectedActionRevision: number; expectedActionStatus: 'ready'; message?: string; }; response: { state: IHostedAppLifecycleState; }; } export const validateHostedAppCompleteBootstrapActionRequest = ( requestArg: unknown, ): string[] => { if (!requestArg || typeof requestArg !== 'object' || Array.isArray(requestArg)) { return ['hosted app bootstrap completion must be an object']; } const request = requestArg as Record; const errors: string[] = []; const allowedKeys = new Set([ 'identity', 'actionId', 'expectedActionRevision', 'expectedActionStatus', 'message', ]); if (Object.keys(request).some((keyArg) => !allowedKeys.has(keyArg))) { errors.push('hosted app bootstrap completion contains fields outside its schema'); } if (!request.identity || typeof request.identity !== 'object' || typeof (request.identity as Record).jwt !== 'string') { errors.push('hosted app bootstrap completion requires a JWT identity'); } if (typeof request.actionId !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/.test(request.actionId)) { errors.push('hosted app bootstrap completion actionId must be canonical'); } if (!Number.isSafeInteger(request.expectedActionRevision) || (request.expectedActionRevision as number) < 1) { errors.push('hosted app bootstrap completion revision must be positive'); } if (request.expectedActionStatus !== 'ready') { errors.push('hosted app bootstrap completion must fence ready status'); } if (request.message !== undefined && (typeof request.message !== 'string' || request.message.length > 4000)) { errors.push('hosted app bootstrap completion message must be bounded'); } return errors; }; export interface IReq_HostedApp_StartManagedUpgrade extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_StartManagedUpgrade > { method: 'hostedAppStartManagedUpgrade'; request: { identity: IIdentityCredential; targetVersion?: string; }; response: { upgradeState: IHostedAppUpgradeState; state: IHostedAppLifecycleState; }; } export interface IReq_HostedApp_GetManagedUpgradeStatus extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_HostedApp_GetManagedUpgradeStatus > { method: 'hostedAppGetManagedUpgradeStatus'; request: { identity: IIdentityCredential; }; response: { upgradeState: IHostedAppUpgradeState; }; } export interface IReq_Admin_GetHostedAppParentUpgradeStatus extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_GetHostedAppParentUpgradeStatus > { method: 'getHostedAppParentUpgradeStatus'; request: { identity: IIdentity; }; response: { isHosted: boolean; unavailableReason?: string; upgradeState: IHostedAppUpgradeState; }; } export interface IReq_Admin_StartHostedAppParentUpgrade extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_Admin_StartHostedAppParentUpgrade > { method: 'startHostedAppParentUpgrade'; request: { identity: IIdentity; targetVersion?: string; }; response: { isHosted: boolean; unavailableReason?: string; upgradeState: IHostedAppUpgradeState; }; }