import * as plugins from './plugins.js'; import type { TControllerSessionId } from '../ts_interfaces/index.js'; const base64UrlPattern = /^[A-Za-z0-9_-]+$/; const maximumNativeIdBytes = 512; const maximumProviderGenerationBytes = 512; export type TControllerSessionLocatorState = | 'initializing' | 'binding' | 'attached' | 'detaching' | 'detached' | 'deleting' | 'completing' | 'tombstoned'; export interface IControllerSessionPendingBinding { bindingId: string; supervisorGeneration: string; attachedAt: Date; } export interface IControllerSessionBindingReference { bindingId: string; detachedAt: Date; } export interface IControllerSessionDeletionRecord { operationId: string; startedAt: Date; priorState: 'attached' | 'detached'; finalBindingId: string; priorDetachedAt?: Date; completedAt?: Date; } export interface IControllerSessionIdentityDocument { id: string; issuerId: string; sessionIdentityId: string; projectIdentityId: string; createdAt: Date; retiredAt?: Date; } export interface IControllerSessionRuntimeBindingDocument { id: string; bindingId: string; issuerId: string; sessionIdentityId: string; projectIdentityId: string; runtimeId: TControllerSessionId; supervisorGeneration: string; providerSessionGeneration?: string; attachedAt: Date; detachedAt?: Date; } export interface IControllerSessionLocatorDocument { id: string; issuerId: string; sessionIdentityId: string; projectIdentityId: string; runtimeId: TControllerSessionId; providerSessionGeneration?: string; identityCreatedAt: Date; state: TControllerSessionLocatorState; updatedAt: Date; pendingBinding?: IControllerSessionPendingBinding; activeBindingId?: string; bindingCleanup?: IControllerSessionBindingReference; detachedBinding?: IControllerSessionBindingReference; deletion?: IControllerSessionDeletionRecord; } const isPlainObject = (valueArg: unknown): valueArg is Record => ( typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg) && ( Object.getPrototypeOf(valueArg) === Object.prototype || Object.getPrototypeOf(valueArg) === null ) ); const hasExactKeys = ( valueArg: Record, requiredKeysArg: readonly string[], optionalKeysArg: readonly string[] = [], ): boolean => { const keys = Object.keys(valueArg); return requiredKeysArg.every((key) => Object.hasOwn(valueArg, key)) && keys.every((key) => requiredKeysArg.includes(key) || optionalKeysArg.includes(key)); }; const isBase64UrlBytes = (valueArg: unknown, byteLengthArg: number): valueArg is string => { if ( typeof valueArg !== 'string' || !base64UrlPattern.test(valueArg) || Buffer.from(valueArg, 'base64url').byteLength !== byteLengthArg ) return false; return Buffer.from(valueArg, 'base64url').toString('base64url') === valueArg; }; const isValidDate = (valueArg: unknown): valueArg is Date => ( valueArg instanceof Date && Number.isFinite(valueArg.getTime()) && valueArg.getTime() >= 0 ); const isRuntimeId = (valueArg: unknown): valueArg is TControllerSessionId => ( isPlainObject(valueArg) && hasExactKeys(valueArg, ['harnessId', 'nativeId']) && (valueArg.harnessId === 'opencode' || valueArg.harnessId === 'flex' || valueArg.harnessId === 'codex') && typeof valueArg.nativeId === 'string' && valueArg.nativeId.length > 0 && Buffer.byteLength(valueArg.nativeId, 'utf8') <= maximumNativeIdBytes ); const isProviderGeneration = (valueArg: unknown): valueArg is string => ( typeof valueArg === 'string' && valueArg.length > 0 && Buffer.byteLength(valueArg, 'utf8') <= maximumProviderGenerationBytes && !/[\u0000-\u001f\u007f]/u.test(valueArg) ); const isPendingBinding = (valueArg: unknown): valueArg is IControllerSessionPendingBinding => ( isPlainObject(valueArg) && hasExactKeys(valueArg, ['bindingId', 'supervisorGeneration', 'attachedAt']) && isBase64UrlBytes(valueArg.bindingId, 32) && isBase64UrlBytes(valueArg.supervisorGeneration, 32) && isValidDate(valueArg.attachedAt) ); const isBindingReference = ( valueArg: unknown, ): valueArg is IControllerSessionBindingReference => ( isPlainObject(valueArg) && hasExactKeys(valueArg, ['bindingId', 'detachedAt']) && isBase64UrlBytes(valueArg.bindingId, 32) && isValidDate(valueArg.detachedAt) ); const isDeletionRecord = (valueArg: unknown): valueArg is IControllerSessionDeletionRecord => { if (!isPlainObject(valueArg)) return false; const completing = Object.hasOwn(valueArg, 'completedAt'); const detached = valueArg.priorState === 'detached'; if (!hasExactKeys( valueArg, [ 'operationId', 'startedAt', 'priorState', 'finalBindingId', ...(detached ? ['priorDetachedAt'] : []), ...(completing ? ['completedAt'] : []), ], )) return false; return isBase64UrlBytes(valueArg.operationId, 24) && isValidDate(valueArg.startedAt) && (valueArg.priorState === 'attached' || valueArg.priorState === 'detached') && isBase64UrlBytes(valueArg.finalBindingId, 32) && (!detached || isValidDate(valueArg.priorDetachedAt)) && (!completing || ( isValidDate(valueArg.completedAt) && valueArg.completedAt.getTime() >= valueArg.startedAt.getTime() )); }; const digest = (valueArg: unknown): string => plugins.crypto .createHash('sha256') .update(JSON.stringify(valueArg), 'utf8') .digest('base64url'); export const controllerSessionIdentityDocumentId = ( issuerIdArg: string, sessionIdentityIdArg: string, ): string => digest(['controller-session-identity-v1', issuerIdArg, sessionIdentityIdArg]); export const controllerSessionLocatorDocumentId = ( issuerIdArg: string, projectIdentityIdArg: string, runtimeIdArg: TControllerSessionId, ): string => digest([ 'controller-session-locator-v1', issuerIdArg, projectIdentityIdArg, runtimeIdArg.harnessId, runtimeIdArg.nativeId, ]); export const assertControllerSessionIdentityDocument = ( valueArg: unknown, ): asserts valueArg is IControllerSessionIdentityDocument => { if ( !isPlainObject(valueArg) || !hasExactKeys( valueArg, ['id', 'issuerId', 'sessionIdentityId', 'projectIdentityId', 'createdAt'], ['retiredAt'], ) || !isBase64UrlBytes(valueArg.issuerId, 32) || !isBase64UrlBytes(valueArg.sessionIdentityId, 32) || !isBase64UrlBytes(valueArg.projectIdentityId, 16) || valueArg.id !== controllerSessionIdentityDocumentId( valueArg.issuerId, valueArg.sessionIdentityId, ) || !isValidDate(valueArg.createdAt) || (valueArg.retiredAt !== undefined && ( !isValidDate(valueArg.retiredAt) || valueArg.retiredAt.getTime() < valueArg.createdAt.getTime() )) ) throw new Error('Invalid controller session identity document.'); }; export const assertControllerSessionRuntimeBindingDocument = ( valueArg: unknown, ): asserts valueArg is IControllerSessionRuntimeBindingDocument => { if ( !isPlainObject(valueArg) || !hasExactKeys( valueArg, [ 'id', 'bindingId', 'issuerId', 'sessionIdentityId', 'projectIdentityId', 'runtimeId', 'supervisorGeneration', 'attachedAt', ], ['providerSessionGeneration', 'detachedAt'], ) || !isBase64UrlBytes(valueArg.bindingId, 32) || valueArg.id !== valueArg.bindingId || !isBase64UrlBytes(valueArg.issuerId, 32) || !isBase64UrlBytes(valueArg.sessionIdentityId, 32) || !isBase64UrlBytes(valueArg.projectIdentityId, 16) || !isRuntimeId(valueArg.runtimeId) || !isBase64UrlBytes(valueArg.supervisorGeneration, 32) || ( valueArg.providerSessionGeneration !== undefined && !isProviderGeneration(valueArg.providerSessionGeneration) ) || !isValidDate(valueArg.attachedAt) || (valueArg.detachedAt !== undefined && ( !isValidDate(valueArg.detachedAt) || valueArg.detachedAt.getTime() < valueArg.attachedAt.getTime() )) ) throw new Error('Invalid controller session runtime binding document.'); }; export const assertControllerSessionLocatorDocument = ( valueArg: unknown, ): asserts valueArg is IControllerSessionLocatorDocument => { if ( !isPlainObject(valueArg) || !hasExactKeys( valueArg, [ 'id', 'issuerId', 'sessionIdentityId', 'projectIdentityId', 'runtimeId', 'identityCreatedAt', 'state', 'updatedAt', ], [ 'providerSessionGeneration', 'pendingBinding', 'activeBindingId', 'bindingCleanup', 'detachedBinding', 'deletion', ], ) || !isBase64UrlBytes(valueArg.issuerId, 32) || !isBase64UrlBytes(valueArg.sessionIdentityId, 32) || !isBase64UrlBytes(valueArg.projectIdentityId, 16) || !isRuntimeId(valueArg.runtimeId) || valueArg.id !== controllerSessionLocatorDocumentId( valueArg.issuerId, valueArg.projectIdentityId, valueArg.runtimeId, ) || ( valueArg.providerSessionGeneration !== undefined && !isProviderGeneration(valueArg.providerSessionGeneration) ) || !isValidDate(valueArg.identityCreatedAt) || !isValidDate(valueArg.updatedAt) || valueArg.updatedAt.getTime() < valueArg.identityCreatedAt.getTime() || ![ 'initializing', 'binding', 'attached', 'detaching', 'detached', 'deleting', 'completing', 'tombstoned', ].includes(String(valueArg.state)) ) throw new Error('Invalid controller session locator document.'); const pendingBinding = valueArg.pendingBinding; const activeBindingId = valueArg.activeBindingId; const bindingCleanup = valueArg.bindingCleanup; const detachedBinding = valueArg.detachedBinding; const deletion = valueArg.deletion; if (pendingBinding !== undefined && !isPendingBinding(pendingBinding)) { throw new Error('Invalid controller session pending binding.'); } if (activeBindingId !== undefined && !isBase64UrlBytes(activeBindingId, 32)) { throw new Error('Invalid controller session active binding.'); } if (bindingCleanup !== undefined && !isBindingReference(bindingCleanup)) { throw new Error('Invalid controller session binding cleanup.'); } if (detachedBinding !== undefined && !isBindingReference(detachedBinding)) { throw new Error('Invalid controller session detached binding.'); } if (deletion !== undefined && !isDeletionRecord(deletion)) { throw new Error('Invalid controller session deletion record.'); } if ( (pendingBinding && pendingBinding.attachedAt.getTime() < valueArg.identityCreatedAt.getTime()) || (bindingCleanup && bindingCleanup.detachedAt.getTime() < valueArg.identityCreatedAt.getTime()) || (detachedBinding && detachedBinding.detachedAt.getTime() < valueArg.identityCreatedAt.getTime()) || (deletion && ( deletion.startedAt.getTime() < valueArg.identityCreatedAt.getTime() || ( deletion.priorDetachedAt !== undefined && deletion.priorDetachedAt.getTime() > deletion.startedAt.getTime() ) )) ) throw new Error('Invalid controller session locator timestamp ordering.'); const noDeletion = deletion === undefined; switch (valueArg.state) { case 'initializing': if ( !pendingBinding || activeBindingId !== undefined || bindingCleanup !== undefined || detachedBinding !== undefined || !noDeletion ) throw new Error('Invalid initializing controller session locator.'); return; case 'binding': { const replacingAttached = activeBindingId !== undefined; if ( !pendingBinding || !noDeletion || ( replacingAttached ? !bindingCleanup || bindingCleanup.bindingId !== activeBindingId || detachedBinding !== undefined : bindingCleanup !== undefined || detachedBinding === undefined ) || pendingBinding.bindingId === activeBindingId ) throw new Error('Invalid binding controller session locator.'); return; } case 'attached': if ( activeBindingId === undefined || pendingBinding !== undefined || detachedBinding !== undefined || !noDeletion || bindingCleanup?.bindingId === activeBindingId ) throw new Error('Invalid attached controller session locator.'); return; case 'detaching': if ( activeBindingId === undefined || !bindingCleanup || bindingCleanup.bindingId !== activeBindingId || pendingBinding !== undefined || detachedBinding !== undefined || !noDeletion ) throw new Error('Invalid detaching controller session locator.'); return; case 'detached': if ( !detachedBinding || pendingBinding !== undefined || activeBindingId !== undefined || bindingCleanup !== undefined || !noDeletion ) throw new Error('Invalid detached controller session locator.'); return; case 'deleting': case 'completing': { const isCompleting = valueArg.state === 'completing'; if ( !deletion || (isCompleting !== (deletion.completedAt !== undefined)) || pendingBinding !== undefined || bindingCleanup !== undefined || ( deletion.priorState === 'attached' ? activeBindingId !== deletion.finalBindingId || detachedBinding !== undefined : activeBindingId !== undefined || !detachedBinding || detachedBinding.bindingId !== deletion.finalBindingId || detachedBinding.detachedAt.getTime() !== deletion.priorDetachedAt?.getTime() ) ) throw new Error(`Invalid ${valueArg.state} controller session locator.`); return; } case 'tombstoned': if ( !deletion?.completedAt || pendingBinding !== undefined || activeBindingId !== undefined || bindingCleanup !== undefined || detachedBinding !== undefined ) throw new Error('Invalid tombstoned controller session locator.'); } }; @plugins.smartdata.managed({ collectionName: 'agl_controller_session_identities' }) @plugins.smartdata.exactPersistence({ assertDocument: assertControllerSessionIdentityDocument, }) export class ControllerSessionIdentityModel extends plugins.smartdata.SmartDataDbDoc< ControllerSessionIdentityModel, IControllerSessionIdentityDocument > { declare static exact: plugins.smartdata.TExact; @plugins.smartdata.unI() public id!: string; @plugins.smartdata.svDb() public issuerId!: string; @plugins.smartdata.svDb() public sessionIdentityId!: string; @plugins.smartdata.svDb() public projectIdentityId!: string; @plugins.smartdata.svDb() public createdAt!: Date; @plugins.smartdata.svDb() public retiredAt?: Date; } @plugins.smartdata.managed({ collectionName: 'agl_controller_session_runtime_bindings' }) @plugins.smartdata.exactPersistence({ assertDocument: assertControllerSessionRuntimeBindingDocument, }) export class ControllerSessionRuntimeBindingModel extends plugins.smartdata.SmartDataDbDoc< ControllerSessionRuntimeBindingModel, IControllerSessionRuntimeBindingDocument > { declare static exact: plugins.smartdata.TExact; @plugins.smartdata.unI() public id!: string; @plugins.smartdata.svDb() public bindingId!: string; @plugins.smartdata.svDb() public issuerId!: string; @plugins.smartdata.svDb() public sessionIdentityId!: string; @plugins.smartdata.svDb() public projectIdentityId!: string; @plugins.smartdata.svDb() public runtimeId!: TControllerSessionId; @plugins.smartdata.svDb() public supervisorGeneration!: string; @plugins.smartdata.svDb() public providerSessionGeneration?: string; @plugins.smartdata.svDb() public attachedAt!: Date; @plugins.smartdata.svDb() public detachedAt?: Date; } @plugins.smartdata.compoundIndex({ name: 'controller_session_locator_scope_state', key: { issuerId: 1, projectIdentityId: 1, 'runtimeId.harnessId': 1, state: 1, id: 1, }, }) @plugins.smartdata.managed({ collectionName: 'agl_controller_session_locators' }) @plugins.smartdata.exactPersistence({ assertDocument: assertControllerSessionLocatorDocument, }) export class ControllerSessionLocatorModel extends plugins.smartdata.SmartDataDbDoc< ControllerSessionLocatorModel, IControllerSessionLocatorDocument > { declare static exact: plugins.smartdata.TExact; @plugins.smartdata.unI() public id!: string; @plugins.smartdata.svDb() public issuerId!: string; @plugins.smartdata.svDb() public sessionIdentityId!: string; @plugins.smartdata.svDb() public projectIdentityId!: string; @plugins.smartdata.svDb() public runtimeId!: TControllerSessionId; @plugins.smartdata.svDb() public providerSessionGeneration?: string; @plugins.smartdata.svDb() public identityCreatedAt!: Date; @plugins.smartdata.svDb() public state!: TControllerSessionLocatorState; @plugins.smartdata.svDb() public updatedAt!: Date; @plugins.smartdata.svDb() public pendingBinding?: IControllerSessionPendingBinding; @plugins.smartdata.svDb() public activeBindingId?: string; @plugins.smartdata.svDb() public bindingCleanup?: IControllerSessionBindingReference; @plugins.smartdata.svDb() public detachedBinding?: IControllerSessionBindingReference; @plugins.smartdata.svDb() public deletion?: IControllerSessionDeletionRecord; }