memeloop 0.2.8 → 0.2.9

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.
Files changed (36) hide show
  1. package/dist/{chunk-NVJCRIEK.js → chunk-34B7MUI6.js} +2 -2
  2. package/dist/{chunk-DACM5AMS.js → chunk-7W4FMKMO.js} +190 -56
  3. package/dist/chunk-7W4FMKMO.js.map +1 -0
  4. package/dist/{chunk-OD6U6VAR.js → chunk-GH5RDPLJ.js} +2 -2
  5. package/dist/{chunk-OD6U6VAR.js.map → chunk-GH5RDPLJ.js.map} +1 -1
  6. package/dist/device-network/cloudDeviceFetchClient.d.ts +9 -7
  7. package/dist/device-network/cloudDeviceFetchClient.d.ts.map +1 -1
  8. package/dist/device-network/deviceCloudConnectionCoordinator.d.ts +5 -5
  9. package/dist/device-network/deviceCloudConnectionCoordinator.d.ts.map +1 -1
  10. package/dist/device-network/deviceOrchestrationTransport.d.ts +7 -0
  11. package/dist/device-network/deviceOrchestrationTransport.d.ts.map +1 -1
  12. package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts +16 -8
  13. package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts.map +1 -1
  14. package/dist/device-network/types.d.ts +4 -2
  15. package/dist/device-network/types.d.ts.map +1 -1
  16. package/dist/device-network-portable.cjs +190 -55
  17. package/dist/device-network-portable.cjs.map +1 -1
  18. package/dist/device-network-portable.js +189 -55
  19. package/dist/device-network-portable.js.map +1 -1
  20. package/dist/device-network.cjs +190 -55
  21. package/dist/device-network.cjs.map +1 -1
  22. package/dist/device-network.js +4 -2
  23. package/dist/index.cjs +488 -180
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +302 -127
  26. package/dist/index.js.map +1 -1
  27. package/dist/loop-api.cjs +1 -1
  28. package/dist/loop-api.cjs.map +1 -1
  29. package/dist/loop-api.js +1 -1
  30. package/dist/mobile.cjs.map +1 -1
  31. package/dist/orchestration/externalOrchestrationController.d.ts.map +1 -1
  32. package/dist/orchestration/workloadExecutionController.d.ts.map +1 -1
  33. package/dist/plugin/loader.d.ts +1 -1
  34. package/package.json +2 -1
  35. package/dist/chunk-DACM5AMS.js.map +0 -1
  36. /package/dist/{chunk-NVJCRIEK.js.map → chunk-34B7MUI6.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sync/attachmentRpcCodec.ts","../src/device-network/libp2pSyncProtocol.ts","../src/sync/protocol.ts","../src/sync/chatSyncEngine.ts","../src/sync/peerNodeAdapter.ts","../src/device-network/deviceGrantMessages.ts","../src/device-network/cloudDeviceFetchClient.ts","../src/device-network/deviceCloudConnectionCoordinator.ts","../src/device-network/jsonFrame.ts","../src/device-network/deviceOrchestrationTransport.ts","../src/device-network/libp2pDeviceSyncTransport.ts","../src/device-network/libp2pRpcProtocol.ts","../src/device-network/localTrustDeviceAuthorizer.ts","../src/device-network/types.ts","../src/device-network/pairingInvite.ts","../src/device-network/reconcileCloudDeviceDirectory.ts","../src/device-network/standardDeviceCloudConnectionAdapter.ts"],"sourcesContent":["/**\n * 将节点 RPC `memeloop.storage.getAttachmentBlob` 的返回值解码为同步引擎可用的 BLOB。\n */\n\nexport function decodeAttachmentBlobRpc(\n result: unknown,\n): { data: Uint8Array; filename: string; mimeType: string; size: number } | null {\n if (result == null || typeof result !== 'object') return null;\n const r = result as {\n found?: boolean;\n error?: string;\n dataBase64?: string;\n filename?: string;\n mimeType?: string;\n size?: number;\n };\n if (r.error || !r.found || typeof r.dataBase64 !== 'string') return null;\n let data: Uint8Array;\n try {\n const binary = atob(r.dataBase64);\n if (!binary.length) return null;\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n return null;\n }\n return {\n data,\n filename: typeof r.filename === 'string' ? r.filename : 'attachment',\n mimeType: typeof r.mimeType === 'string' ? r.mimeType : 'application/octet-stream',\n size: typeof r.size === 'number' && r.size > 0 ? r.size : data.byteLength,\n };\n}\n","import type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_SYNC_REQUEST_TYPE = 'memeloop-sync-request-v2';\nexport const LIBP2P_SYNC_RESPONSE_TYPE = 'memeloop-sync-response-v2';\n\nexport type Libp2pSyncMethod =\n | 'exchangeVersionFrontierPage'\n | 'pullMissingEvents'\n | 'pullAttachmentChunk'\n | 'pushEvents'\n | 'pushAttachmentChunk';\n\nexport interface Libp2pSyncRequest {\n type: typeof LIBP2P_SYNC_REQUEST_TYPE;\n id: string;\n method: Libp2pSyncMethod;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pSyncResponse =\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nexport const MAX_SYNC_ATTACHMENT_CHUNK_BYTES = 3 * 1024 * 1024;\nexport const MAX_SYNC_ATTACHMENT_BYTES = 64 * 1024 * 1024;\n\nexport interface AttachmentChunkWire {\n dataBase64Url: string;\n byteLength: number;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nconst syncMethods = new Set<Libp2pSyncMethod>([\n 'exchangeVersionFrontierPage',\n 'pullMissingEvents',\n 'pullAttachmentChunk',\n 'pushEvents',\n 'pushAttachmentChunk',\n]);\n\nexport function isLibp2pSyncRequest(value: unknown): value is Libp2pSyncRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_SYNC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= 128 &&\n typeof record.method === 'string' &&\n syncMethods.has(record.method as Libp2pSyncMethod) &&\n 'params' in record\n );\n}\n\nexport function isLibp2pSyncResponse(value: unknown): value is Libp2pSyncResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_SYNC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > 128 || typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) {\n return false;\n }\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n /^[a-z][a-z\\d_]{0,63}$/u.test(error.code);\n}\n\nfunction isAttachmentChunkWire(value: unknown): value is AttachmentChunkWire {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, [\n 'dataBase64Url',\n 'byteLength',\n 'offset',\n 'totalSize',\n 'done',\n 'filename',\n 'mimeType',\n ]) &&\n typeof record.dataBase64Url === 'string' &&\n typeof record.byteLength === 'number' &&\n typeof record.offset === 'number' &&\n typeof record.totalSize === 'number' &&\n typeof record.done === 'boolean' &&\n typeof record.filename === 'string' &&\n typeof record.mimeType === 'string'\n );\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n\nexport async function attachmentChunkFromWire(value: unknown): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n> {\n if (value === null) return null;\n if (\n !isAttachmentChunkWire(value) ||\n !Number.isSafeInteger(value.byteLength) || value.byteLength < 0 ||\n value.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.byteLength > value.totalSize ||\n value.done !== (value.offset + value.byteLength === value.totalSize) ||\n (!value.done && value.byteLength === 0) ||\n value.dataBase64Url.length > Math.ceil(MAX_SYNC_ATTACHMENT_CHUNK_BYTES / 3) * 4 + 4 ||\n value.filename.length > 512 || value.mimeType.length > 256\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let data: Uint8Array;\n try {\n const base64 = value.dataBase64Url.replace(/-/g, '+').replace(/_/g, '/');\n const paddedBase64 = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');\n const binary = atob(paddedBase64);\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n throw new Error('invalid_sync_attachment_chunk');\n }\n if (data.byteLength !== value.byteLength) throw new Error('invalid_sync_attachment_chunk');\n return {\n data,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n\nexport function attachmentChunkToWire(value: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}): AttachmentChunkWire {\n if (\n value.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.data.byteLength > value.totalSize ||\n value.done !== (value.offset + value.data.byteLength === value.totalSize) ||\n (!value.done && value.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let binary = '';\n for (let offset = 0; offset < value.data.length; offset += 32_768) {\n binary += String.fromCharCode(...value.data.subarray(offset, offset + 32_768));\n }\n return {\n dataBase64Url: btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, ''),\n byteLength: value.data.byteLength,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\n\n/** Highest contiguous originSequence for each conversation+origin pair. */\nexport type VersionVector = Record<string, number>;\n\n/**\n * Version-vector entries are scoped to one conversation and one message\n * origin. Lamport clocks are allocated per conversation, so a node-wide key\n * would incorrectly hide a new short conversation after a long one was\n * acknowledged.\n */\nexport function versionVectorKey(conversationId: string, originNodeId: string): string {\n return JSON.stringify([conversationId, originNodeId]);\n}\n\nexport function parseVersionVectorKey(\n key: string,\n): { conversationId: string; originNodeId: string } | undefined {\n try {\n const value: unknown = JSON.parse(key);\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n typeof value[0] !== 'string' ||\n value[0].length === 0 ||\n typeof value[1] !== 'string' ||\n value[1].length === 0\n ) return undefined;\n return { conversationId: value[0], originNodeId: value[1] };\n } catch {\n return undefined;\n }\n}\n\nexport interface ConversationMeta {\n conversationId: string;\n title: string;\n lastMessagePreview: string;\n lastMessageTimestamp: number;\n messageCount: number;\n originNodeId: string;\n /** Lamport clock of the origin metadata event; never substitute messageCount. */\n originClock: number;\n definitionId: string;\n instanceDelta?: Record<string, unknown>;\n isUserInitiated: boolean;\n sourceChannel?: {\n channelId: string;\n platform: string;\n imUserId: string;\n };\n}\n\nexport function isConversationMeta(value: unknown): value is ConversationMeta {\n if (value === null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.conversationId === 'string' &&\n typeof o.title === 'string' &&\n typeof o.originNodeId === 'string' &&\n typeof o.originClock === 'number' &&\n typeof o.definitionId === 'string' &&\n typeof o.messageCount === 'number' &&\n typeof o.lastMessageTimestamp === 'number' &&\n typeof o.isUserInitiated === 'boolean'\n );\n}\n\nexport interface VersionRange {\n conversationId: string;\n originNodeId: string;\n fromExclusive: number;\n toInclusive: number;\n}\n\nexport function computeMissingVersionRanges(\n currentVersion: VersionVector,\n availableVersion: VersionVector,\n): VersionRange[] {\n const ranges: VersionRange[] = [];\n for (const [key, availableClock] of Object.entries(availableVersion)) {\n const identity = parseVersionVectorKey(key);\n if (!identity) continue;\n const currentClock = currentVersion[key] ?? 0;\n if (availableClock > currentClock) {\n ranges.push({ ...identity, fromExclusive: currentClock, toInclusive: availableClock });\n }\n }\n return ranges.sort((left, right) =>\n compareCodeUnits(left.conversationId, right.conversationId) ||\n compareCodeUnits(left.originNodeId, right.originNodeId)\n );\n}\n\nexport function versionVectorCoversRange(\n vector: VersionVector,\n range: VersionRange,\n): boolean {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n return (vector[key] ?? 0) >= range.toInclusive;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/** Bounded, forward-only raw event page used by peer anti-entropy. */\nexport interface ConversationEventSyncPage {\n items: ConversationEvent[];\n /** Cursor of the final returned matching event. */\n nextCursor?: ConversationEventCursor;\n}\n","import type { AttachmentReference, ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport {\n assertCanonicalConversationEvent,\n assertCanonicalConversationEvents,\n canonicalConversationEventBytes,\n conversationEventAttachmentReferences,\n} from '../conversation/index.js';\nimport { MAX_SYNC_ATTACHMENT_BYTES, MAX_SYNC_ATTACHMENT_CHUNK_BYTES } from '../device-network/libp2pSyncProtocol.js';\nimport type { ConversationEventPage as StoredConversationEventPage, MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport { type ConversationEventSyncPage, type VersionRange, versionVectorKey } from './protocol.js';\n\nimport type { IAgentStorage } from '../types.js';\nimport { assertAgentUserMessageWithinLimits, assertConversationMessageWithinPagingLimits } from '../userMessageAdmission.js';\n\nconst EVENT_PUSH_PAGE_MAX_BYTES = 12 * 1024 * 1024;\nconst EVENT_PAGE_MAX_ITEMS = 128;\nconst FRONTIER_PAGE_MAX_ITEMS = 128;\nconst MAX_SYNC_ID_LENGTH = 512;\nconst MAX_SYNC_CONVERSATION_SCOPE = 256;\nconst MAX_SYNC_WORK_PAGES_PER_PEER_PASS = 64;\n/**\n * Frontier discovery is cheap, bounded metadata work rather than body\n * transfer. Keeping a separate ceiling lets a restarted engine rebuild its\n * position from durable frontiers without weakening the 64 transfer-page\n * limit. 2,048 pages cover 262,144 distinct origin frontiers per pass.\n */\nconst MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS = 2_048;\nconst MAX_SYNC_EVENTS_PER_PEER_PASS = 4_096;\nconst MAX_SYNC_BYTES_PER_PEER_PASS = 80 * 1024 * 1024;\nconst MAX_SYNC_PEERS_PER_PASS = 64;\nconst utf8Encoder = new TextEncoder();\n\ninterface PeerSyncContinuation {\n localAfter?: MessageVersionFrontierCursor;\n remoteAfter?: MessageVersionFrontierCursor;\n localDone: boolean;\n remoteDone: boolean;\n}\n\ninterface PeerSyncWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n global: SyncPassWorkBudget;\n}\n\ninterface SyncPassWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n limits: ChatSyncPassLimits;\n}\n\nexport interface SyncIoOptions {\n signal?: AbortSignal;\n}\n\nexport interface ChatSyncPassProgress {\n peers: number;\n /** Frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages; hard-limited independently of discovery. */\n pages: number;\n events: number;\n bytes: number;\n}\n\nexport interface ChatSyncPassResult {\n complete: boolean;\n progress: ChatSyncPassProgress;\n /** Present only when another bounded pass can make forward progress. */\n continuation?: {\n reason: 'work-budget';\n pendingPeerIds: string[];\n };\n}\n\nexport interface ChatSyncPassLimits {\n maxPeers: number;\n maxFrontierPages: number;\n maxPages: number;\n maxEvents: number;\n maxBytes: number;\n}\n\nexport interface ChatSyncPeer {\n nodeId: string;\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n >;\n pushEvents?(events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n chunk: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n },\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport interface ChatSyncEngineOptions {\n nodeId: string;\n storage: IAgentStorage;\n peers: () => ChatSyncPeer[];\n /** Surface body-transfer failures to an interactive caller instead of relying on the next pass. */\n failOnMessageSyncError?: boolean;\n signal?: AbortSignal;\n /** Restrict this pass to these conversations; undefined means the full store. */\n conversationIds?: readonly string[];\n /** Optional lower ceilings for one foreground pass; hard protocol ceilings cannot be raised. */\n passLimits?: Partial<ChatSyncPassLimits>;\n}\n\n/** Bidirectional, raw-event anti-entropy for conversation state. */\nexport class ChatSyncEngine {\n private readonly nodeId: string;\n private readonly storage: IAgentStorage;\n private readonly getPeers: () => ChatSyncPeer[];\n private readonly failOnMessageSyncError: boolean;\n private readonly defaultSignal?: AbortSignal;\n private activeSignal?: AbortSignal;\n private readonly conversationIds?: string[];\n private readonly passLimits: ChatSyncPassLimits;\n private readonly continuations = new Map<string, PeerSyncContinuation>();\n private readonly pendingAttachmentPushes = new Map<string, Set<string>>();\n private nextPeerAfter?: string;\n private inFlightSync?: Promise<ChatSyncPassResult>;\n\n constructor(options: ChatSyncEngineOptions) {\n if (!isValidSyncIdentifier(options.nodeId)) throw new Error('invalid_sync_node_id');\n this.nodeId = options.nodeId;\n this.storage = options.storage;\n this.getPeers = options.peers;\n this.failOnMessageSyncError = options.failOnMessageSyncError ?? false;\n this.defaultSignal = options.signal;\n this.passLimits = resolvePassLimits(options.passLimits);\n this.conversationIds = options.conversationIds === undefined\n ? undefined\n : [...new Set(options.conversationIds)].sort(compareCodeUnits);\n if (\n this.conversationIds !== undefined &&\n (this.conversationIds.length > MAX_SYNC_CONVERSATION_SCOPE ||\n this.conversationIds.some(conversationId => !isValidSyncIdentifier(conversationId)))\n ) {\n throw new Error('invalid_sync_conversation_scope');\n }\n }\n\n public syncOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n if (this.inFlightSync) return this.inFlightSync;\n this.activeSignal = options.signal ?? this.defaultSignal;\n const running = this.runSyncOnce();\n this.inFlightSync = running;\n const release = (): void => {\n if (this.inFlightSync === running) {\n this.inFlightSync = undefined;\n this.activeSignal = undefined;\n }\n };\n void running.then(release, release);\n return running;\n }\n\n private async runSyncOnce(): Promise<ChatSyncPassResult> {\n this.throwIfAborted();\n const peers = this.collectPeers();\n const activePeerIds = new Set(peers.map(peer => peer.nodeId));\n this.garbageCollectPeerState(activePeerIds);\n if (this.conversationIds?.length === 0) {\n return {\n complete: true,\n progress: { peers: 0, frontierPages: 0, pages: 0, events: 0, bytes: 0 },\n };\n }\n if (!this.storage.getEventVersionFrontierPage || !this.storage.getEventVersionFrontiersForKeys) {\n throw new Error('sync_event_frontier_store_not_configured');\n }\n const orderedPeers = rotatePeers(peers, this.nextPeerAfter);\n const globalBudget = createSyncPassWorkBudget(this.passLimits);\n const progress: ChatSyncPassProgress = {\n peers: 0,\n frontierPages: 0,\n pages: 0,\n events: 0,\n bytes: 0,\n };\n const pendingPeerIds: string[] = [];\n let complete = true;\n let processedPeers = 0;\n const scheduledPeers = orderedPeers.slice(0, this.passLimits.maxPeers);\n for (const peer of scheduledPeers) {\n if (globalBudget.frontierPages >= globalBudget.limits.maxFrontierPages) {\n globalBudget.exhausted = true;\n complete = false;\n break;\n }\n const budget = createPeerSyncWorkBudget(globalBudget);\n try {\n const peerComplete = await this.syncPeerFrontierPages(peer, scheduledPeers, budget);\n if (!peerComplete) {\n complete = false;\n if (budget.exhausted) {\n pendingPeerIds.push(peer.nodeId);\n } else if (this.failOnMessageSyncError) {\n throw new Error(`event_sync_incomplete:${peer.nodeId}`);\n }\n }\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n complete = false;\n } finally {\n processedPeers += 1;\n this.nextPeerAfter = peer.nodeId;\n progress.peers += 1;\n progress.frontierPages += budget.frontierPages;\n progress.pages += budget.pages;\n progress.events += budget.events;\n progress.bytes += budget.bytes;\n }\n if (globalBudget.exhausted) break;\n }\n const skippedPeers = orderedPeers.slice(processedPeers);\n if (skippedPeers.length > 0) {\n complete = false;\n for (const peer of skippedPeers.slice(0, this.passLimits.maxPeers)) {\n pendingPeerIds.push(peer.nodeId);\n }\n } else if (complete) {\n this.nextPeerAfter = undefined;\n }\n const boundedPendingPeerIds = [...new Set(pendingPeerIds)].slice(0, this.passLimits.maxPeers);\n return {\n complete,\n progress,\n ...(boundedPendingPeerIds.length > 0\n ? { continuation: { reason: 'work-budget' as const, pendingPeerIds: boundedPendingPeerIds } }\n : {}),\n };\n }\n\n public antiEntropyOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n return this.syncOnce(options);\n }\n\n private async syncPeerFrontierPages(\n peer: ChatSyncPeer,\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const continuation = this.continuations.get(peer.nodeId);\n let localAfter = continuation?.localAfter;\n let remoteAfter = continuation?.remoteAfter;\n let localDone = continuation?.localDone ?? false;\n let remoteDone = continuation?.remoteDone ?? false;\n do {\n this.throwIfAborted();\n if (!consumeFrontierScanPage(budget)) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n const localPage: MessageVersionFrontierPage = localDone\n ? { items: [] }\n : await this.storage.getEventVersionFrontierPage({\n limit: FRONTIER_PAGE_MAX_ITEMS,\n ...(localAfter ? { after: localAfter } : {}),\n ...(this.conversationIds ? { conversationIds: this.conversationIds } : {}),\n signal: this.activeSignal,\n });\n this.assertValidFrontierPage(localPage, localAfter, 'storage');\n const exchange = await peer.exchangeVersionFrontierPage(\n localPage.items,\n remoteAfter,\n !remoteDone,\n this.conversationIds,\n { signal: this.activeSignal },\n );\n this.assertValidFrontierPage(exchange.remotePage, remoteAfter, peer.nodeId, remoteDone);\n if (\n !isValidVersionRanges(exchange.missingForRemote) ||\n !rangesMatchOfferedFrontiers(exchange.missingForRemote, localPage.items)\n ) {\n throw new Error(`inconsistent_sync_exchange:${peer.nodeId}`);\n }\n this.assertScopedRanges(exchange.missingForRemote, peer.nodeId);\n const pushComplete = await this.pushEventsToPeer(peer, exchange.missingForRemote, budget);\n if (!pushComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n const localForRemote = await this.storage.getEventVersionFrontiersForKeys(\n exchange.remotePage.items.map(frontier => ({\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n })),\n { signal: this.activeSignal },\n );\n const localByKey = new Map(localForRemote.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n const missingForLocal = exchange.remotePage.items.flatMap(frontier => {\n const current = localByKey.get(versionVectorKey(\n frontier.conversationId,\n frontier.originNodeId,\n )) ?? 0;\n return frontier.maxContiguousOriginSequence > current\n ? [{\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n fromExclusive: current,\n toInclusive: frontier.maxContiguousOriginSequence,\n }]\n : [];\n });\n this.assertScopedRanges(missingForLocal, peer.nodeId);\n const pullComplete = await this.pullEventsFromPeer(\n peer,\n missingForLocal,\n attachmentPeers,\n budget,\n );\n if (!pullComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n localAfter = localPage.nextCursor;\n remoteAfter = exchange.remotePage.nextCursor;\n localDone = localDone || localAfter === undefined;\n remoteDone = remoteDone || remoteAfter === undefined;\n } while (!localDone || !remoteDone);\n this.continuations.delete(peer.nodeId);\n this.pendingAttachmentPushes.delete(peer.nodeId);\n return true;\n }\n\n private async pushEventsToPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pushEvents || !this.storage.getConversationEventPage) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n const coverage = createCoverageProgress(ranges);\n const pushedHashes = new Set<string>();\n const pendingPushes = this.pendingAttachmentPushes.get(peer.nodeId) ?? new Set<string>();\n this.pendingAttachmentPushes.set(peer.nodeId, pendingPushes);\n let batch: ConversationEvent[] = [];\n const flush = async (): Promise<void> => {\n if (batch.length === 0) return;\n const flushed = batch;\n await peer.pushEvents!(flushed, { signal: this.activeSignal });\n for (const event of flushed) {\n for (const attachment of conversationEventAttachmentReferences(event)) {\n pendingPushes.delete(`${event.conversationId}\\u0000${attachment.contentHash}`);\n }\n }\n batch = [];\n };\n\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) {\n await flush();\n return false;\n }\n const page = await this.storage.getConversationEventPage(conversationId, {\n limit: EVENT_PAGE_MAX_ITEMS,\n after: cursor,\n direction: 'forward',\n signal: this.activeSignal,\n ranges: conversationRanges.map(range => ({\n originNodeId: range.originNodeId,\n fromExclusive: range.fromExclusive,\n toInclusive: range.toInclusive,\n })),\n });\n this.assertValidStoredEventPage(page, conversationId, cursor);\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) {\n await flush();\n return false;\n }\n const range = conversationRanges.find(candidate => eventInRange(event, candidate));\n if (!range) continue;\n recordObservedSequence(coverage, event);\n for (const attachment of conversationEventAttachmentReferences(event)) {\n const attachmentKey = `${conversationId}\\u0000${attachment.contentHash}`;\n if (pushedHashes.has(attachmentKey) || pendingPushes.has(attachmentKey)) continue;\n if (!await this.pushAttachmentToPeer(peer, conversationId, attachment, budget)) {\n await flush();\n return false;\n }\n pushedHashes.add(attachmentKey);\n pendingPushes.add(attachmentKey);\n }\n\n const candidate = [...batch, event];\n if (candidate.length > EVENT_PAGE_MAX_ITEMS || jsonByteLength(candidate) > EVENT_PUSH_PAGE_MAX_BYTES) {\n if (batch.length === 0) throw new Error('sync_event_too_large');\n await flush();\n batch = [event];\n if (jsonByteLength(batch) > EVENT_PUSH_PAGE_MAX_BYTES) {\n throw new Error('sync_event_too_large');\n }\n } else {\n batch = candidate;\n }\n }\n cursor = page.hasMoreAfter ? page.endCursor : undefined;\n } while (cursor !== undefined);\n }\n await flush();\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async pullEventsFromPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pullMissingEvents || !this.storage.insertEventsIfAbsent) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n let coverage = createCoverageProgress(ranges);\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) return false;\n const page = await peer.pullMissingEvents(\n conversationId,\n conversationRanges,\n cursor,\n { signal: this.activeSignal },\n );\n this.assertValidEventPage(page, conversationId, conversationRanges, cursor, peer.nodeId);\n assertCanonicalConversationEvents(page.items);\n const candidateCoverage = cloneCoverageProgress(coverage);\n const acceptedEvents: ConversationEvent[] = [];\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) break;\n recordObservedSequence(candidateCoverage, event);\n acceptedEvents.push(event);\n }\n // BLOBs land before their referencing event. A failed or corrupt BLOB\n // therefore cannot leak into the durable frontier on a later retry.\n if (!await this.ensureAttachmentsFromEvents(acceptedEvents, attachmentPeers, budget)) {\n return false;\n }\n if (acceptedEvents.length > 0) {\n await this.storage.insertEventsIfAbsent(acceptedEvents);\n }\n coverage = candidateCoverage;\n if (acceptedEvents.length !== page.items.length) return false;\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n }\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async ensureAttachmentsFromEvents(\n events: ConversationEvent[],\n peers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const references = new Map<string, { conversationId: string; reference: AttachmentReference }>();\n for (const event of events) {\n for (const reference of conversationEventAttachmentReferences(event)) {\n references.set(`${event.conversationId}\\u0000${reference.contentHash}`, {\n conversationId: event.conversationId,\n reference,\n });\n }\n }\n for (const { conversationId, reference } of references.values()) {\n if (await this.hasLocalAttachment(reference)) continue;\n if (\n !this.storage.stageAttachmentChunk || !this.storage.commitStagedAttachment ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES\n ) return false;\n const capablePeers = peers.filter(peer => peer.pullAttachmentChunk !== undefined);\n if (capablePeers.length === 0) return false;\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let fetched = false;\n for (const peer of capablePeers) {\n const pull = peer.pullAttachmentChunk?.bind(peer);\n if (!pull) continue;\n try {\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const chunk = await pull(\n conversationId,\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n if (\n !chunk || chunk.offset !== offset || chunk.totalSize !== reference.size ||\n chunk.filename !== reference.filename || chunk.mimeType !== reference.mimeType ||\n chunk.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n chunk.done !== (offset + chunk.data.byteLength === reference.size) ||\n (!chunk.done && chunk.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n const nextOffset = await this.storage.stageAttachmentChunk(\n reference,\n offset,\n chunk.data,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !Number.isSafeInteger(nextOffset) || nextOffset !== offset + chunk.data.byteLength ||\n nextOffset > reference.size\n ) {\n throw new Error('sync_attachment_cursor_mismatch');\n }\n offset = nextOffset;\n if (offset === reference.size) {\n await this.storage.commitStagedAttachment(\n reference.contentHash,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n fetched = await this.hasLocalAttachment(reference);\n break;\n }\n }\n } catch {\n this.throwIfAborted();\n // Another authorized peer may still have the content-addressed body.\n }\n if (fetched) break;\n }\n if (!fetched) return false;\n }\n return true;\n }\n\n private async hasLocalAttachment(reference: AttachmentReference): Promise<boolean> {\n const stored = await this.storage.getAttachment(reference.contentHash);\n return stored !== null && stored.size === reference.size && stored.filename === reference.filename &&\n stored.mimeType === reference.mimeType && this.storage.verifyAttachment !== undefined &&\n await this.storage.verifyAttachment(reference.contentHash, { signal: this.activeSignal });\n }\n\n private async pushAttachmentToPeer(\n peer: ChatSyncPeer,\n conversationId: string,\n reference: AttachmentReference,\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (\n !peer.pushAttachmentChunk || !this.storage.readAttachmentRange ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES || !await this.hasLocalAttachment(reference)\n ) {\n return false;\n }\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const data = await this.storage.readAttachmentRange(\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !data || data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n offset + data.byteLength > reference.size ||\n (data.byteLength === 0 && offset !== reference.size)\n ) return false;\n const done = offset + data.byteLength === reference.size;\n await peer.pushAttachmentChunk(\n conversationId,\n reference.contentHash,\n {\n data,\n offset,\n totalSize: reference.size,\n done,\n filename: reference.filename,\n mimeType: reference.mimeType,\n },\n { signal: this.activeSignal },\n );\n offset += data.byteLength;\n if (done) return true;\n }\n return false;\n }\n\n private assertValidEventPage(\n page: ConversationEventSyncPage,\n conversationId: string,\n ranges: VersionRange[],\n previousCursor: ConversationEventCursor | undefined,\n peerId: string,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS\n ) {\n throw new Error(`invalid_event_sync_page:${peerId}`);\n }\n assertBoundedCanonicalEventBytes(page.items, `invalid_event_sync_page:${peerId}`);\n let lastCursor = previousCursor;\n for (const event of page.items) {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n } catch {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n if (\n event.conversationId !== conversationId ||\n !ranges.some(range => eventInRange(event, range))\n ) {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error(`invalid_event_sync_order:${peerId}`);\n }\n lastCursor = currentCursor;\n }\n if (page.nextCursor === undefined) return;\n if (!isConversationEventCursor(page.nextCursor)) throw new Error(`invalid_event_sync_cursor:${peerId}`);\n if (previousCursor && compareEventCursor(page.nextCursor, previousCursor) <= 0) {\n throw new Error(`event_sync_cursor_did_not_advance:${peerId}`);\n }\n const lastItem = page.items.at(-1);\n if (!lastItem || compareEventCursor(page.nextCursor, eventCursor(lastItem)) !== 0) {\n throw new Error(`event_sync_cursor_not_last_item:${peerId}`);\n }\n }\n\n private assertValidStoredEventPage(\n page: StoredConversationEventPage,\n conversationId: string,\n previousCursor: ConversationEventCursor | undefined,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, [\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]) || !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS ||\n typeof page.hasMoreBefore !== 'boolean' || typeof page.hasMoreAfter !== 'boolean' ||\n page.items.some(event => {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n return event.conversationId !== conversationId;\n } catch {\n return true;\n }\n })\n ) {\n throw new Error('invalid_storage_event_page');\n }\n assertBoundedCanonicalEventBytes(page.items, 'invalid_storage_event_page');\n let lastCursor = previousCursor;\n for (const event of page.items) {\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error('invalid_storage_event_order');\n }\n lastCursor = currentCursor;\n }\n if (!page.hasMoreAfter) return;\n if (\n page.items.length === 0 || !page.endCursor || !isConversationEventCursor(page.endCursor) ||\n previousCursor && compareEventCursor(page.endCursor, previousCursor) <= 0 ||\n lastCursor && compareEventCursor(page.endCursor, lastCursor) !== 0\n ) {\n throw new Error('storage_event_cursor_did_not_advance');\n }\n }\n\n public getStorage(): IAgentStorage {\n return this.storage;\n }\n\n private assertScopedRanges(ranges: VersionRange[], peerId: string): void {\n if (this.conversationIds === undefined) return;\n const allowed = new Set(this.conversationIds);\n if (ranges.some(range => !allowed.has(range.conversationId))) {\n throw new Error(`sync_peer_scope_escalation:${peerId}`);\n }\n }\n\n private assertValidFrontierPage(\n page: MessageVersionFrontierPage,\n previous: MessageVersionFrontierCursor | undefined,\n source: string,\n expectedEmpty = false,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > FRONTIER_PAGE_MAX_ITEMS ||\n expectedEmpty && (page.items.length > 0 || page.nextCursor !== undefined)\n ) {\n throw new Error(`invalid_sync_frontier_page:${source}`);\n }\n let last = previous;\n for (const frontier of page.items) {\n if (!isValidFrontier(frontier)) throw new Error(`invalid_sync_frontier:${source}`);\n const cursor = { conversationId: frontier.conversationId, originNodeId: frontier.originNodeId };\n if (last && compareFrontierCursor(cursor, last) <= 0) {\n throw new Error(`invalid_sync_frontier_order:${source}`);\n }\n last = cursor;\n }\n if (page.nextCursor === undefined) return;\n if (\n !last || !isValidFrontierCursor(page.nextCursor) ||\n compareFrontierCursor(page.nextCursor, last) !== 0 ||\n previous && compareFrontierCursor(page.nextCursor, previous) <= 0\n ) {\n throw new Error(`sync_frontier_cursor_did_not_advance:${source}`);\n }\n }\n\n private saveContinuation(peerId: string, continuation: PeerSyncContinuation): void {\n this.continuations.set(peerId, {\n localDone: continuation.localDone,\n remoteDone: continuation.remoteDone,\n ...(continuation.localAfter ? { localAfter: { ...continuation.localAfter } } : {}),\n ...(continuation.remoteAfter ? { remoteAfter: { ...continuation.remoteAfter } } : {}),\n });\n }\n\n private collectPeers(): ChatSyncPeer[] {\n const unique = new Map<string, ChatSyncPeer>();\n for (const peer of this.getPeers()) {\n if (!isValidSyncIdentifier(peer.nodeId)) throw new Error('invalid_sync_peer_id');\n if (peer.nodeId === this.nodeId || unique.has(peer.nodeId)) continue;\n unique.set(peer.nodeId, peer);\n }\n return [...unique.values()].sort((left, right) => compareCodeUnits(left.nodeId, right.nodeId));\n }\n\n private garbageCollectPeerState(activePeerIds: ReadonlySet<string>): void {\n for (const peerId of this.continuations.keys()) {\n if (!activePeerIds.has(peerId)) this.continuations.delete(peerId);\n }\n for (const peerId of this.pendingAttachmentPushes.keys()) {\n if (!activePeerIds.has(peerId)) this.pendingAttachmentPushes.delete(peerId);\n }\n if (this.nextPeerAfter !== undefined && !activePeerIds.has(this.nextPeerAfter)) {\n this.nextPeerAfter = undefined;\n }\n }\n\n private throwIfAborted(): void {\n if (!this.activeSignal?.aborted) return;\n throw this.activeSignal.reason instanceof Error\n ? this.activeSignal.reason\n : new Error('chat_sync_aborted');\n }\n}\n\nfunction assertAdmittedConversationMessageEvent(event: ConversationEvent): void {\n if (event.kind !== 'message') return;\n const message = {\n ...event.message,\n conversationId: event.conversationId,\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n lamportClock: event.lamportClock,\n timestamp: event.timestamp,\n };\n if (event.message.role === 'user') assertAgentUserMessageWithinLimits(message);\n else assertConversationMessageWithinPagingLimits(message);\n}\n\nfunction isValidFrontier(value: unknown): value is MessageVersionFrontier {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'conversationId',\n 'originNodeId',\n 'maxContiguousOriginSequence',\n ])\n ) return false;\n const frontier = value as Partial<MessageVersionFrontier>;\n return isValidSyncIdentifier(frontier.conversationId) &&\n isValidSyncIdentifier(frontier.originNodeId) &&\n typeof frontier.maxContiguousOriginSequence === 'number' &&\n Number.isSafeInteger(frontier.maxContiguousOriginSequence) &&\n frontier.maxContiguousOriginSequence > 0;\n}\n\nfunction isValidVersionRanges(value: unknown): value is VersionRange[] {\n if (!Array.isArray(value) || value.length > FRONTIER_PAGE_MAX_ITEMS) return false;\n const identities = new Set<string>();\n for (const item of value) {\n if (\n !isPlainRecord(item) || !hasOnlyKeys(item, [\n 'conversationId',\n 'originNodeId',\n 'fromExclusive',\n 'toInclusive',\n ])\n ) return false;\n const range = item as Partial<VersionRange>;\n if (\n !isValidSyncIdentifier(range.conversationId) ||\n !isValidSyncIdentifier(range.originNodeId) ||\n typeof range.fromExclusive !== 'number' || !Number.isSafeInteger(range.fromExclusive) ||\n range.fromExclusive < 0 || typeof range.toInclusive !== 'number' ||\n !Number.isSafeInteger(range.toInclusive) || range.toInclusive <= range.fromExclusive\n ) return false;\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (identities.has(key)) return false;\n identities.add(key);\n }\n return true;\n}\n\nfunction rangesMatchOfferedFrontiers(\n ranges: VersionRange[],\n frontiers: MessageVersionFrontier[],\n): boolean {\n const offered = new Map(frontiers.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n return ranges.every(range => offered.get(versionVectorKey(range.conversationId, range.originNodeId)) === range.toInclusive);\n}\n\nfunction isValidFrontierCursor(value: unknown): value is MessageVersionFrontierCursor {\n if (!isPlainRecord(value) || !hasOnlyKeys(value, ['conversationId', 'originNodeId'])) return false;\n const cursor = value as Partial<MessageVersionFrontierCursor>;\n return isValidSyncIdentifier(cursor.conversationId) &&\n isValidSyncIdentifier(cursor.originNodeId);\n}\n\nfunction compareFrontierCursor(\n left: MessageVersionFrontierCursor,\n right: MessageVersionFrontierCursor,\n): number {\n return compareUtf8Bytes(left.conversationId, right.conversationId) ||\n compareUtf8Bytes(left.originNodeId, right.originNodeId);\n}\n\nfunction resolvePassLimits(input: Partial<ChatSyncPassLimits> | undefined): ChatSyncPassLimits {\n const limits: ChatSyncPassLimits = {\n maxPeers: input?.maxPeers ?? MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: input?.maxFrontierPages ?? MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: input?.maxPages ?? MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: input?.maxEvents ?? MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: input?.maxBytes ?? MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n const hardLimits: ChatSyncPassLimits = {\n maxPeers: MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n for (const key of Object.keys(limits) as Array<keyof ChatSyncPassLimits>) {\n if (!Number.isSafeInteger(limits[key]) || limits[key] <= 0 || limits[key] > hardLimits[key]) {\n throw new Error(`invalid_sync_pass_limit:${key}`);\n }\n }\n return limits;\n}\n\nfunction createSyncPassWorkBudget(limits: ChatSyncPassLimits): SyncPassWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, limits };\n}\n\nfunction createPeerSyncWorkBudget(global: SyncPassWorkBudget): PeerSyncWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, global };\n}\n\nfunction consumeFrontierScanPage(budget: PeerSyncWorkBudget): boolean {\n if (\n budget.frontierPages + 1 > MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS ||\n budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages\n ) {\n budget.exhausted = true;\n if (budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages) {\n budget.global.exhausted = true;\n }\n return false;\n }\n budget.frontierPages += 1;\n budget.global.frontierPages += 1;\n return true;\n}\n\nfunction consumeWorkPages(budget: PeerSyncWorkBudget, count: number): boolean {\n if (\n budget.pages + count > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.global.pages + count > budget.global.limits.maxPages\n ) {\n budget.exhausted = true;\n if (budget.global.pages + count > budget.global.limits.maxPages) budget.global.exhausted = true;\n return false;\n }\n budget.pages += count;\n budget.global.pages += count;\n return true;\n}\n\nfunction consumeWorkEvent(budget: PeerSyncWorkBudget, event: ConversationEvent): boolean {\n const bytes = canonicalConversationEventBytes(event).byteLength;\n if (\n budget.events + 1 > MAX_SYNC_EVENTS_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.events += 1;\n budget.bytes += bytes;\n budget.global.events += 1;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction reserveAttachmentWork(budget: PeerSyncWorkBudget, bytes: number): boolean {\n const chunks = Math.max(1, Math.ceil(bytes / MAX_SYNC_ATTACHMENT_CHUNK_BYTES));\n if (\n budget.pages + chunks > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.pages += chunks;\n budget.bytes += bytes;\n budget.global.pages += chunks;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction rotatePeers(peers: ChatSyncPeer[], after: string | undefined): ChatSyncPeer[] {\n if (peers.length === 0 || after === undefined) return peers;\n const start = peers.findIndex(peer => compareCodeUnits(peer.nodeId, after) > 0);\n if (start < 0) return peers;\n return [...peers.slice(start), ...peers.slice(0, start)];\n}\n\nfunction groupRangesByConversation(ranges: VersionRange[]): Map<string, VersionRange[]> {\n const grouped = new Map<string, VersionRange[]>();\n for (const range of ranges) {\n const values = grouped.get(range.conversationId) ?? [];\n values.push(range);\n grouped.set(range.conversationId, values);\n }\n return grouped;\n}\n\nfunction eventInRange(event: ConversationEvent, range: VersionRange): boolean {\n return event.conversationId === range.conversationId &&\n event.originNodeId === range.originNodeId &&\n event.originSequence > range.fromExclusive &&\n event.originSequence <= range.toInclusive;\n}\n\ninterface CoverageProgress {\n nextExpected: number;\n toInclusive: number;\n}\n\nfunction createCoverageProgress(ranges: VersionRange[]): Map<string, CoverageProgress> {\n const coverage = new Map<string, CoverageProgress>();\n for (const range of ranges) {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (coverage.has(key)) throw new Error('sync_duplicate_version_range');\n coverage.set(key, {\n nextExpected: range.fromExclusive + 1,\n toInclusive: range.toInclusive,\n });\n }\n return coverage;\n}\n\nfunction cloneCoverageProgress(\n coverage: Map<string, CoverageProgress>,\n): Map<string, CoverageProgress> {\n return new Map([...coverage].map(([key, value]) => [key, { ...value }]));\n}\n\nfunction recordObservedSequence(\n coverage: Map<string, CoverageProgress>,\n event: ConversationEvent,\n): void {\n const key = versionVectorKey(event.conversationId, event.originNodeId);\n const progress = coverage.get(key);\n if (!progress || event.originSequence !== progress.nextExpected) {\n throw new Error('sync_non_contiguous_origin_sequence');\n }\n progress.nextExpected += 1;\n}\n\nfunction rangesHaveExactCoverage(\n coverage: Map<string, CoverageProgress>,\n): boolean {\n return [...coverage.values()].every(progress => progress.nextExpected === progress.toInclusive + 1);\n}\n\nfunction isConversationEventCursor(value: unknown): value is ConversationEventCursor {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'originNodeId',\n 'originSequence',\n 'eventId',\n ])\n ) return false;\n const cursor = value as Partial<ConversationEventCursor>;\n return isValidSyncIdentifier(cursor.originNodeId) &&\n typeof cursor.originSequence === 'number' && Number.isSafeInteger(cursor.originSequence) &&\n cursor.originSequence > 0 && isValidSyncIdentifier(cursor.eventId);\n}\n\nfunction eventCursor(event: ConversationEvent): ConversationEventCursor {\n return {\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n eventId: event.eventId,\n };\n}\n\nfunction compareEventCursor(left: ConversationEventCursor, right: ConversationEventCursor): number {\n return compareUtf8Bytes(left.originNodeId, right.originNodeId) ||\n left.originSequence - right.originSequence ||\n compareUtf8Bytes(left.eventId, right.eventId);\n}\n\n/** Matches SQLite's default BINARY ordering used by the production event index. */\nfunction compareUtf8Bytes(left: string, right: string): number {\n if (left === right) return 0;\n const leftBytes = utf8Encoder.encode(left);\n const rightBytes = utf8Encoder.encode(right);\n const length = Math.min(leftBytes.length, rightBytes.length);\n for (let index = 0; index < length; index += 1) {\n const difference = leftBytes[index] - rightBytes[index];\n if (difference !== 0) return difference;\n }\n return leftBytes.length - rightBytes.length;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction jsonByteLength(events: readonly ConversationEvent[]): number {\n return canonicalEventArrayBytes(events);\n}\n\nfunction canonicalEventArrayBytes(events: readonly ConversationEvent[]): number {\n let bytes = 2 + Math.max(0, events.length - 1);\n for (const event of events) bytes += canonicalConversationEventBytes(event).byteLength;\n return bytes;\n}\n\nfunction assertBoundedCanonicalEventBytes(\n events: readonly ConversationEvent[],\n errorCode: string,\n): void {\n if (canonicalEventArrayBytes(events) > EVENT_PUSH_PAGE_MAX_BYTES) throw new Error(errorCode);\n}\n\nfunction isValidSyncIdentifier(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n utf8Encoder.encode(value).byteLength <= MAX_SYNC_ID_LENGTH &&\n !Array.from(value).some(character => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 31 || codePoint === 127;\n });\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n try {\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === Object.prototype || prototype === null;\n } catch {\n return false;\n }\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { AttachmentChunk } from '../device-network/types.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { ConversationEventSyncPage, VersionRange } from './protocol.js';\n\nimport type { ChatSyncPeer, SyncIoOptions } from './chatSyncEngine.js';\n\nexport interface PeerNodeTransport {\n nodeId: string;\n exchangeVersionFrontierPage(\n targetNodeId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n targetNodeId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n\n /** 从指定节点拉取附件 BLOB(如 `memeloop.storage.getAttachmentBlob`)。 */\n pullAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents?(\n targetNodeId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void>;\n pushAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport class PeerNodeSyncAdapter implements ChatSyncPeer {\n public readonly nodeId: string;\n private readonly transport: PeerNodeTransport;\n\n constructor(nodeId: string, transport: PeerNodeTransport) {\n this.nodeId = nodeId;\n this.transport = transport;\n }\n\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ) {\n return this.transport.exchangeVersionFrontierPage(\n this.nodeId,\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n options,\n );\n }\n\n pullMissingEvents(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n const function_ = this.transport.pullMissingEvents?.bind(this.transport);\n if (!function_) {\n return Promise.reject(new Error('Peer transport does not support event synchronization'));\n }\n return function_(this.nodeId, conversationId, ranges, cursor, options);\n }\n\n pullAttachmentChunk(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ) {\n const function_ = this.transport.pullAttachmentChunk?.bind(this.transport);\n if (!function_) {\n return Promise.resolve(null);\n }\n return function_(this.nodeId, conversationId, contentHash, offset, maxBytes, options);\n }\n\n pushEvents(events: ConversationEvent[], options?: SyncIoOptions): Promise<void> {\n const function_ = this.transport.pushEvents?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support event push'));\n return function_(this.nodeId, events, options);\n }\n\n pushAttachmentChunk(\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n const function_ = this.transport.pushAttachmentChunk?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support attachment push'));\n return function_(this.nodeId, conversationId, contentHash, chunk, options);\n }\n}\n","import { domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { DeviceConnectionGrant, DeviceConnectionGrantStringScope, DeviceRelayReservationToken, MemeLoopProtocol } from './types.js';\n\nexport const DEVICE_BINDING_SIGNATURE_DOMAIN = 'memeloop-device-binding-v2';\nexport const DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN = 'memeloop-device-connection-grant-v2';\nexport const DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN = 'memeloop-device-relay-admission-v2';\nexport const DEVICE_CONNECTION_GRANT_MAX_PEERS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS = 128;\nexport const DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH = 512;\nexport const DEVICE_CONNECTION_GRANT_MAX_TTL_MS = 10 * 60_000;\nexport const DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS = 40 * 60_000;\nexport const DEVICE_GRANT_MAX_CLOCK_SKEW_MS = 30_000;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESSES = 64;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH = 2_048;\n\nconst DEVICE_SIGNATURE_LIMITS = Object.freeze({\n maxDepth: 8,\n maxNodes: 2_048,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: 1_048_576,\n});\n\nconst DEVICE_PROTOCOLS: ReadonlySet<string> = new Set<MemeLoopProtocol>([\n '/memeloop/orchestration/2.0.0',\n '/memeloop/pairing/2.0.0',\n '/memeloop/relay-admission/2.0.0',\n '/memeloop/rpc/2.0.0',\n '/memeloop/sync/2.0.0',\n]);\n\nexport function buildDeviceBindingMessage(input: {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n nonce: string;\n}): Uint8Array {\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_BINDING_SIGNATURE_DOMAIN,\n input,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\nexport function buildDeviceConnectionGrantMessage(\n grant: Omit<DeviceConnectionGrant, 'signature'>,\n): Uint8Array {\n if (!hasCanonicalDeviceConnectionGrantClaims({ ...grant, signature: 'validation-signature' })) {\n throw new Error('invalid device connection grant claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,\n grant,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** True only for the one canonical, bounded encoding accepted by v2 verifiers. */\nexport function hasCanonicalDeviceConnectionGrantClaims(\n value: unknown,\n): value is DeviceConnectionGrant {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const grant = value as Record<string, unknown>;\n return (\n hasOnlyKeys(grant, [\n 'issuer',\n 'accountId',\n 'subjectPeerId',\n 'allowedPeerIds',\n 'protocols',\n 'rpcMethodScope',\n 'conversationScope',\n 'definitionScope',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) &&\n grant.issuer === 'memeloop-cloud' &&\n canonicalScopeValue(grant.accountId) &&\n canonicalScopeValue(grant.subjectPeerId) &&\n canonicalStringList(grant.allowedPeerIds, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_PEERS,\n }) &&\n canonicalStringList(grant.protocols, {\n maxEntries: DEVICE_PROTOCOLS.size,\n allowedValues: DEVICE_PROTOCOLS,\n }) &&\n canonicalScope(grant.rpcMethodScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS,\n }) &&\n canonicalScope(grant.conversationScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n canonicalScope(grant.definitionScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n validLifetime(\n grant.issuedAt,\n grant.expiresAt,\n DEVICE_CONNECTION_GRANT_MAX_TTL_MS,\n ) &&\n canonicalScopeValue(grant.signature)\n );\n}\n\nfunction canonicalScopeValue(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n value.length <= DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH &&\n hasPairedUtf16(value) && !value.includes(',') && !value.includes('\\n') &&\n !value.includes('\\r');\n}\n\nexport function deviceConnectionGrantAllowsProtocol(\n grant: DeviceConnectionGrant,\n protocol: MemeLoopProtocol,\n): boolean {\n return hasCanonicalDeviceConnectionGrantClaims(grant) && grant.protocols.includes(protocol);\n}\n\nexport function deviceConnectionGrantAllowsRpc(\n grant: DeviceConnectionGrant,\n input: { method: string; conversationId?: string; definitionId?: string },\n): boolean {\n if (!deviceConnectionGrantAllowsProtocol(grant, '/memeloop/rpc/2.0.0')) return false;\n if (!canonicalScopeValue(input.method)) return false;\n if (input.conversationId !== undefined && !canonicalScopeValue(input.conversationId)) return false;\n if (input.definitionId !== undefined && !canonicalScopeValue(input.definitionId)) return false;\n if (!scopeAllows(grant.rpcMethodScope, input.method)) return false;\n if (input.conversationId !== undefined && !scopeAllows(grant.conversationScope, input.conversationId)) {\n return false;\n }\n if (input.definitionId !== undefined && !scopeAllows(grant.definitionScope, input.definitionId)) {\n return false;\n }\n return true;\n}\n\nfunction scopeAllows(scope: DeviceConnectionGrantStringScope, value: string): boolean {\n return scope.mode === 'all' || (scope.mode === 'ids' && scope.ids.includes(value));\n}\n\nfunction canonicalScope(value: unknown, options: CanonicalStringListOptions): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const scope = value as Record<string, unknown>;\n if (scope.mode === 'none' || scope.mode === 'all') {\n return Object.keys(scope).length === 1;\n }\n return scope.mode === 'ids' && Object.keys(scope).length === 2 &&\n Object.hasOwn(scope, 'ids') && canonicalStringList(scope.ids, options) &&\n (scope.ids as unknown[]).length > 0;\n}\n\ninterface CanonicalStringListOptions {\n maxEntries: number;\n allowedValues?: ReadonlySet<string>;\n}\n\nfunction canonicalStringList(value: unknown, options: CanonicalStringListOptions): boolean {\n if (!Array.isArray(value) || value.length > options.maxEntries) return false;\n let previous: string | undefined;\n for (const entry of value) {\n if (\n !canonicalScopeValue(entry) ||\n (options.allowedValues && !options.allowedValues.has(entry)) ||\n (previous !== undefined && previous >= entry)\n ) return false;\n previous = entry;\n }\n return true;\n}\n\nexport function buildDeviceRelayReservationTokenMessage(\n token: Omit<DeviceRelayReservationToken, 'signature'>,\n): Uint8Array {\n if (\n !hasCanonicalDeviceRelayReservationTokenClaims({\n ...token,\n signature: 'validation-signature',\n })\n ) {\n throw new Error('invalid device relay reservation token claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,\n token,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** Reject ambiguous/unbounded relay claims before signing or verification. */\nexport function hasCanonicalDeviceRelayReservationTokenClaims(\n value: unknown,\n): value is DeviceRelayReservationToken {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const token = value as Record<string, unknown>;\n return hasOnlyKeys(token, [\n 'issuer',\n 'accountId',\n 'peerId',\n 'relayMultiaddrs',\n 'bootstrapMultiaddrs',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) && token.issuer === 'memeloop-cloud' && canonicalScopeValue(token.accountId) &&\n canonicalScopeValue(token.peerId) && validLifetime(\n token.issuedAt,\n token.expiresAt,\n DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS,\n ) &&\n canonicalAddressList(token.relayMultiaddrs, false) &&\n canonicalAddressList(token.bootstrapMultiaddrs, true) &&\n canonicalScopeValue(token.signature);\n}\n\nfunction canonicalAddressList(value: unknown, allowEmpty: boolean): boolean {\n if (!Array.isArray(value) || value.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESSES) {\n return false;\n }\n if (!allowEmpty && value.length === 0) return false;\n let previous: string | undefined;\n for (const address of value) {\n if (\n typeof address !== 'string' || address.length === 0 ||\n address.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH ||\n address !== address.trim() || !hasPairedUtf16(address) || !address.startsWith('/') ||\n containsAsciiControlOrSpace(address) ||\n (previous !== undefined && previous >= address)\n ) return false;\n previous = address;\n }\n return true;\n}\n\nfunction validLifetime(issuedAt: unknown, expiresAt: unknown, maxTtlMs: number): boolean {\n return Number.isSafeInteger(issuedAt) && Number.isSafeInteger(expiresAt) &&\n (issuedAt as number) >= 0 && (expiresAt as number) > (issuedAt as number) &&\n (expiresAt as number) - (issuedAt as number) <= maxTtlMs;\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key)) &&\n allowed.every(key => Object.hasOwn(record, key));\n}\n\nfunction hasPairedUtf16(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (next < 0xdc00 || next > 0xdfff) return false;\n index += 1;\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n return false;\n }\n }\n return true;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n","import { hasCanonicalDeviceConnectionGrantClaims, hasCanonicalDeviceRelayReservationTokenClaims } from './deviceGrantMessages.js';\nimport type { CloudDeviceClient, CloudDeviceRecord, DeviceCloudCommitFence, DeviceConnectionGrant, DeviceRelayReservationToken } from './types.js';\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_RESPONSE_MAX_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_ERROR_MAX_CHARACTERS = 4_096;\nconst DEFAULT_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\nconst CLOUD_URL_MAX_CHARACTERS = 2_048;\nconst CLOUD_ACCESS_TOKEN_MAX_CHARACTERS = 16_384;\n\ntype Awaitable<T> = T | Promise<T>;\ntype ConnectionGrantRequest = Parameters<CloudDeviceClient['createConnectionGrant']>[0];\n\nexport type CloudDeviceFetch = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport type CloudDeviceAccessTokenSupplier = (\n signal: AbortSignal,\n) => Awaitable<string | undefined>;\n\nexport interface DeviceCloudTokenStorage {\n loadConnectionGrant(input: ConnectionGrantRequest): Awaitable<unknown>;\n /** The final durable write must atomically reject a stale generation fence. */\n saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): Awaitable<void>;\n loadRelayReservation(peerId: string): Awaitable<unknown>;\n /** The final durable write must atomically reject a stale generation fence. */\n saveRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): Awaitable<void>;\n clear(): Awaitable<void>;\n}\n\nexport class MemoryDeviceCloudTokenStorage implements DeviceCloudTokenStorage {\n private readonly grants = new Map<string, DeviceConnectionGrant>();\n private readonly relayReservations = new Map<string, DeviceRelayReservationToken>();\n\n public loadConnectionGrant(input: ConnectionGrantRequest): DeviceConnectionGrant | undefined {\n return this.grants.get(connectionGrantCacheKey(input));\n }\n\n public saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): void {\n const write = (): void => {\n this.grants.set(connectionGrantCacheKey(input), grant);\n };\n if (!fence) {\n write();\n return;\n }\n if (!fence.commitSynchronous(write)) fence.throwIfStale();\n }\n\n public loadRelayReservation(peerId: string): DeviceRelayReservationToken | undefined {\n return this.relayReservations.get(peerId);\n }\n\n public saveRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): void {\n const write = (): void => {\n this.relayReservations.set(peerId, token);\n };\n if (!fence) {\n write();\n return;\n }\n if (!fence.commitSynchronous(write)) fence.throwIfStale();\n }\n\n public clear(): void {\n this.grants.clear();\n this.relayReservations.clear();\n }\n}\n\nexport type CloudDeviceFetchErrorCode =\n | 'cloud_request_failed'\n | 'cloud_http_error'\n | 'cloud_response_invalid_json'\n | 'cloud_response_invalid_shape'\n | 'cloud_response_too_large';\n\nexport class CloudDeviceFetchError extends Error {\n public readonly code: CloudDeviceFetchErrorCode;\n public readonly status?: number;\n public readonly responseBody?: string;\n\n constructor(\n code: CloudDeviceFetchErrorCode,\n options?: { cause?: unknown; status?: number; responseBody?: string },\n ) {\n const detail = options?.status === undefined\n ? code\n : `${code}: ${options.status} ${(options.responseBody ?? '').trim()}`.trim();\n super(detail, options?.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'CloudDeviceFetchError';\n this.code = code;\n this.status = options?.status;\n this.responseBody = options?.responseBody;\n }\n}\n\nexport interface CloudDeviceFetchClientOptions {\n baseUrl: string;\n fetch?: CloudDeviceFetch;\n accessToken?: string;\n getAccessToken?: CloudDeviceAccessTokenSupplier;\n credentials?: RequestCredentials;\n requestTimeoutMs?: number;\n responseMaxBytes?: number;\n errorMaxCharacters?: number;\n tokenStorage?: DeviceCloudTokenStorage;\n tokenSafetyMarginMs?: number;\n now?: () => number;\n onTokenStorageError?: (operation: 'load' | 'save', error: unknown) => void;\n}\n\n/** Browser/React Native-safe transport for the audited MemeLoop Cloud device API. */\nexport class CloudDeviceFetchClient implements CloudDeviceClient {\n public readonly baseUrl: string;\n private readonly fetchImplementation: CloudDeviceFetch;\n private readonly getAccessToken?: CloudDeviceAccessTokenSupplier;\n private readonly credentials: RequestCredentials;\n private readonly requestTimeoutMs: number;\n private readonly responseMaxBytes: number;\n private readonly errorMaxCharacters: number;\n private readonly tokenStorage: DeviceCloudTokenStorage;\n private readonly tokenSafetyMarginMs: number;\n private readonly now: () => number;\n\n constructor(private readonly options: CloudDeviceFetchClientOptions) {\n this.baseUrl = normalizeCloudDeviceBaseUrl(options.baseUrl);\n if (options.fetch) {\n this.fetchImplementation = options.fetch;\n } else if (typeof globalThis.fetch === 'function') {\n this.fetchImplementation = globalThis.fetch.bind(globalThis);\n } else {\n throw new TypeError('cloud_fetch_required');\n }\n if (options.accessToken !== undefined && options.getAccessToken !== undefined) {\n throw new TypeError('cloud_access_token_supplier_ambiguous');\n }\n if (options.accessToken !== undefined) {\n const accessToken = normalizeAccessToken(options.accessToken);\n this.getAccessToken = () => accessToken;\n } else {\n this.getAccessToken = options.getAccessToken;\n }\n this.credentials = options.credentials ?? 'omit';\n this.requestTimeoutMs = positiveFinite(\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n 'requestTimeoutMs',\n );\n this.responseMaxBytes = positiveFinite(\n options.responseMaxBytes ?? DEFAULT_RESPONSE_MAX_BYTES,\n 'responseMaxBytes',\n );\n this.errorMaxCharacters = positiveFinite(\n options.errorMaxCharacters ?? DEFAULT_ERROR_MAX_CHARACTERS,\n 'errorMaxCharacters',\n );\n this.tokenSafetyMarginMs = nonNegativeFinite(\n options.tokenSafetyMarginMs ?? DEFAULT_TOKEN_SAFETY_MARGIN_MS,\n 'tokenSafetyMarginMs',\n );\n this.tokenStorage = options.tokenStorage ?? new MemoryDeviceCloudTokenStorage();\n this.now = options.now ?? Date.now;\n }\n\n public async createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }> {\n const value = await this.request('/api/devices/binding/nonce', { method: 'POST' }, signal);\n if (\n !isRecord(value) || !nonEmptyString(value.nonce) || !nonEmptyString(value.accountId) ||\n !nonEmptyString(value.expiresAt)\n ) {\n throw invalidShape();\n }\n return { nonce: value.nonce, accountId: value.accountId, expiresAt: value.expiresAt };\n }\n\n public async registerDevice(\n input: Parameters<CloudDeviceClient['registerDevice']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }> {\n const value = await this.request('/api/devices/register', {\n method: 'POST',\n body: JSON.stringify({\n peerId: input.identity.peerId,\n publicKeyMultibase: input.identity.publicKeyMultibase,\n deviceName: input.identity.deviceName,\n platform: input.identity.platform,\n cloudNonce: input.cloudNonce,\n signature: input.signature,\n capabilities: input.capabilities,\n multiaddrs: input.multiaddrs,\n relayReservations: input.relayReservations,\n }),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean' || !nonEmptyString(value.peerId)) {\n throw invalidShape();\n }\n return { ok: value.ok, peerId: value.peerId };\n }\n\n public async listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]> {\n const value = await this.request('/api/devices', { method: 'GET' }, signal);\n if (\n !isRecord(value) || !Array.isArray(value.devices) ||\n !value.devices.every(isCloudDeviceRecord)\n ) {\n throw invalidShape();\n }\n return value.devices;\n }\n\n public async getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }> {\n const value = await this.request(\n '/api/devices/connection-grant/public-key',\n { method: 'GET' },\n signal,\n );\n if (\n !isRecord(value) || value.issuer !== 'memeloop-cloud' ||\n !nonEmptyString(value.publicKeyMultibase)\n ) {\n throw invalidShape();\n }\n return { issuer: value.issuer, publicKeyMultibase: value.publicKeyMultibase };\n }\n\n public async createConnectionGrant(\n input: ConnectionGrantRequest,\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceConnectionGrant> {\n assertFenceSignal(signal, fence);\n fence?.throwIfStale();\n if (!isCanonicalConnectionGrantRequest(input)) {\n throw new TypeError('invalid_connection_grant_scope');\n }\n const cacheInput = normalizedConnectionGrantRequest(input);\n const cached = await this.loadCachedGrant(cacheInput);\n throwIfAborted(signal);\n fence?.throwIfStale();\n if (isUsableConnectionGrant(cached, cacheInput, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/connection-grant', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableConnectionGrant(value, cacheInput, this.now())) throw invalidShape();\n fence?.throwIfStale();\n await this.saveCachedGrant(cacheInput, value, fence);\n fence?.throwIfStale();\n return value;\n }\n\n public async createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceRelayReservationToken> {\n assertFenceSignal(signal, fence);\n fence?.throwIfStale();\n const cached = await this.loadCachedRelayReservation(input.peerId);\n throwIfAborted(signal);\n fence?.throwIfStale();\n if (isUsableRelayReservation(cached, input.peerId, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/relay-reservation', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableRelayReservation(value, input.peerId, this.now())) throw invalidShape();\n fence?.throwIfStale();\n await this.saveCachedRelayReservation(input.peerId, value, fence);\n fence?.throwIfStale();\n return value;\n }\n\n public async heartbeat(\n input: Parameters<CloudDeviceClient['heartbeat']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean }> {\n const value = await this.request('/api/devices/heartbeat', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean') throw invalidShape();\n return { ok: value.ok };\n }\n\n /** Clear every grant/relay token owned by this client configuration. */\n public async clearCachedTokens(signal?: AbortSignal): Promise<void> {\n throwIfAborted(signal);\n try {\n await this.tokenStorage.clear();\n } catch (error) {\n this.options.onTokenStorageError?.('save', error);\n throw error;\n }\n throwIfAborted(signal);\n }\n\n private async request(path: string, init: RequestInit, signal?: AbortSignal): Promise<unknown> {\n const request = createRequestSignal(signal, this.requestTimeoutMs);\n try {\n throwIfAborted(request.signal);\n const accessToken = await this.getAccessToken?.(request.signal);\n throwIfAborted(request.signal);\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (accessToken !== undefined) {\n headers.authorization = `Bearer ${normalizeAccessToken(accessToken)}`;\n }\n let response: Response;\n try {\n response = await this.fetchImplementation(`${this.baseUrl}${path}`, {\n ...init,\n credentials: this.credentials,\n headers,\n redirect: 'error',\n signal: request.signal,\n });\n } catch (error) {\n if (request.signal.aborted) throw abortReason(request.signal);\n throw new CloudDeviceFetchError('cloud_request_failed', { cause: error });\n }\n const responseText = await readBoundedCloudResponse(\n response,\n this.responseMaxBytes,\n request.signal,\n );\n if (!response.ok) {\n const responseBody = responseText.slice(0, this.errorMaxCharacters);\n throw new CloudDeviceFetchError('cloud_http_error', {\n status: response.status,\n responseBody,\n });\n }\n try {\n return JSON.parse(responseText) as unknown;\n } catch (error) {\n throw new CloudDeviceFetchError('cloud_response_invalid_json', { cause: error });\n }\n } finally {\n request.dispose();\n }\n }\n\n private async loadCachedGrant(input: ConnectionGrantRequest): Promise<unknown> {\n try {\n return await this.tokenStorage.loadConnectionGrant(input);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveConnectionGrant(input, grant, fence);\n } catch (error) {\n if (fence && !fence.isCurrent()) fence.throwIfStale();\n this.options.onTokenStorageError?.('save', error);\n }\n }\n\n private async loadCachedRelayReservation(peerId: string): Promise<unknown> {\n try {\n return await this.tokenStorage.loadRelayReservation(peerId);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveRelayReservation(peerId, token, fence);\n } catch (error) {\n if (fence && !fence.isCurrent()) fence.throwIfStale();\n this.options.onTokenStorageError?.('save', error);\n }\n }\n}\n\nfunction assertFenceSignal(\n signal: AbortSignal | undefined,\n fence: DeviceCloudCommitFence | undefined,\n): void {\n if (fence && signal && fence.signal !== signal) {\n throw new TypeError('device_cloud_generation_signal_mismatch');\n }\n}\n\nexport function normalizeCloudDeviceBaseUrl(value: string): string {\n const baseUrl = value.trim();\n if (!baseUrl || baseUrl.length > CLOUD_URL_MAX_CHARACTERS) throw new Error('invalid_cloud_url');\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new Error('invalid_cloud_url');\n }\n const loopback = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' ||\n parsed.hostname === '[::1]';\n if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopback)) {\n throw new Error('cloud_url_requires_https');\n }\n if (\n parsed.username || parsed.password || parsed.search || parsed.hash ||\n (parsed.pathname !== '' && parsed.pathname !== '/')\n ) {\n throw new Error('invalid_cloud_url');\n }\n return parsed.origin;\n}\n\nfunction normalizeAccessToken(value: string): string {\n const accessToken = value.trim();\n if (!accessToken || accessToken.length > CLOUD_ACCESS_TOKEN_MAX_CHARACTERS) {\n throw new Error('invalid_cloud_access_token');\n }\n return accessToken;\n}\n\nfunction positiveFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0) throw new TypeError(`${name} must be positive and finite`);\n return value;\n}\n\nfunction nonNegativeFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0) throw new TypeError(`${name} must be non-negative and finite`);\n return value;\n}\n\nfunction createRequestSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abortFromParent = (): void => {\n controller.abort(parent?.reason);\n };\n if (parent?.aborted) abortFromParent();\n else parent?.addEventListener('abort', abortFromParent, { once: true });\n const timeout = setTimeout(() => {\n controller.abort(new Error('cloud_request_timeout'));\n }, timeoutMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timeout);\n parent?.removeEventListener('abort', abortFromParent);\n },\n };\n}\n\nasync function readBoundedCloudResponse(\n response: Response,\n maximumBytes: number,\n signal: AbortSignal,\n): Promise<string> {\n const declaredLength = Number(response.headers.get('content-length') ?? '0');\n if (Number.isFinite(declaredLength) && declaredLength > maximumBytes) {\n await response.body?.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n throwIfAborted(signal);\n if (!response.body || typeof response.body.getReader !== 'function') {\n const text = await awaitWithAbort(response.text(), signal);\n throwIfAborted(signal);\n if (new TextEncoder().encode(text).byteLength > maximumBytes) {\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n return text;\n }\n const reader = response.body.getReader();\n const cancelReader = (): void => {\n void reader.cancel('cloud_request_aborted');\n };\n signal.addEventListener('abort', cancelReader, { once: true });\n const decoder = new TextDecoder('utf-8', { fatal: true });\n let totalBytes = 0;\n let text = '';\n try {\n for (;;) {\n throwIfAborted(signal);\n const { done, value } = await reader.read();\n if (done) break;\n totalBytes += value.byteLength;\n if (totalBytes > maximumBytes) {\n await reader.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n text += decoder.decode(value, { stream: true });\n }\n throwIfAborted(signal);\n return text + decoder.decode();\n } finally {\n signal.removeEventListener('abort', cancelReader);\n }\n}\n\nasync function awaitWithAbort<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n throwIfAborted(signal);\n let rejectAbort!: (reason: Error) => void;\n const aborted = new Promise<never>((_resolve, reject) => {\n rejectAbort = reject;\n });\n const onAbort = (): void => {\n rejectAbort(abortReason(signal));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n return await Promise.race([promise, aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortReason(signal);\n}\n\nfunction abortReason(signal: AbortSignal): Error {\n return signal.reason instanceof Error ? signal.reason : new Error('cloud_request_aborted');\n}\n\nfunction invalidShape(): CloudDeviceFetchError {\n return new CloudDeviceFetchError('cloud_response_invalid_shape');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction nonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\nfunction stringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(item => typeof item === 'string');\n}\n\nfunction isCloudDeviceRecord(value: unknown): value is CloudDeviceRecord {\n if (\n !isRecord(value) || !nonEmptyString(value.accountId) || !nonEmptyString(value.peerId) ||\n !nonEmptyString(value.publicKeyMultibase) || !nonEmptyString(value.deviceName) ||\n (value.platform !== 'desktop' && value.platform !== 'mobile' && value.platform !== 'cli' &&\n value.platform !== 'web') ||\n !isDeviceCapabilities(value.capabilities) ||\n !stringArray(value.multiaddrs) || !stringArray(value.relayReservations) ||\n typeof value.lastSeen !== 'number' || !Number.isFinite(value.lastSeen)\n ) {\n return false;\n }\n return value.revokedAt === undefined ||\n (typeof value.revokedAt === 'number' && Number.isFinite(value.revokedAt));\n}\n\nfunction isDeviceCapabilities(value: unknown): boolean {\n if (\n !isRecord(value) || !stringArray(value.tools) || !stringArray(value.mcpServers) ||\n typeof value.hasWiki !== 'boolean' || !stringArray(value.imChannels) ||\n !Array.isArray(value.wikis) ||\n (value.agentLoop !== undefined && typeof value.agentLoop !== 'boolean')\n ) {\n return false;\n }\n return value.wikis.every(wiki =>\n isRecord(wiki) && nonEmptyString(wiki.wikiId) &&\n (wiki.title === undefined || typeof wiki.title === 'string') &&\n (wiki.pathHint === undefined || typeof wiki.pathHint === 'string')\n );\n}\n\nfunction normalizedConnectionGrantRequest(input: ConnectionGrantRequest): ConnectionGrantRequest {\n return {\n subjectPeerId: input.subjectPeerId,\n allowedPeerIds: [...input.allowedPeerIds],\n protocols: [...input.protocols],\n rpcMethodScope: cloneScope(input.rpcMethodScope),\n conversationScope: cloneScope(input.conversationScope),\n definitionScope: cloneScope(input.definitionScope),\n };\n}\n\nfunction connectionGrantCacheKey(input: ConnectionGrantRequest): string {\n const normalized = normalizedConnectionGrantRequest(input);\n return JSON.stringify([\n normalized.subjectPeerId,\n normalized.allowedPeerIds,\n normalized.protocols,\n normalized.rpcMethodScope,\n normalized.conversationScope,\n normalized.definitionScope,\n ]);\n}\n\nfunction sameStringList(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction cloneScope<T extends ConnectionGrantRequest['rpcMethodScope']>(scope: T): T {\n return (scope.mode === 'ids' ? { mode: 'ids', ids: [...scope.ids] } : { mode: scope.mode }) as T;\n}\n\nfunction sameScope(\n left: ConnectionGrantRequest['rpcMethodScope'],\n right: ConnectionGrantRequest['rpcMethodScope'],\n): boolean {\n return left.mode === right.mode &&\n (left.mode !== 'ids' || (right.mode === 'ids' && sameStringList(left.ids, right.ids)));\n}\n\nfunction isCanonicalConnectionGrantRequest(input: ConnectionGrantRequest): boolean {\n return hasCanonicalDeviceConnectionGrantClaims({\n ...input,\n issuer: 'memeloop-cloud',\n accountId: 'validation-account',\n issuedAt: 0,\n expiresAt: 1,\n signature: 'validation-signature',\n });\n}\n\nfunction isUsableConnectionGrant(\n value: unknown,\n input: ConnectionGrantRequest,\n usableAfter: number,\n): value is DeviceConnectionGrant {\n if (!isRecord(value)) return false;\n const grant = value as unknown as DeviceConnectionGrant;\n if (!hasCanonicalDeviceConnectionGrantClaims(grant)) return false;\n return grant.issuer === 'memeloop-cloud' && grant.subjectPeerId === input.subjectPeerId &&\n nonEmptyString(grant.accountId) && sameStringList(grant.allowedPeerIds, input.allowedPeerIds) &&\n sameStringList(grant.protocols, input.protocols) &&\n sameScope(grant.rpcMethodScope, input.rpcMethodScope) &&\n sameScope(grant.conversationScope, input.conversationScope) &&\n sameScope(grant.definitionScope, input.definitionScope) &&\n typeof grant.issuedAt === 'number' && Number.isFinite(grant.issuedAt) &&\n typeof grant.expiresAt === 'number' && Number.isFinite(grant.expiresAt) &&\n grant.expiresAt > usableAfter && nonEmptyString(grant.signature);\n}\n\nfunction isUsableRelayReservation(\n value: unknown,\n peerId: string,\n usableAfter: number,\n): value is DeviceRelayReservationToken {\n if (!isRecord(value)) return false;\n const token = value as unknown as DeviceRelayReservationToken;\n return hasCanonicalDeviceRelayReservationTokenClaims(token) && token.peerId === peerId &&\n typeof value.issuedAt === 'number' && Number.isFinite(value.issuedAt) &&\n typeof value.expiresAt === 'number' && Number.isFinite(value.expiresAt) &&\n value.expiresAt > usableAfter && nonEmptyString(value.signature);\n}\n","import type { DeviceCloudCommitFence, SyncResult } from './types.js';\n\nexport type { DeviceCloudCommitFence } from './types.js';\n\nexport type DeviceCloudConnectionStatus =\n | 'not-configured'\n | 'connecting'\n | 'online'\n | 'degraded'\n | 'offline'\n | 'error';\n\nexport type DeviceCloudConnectionComponent =\n | 'authorizer'\n | 'registration'\n | 'relay'\n | 'heartbeat'\n | 'directory';\n\nexport type DeviceCloudComponentStatus = 'pending' | 'ready' | 'failed' | 'not-run';\n\nexport type DeviceCloudErrorClassification = 'offline' | 'error' | 'registration-invalid';\n\n/** A deliberately small, stable error safe to persist, render, and log. */\nexport interface DeviceCloudConnectionError {\n readonly code:\n | 'DEVICE_CLOUD_STEP_FAILED'\n | 'DEVICE_CLOUD_DISPOSE_FAILED'\n | 'DEVICE_CLOUD_OBSERVER_FAILED';\n readonly classification: DeviceCloudErrorClassification;\n readonly component?: DeviceCloudConnectionComponent;\n}\n\nexport interface DeviceCloudConnectionSnapshot {\n readonly status: DeviceCloudConnectionStatus;\n readonly generation: number;\n readonly components: Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>>;\n readonly lastError?: DeviceCloudConnectionError;\n readonly nextRetryAt?: number;\n}\n\nexport class DeviceCloudStaleGenerationError extends Error {\n public readonly code = 'DEVICE_CLOUD_STALE_GENERATION';\n\n constructor() {\n super('Device Cloud generation is stale');\n this.name = 'DeviceCloudStaleGenerationError';\n }\n}\n\nexport interface DeviceCloudStepResult {\n commit?: (fence: DeviceCloudCommitFence) => Promise<unknown>;\n}\n\nexport interface DeviceCloudConnectionAdapter<Configuration> {\n isConfigured(configuration: Configuration | undefined): configuration is Configuration;\n relayRequiredForOnline(configuration: Configuration): boolean;\n ensureAuthorizer(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n registerDevice(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n ensureRelay(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n heartbeat(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n syncDirectory(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n /**\n * Optional background anti-entropy hooks. The coordinator keeps one run per\n * peer and generation, retries incomplete bounded results, and aborts every\n * old-generation run before activating replacement configuration.\n */\n listBackgroundSyncPeerIds?(\n configuration: Configuration,\n signal: AbortSignal,\n ): readonly string[] | Promise<readonly string[]>;\n syncDevice?(\n configuration: Configuration,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult>;\n /** Clear every generation-scoped authorizer, relay, token, trust, and address effect. */\n dispose?(configuration: Configuration, signal: AbortSignal): Promise<void>;\n classifyError?(error: unknown): DeviceCloudErrorClassification;\n}\n\nexport interface DeviceCloudConnectionCoordinatorOptions<Configuration> {\n adapter: DeviceCloudConnectionAdapter<Configuration>;\n configuration?: Configuration;\n heartbeatIntervalMs?: number;\n initialBackoffMs?: number;\n maxBackoffMs?: number;\n jitterRatio?: number;\n backgroundSyncInitialBackoffMs?: number;\n backgroundSyncMaxBackoffMs?: number;\n now?: () => number;\n random?: () => number;\n /** Async status persistence must use the fence at its final write point. */\n onStatus?: (\n snapshot: DeviceCloudConnectionSnapshot,\n fence: DeviceCloudCommitFence,\n ) => void | Promise<void>;\n logWarning?: (message: string, error: DeviceCloudConnectionError) => void | Promise<void>;\n}\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 60_000;\nconst DEFAULT_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_MAX_BACKOFF_MS = 60_000;\nconst DEFAULT_JITTER_RATIO = 0.2;\nconst DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS = 60_000;\nconst MAX_BACKGROUND_SYNC_PEERS = 1_024;\nconst MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS = 512;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nfunction emptyComponents(): Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>> {\n return Object.freeze({\n authorizer: 'not-run',\n registration: 'not-run',\n relay: 'not-run',\n heartbeat: 'not-run',\n directory: 'not-run',\n });\n}\n\nfunction assertPositiveFiniteDelay(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0 || value > MAX_TIMER_DELAY_MS) {\n throw new TypeError(`${name} must be a finite integer between 1 and ${MAX_TIMER_DELAY_MS}`);\n }\n}\n\nfunction normalizeBackgroundSyncPeerIds(peerIds: unknown): string[] {\n if (!Array.isArray(peerIds) || peerIds.length > MAX_BACKGROUND_SYNC_PEERS) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n const normalized: unknown[] = [...new Set<unknown>(peerIds)];\n if (\n normalized.some(peerId =>\n typeof peerId !== 'string' || peerId.length === 0 ||\n peerId.length > MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS || peerId !== peerId.trim()\n )\n ) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n return normalized.map(peerId => String(peerId)).sort();\n}\n\nasync function abortableDelay(delayMs: number, signal: AbortSignal): Promise<void> {\n signal.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n reject(signal.reason instanceof Error ? signal.reason : new Error('operation_aborted'));\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, delayMs);\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) onAbort();\n });\n signal.throwIfAborted();\n}\n\nfunction safeError(\n code: DeviceCloudConnectionError['code'],\n classification: DeviceCloudErrorClassification,\n component?: DeviceCloudConnectionComponent,\n): DeviceCloudConnectionError {\n return Object.freeze(\n component === undefined\n ? { code, classification }\n : { code, classification, component },\n );\n}\n\nfunction freezeSnapshot(snapshot: DeviceCloudConnectionSnapshot): DeviceCloudConnectionSnapshot {\n return Object.freeze({\n ...snapshot,\n components: Object.freeze({ ...snapshot.components }),\n ...(snapshot.lastError === undefined ? {} : { lastError: Object.freeze({ ...snapshot.lastError }) }),\n });\n}\n\n/** Portable, generation-safe Cloud lifecycle shared by every MemeLoop host. */\nexport class DeviceCloudConnectionCoordinator<Configuration> {\n private configuration: Configuration | undefined;\n private desiredConfiguration: Configuration | undefined;\n private generation = 0;\n private requestedGeneration = 0;\n private transition?: Promise<void>;\n private controller = new AbortController();\n private timer?: ReturnType<typeof setTimeout>;\n private inFlight?: Promise<void>;\n private readonly backgroundSyncRuns = new Map<string, {\n generation: number;\n promise: Promise<void>;\n }>();\n private started = false;\n private generationActivated = false;\n private consecutiveFailures = 0;\n private snapshotValue: DeviceCloudConnectionSnapshot = freezeSnapshot({\n status: 'not-configured',\n generation: 0,\n components: emptyComponents(),\n });\n private readonly heartbeatIntervalMs: number;\n private readonly initialBackoffMs: number;\n private readonly maxBackoffMs: number;\n private readonly jitterRatio: number;\n private readonly backgroundSyncInitialBackoffMs: number;\n private readonly backgroundSyncMaxBackoffMs: number;\n private readonly now: () => number;\n private readonly random: () => number;\n\n constructor(private readonly options: DeviceCloudConnectionCoordinatorOptions<Configuration>) {\n this.configuration = options.configuration;\n this.desiredConfiguration = options.configuration;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\n this.initialBackoffMs = options.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;\n this.maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;\n this.jitterRatio = options.jitterRatio ?? DEFAULT_JITTER_RATIO;\n this.backgroundSyncInitialBackoffMs = options.backgroundSyncInitialBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS;\n this.backgroundSyncMaxBackoffMs = options.backgroundSyncMaxBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS;\n this.now = options.now ?? Date.now;\n this.random = options.random ?? Math.random;\n assertPositiveFiniteDelay(this.heartbeatIntervalMs, 'heartbeatIntervalMs');\n assertPositiveFiniteDelay(this.initialBackoffMs, 'initialBackoffMs');\n assertPositiveFiniteDelay(this.maxBackoffMs, 'maxBackoffMs');\n assertPositiveFiniteDelay(\n this.backgroundSyncInitialBackoffMs,\n 'backgroundSyncInitialBackoffMs',\n );\n assertPositiveFiniteDelay(\n this.backgroundSyncMaxBackoffMs,\n 'backgroundSyncMaxBackoffMs',\n );\n if (this.maxBackoffMs < this.initialBackoffMs) {\n throw new TypeError('maxBackoffMs must be greater than or equal to initialBackoffMs');\n }\n if (this.backgroundSyncMaxBackoffMs < this.backgroundSyncInitialBackoffMs) {\n throw new TypeError(\n 'backgroundSyncMaxBackoffMs must be greater than or equal to backgroundSyncInitialBackoffMs',\n );\n }\n if (!Number.isFinite(this.jitterRatio) || this.jitterRatio < 0 || this.jitterRatio > 1) {\n throw new TypeError('jitterRatio must be a finite number between 0 and 1');\n }\n this.resetSnapshot();\n }\n\n public get snapshot(): DeviceCloudConnectionSnapshot {\n return this.snapshotValue;\n }\n\n public async start(): Promise<void> {\n if (this.started) return this.runNow();\n this.started = true;\n const transition = this.transition;\n if (transition) {\n await transition;\n return;\n }\n await this.runCurrent();\n }\n\n public stop(): Promise<void> {\n if (\n !this.started && !this.inFlight && !this.transition && !this.generationActivated &&\n this.backgroundSyncRuns.size === 0\n ) {\n return Promise.resolve();\n }\n this.started = false;\n return this.requestTransition('device cloud coordinator stopped');\n }\n\n public setConfiguration(configuration: Configuration | undefined): Promise<void> {\n this.desiredConfiguration = configuration;\n return this.requestTransition('device cloud configuration changed');\n }\n\n public runNow(): Promise<void> {\n if (this.transition) {\n return this.started ? this.transition : this.transition.then(() => this.runCurrent());\n }\n return this.runCurrent();\n }\n\n private runCurrent(): Promise<void> {\n if (this.inFlight) return this.inFlight;\n if (!this.options.adapter.isConfigured(this.configuration)) {\n this.resetSnapshot();\n return Promise.resolve();\n }\n const generation = this.generation;\n const configuration = this.configuration;\n const signal = this.controller.signal;\n this.generationActivated = true;\n const run = this.maintain(configuration, generation, signal);\n const tracked = run.finally(() => {\n if (this.inFlight === tracked) this.inFlight = undefined;\n });\n this.inFlight = tracked;\n return tracked;\n }\n\n private requestTransition(reason: string): Promise<void> {\n this.requestedGeneration += 1;\n this.clearTimer();\n this.controller.abort(new Error(reason));\n if (!this.transition) {\n const transition = this.drainTransitions().finally(() => {\n if (this.transition === transition) this.transition = undefined;\n });\n this.transition = transition;\n }\n return this.transition;\n }\n\n private async drainTransitions(): Promise<void> {\n while (this.generation !== this.requestedGeneration) {\n const previousConfiguration = this.configuration;\n const previousRun = this.inFlight;\n await previousRun?.catch(() => undefined);\n await this.drainBackgroundSyncGeneration(this.generation);\n\n if (\n this.generationActivated &&\n this.options.adapter.isConfigured(previousConfiguration)\n ) {\n try {\n await this.options.adapter.dispose?.(previousConfiguration, new AbortController().signal);\n } catch {\n this.warn(\n 'Device Cloud generation cleanup failed',\n safeError('DEVICE_CLOUD_DISPOSE_FAILED', 'error'),\n );\n }\n }\n this.generationActivated = false;\n\n // Requests arriving while cleanup was in progress are deliberately\n // coalesced: only the newest desired configuration is ever activated.\n this.configuration = this.desiredConfiguration;\n this.generation = this.requestedGeneration;\n this.consecutiveFailures = 0;\n this.controller = new AbortController();\n if (this.inFlight === previousRun) this.inFlight = undefined;\n this.resetSnapshot();\n\n if (this.started && this.options.adapter.isConfigured(this.configuration)) {\n await this.runCurrent().catch((error: unknown) => {\n if (this.isCurrent(this.generation, this.controller.signal)) throw error;\n });\n }\n }\n }\n\n private async maintain(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.updateSnapshot(generation, {\n status: 'connecting',\n lastError: undefined,\n nextRetryAt: undefined,\n });\n\n let activeComponent: DeviceCloudConnectionComponent = 'authorizer';\n try {\n if (this.snapshotValue.components.authorizer !== 'ready') {\n activeComponent = 'authorizer';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.ensureAuthorizer(configuration, signal, fence));\n }\n if (this.snapshotValue.components.registration !== 'ready') {\n activeComponent = 'registration';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.registerDevice(configuration, signal, fence));\n }\n\n let relayFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'relay';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.ensureRelay(configuration, signal, fence));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n relayFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'relay');\n this.warn('Device Cloud relay maintenance failed', relayFailure);\n }\n\n activeComponent = 'heartbeat';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.heartbeat(configuration, signal, fence));\n\n let directoryFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'directory';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.syncDirectory(configuration, signal, fence));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n directoryFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'directory');\n this.warn('Device Cloud directory synchronization failed', directoryFailure);\n }\n\n if (!directoryFailure) this.startBackgroundSync(configuration, generation, signal);\n\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures = 0;\n const relayRequired = this.options.adapter.relayRequiredForOnline(configuration);\n const nextRetryAt = this.retryAt(this.heartbeatIntervalMs);\n await this.updateSnapshot(generation, {\n status: directoryFailure || (relayRequired && relayFailure) ? 'degraded' : 'online',\n lastError: directoryFailure ?? relayFailure,\n nextRetryAt,\n });\n this.schedule(this.heartbeatIntervalMs, generation);\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures += 1;\n const classification = this.classify(error);\n if (classification === 'registration-invalid') {\n await this.setComponent('registration', 'not-run', generation);\n }\n const status = classification === 'error' ? 'error' : 'offline';\n const delay = this.backoffDelay();\n await this.updateSnapshot(generation, {\n status,\n lastError: safeError('DEVICE_CLOUD_STEP_FAILED', classification, activeComponent),\n nextRetryAt: this.retryAt(delay),\n });\n this.schedule(delay, generation);\n throw error;\n }\n }\n\n private async runStep(\n component: DeviceCloudConnectionComponent,\n generation: number,\n signal: AbortSignal,\n operation: (fence: DeviceCloudCommitFence) => Promise<DeviceCloudStepResult | undefined>,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'pending', generation);\n try {\n const fence = this.createCommitFence(generation, signal);\n const result = await operation(fence);\n if (!this.isCurrent(generation, signal)) return;\n await result?.commit?.(fence);\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'ready', generation);\n } catch (error) {\n if (this.isCurrent(generation, signal)) await this.setComponent(component, 'failed', generation);\n throw error;\n }\n }\n\n private createCommitFence(generation: number, signal: AbortSignal): DeviceCloudCommitFence {\n return Object.freeze({\n generation,\n signal,\n isCurrent: () => this.isCurrent(generation, signal),\n throwIfStale: () => {\n if (!this.isCurrent(generation, signal)) throw new DeviceCloudStaleGenerationError();\n },\n commitSynchronous: <Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ) => {\n if (!this.isCurrent(generation, signal)) return false;\n operation();\n return true;\n },\n });\n }\n\n private classify(error: unknown): DeviceCloudErrorClassification {\n try {\n const classification = this.options.adapter.classifyError?.(error) ?? 'offline';\n return classification === 'offline' || classification === 'error' || classification === 'registration-invalid'\n ? classification\n : 'error';\n } catch {\n return 'error';\n }\n }\n\n private backoffDelay(): number {\n const exponential = Math.min(\n this.maxBackoffMs,\n this.initialBackoffMs * 2 ** Math.max(0, this.consecutiveFailures - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n throw new TypeError('random() must return a finite number between 0 and 1');\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private startBackgroundSync(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): void {\n const listBackgroundSyncPeerIds = this.options.adapter.listBackgroundSyncPeerIds?.bind(\n this.options.adapter,\n );\n const syncDevice = this.options.adapter.syncDevice?.bind(this.options.adapter);\n if (!listBackgroundSyncPeerIds || !syncDevice || !this.isCurrent(generation, signal)) return;\n void Promise.resolve()\n .then(async () => {\n const rawPeerIds = await listBackgroundSyncPeerIds(configuration, signal);\n if (!this.isCurrent(generation, signal)) return;\n const peerIds = normalizeBackgroundSyncPeerIds(rawPeerIds);\n for (const peerId of peerIds) {\n if (!this.isCurrent(generation, signal)) return;\n const existing = this.backgroundSyncRuns.get(peerId);\n if (existing?.generation === generation) continue;\n const run = this.runBackgroundSyncDevice(\n configuration,\n peerId,\n generation,\n signal,\n syncDevice,\n );\n const record = { generation, promise: run };\n this.backgroundSyncRuns.set(peerId, record);\n const release = (): void => {\n if (this.backgroundSyncRuns.get(peerId) === record) {\n this.backgroundSyncRuns.delete(peerId);\n }\n };\n void run.then(release, release);\n }\n })\n .catch((error: unknown) => {\n if (!this.isCurrent(generation, signal)) return;\n this.warn(\n 'Device Cloud background sync discovery failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n });\n }\n\n private async runBackgroundSyncDevice(\n configuration: Configuration,\n peerId: string,\n generation: number,\n signal: AbortSignal,\n syncDevice: NonNullable<DeviceCloudConnectionAdapter<Configuration>['syncDevice']>,\n ): Promise<void> {\n let attempt = 0;\n while (this.isCurrent(generation, signal)) {\n try {\n const result = await syncDevice(configuration, peerId, signal);\n if (!this.isCurrent(generation, signal) || result.complete) return;\n attempt = 0;\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n attempt += 1;\n this.warn(\n 'Device Cloud background sync failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n }\n const delay = this.backgroundSyncBackoffDelay(attempt);\n try {\n await abortableDelay(delay, signal);\n } catch {\n return;\n }\n }\n }\n\n private backgroundSyncBackoffDelay(attempt: number): number {\n const exponential = Math.min(\n this.backgroundSyncMaxBackoffMs,\n this.backgroundSyncInitialBackoffMs * 2 ** Math.max(0, attempt - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n return this.backgroundSyncInitialBackoffMs;\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private async drainBackgroundSyncGeneration(generation: number): Promise<void> {\n const runs = [...this.backgroundSyncRuns.values()]\n .filter(run => run.generation === generation)\n .map(run => run.promise.catch(() => undefined));\n await Promise.all(runs);\n }\n\n private readNow(): number {\n const value = this.now();\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError('now() must return a finite non-negative safe integer timestamp');\n }\n return value;\n }\n\n private retryAt(delayMs: number): number {\n const now = this.readNow();\n if (now > Number.MAX_SAFE_INTEGER - delayMs) {\n throw new TypeError('now() plus delay must remain a safe integer timestamp');\n }\n return now + delayMs;\n }\n\n private schedule(delayMs: number, generation: number): void {\n if (!this.started || !this.isCurrent(generation, this.controller.signal)) return;\n this.clearTimer();\n this.timer = setTimeout(() => {\n if (!this.isCurrent(generation, this.controller.signal)) return;\n void this.runNow().catch(() => {\n this.warn(\n 'Device Cloud scheduled maintenance failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', 'offline'),\n );\n });\n }, delayMs);\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private isCurrent(generation: number, signal: AbortSignal): boolean {\n return generation === this.generation && generation === this.requestedGeneration && !signal.aborted;\n }\n\n private async setComponent(\n component: DeviceCloudConnectionComponent,\n status: DeviceCloudComponentStatus,\n generation: number,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n this.snapshotValue = freezeSnapshot({\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components, [component]: status },\n });\n this.emit();\n }\n\n private async updateSnapshot(\n generation: number,\n update: Partial<Omit<DeviceCloudConnectionSnapshot, 'generation' | 'components'>>,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n const next: DeviceCloudConnectionSnapshot = {\n ...this.snapshotValue,\n ...update,\n ...(update.lastError === undefined ? { lastError: undefined } : {}),\n };\n this.snapshotValue = freezeSnapshot(next);\n this.emit();\n }\n\n private resetSnapshot(): void {\n this.snapshotValue = freezeSnapshot({\n status: this.options.adapter.isConfigured(this.configuration)\n ? 'offline'\n : 'not-configured',\n generation: this.generation,\n components: emptyComponents(),\n });\n this.emit();\n }\n\n /** Status observers are telemetry only: never part of a network transition. */\n private emit(): void {\n const snapshot = this.snapshotValue;\n const signal = this.controller.signal;\n void Promise.resolve()\n .then(async () => {\n if (!this.isCurrent(snapshot.generation, signal)) return;\n await this.options.onStatus?.(\n snapshot,\n this.createCommitFence(snapshot.generation, signal),\n );\n })\n .catch(() => {\n this.warn(\n 'Device Cloud status observer failed',\n safeError('DEVICE_CLOUD_OBSERVER_FAILED', 'error'),\n );\n });\n }\n\n private warn(message: string, error: DeviceCloudConnectionError): void {\n const boundedMessage = message.slice(0, 160);\n void Promise.resolve()\n .then(() => this.options.logWarning?.(boundedMessage, error))\n .catch(() => undefined);\n }\n}\n","export type JsonFrameErrorCode =\n | 'FRAME_TOO_LARGE'\n | 'TRUNCATED_FRAME'\n | 'INVALID_UTF8'\n | 'INVALID_JSON'\n | 'IDLE_TIMEOUT'\n | 'TOTAL_TIMEOUT'\n | 'ABORTED';\n\nexport class JsonFrameError extends Error {\n public readonly code: JsonFrameErrorCode;\n\n constructor(code: JsonFrameErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'JsonFrameError';\n this.code = code;\n }\n}\n\nexport interface JsonFrameReaderOptions {\n maxPayloadBytes: number;\n idleTimeoutMs: number;\n totalTimeoutMs: number;\n signal?: AbortSignal;\n abort?: (error: JsonFrameError) => void | Promise<void>;\n}\n\nconst HEADER_BYTES = 4;\nconst MAX_UINT32 = 0xffff_ffff;\n\nfunction assertPositiveInteger(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n}\n\nfunction validateMaxPayloadBytes(maxPayloadBytes: number): void {\n assertPositiveInteger(maxPayloadBytes, 'maxPayloadBytes');\n if (maxPayloadBytes > MAX_UINT32) {\n throw new TypeError('maxPayloadBytes must fit in an unsigned 32-bit frame length');\n }\n}\n\nexport function encodeJsonFrame(value: unknown, maxPayloadBytes = MAX_UINT32): Uint8Array {\n validateMaxPayloadBytes(maxPayloadBytes);\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(value);\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized', {\n cause: error,\n });\n }\n if (serialized === undefined) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized');\n }\n const payload = new TextEncoder().encode(serialized);\n if (payload.byteLength > maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${maxPayloadBytes} bytes`,\n );\n }\n const frame = new Uint8Array(HEADER_BYTES + payload.byteLength);\n new DataView(frame.buffer, frame.byteOffset, HEADER_BYTES).setUint32(0, payload.byteLength, false);\n frame.set(payload, HEADER_BYTES);\n return frame;\n}\n\nexport async function* encodeJsonFrames(\n values: AsyncIterable<unknown> | Iterable<unknown>,\n maxPayloadBytes = MAX_UINT32,\n): AsyncIterable<Uint8Array> {\n for await (const value of values) {\n yield encodeJsonFrame(value, maxPayloadBytes);\n }\n}\n\nfunction abortedError(signal?: AbortSignal): JsonFrameError {\n return new JsonFrameError('ABORTED', 'JSON frame reading was aborted', {\n cause: signal?.reason,\n });\n}\n\ninterface JsonFrameDeadline {\n at: number;\n code: 'IDLE_TIMEOUT' | 'TOTAL_TIMEOUT';\n message: string;\n}\n\n/**\n * Select the deadline that governs one iterator pull. The selection remains\n * stable for the lifetime of that pull: a delayed timer must report the first\n * deadline that was crossed, rather than whichever deadlines happen to be\n * expired when its callback runs. Total timeout wins an exact tie so a frame\n * whose idle and total budgets end together is classified deterministically.\n */\nfunction selectReadDeadline(\n idleDeadline: number,\n totalDeadline: number | undefined,\n): JsonFrameDeadline {\n if (totalDeadline !== undefined && totalDeadline <= idleDeadline) {\n return {\n at: totalDeadline,\n code: 'TOTAL_TIMEOUT',\n message: 'JSON frame total timeout expired',\n };\n }\n return {\n at: idleDeadline,\n code: 'IDLE_TIMEOUT',\n message: 'JSON frame idle timeout expired',\n };\n}\n\nasync function readNextChunk(\n iterator: AsyncIterator<Uint8Array>,\n idleDeadline: number,\n totalDeadline: number | undefined,\n signal: AbortSignal | undefined,\n): Promise<IteratorResult<Uint8Array>> {\n if (signal?.aborted) throw abortedError(signal);\n const now = Date.now();\n const deadline = selectReadDeadline(idleDeadline, totalDeadline);\n if (deadline.at <= now) {\n throw new JsonFrameError(deadline.code, deadline.message);\n }\n\n return new Promise<IteratorResult<Uint8Array>>((resolve, reject) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const finish = (callback: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n callback();\n };\n const onAbort = () => {\n finish(() => {\n reject(abortedError(signal));\n });\n };\n\n const onTimeout = () => {\n if (settled) return;\n const remainingMs = deadline.at - Date.now();\n if (remainingMs > 0) {\n // Node and browser timers may fire slightly early (and fractional\n // delays are truncated). Never turn that scheduler detail into a\n // timeout classification bug: wait until the selected absolute\n // deadline has actually elapsed.\n timer = setTimeout(onTimeout, Math.max(1, remainingMs));\n return;\n }\n finish(() => {\n reject(new JsonFrameError(deadline.code, deadline.message));\n });\n };\n\n timer = setTimeout(onTimeout, Math.max(1, deadline.at - now));\n signal?.addEventListener('abort', onAbort, { once: true });\n // Cover an abort racing between the entry check and listener attachment.\n if (signal?.aborted) {\n onAbort();\n return;\n }\n void iterator.next().then(\n (result) => {\n finish(() => {\n resolve(result);\n });\n },\n (error: unknown) => {\n finish(() => {\n reject(\n error instanceof Error ? error : new Error('JSON frame source failed', {\n cause: error,\n }),\n );\n });\n },\n );\n });\n}\n\n/**\n * Decode uint32be-length-prefixed, strict UTF-8 JSON frames from an arbitrary\n * chunked byte stream. Buffered remainder is retained so one chunk may contain\n * any number of complete or partial frames.\n */\nexport function createJsonFrameReader(\n source: AsyncIterable<Uint8Array>,\n options: JsonFrameReaderOptions,\n): AsyncIterable<unknown> {\n validateMaxPayloadBytes(options.maxPayloadBytes);\n assertPositiveInteger(options.idleTimeoutMs, 'idleTimeoutMs');\n assertPositiveInteger(options.totalTimeoutMs, 'totalTimeoutMs');\n\n return (async function* readFrames(): AsyncIterable<unknown> {\n const iterator = source[Symbol.asyncIterator]();\n const header = new Uint8Array(HEADER_BYTES);\n let headerBytes = 0;\n let payload: Uint8Array | undefined;\n let payloadBytes = 0;\n let expectedPayloadBytes: number | undefined;\n let idleDeadline = Date.now() + options.idleTimeoutMs;\n let totalDeadline: number | undefined;\n let abortCalled = false;\n let completed = false;\n\n const abortOnce = (error: JsonFrameError): void => {\n if (abortCalled) return;\n abortCalled = true;\n try {\n // Aborting is a notification/cancellation boundary, not part of error\n // delivery. A defective host abort implementation must never prevent\n // the framing error from reaching the caller.\n void Promise.resolve(options.abort?.(error)).catch(() => undefined);\n } catch {\n // A synchronous host error is intentionally isolated for the same\n // reason as a rejected abort promise.\n }\n };\n\n const decodePayload = (bytes: Uint8Array): unknown => {\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch (error) {\n throw new JsonFrameError('INVALID_UTF8', 'JSON frame payload is not valid UTF-8', {\n cause: error,\n });\n }\n try {\n return JSON.parse(text) as unknown;\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame payload is not valid JSON', {\n cause: error,\n });\n }\n };\n\n const onExternalAbort = (): void => {\n abortOnce(abortedError(options.signal));\n };\n options.signal?.addEventListener('abort', onExternalAbort, { once: true });\n if (options.signal?.aborted) onExternalAbort();\n\n try {\n for (;;) {\n const result = await readNextChunk(\n iterator,\n idleDeadline,\n totalDeadline,\n options.signal,\n );\n if (result.done) {\n if (headerBytes > 0 || expectedPayloadBytes !== undefined) {\n throw new JsonFrameError('TRUNCATED_FRAME', 'JSON frame stream ended mid-frame');\n }\n completed = true;\n return;\n }\n if (!(result.value instanceof Uint8Array)) {\n throw new TypeError('JSON frame source must yield Uint8Array chunks');\n }\n if (result.value.byteLength === 0) continue;\n const now = Date.now();\n idleDeadline = now + options.idleTimeoutMs;\n totalDeadline ??= now + options.totalTimeoutMs;\n\n // Retain at most the current source chunk and copy every frame byte\n // exactly once into the fixed header or exact-size payload allocation.\n // The source is not pulled again until this chunk is fully consumed,\n // so producers may safely reuse their buffer on the next pull while\n // byte-at-a-time input remains O(n).\n let chunkOffset = 0;\n while (chunkOffset < result.value.byteLength) {\n if (expectedPayloadBytes === undefined) {\n const headerRemaining = HEADER_BYTES - headerBytes;\n const copied = Math.min(headerRemaining, result.value.byteLength - chunkOffset);\n header.set(result.value.subarray(chunkOffset, chunkOffset + copied), headerBytes);\n headerBytes += copied;\n chunkOffset += copied;\n if (headerBytes < HEADER_BYTES) continue;\n\n expectedPayloadBytes = new DataView(\n header.buffer,\n header.byteOffset,\n HEADER_BYTES,\n ).getUint32(0, false);\n if (expectedPayloadBytes > options.maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${options.maxPayloadBytes} bytes`,\n );\n }\n payload = new Uint8Array(expectedPayloadBytes);\n payloadBytes = 0;\n }\n\n const payloadRemaining = expectedPayloadBytes - payloadBytes;\n const copied = Math.min(payloadRemaining, result.value.byteLength - chunkOffset);\n if (copied > 0) {\n payload!.set(result.value.subarray(chunkOffset, chunkOffset + copied), payloadBytes);\n payloadBytes += copied;\n chunkOffset += copied;\n }\n if (payloadBytes < expectedPayloadBytes) continue;\n\n const value = decodePayload(payload!);\n headerBytes = 0;\n payload = undefined;\n payloadBytes = 0;\n expectedPayloadBytes = undefined;\n const hasRemainingChunkBytes = chunkOffset < result.value.byteLength;\n totalDeadline = undefined;\n yield value;\n if (options.signal?.aborted) throw abortedError(options.signal);\n // Consumer backpressure is neither source idleness nor time spent\n // receiving the next frame. Start both clocks only after the\n // consumer resumes and before processing coalesced remainder bytes.\n const resumedAt = Date.now();\n idleDeadline = resumedAt + options.idleTimeoutMs;\n if (hasRemainingChunkBytes) {\n totalDeadline = resumedAt + options.totalTimeoutMs;\n }\n }\n }\n } catch (error) {\n const frameError = error instanceof JsonFrameError\n ? error\n : new JsonFrameError('ABORTED', 'JSON frame source failed', { cause: error });\n abortOnce(frameError);\n throw frameError;\n } finally {\n options.signal?.removeEventListener('abort', onExternalAbort);\n if (!completed) abortOnce(abortedError(options.signal));\n // An async generator can be blocked in an uncooperative await. The\n // underlying stream abort above is the cancellation boundary; waiting\n // for iterator.return() here would let that source deadlock the caller.\n try {\n const returned = iterator.return?.();\n if (returned !== undefined) void Promise.resolve(returned).catch(() => undefined);\n } catch {\n // Iterator cleanup is best effort and must not replace a frame error.\n }\n }\n })();\n}\n","import { OrchestrationError } from '../orchestration/errors.js';\nimport type { RemoteOrchestrationRequest, RemoteOrchestrationResponse, RemoteOrchestrationTransport, RemoteOrchestrationTransportOptions } from '../orchestration/remoteClient.js';\nimport { createJsonFrameReader, encodeJsonFrames, JsonFrameError } from './jsonFrame.js';\nimport type { DeviceConnectionGrant, DeviceNetworkService, MemeLoopDuplexStream } from './types.js';\n\nexport const DEVICE_ORCHESTRATION_PROTOCOL = '/memeloop/orchestration/2.0.0' as const;\nexport const DEVICE_ORCHESTRATION_FRAME_LIMITS = Object.freeze({\n maxPayloadBytes: 1024 * 1024,\n requestIdleTimeoutMs: 10_000,\n requestTotalTimeoutMs: 30_000,\n watchIdleTimeoutMs: 90_000,\n watchBookmarkIntervalMs: 30_000,\n});\nconst DEFAULT_MAX_FRAME_BYTES = DEVICE_ORCHESTRATION_FRAME_LIMITS.maxPayloadBytes;\nconst REQUEST_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestIdleTimeoutMs;\nconst REQUEST_TOTAL_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestTotalTimeoutMs;\nconst WATCH_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchIdleTimeoutMs;\nconst WATCH_BOOKMARK_INTERVAL_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchBookmarkIntervalMs;\n\nexport interface DeviceOrchestrationTransportOptions {\n deviceNetwork: Pick<DeviceNetworkService, 'openStream'>;\n peerId: string;\n grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => DeviceConnectionGrant | undefined | Promise<DeviceConnectionGrant | undefined>;\n maxFrameBytes?: number;\n}\n\nexport interface DeviceOrchestrationStreamHandlerInput {\n remotePeerId: string;\n stream: MemeLoopDuplexStream;\n authorize?: (presentedGrant: DeviceConnectionGrant | undefined) => boolean | Promise<boolean>;\n}\n\nexport type RemoteOrchestrationHandler = {\n request(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): Promise<RemoteOrchestrationResponse>;\n watch(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): AsyncIterable<RemoteOrchestrationResponse>;\n};\n\nexport interface DeviceOrchestrationStreamHandlerOptions {\n resolveHandler: (\n remotePeerId: string,\n ) => RemoteOrchestrationHandler | Promise<RemoteOrchestrationHandler>;\n maxFrameBytes?: number;\n}\n\nexport type DeviceOrchestrationStreamHandler = (\n input: DeviceOrchestrationStreamHandlerInput,\n) => Promise<void>;\n\ninterface DeviceOrchestrationRequestEnvelope {\n type: 'memeloop-device-orchestration-request-v2';\n request: RemoteOrchestrationRequest;\n deadline?: string;\n grant?: DeviceConnectionGrant;\n}\n\nfunction orchestrationTransportError(\n code: 'CANCELLED' | 'EXHAUSTED' | 'INVALID' | 'UNAVAILABLE',\n message: string,\n): OrchestrationError {\n return new OrchestrationError({\n code,\n message,\n retryable: code === 'UNAVAILABLE',\n });\n}\n\nfunction assertFrameLimit(limit: number): void {\n if (!Number.isSafeInteger(limit) || limit < 256) {\n throw new TypeError('maxFrameBytes must be a safe integer of at least 256');\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled');\n }\n}\n\nasync function openAuthenticatedStream(\n options: DeviceOrchestrationTransportOptions,\n signal?: AbortSignal,\n): Promise<{\n stream: MemeLoopDuplexStream;\n grant: DeviceConnectionGrant | undefined;\n}> {\n const grant = await options.grantProvider?.(options.peerId, signal);\n return {\n stream: await options.deviceNetwork.openStream(\n options.peerId,\n DEVICE_ORCHESTRATION_PROTOCOL,\n {\n presentedGrant: grant,\n signal,\n },\n ),\n grant,\n };\n}\n\nasync function writeRequest(\n stream: MemeLoopDuplexStream,\n request: RemoteOrchestrationRequest,\n grant: DeviceConnectionGrant | undefined,\n deadline: string | undefined,\n maxFrameBytes: number,\n): Promise<void> {\n const envelope: DeviceOrchestrationRequestEnvelope = {\n type: 'memeloop-device-orchestration-request-v2',\n request,\n ...(deadline ? { deadline } : {}),\n ...(grant ? { grant } : {}),\n };\n await stream.sink(encodeJsonFrames([envelope], maxFrameBytes));\n}\n\nfunction abortStreamOnce(stream: MemeLoopDuplexStream): (error: Error) => Promise<void> {\n let aborted = false;\n return async (error) => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n}\n\nfunction frameReader(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n idleTimeoutMs: number,\n signal: AbortSignal | undefined,\n abort: (error: Error) => Promise<void>,\n): AsyncIterable<unknown> {\n return createJsonFrameReader(stream.source, {\n maxPayloadBytes: maxFrameBytes,\n idleTimeoutMs,\n totalTimeoutMs: REQUEST_TOTAL_TIMEOUT_MS,\n signal,\n abort,\n });\n}\n\nfunction mapFrameError(error: unknown): never {\n if (!(error instanceof JsonFrameError)) throw error;\n if (error.code === 'ABORTED') {\n throw orchestrationTransportError('CANCELLED', error.message);\n }\n if (error.code === 'FRAME_TOO_LARGE') {\n throw orchestrationTransportError('EXHAUSTED', error.message);\n }\n if (error.code === 'IDLE_TIMEOUT' || error.code === 'TOTAL_TIMEOUT') {\n throw orchestrationTransportError('UNAVAILABLE', error.message);\n }\n throw orchestrationTransportError('INVALID', error.message);\n}\n\n/**\n * Carry the portable resource protocol over an already authenticated and\n * encrypted device-network stream. No bearer credential crosses the link:\n * authorization is bound to the paired peer identity opening the protocol.\n */\nexport function createDeviceOrchestrationTransport(\n options: DeviceOrchestrationTransportOptions,\n): RemoteOrchestrationTransport {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n\n return {\n async request(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const deadline = transportOptions.deadline;\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(stream, request, grant, deadline, maxFrameBytes);\n let response: RemoteOrchestrationResponse | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n if (response) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request returned multiple responses',\n );\n }\n response = value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n if (!response) {\n throw orchestrationTransportError(\n 'UNAVAILABLE',\n 'device orchestration request returned no response',\n );\n }\n return response;\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n async *watch(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration watch was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(\n stream,\n request,\n grant,\n transportOptions.deadline,\n maxFrameBytes,\n );\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n WATCH_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n throwIfAborted(transportOptions.signal);\n yield value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n };\n}\n\nasync function readSingleRequest(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n): Promise<DeviceOrchestrationRequestEnvelope> {\n const abort = abortStreamOnce(stream);\n let envelope: DeviceOrchestrationRequestEnvelope | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n undefined,\n abort,\n )\n ) {\n if (envelope) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration stream accepts exactly one request',\n );\n }\n if (\n value === null ||\n typeof value !== 'object' ||\n Array.isArray(value) ||\n (value as Record<string, unknown>).type !== 'memeloop-device-orchestration-request-v2' ||\n (value as Record<string, unknown>).request === null ||\n typeof (value as Record<string, unknown>).request !== 'object'\n ) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request envelope is invalid',\n );\n }\n envelope = value as DeviceOrchestrationRequestEnvelope;\n }\n if (!envelope) {\n throw orchestrationTransportError('INVALID', 'device orchestration request is missing');\n }\n return envelope;\n}\n\nasync function* withWatchBookmarks(\n source: AsyncIterable<RemoteOrchestrationResponse>,\n request: RemoteOrchestrationRequest,\n signal: AbortSignal,\n): AsyncIterable<RemoteOrchestrationResponse> {\n const iterator = source[Symbol.asyncIterator]();\n type WatchActivity =\n | { kind: 'value'; value: IteratorResult<RemoteOrchestrationResponse> }\n | { kind: 'error'; error: unknown }\n | { kind: 'aborted' };\n\n let activity: WatchActivity | undefined;\n let activityWaiter: ((value: WatchActivity | { kind: 'bookmark' }) => void) | undefined;\n let bookmarkTimer: ReturnType<typeof setTimeout> | undefined;\n let readInFlight = false;\n let lastResourceVersion = watchResourceVersion(request.payload.options) ?? '0';\n\n const clearBookmarkTimer = () => {\n if (bookmarkTimer !== undefined) clearTimeout(bookmarkTimer);\n bookmarkTimer = undefined;\n };\n const publishActivity = (value: WatchActivity) => {\n if (activityWaiter) {\n const resolve = activityWaiter;\n activityWaiter = undefined;\n clearBookmarkTimer();\n resolve(value);\n return;\n }\n activity = value;\n };\n const readNext = () => {\n if (readInFlight) return;\n readInFlight = true;\n void iterator.next().then(\n (value) => {\n readInFlight = false;\n publishActivity({ kind: 'value', value });\n },\n (error: unknown) => {\n readInFlight = false;\n publishActivity({ kind: 'error', error });\n },\n );\n };\n const waitForActivity = (): Promise<WatchActivity | { kind: 'bookmark' }> => {\n if (activity) {\n const value = activity;\n activity = undefined;\n return Promise.resolve(value);\n }\n if (signal.aborted) return Promise.resolve({ kind: 'aborted' });\n return new Promise((resolve) => {\n activityWaiter = resolve;\n bookmarkTimer = setTimeout(() => {\n bookmarkTimer = undefined;\n activityWaiter = undefined;\n resolve({ kind: 'bookmark' });\n }, WATCH_BOOKMARK_INTERVAL_MS);\n });\n };\n const onAbort = () => {\n publishActivity({ kind: 'aborted' });\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n readNext();\n try {\n for (;;) {\n const result = await waitForActivity();\n if (result.kind === 'aborted') return;\n if (result.kind === 'bookmark') {\n yield {\n protocol: request.protocol,\n requestId: request.requestId,\n ok: true,\n result: { type: 'BOOKMARK', resourceVersion: lastResourceVersion },\n };\n continue;\n }\n if (result.kind === 'error') throw result.error;\n if (result.value.done) return;\n const response = result.value.value;\n lastResourceVersion = response.ok\n ? watchResourceVersion(response.result) ?? lastResourceVersion\n : lastResourceVersion;\n yield response;\n readNext();\n }\n } finally {\n clearBookmarkTimer();\n activityWaiter = undefined;\n signal.removeEventListener('abort', onAbort);\n void iterator.return?.();\n }\n}\n\nfunction watchResourceVersion(value: unknown): string | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const resourceVersion = (value as Record<string, unknown>).resourceVersion;\n return typeof resourceVersion === 'string' && resourceVersion.length > 0\n ? resourceVersion\n : undefined;\n}\n\n/** Bind a trusted peer identity to a policy-scoped orchestration handler. */\nexport function createDeviceOrchestrationStreamHandler(\n options: DeviceOrchestrationStreamHandlerOptions,\n): DeviceOrchestrationStreamHandler {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n return async ({ remotePeerId, stream, authorize }) => {\n const abort = new AbortController();\n const abortFromStream = (): void => {\n if (!abort.signal.aborted) {\n abort.abort(stream.signal?.reason ?? new Error('device orchestration stream closed'));\n }\n };\n stream.signal?.addEventListener('abort', abortFromStream, { once: true });\n if (stream.signal?.aborted) abortFromStream();\n try {\n const envelope = await readSingleRequest(stream, maxFrameBytes);\n if (authorize && !(await authorize(envelope.grant))) {\n throw orchestrationTransportError('UNAVAILABLE', 'device_not_trusted');\n }\n const request = envelope.request;\n const handler = await options.resolveHandler(remotePeerId);\n if (request.operation === 'watch') {\n await stream.sink(\n encodeJsonFrames(\n withWatchBookmarks(handler.watch(request, { signal: abort.signal }), request, abort.signal),\n maxFrameBytes,\n ),\n );\n } else {\n const response = await handler.request(request, {\n signal: stream.signal,\n deadline: envelope.deadline ?? new Date(Date.now() + REQUEST_TOTAL_TIMEOUT_MS).toISOString(),\n });\n if (stream.signal?.aborted) return;\n await stream.sink(encodeJsonFrames([response], maxFrameBytes));\n }\n } finally {\n stream.signal?.removeEventListener('abort', abortFromStream);\n if (!abort.signal.aborted) abort.abort();\n await stream.close().catch(() => undefined);\n }\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\nimport { createJsonFrameReader, encodeJsonFrames } from './jsonFrame.js';\nimport {\n attachmentChunkFromWire,\n attachmentChunkToWire,\n isLibp2pSyncResponse,\n LIBP2P_SYNC_REQUEST_TYPE,\n type Libp2pSyncMethod,\n type Libp2pSyncRequest,\n} from './libp2pSyncProtocol.js';\nimport type { AttachmentChunk, Device, DeviceConnectionGrant, DeviceNetworkService, DeviceSyncTransport, ExchangeVersionFrontierPageResult } from './types.js';\n\nexport interface Libp2pDeviceSyncTransportOptions {\n nodeId: string;\n deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n grantProvider?: (peerId: string, signal?: AbortSignal) => Promise<DeviceConnectionGrant | undefined>;\n signal?: AbortSignal;\n}\n\nexport class Libp2pDeviceSyncTransport implements DeviceSyncTransport {\n public readonly nodeId: string;\n private readonly deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n private readonly grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => Promise<DeviceConnectionGrant | undefined>;\n private readonly signal?: AbortSignal;\n\n constructor(options: Libp2pDeviceSyncTransportOptions) {\n this.nodeId = options.nodeId;\n this.deviceNetwork = options.deviceNetwork;\n this.grantProvider = options.grantProvider;\n this.signal = options.signal;\n }\n\n public listPeers(): Promise<Device[]> {\n return this.deviceNetwork.listDevices();\n }\n\n public exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult> {\n return this.request(peerId, 'exchangeVersionFrontierPage', {\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n }, options?.signal) as Promise<ExchangeVersionFrontierPageResult>;\n }\n\n public pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n return this.request(peerId, 'pullMissingEvents', { conversationId, ranges, cursor }, options?.signal) as Promise<ConversationEventSyncPage>;\n }\n\n public async pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null> {\n const result = await this.request(\n peerId,\n 'pullAttachmentChunk',\n { conversationId, contentHash, offset, maxBytes },\n options?.signal,\n );\n return attachmentChunkFromWire(result);\n }\n\n public async pushEvents(\n peerId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushEvents', { events }, options?.signal);\n }\n\n public async pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushAttachmentChunk', {\n conversationId,\n contentHash,\n chunk: attachmentChunkToWire(chunk),\n }, options?.signal);\n }\n\n private async request(\n peerId: string,\n method: Libp2pSyncMethod,\n parameters: unknown,\n operationSignal?: AbortSignal,\n ): Promise<unknown> {\n const signal = operationSignal ?? this.signal;\n const grant = await this.grantProvider?.(peerId, signal);\n const stream = await this.deviceNetwork.openStream(peerId, '/memeloop/sync/2.0.0', {\n presentedGrant: grant,\n signal,\n });\n let aborted = false;\n const abort = async (error: Error): Promise<void> => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n const request: Libp2pSyncRequest = {\n type: LIBP2P_SYNC_REQUEST_TYPE,\n id: crypto.randomUUID(),\n method,\n params: parameters,\n grant,\n };\n try {\n await stream.sink(encodeJsonFrames([request], 16 * 1024 * 1024));\n let response: unknown;\n for await (\n const value of createJsonFrameReader(stream.source, {\n maxPayloadBytes: 16 * 1024 * 1024,\n idleTimeoutMs: 15_000,\n totalTimeoutMs: 120_000,\n signal,\n abort,\n })\n ) {\n if (response !== undefined) throw new Error('sync_response_multiple');\n response = value;\n }\n if (!isLibp2pSyncResponse(response)) throw new Error('invalid_sync_response');\n if (response.id !== request.id) throw new Error('sync_response_id_mismatch');\n if (!response.ok) throw new Error(response.error.code);\n return response.result;\n } catch (error) {\n await abort(error instanceof Error ? error : new Error('sync_transport_failed'));\n if (signal?.aborted) signal.throwIfAborted();\n throw error;\n } finally {\n await stream.close().catch(() => undefined);\n }\n }\n}\n","import { hasCanonicalDeviceConnectionGrantClaims } from './deviceGrantMessages.js';\nimport type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_RPC_REQUEST_TYPE = 'memeloop-rpc-request-v2';\nexport const LIBP2P_RPC_RESPONSE_TYPE = 'memeloop-rpc-response-v2';\n\nexport interface Libp2pRpcRequest {\n type: typeof LIBP2P_RPC_REQUEST_TYPE;\n id: string;\n method: string;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pRpcResponse =\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nconst MAX_RPC_ID_LENGTH = 128;\nconst MAX_RPC_METHOD_LENGTH = 256;\nconst RPC_ERROR_CODE_PATTERN = /^[a-z][a-z\\d_]{0,63}$/u;\n\nexport function isLibp2pRpcRequest(value: unknown): value is Libp2pRpcRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_RPC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= MAX_RPC_ID_LENGTH &&\n typeof record.method === 'string' &&\n record.method.length > 0 && record.method.length <= MAX_RPC_METHOD_LENGTH &&\n 'params' in record &&\n (record.grant === undefined || hasCanonicalDeviceConnectionGrantClaims(record.grant))\n );\n}\n\nexport function isLibp2pRpcResponse(value: unknown): value is Libp2pRpcResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_RPC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > MAX_RPC_ID_LENGTH ||\n typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) return false;\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n RPC_ERROR_CODE_PATTERN.test(error.code);\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key));\n}\n","import type { DeviceAuthorizer, MemeLoopProtocol, TrustedDeviceRecord } from './types.js';\n\nexport interface LocalTrustDeviceAuthorizerOptions {\n trustedDevices?: Iterable<TrustedDeviceRecord>;\n getTrustedDevice?: (peerId: string) => TrustedDeviceRecord | undefined;\n allowPairingProtocol?: boolean;\n}\n\nconst PAIRING_PROTOCOL: MemeLoopProtocol = '/memeloop/pairing/2.0.0';\n\nexport class LocalTrustDeviceAuthorizer implements DeviceAuthorizer {\n private readonly trustedDevices = new Map<string, TrustedDeviceRecord>();\n private readonly allowPairingProtocol: boolean;\n\n constructor(private readonly options: LocalTrustDeviceAuthorizerOptions = {}) {\n this.allowPairingProtocol = options.allowPairingProtocol ?? true;\n for (const record of options.trustedDevices ?? []) {\n this.trustedDevices.set(record.peerId, record);\n }\n }\n\n public setTrustedDevice(record: TrustedDeviceRecord): void {\n this.trustedDevices.set(record.peerId, record);\n }\n\n public removeTrustedDevice(peerId: string): void {\n this.trustedDevices.delete(peerId);\n }\n\n public async canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n }): Promise<boolean> {\n const record = this.options.getTrustedDevice?.(input.remotePeerId) ?? this.trustedDevices.get(input.remotePeerId);\n if (record?.revokedAt !== undefined) return false;\n if (input.protocol === PAIRING_PROTOCOL) return this.allowPairingProtocol;\n // Cloud directory entries are discovery metadata, not local trust. Only\n // an explicit local pairing may authorize business protocols here;\n // cloud-account peers must be evaluated by CloudDeviceAuthorizer with a\n // current signed grant.\n return record?.trustMode === 'local-pairing';\n }\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\n\nexport type DevicePlatform = 'desktop' | 'mobile' | 'cli' | 'web';\nexport type DeviceTrustMode = 'local-pairing' | 'cloud-account';\nexport type DeviceReachabilityState = 'nearby' | 'online' | 'offline' | 'connecting';\nexport type DeviceNetworkPath = 'lan' | 'direct' | 'relay';\nexport type DeviceProtocolDirection = 'inbound' | 'outbound';\nexport type PairingSessionDirection = 'inbound' | 'outbound';\nexport type PairingSessionStatus = 'pending' | 'accepted' | 'rejected' | 'expired';\n\n/** Generation-scoped authority for a final synchronous host or persistence write. */\nexport interface DeviceCloudCommitFence {\n readonly generation: number;\n readonly signal: AbortSignal;\n isCurrent(): boolean;\n throwIfStale(): void;\n commitSynchronous<Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ): boolean;\n}\n\nexport type MemeLoopProtocol =\n | '/memeloop/rpc/2.0.0'\n | '/memeloop/sync/2.0.0'\n | '/memeloop/pairing/2.0.0'\n | '/memeloop/orchestration/2.0.0'\n | '/memeloop/relay-admission/2.0.0';\n\nexport interface DeviceCapabilities {\n tools: string[];\n mcpServers: string[];\n hasWiki: boolean;\n agentLoop?: boolean;\n imChannels: string[];\n wikis: Array<{\n wikiId: string;\n title?: string;\n pathHint?: string;\n }>;\n}\n\n/** Device identity fields safe to disclose to Cloud and remote peers. */\nexport interface PublicDeviceIdentity {\n peerId: string;\n publicKeyMultibase: string;\n createdAt: number;\n deviceName: string;\n platform: DevicePlatform;\n}\n\n/** Host-local identity. Private-key material must never cross an adapter boundary. */\nexport interface LocalDeviceIdentity extends PublicDeviceIdentity {\n privateKeyRef: string;\n privateKeyPkcs8Base64Url?: string;\n privateKeyRawSeedBase64Url?: string;\n}\n\nexport interface DeviceNetworkListenOptions {\n addresses: string[];\n announce?: string[];\n}\n\nexport interface DeviceReachability {\n state: DeviceReachabilityState;\n paths: DeviceNetworkPath[];\n}\n\nexport interface Device {\n peerId: string;\n displayName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n trusted?: boolean;\n reachability: DeviceReachability;\n capabilities: DeviceCapabilities;\n multiaddrs?: string[];\n lastSeen?: number;\n}\n\nexport interface TrustedDeviceRecord {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n accountId?: string;\n createdAt: number;\n lastSeen?: number;\n revokedAt?: number;\n}\n\nexport interface DeviceTrustStore {\n loadTrustedDevices(): Promise<TrustedDeviceRecord[]>;\n saveTrustedDevice(record: TrustedDeviceRecord): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n}\n\nexport interface DeviceAccountBindingRequest {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n cloudNonce: string;\n signature: string;\n}\n\nexport interface CloudDeviceRecord {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n lastSeen: number;\n revokedAt?: number;\n}\n\nexport interface DeviceConnectionGrant {\n issuer: 'memeloop-cloud';\n accountId: string;\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DeviceConnectionGrantStringScope =\n | { mode: 'none' }\n | { mode: 'all' }\n | { mode: 'ids'; ids: string[] };\n\nexport interface DeviceConnectionGrantVerificationInput {\n grant: DeviceConnectionGrant;\n verificationPublicKeyMultibase: string;\n subjectPeerId?: string;\n allowedPeerId?: string;\n now?: number;\n}\n\nexport interface DeviceRelayReservationToken {\n issuer: 'memeloop-cloud';\n accountId: string;\n peerId: string;\n relayMultiaddrs: string[];\n bootstrapMultiaddrs: string[];\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport interface DeviceRelayReservationTokenVerificationInput {\n token: DeviceRelayReservationToken;\n verificationPublicKeyMultibase: string;\n peerId?: string;\n now?: number;\n}\n\nexport interface PairingSession {\n sessionId: string;\n localPeerId: string;\n remotePeerId: string;\n remotePublicKeyMultibase: string;\n remoteDeviceName: string;\n remotePlatform: DevicePlatform;\n remoteCapabilities: DeviceCapabilities;\n remoteMultiaddrs: string[];\n direction: PairingSessionDirection;\n status: PairingSessionStatus;\n confirmCode: string;\n createdAt: number;\n expiresAt: number;\n}\n\nexport interface LocalPairingRequestOptions {\n multiaddrs?: string[];\n /** Cancels dialing and the in-flight pairing frame exchange. */\n signal?: AbortSignal;\n}\n\nexport interface SyncProgress {\n passes: number;\n peers: number;\n /** Bounded frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages. */\n pages: number;\n events: number;\n bytes: number;\n elapsedMs: number;\n}\n\nexport interface SyncContinuation {\n reason: 'pass-limit' | 'time-limit';\n /**\n * Continuations never carry an authoritative cursor. A later call resumes\n * from the durable event frontier, so cancellation or process restart cannot\n * skip acknowledged work.\n */\n resumeFrom: 'durable-frontier';\n}\n\nexport interface SyncResult {\n /** The bounded operation itself succeeded, including an incomplete resumable result. */\n ok: true;\n peerId: string;\n syncedAt: number;\n complete: boolean;\n progress: SyncProgress;\n continuation?: SyncContinuation;\n}\n\nexport type DeviceNetworkUnavailableCode =\n | 'device_network_pairing_unavailable'\n | 'device_network_stream_unavailable'\n | 'device_network_sync_unavailable';\n\n/** Stable, non-secret error for an adapter that cannot perform a network operation. */\nexport class DeviceNetworkUnavailableError extends Error {\n public readonly code: DeviceNetworkUnavailableCode;\n\n constructor(code: DeviceNetworkUnavailableCode) {\n super(code);\n this.name = 'DeviceNetworkUnavailableError';\n this.code = code;\n }\n}\n\nexport interface MemeLoopDuplexStream {\n source: AsyncIterable<Uint8Array>;\n sink(source: AsyncIterable<Uint8Array>): Promise<void>;\n close(): Promise<void>;\n abort(error: Error): void | Promise<void>;\n /** Aborts when the underlying remote stream disconnects or is reset. */\n signal?: AbortSignal;\n}\n\nexport interface DeviceRpcHandlerInput {\n remotePeerId: string;\n method: string;\n parameters: unknown;\n presentedGrant?: DeviceConnectionGrant;\n /** Aborts when the authenticated transport request is cancelled or disconnected. */\n signal?: AbortSignal;\n}\n\nexport type DeviceRpcHandler = (input: DeviceRpcHandlerInput) => Promise<unknown>;\n\nexport interface DeviceStreamOptions {\n presentedGrant?: DeviceConnectionGrant;\n signal?: AbortSignal;\n}\n\nexport type AgentExecutionLocation = { kind: 'local' } | { kind: 'device'; peerId: string };\n\nexport type AgentExecutionState = 'idle' | 'running' | 'stopping';\n\nexport interface ConversationExecutionPlacement {\n conversationId: string;\n location: AgentExecutionLocation;\n state: AgentExecutionState;\n updatedAt: number;\n}\n\nexport interface DeviceAuthorizer {\n canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n direction?: DeviceProtocolDirection;\n presentedGrant?: DeviceConnectionGrant;\n }): Promise<boolean>;\n}\n\nexport interface CloudDeviceClient {\n listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]>;\n getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }>;\n createConnectionGrant(\n input: {\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceConnectionGrant>;\n createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceRelayReservationToken>;\n createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }>;\n registerDevice(\n input: Pick<DeviceAccountBindingRequest, 'cloudNonce' | 'signature'> & {\n identity: PublicDeviceIdentity;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n },\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }>;\n heartbeat(input: {\n peerId: string;\n timestamp: number;\n nonce: string;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signature: string;\n }, signal?: AbortSignal): Promise<{ ok: boolean }>;\n}\n\nexport interface DeviceNetworkService {\n start(): Promise<void>;\n stop(): Promise<void>;\n getLocalDevice(): Promise<Device>;\n listDevices(): Promise<Device[]>;\n observeDevices(listener: (devices: Device[]) => void): () => void;\n listPairingSessions(): Promise<PairingSession[]>;\n observePairingSessions(listener: (sessions: PairingSession[]) => void): () => void;\n requestLocalPairing(\n peerId: string,\n options?: LocalPairingRequestOptions,\n ): Promise<PairingSession>;\n acceptPairing(sessionId: string): Promise<void>;\n rejectPairing(sessionId: string): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n openStream(\n peerId: string,\n protocol: MemeLoopProtocol,\n options?: DeviceStreamOptions,\n ): Promise<MemeLoopDuplexStream>;\n sendRpc<T>(\n peerId: string,\n method: string,\n parameters: unknown,\n options?: DeviceStreamOptions,\n ): Promise<T>;\n syncWithDevice(peerId: string, options?: DeviceSyncOptions): Promise<SyncResult>;\n\n /** Configure Cloud connection. When set, syncCloudDevices() and CloudDeviceAuthorizer become available. */\n configureCloud?(config: { cloudUrl: string; accessToken: string }): void;\n /** Apply a Cloud-signed private relay admission token and connect to advertised relay/bootstrap peers. */\n configureRelayReservation?(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<void>;\n /** Fetch devices from Cloud directory and persist into local trust store. Returns synced devices. */\n syncCloudDevices?(): Promise<CloudDeviceRecord[]>;\n}\n\nexport interface DeviceSyncOptions {\n presentedGrant?: DeviceConnectionGrant;\n /** Restrict synchronization to active conversations; undefined syncs all. */\n conversationIds?: string[];\n signal?: AbortSignal;\n}\n\nexport interface ExchangeVersionFrontierPageResult {\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n}\n\nexport interface AttachmentChunk {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nexport interface DeviceSyncTransport {\n listPeers(): Promise<Device[]>;\n exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult>;\n pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents(peerId: string, events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n","import { canonicalJsonString, domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { Device } from './types.js';\n\nexport const DEVICE_PAIRING_INVITE_PROTOCOL = 'memeloop-device-pairing-v2';\nexport const DEVICE_PAIRING_INVITE_TTL_MS = 5 * 60_000;\nexport const DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS = 30_000;\nconst MAX_INVITE_LENGTH = 16 * 1024;\nconst MAX_ADDRESSES = 8;\nconst PAIRING_CANONICAL_LIMITS = Object.freeze({\n maxDepth: 4,\n maxNodes: 64,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: MAX_INVITE_LENGTH,\n});\n\nexport interface DevicePairingInvite {\n protocol: typeof DEVICE_PAIRING_INVITE_PROTOCOL;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n multiaddrs: string[];\n createdAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DevicePairingInviteUnsignedPayload = Omit<DevicePairingInvite, 'signature'>;\n\nexport interface DevicePairingInviteIdentityVerifierInput {\n invite: DevicePairingInvite;\n payload: Uint8Array;\n}\n\nexport type DevicePairingInviteIdentityVerifier = (\n input: DevicePairingInviteIdentityVerifierInput,\n) => boolean | Promise<boolean>;\n\nexport interface CreateDevicePairingInviteOptions {\n now?: number;\n ttlMs?: number;\n sign(payload: Uint8Array): Promise<string>;\n}\n\nexport interface ParseDevicePairingInviteOptions {\n now?: number;\n /** Must bind publicKeyMultibase -> peerId and verify signature over payload. */\n verifyIdentity: DevicePairingInviteIdentityVerifier;\n}\n\nfunction requireText(value: string, name: string, maxLength: number): string {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > maxLength) {\n throw new Error(`invalid device pairing invite ${name}`);\n }\n return trimmed;\n}\n\nfunction validatePeerBoundAddress(address: string, peerId: string): boolean {\n if (\n address.length === 0 || address.length > 2_048 || address !== address.trim() ||\n !address.startsWith('/') || address.endsWith('/') || address.includes('//') ||\n containsAsciiControlOrSpace(address)\n ) return false;\n const parts = address.split('/');\n const peerIndexes: number[] = [];\n const circuitIndexes: number[] = [];\n for (let index = 1; index < parts.length; index += 1) {\n if (!parts[index]) return false;\n if (parts[index] === 'p2p-circuit') circuitIndexes.push(index);\n if (parts[index] !== 'p2p') continue;\n const peerId = parts[index + 1];\n if (!peerId) return false;\n peerIndexes.push(index);\n index += 1;\n }\n const destinationIndex = peerIndexes.at(-1);\n if (destinationIndex !== parts.length - 2 || parts[destinationIndex + 1] !== peerId) {\n return false;\n }\n if (circuitIndexes.length === 0) return peerIndexes.length === 1;\n if (circuitIndexes.length !== 1 || peerIndexes.length !== 2) return false;\n return peerIndexes[0] < circuitIndexes[0] && circuitIndexes[0] < destinationIndex;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n\nfunction validateAddresses(addresses: readonly string[], peerId: string): string[] {\n const unique = [...new Set(addresses.map((address) => address.trim()))].filter(Boolean);\n if (\n unique.length === 0 ||\n unique.length > MAX_ADDRESSES ||\n unique.some(address => !validatePeerBoundAddress(address, peerId))\n ) {\n throw new Error('device pairing invite requires structurally valid PeerId-bound multiaddrs');\n }\n return unique;\n}\n\nfunction validateLifetime(createdAt: number, expiresAt: number, now: number): void {\n if (\n !Number.isSafeInteger(now) || now < 0 ||\n !Number.isSafeInteger(createdAt) ||\n !Number.isSafeInteger(expiresAt) ||\n createdAt < 0 ||\n expiresAt <= createdAt ||\n expiresAt - createdAt > DEVICE_PAIRING_INVITE_TTL_MS\n ) {\n throw new Error('invalid device pairing invite lifetime');\n }\n if (createdAt > now + DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS) {\n throw new Error('device pairing invite is from the future');\n }\n if (expiresAt <= now) throw new Error('device pairing invite has expired');\n}\n\nfunction unsignedPayload(invite: DevicePairingInviteUnsignedPayload): DevicePairingInviteUnsignedPayload {\n const peerId = requireText(invite.peerId, 'peerId', 256);\n return {\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId,\n publicKeyMultibase: requireText(invite.publicKeyMultibase, 'publicKeyMultibase', 4096),\n deviceName: requireText(invite.deviceName, 'deviceName', 256),\n multiaddrs: [...validateAddresses(invite.multiaddrs, peerId)].sort(),\n createdAt: invite.createdAt,\n expiresAt: invite.expiresAt,\n };\n}\n\nexport function canonicalDevicePairingInviteBytes(\n invite: DevicePairingInviteUnsignedPayload,\n): Uint8Array {\n const payload = unsignedPayload(invite);\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_PAIRING_INVITE_PROTOCOL,\n payload,\n PAIRING_CANONICAL_LIMITS,\n );\n}\n\nexport async function createDevicePairingInvite(\n device: Pick<Device, 'peerId' | 'displayName' | 'multiaddrs'> & {\n publicKeyMultibase: string;\n },\n options: CreateDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n const createdAt = options.now ?? Date.now();\n const ttlMs = options.ttlMs ?? DEVICE_PAIRING_INVITE_TTL_MS;\n if (!Number.isSafeInteger(createdAt) || !Number.isSafeInteger(ttlMs) || ttlMs <= 0) {\n throw new Error('invalid device pairing invite lifetime');\n }\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: device.peerId,\n publicKeyMultibase: device.publicKeyMultibase,\n deviceName: device.displayName,\n multiaddrs: device.multiaddrs ?? [],\n createdAt,\n expiresAt: createdAt + ttlMs,\n });\n validateLifetime(payload.createdAt, payload.expiresAt, createdAt);\n const signature = requireText(\n await options.sign(canonicalDevicePairingInviteBytes(payload)),\n 'signature',\n 4096,\n );\n return { ...payload, signature };\n}\n\nexport function encodeDevicePairingInvite(invite: DevicePairingInvite): string {\n const payload = unsignedPayload(invite);\n const signature = requireText(invite.signature, 'signature', 4096);\n return canonicalJsonString({ ...payload, signature }, PAIRING_CANONICAL_LIMITS);\n}\n\nexport async function parseDevicePairingInvite(\n serialized: string,\n options: ParseDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n if (!serialized || serialized.length > MAX_INVITE_LENGTH) {\n throw new Error('invalid device pairing invite length');\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n throw new Error('device pairing invite is not valid JSON');\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('invalid device pairing invite');\n }\n const record = parsed as Record<string, unknown>;\n const expectedKeys = [\n 'protocol',\n 'peerId',\n 'publicKeyMultibase',\n 'deviceName',\n 'multiaddrs',\n 'createdAt',\n 'expiresAt',\n 'signature',\n ];\n if (\n Object.keys(record).length !== expectedKeys.length ||\n expectedKeys.some(key => !Object.hasOwn(record, key)) ||\n record.protocol !== DEVICE_PAIRING_INVITE_PROTOCOL ||\n typeof record.peerId !== 'string' ||\n typeof record.publicKeyMultibase !== 'string' ||\n typeof record.deviceName !== 'string' ||\n !Array.isArray(record.multiaddrs) ||\n record.multiaddrs.some((address) => typeof address !== 'string') ||\n typeof record.createdAt !== 'number' ||\n typeof record.expiresAt !== 'number' ||\n typeof record.signature !== 'string'\n ) {\n throw new Error('invalid device pairing invite');\n }\n validateLifetime(record.createdAt, record.expiresAt, options.now ?? Date.now());\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: record.peerId,\n publicKeyMultibase: record.publicKeyMultibase,\n deviceName: record.deviceName,\n multiaddrs: record.multiaddrs as string[],\n createdAt: record.createdAt,\n expiresAt: record.expiresAt,\n });\n const invite: DevicePairingInvite = {\n ...payload,\n signature: requireText(record.signature, 'signature', 4096),\n };\n if (\n !await options.verifyIdentity({\n invite,\n payload: canonicalDevicePairingInviteBytes(payload),\n })\n ) {\n throw new Error('device pairing invite identity verification failed');\n }\n return invite;\n}\n","import type { CloudDeviceRecord, Device, DeviceTrustStore, TrustedDeviceRecord } from './types.js';\n\nconst DEFAULT_CLOUD_DEVICE_FRESHNESS_MS = 3 * 60_000;\n\ntype Awaitable<T> = T | Promise<T>;\n\n/**\n * Host-owned live address/discovery overlay. Implementations can bridge this\n * to libp2p, a browser transport, or a mobile transport without Core importing\n * any one of those concrete network stacks.\n */\nexport interface DeviceCloudLiveDirectoryCapability {\n listCloudDeviceAddressPeerIds(): Awaitable<readonly string[]>;\n setCloudDeviceAddresses(peerId: string, multiaddrs: readonly string[]): Awaitable<void>;\n removeCloudDeviceAddresses(peerId: string): Awaitable<void>;\n upsertCloudDiscoveredDevice?(device: Device): Awaitable<void>;\n removeCloudDiscoveredDevice?(peerId: string): Awaitable<void>;\n upsertCloudTrustedDevice?(record: TrustedDeviceRecord): Awaitable<void>;\n removeCloudTrustedDevice?(peerId: string): Awaitable<void>;\n}\n\nexport interface CloudDeviceDirectoryReconcileLogger {\n warn(message: string, details?: Record<string, unknown>): void;\n}\n\nexport interface CloudDeviceDirectoryReconcileResult {\n cloudDevices: CloudDeviceRecord[];\n devices: Device[];\n removedPeerIds: string[];\n}\n\n/** Reconcile a fetched Cloud snapshot into durable trust and a live address overlay. */\nexport async function reconcileCloudDeviceDirectory(input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds?: Iterable<string>;\n freshnessMs?: number;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n logger?: CloudDeviceDirectoryReconcileLogger;\n now?: () => number;\n trustStore: DeviceTrustStore;\n}): Promise<CloudDeviceDirectoryReconcileResult> {\n const now = input.now?.() ?? Date.now();\n const freshnessMs = input.freshnessMs ?? DEFAULT_CLOUD_DEVICE_FRESHNESS_MS;\n if (!Number.isFinite(freshnessMs) || freshnessMs < 0) {\n throw new TypeError('freshnessMs must be finite and non-negative');\n }\n const existingRecords = await input.trustStore.loadTrustedDevices();\n const liveAddressPeerIds = await input.liveDirectory.listCloudDeviceAddressPeerIds();\n const existingByPeerId = new Map(existingRecords.map(record => [record.peerId, record]));\n const excludedPeerIds = new Set(input.excludePeerIds ?? []);\n const recordsByPeerId = new Map<string, CloudDeviceRecord>();\n for (const record of input.cloudDevices) {\n if (recordsByPeerId.has(record.peerId)) throw new Error('cloud_directory_duplicate_peer');\n recordsByPeerId.set(record.peerId, record);\n }\n const activeCloudDevices = [...recordsByPeerId.values()].filter(\n record => record.revokedAt === undefined && !excludedPeerIds.has(record.peerId),\n );\n const activePeerIds = new Set(activeCloudDevices.map(record => record.peerId));\n const removedPeerIds: string[] = [];\n\n const previousCloudPeerIds = new Set([\n ...existingRecords\n .filter(record => record.trustMode === 'cloud-account')\n .map(record => record.peerId),\n ...liveAddressPeerIds,\n ]);\n for (const peerId of previousCloudPeerIds) {\n if (activePeerIds.has(peerId)) continue;\n const existing = existingByPeerId.get(peerId);\n if (existing?.trustMode === 'cloud-account') {\n await input.trustStore.removeTrustedDevice(peerId);\n await input.liveDirectory.removeCloudTrustedDevice?.(peerId);\n }\n await input.liveDirectory.removeCloudDeviceAddresses(peerId);\n await input.liveDirectory.removeCloudDiscoveredDevice?.(peerId);\n removedPeerIds.push(peerId);\n }\n\n const devices: Device[] = [];\n for (const cloudDevice of activeCloudDevices) {\n const existing = existingByPeerId.get(cloudDevice.peerId);\n const trustMode = existing?.trustMode === 'local-pairing'\n ? 'local-pairing' as const\n : 'cloud-account' as const;\n let trustedRecord = existing;\n if (trustMode === 'cloud-account') {\n trustedRecord = {\n peerId: cloudDevice.peerId,\n publicKeyMultibase: cloudDevice.publicKeyMultibase,\n deviceName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n accountId: cloudDevice.accountId,\n createdAt: existing?.createdAt ?? now,\n lastSeen: cloudDevice.lastSeen,\n revokedAt: cloudDevice.revokedAt,\n };\n if (\n existing?.trustMode === 'cloud-account' &&\n existing.publicKeyMultibase !== cloudDevice.publicKeyMultibase\n ) {\n input.logger?.warn(\n '[device-network] Cloud directory rotated a cloud-account device public key',\n { peerId: existing.peerId, accountId: existing.accountId },\n );\n }\n if (!existing || !sameTrustedDevice(existing, trustedRecord)) {\n await input.trustStore.saveTrustedDevice(trustedRecord);\n }\n await input.liveDirectory.upsertCloudTrustedDevice?.(trustedRecord);\n }\n\n const device = cloudRecordToDevice(cloudDevice, trustMode, now, freshnessMs);\n await input.liveDirectory.setCloudDeviceAddresses(\n device.peerId,\n device.multiaddrs ?? [],\n );\n await input.liveDirectory.upsertCloudDiscoveredDevice?.(device);\n devices.push(device);\n }\n\n return { cloudDevices: activeCloudDevices, devices, removedPeerIds };\n}\n\nexport function cloudRecordToDevice(\n cloudDevice: CloudDeviceRecord,\n trustMode: Device['trustMode'],\n now = Date.now(),\n freshnessMs = DEFAULT_CLOUD_DEVICE_FRESHNESS_MS,\n): Device {\n const directMultiaddrs = normalizedAddresses(cloudDevice.multiaddrs)\n .filter(address => !address.includes('/p2p-circuit'));\n const relayMultiaddrs = normalizedAddresses([\n ...cloudDevice.multiaddrs.filter(address => address.includes('/p2p-circuit')),\n ...cloudDevice.relayReservations,\n ]);\n const paths: Device['reachability']['paths'] = [\n ...(directMultiaddrs.length > 0 ? ['direct' as const] : []),\n ...(relayMultiaddrs.length > 0 ? ['relay' as const] : []),\n ];\n const fresh = Number.isFinite(cloudDevice.lastSeen) &&\n cloudDevice.lastSeen >= now - freshnessMs;\n return {\n peerId: cloudDevice.peerId,\n displayName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n trusted: true,\n reachability: {\n state: fresh && paths.length > 0 ? 'online' : 'offline',\n paths: fresh ? paths : [],\n },\n capabilities: cloudDevice.capabilities,\n multiaddrs: normalizedAddresses([...directMultiaddrs, ...relayMultiaddrs]),\n lastSeen: cloudDevice.lastSeen,\n };\n}\n\nfunction normalizedAddresses(addresses: readonly string[]): string[] {\n return [...new Set(addresses.map(address => address.trim()).filter(Boolean))];\n}\n\nfunction sameTrustedDevice(left: TrustedDeviceRecord, right: TrustedDeviceRecord): boolean {\n return left.peerId === right.peerId &&\n left.publicKeyMultibase === right.publicKeyMultibase &&\n left.deviceName === right.deviceName &&\n left.platform === right.platform &&\n left.trustMode === right.trustMode &&\n left.accountId === right.accountId &&\n left.createdAt === right.createdAt &&\n left.lastSeen === right.lastSeen &&\n left.revokedAt === right.revokedAt;\n}\n","import { CloudDeviceFetchError } from './cloudDeviceFetchClient.js';\nimport type { DeviceCloudCommitFence, DeviceCloudConnectionAdapter, DeviceCloudStepResult } from './deviceCloudConnectionCoordinator.js';\nimport { buildDeviceHeartbeatMessage, DEVICE_HEARTBEAT_LIMITS } from './deviceHeartbeat.js';\nimport { type CloudDeviceDirectoryReconcileLogger, type DeviceCloudLiveDirectoryCapability, reconcileCloudDeviceDirectory } from './reconcileCloudDeviceDirectory.js';\nimport type {\n CloudDeviceClient,\n CloudDeviceRecord,\n DeviceCapabilities,\n DeviceRelayReservationToken,\n DeviceTrustStore,\n LocalDeviceIdentity,\n PublicDeviceIdentity,\n SyncResult,\n} from './types.js';\n\nconst DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\nconst REGISTRATION_INVALID_ERROR_CODES = new Set([\n 'device_not_found',\n 'device_registration_invalid',\n 'device_registration_not_found',\n 'invalid_device_registration',\n 'registration_invalid',\n]);\n\ntype Awaitable<T> = T | Promise<T>;\n\nclass DeviceCloudRegistrationInvalidError extends Error {\n public readonly code = 'DEVICE_CLOUD_REGISTRATION_INVALID';\n\n constructor(cause?: unknown) {\n super(\n 'cloud device heartbeat rejected',\n cause === undefined ? undefined : { cause },\n );\n this.name = 'DeviceCloudRegistrationInvalidError';\n }\n}\n\nexport interface StandardDeviceCloudNetworkCapability {\n getMultiaddrs(): readonly string[];\n /** Final host write must reject a stale fence at its durable commit point. */\n configureRelayReservation(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Awaitable<void>;\n clearRelayReservation(signal: AbortSignal): Awaitable<void>;\n}\n\nexport interface StandardDeviceCloudConnectionAdapterOptions {\n capabilities: () => Awaitable<DeviceCapabilities>;\n /** Final host write must reject a stale fence at its durable commit point. */\n configureConnectionGrantPublicKey: (\n value: { issuer: 'memeloop-cloud'; publicKeyMultibase: string },\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n /**\n * Atomically publish a fetched Cloud directory snapshot only when the\n * supplied generation is still current. Implementations backed by async\n * persistence must perform an expected-generation CAS in the same durable\n * transaction as the snapshot write; a check followed by an awaited write\n * is not sufficient.\n */\n commitCloudDirectorySnapshot: (\n input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds: readonly string[];\n freshnessMs?: number;\n now: number;\n },\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n clearConnectionGrantPublicKey: (signal: AbortSignal) => Awaitable<void>;\n clearTokenCache: (client: CloudDeviceClient, signal: AbortSignal) => Awaitable<void>;\n directoryFreshnessMs?: number;\n directoryLogger?: CloudDeviceDirectoryReconcileLogger;\n identity: LocalDeviceIdentity;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n network: StandardDeviceCloudNetworkCapability;\n now?: () => number;\n relayRequiredForOnline?: (multiaddrs: readonly string[]) => boolean;\n relayTokenSafetyMarginMs?: number;\n signDeviceBinding: (input: {\n accountId: string;\n identity: LocalDeviceIdentity;\n nonce: string;\n signal: AbortSignal;\n }) => Awaitable<string>;\n signHeartbeat: (input: {\n peerId: string;\n timestamp: number;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signal: AbortSignal;\n }) => Awaitable<{ nonce: string; signature: string }>;\n /** Host wrapper obtains the scoped Cloud grant before entering libp2p sync. */\n syncDevice?: (\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ) => Promise<SyncResult>;\n trustStore: DeviceTrustStore;\n}\n\n/** Shared host adapter for Cloud registration, relay, heartbeat, and directory maintenance. */\nexport class StandardDeviceCloudConnectionAdapter implements DeviceCloudConnectionAdapter<CloudDeviceClient> {\n private relayReservation?: DeviceRelayReservationToken;\n private relayReservationClient?: CloudDeviceClient;\n private backgroundSyncPeerIds: string[] = [];\n private readonly now: () => number;\n private readonly relayTokenSafetyMarginMs: number;\n\n constructor(private readonly options: StandardDeviceCloudConnectionAdapterOptions) {\n this.now = options.now ?? Date.now;\n this.relayTokenSafetyMarginMs = options.relayTokenSafetyMarginMs ??\n DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS;\n if (!Number.isFinite(this.relayTokenSafetyMarginMs) || this.relayTokenSafetyMarginMs < 0) {\n throw new TypeError('relayTokenSafetyMarginMs must be finite and non-negative');\n }\n }\n\n public isConfigured(\n configuration: CloudDeviceClient | undefined,\n ): configuration is CloudDeviceClient {\n return configuration !== undefined;\n }\n\n public relayRequiredForOnline(_configuration: CloudDeviceClient): boolean {\n const addresses = this.options.network.getMultiaddrs();\n return this.options.relayRequiredForOnline?.(addresses) ??\n !hasValidDirectCloudDeviceAddress(addresses, this.options.identity.peerId);\n }\n\n public async ensureAuthorizer(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult> {\n const publicKey = await client.getConnectionGrantPublicKey(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.configureConnectionGrantPublicKey(publicKey, signal, fence);\n fence.throwIfStale();\n },\n };\n }\n\n public async registerDevice(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<undefined> {\n const nonce = await client.createBindingNonce(signal);\n throwIfAborted(signal);\n const signature = await this.options.signDeviceBinding({\n accountId: nonce.accountId,\n identity: this.options.identity,\n nonce: nonce.nonce,\n signal,\n });\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const registration = await client.registerDevice({\n // Construct a fresh public projection at the capability boundary. A\n // custom CloudDeviceClient must never observe host-local key references\n // or serialized private-key material through structural typing.\n identity: toPublicDeviceIdentity(this.options.identity),\n cloudNonce: nonce.nonce,\n signature,\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n }, signal);\n if (!registration.ok || registration.peerId !== this.options.identity.peerId) {\n throw new Error('cloud device registration rejected');\n }\n return undefined;\n }\n\n public async ensureRelay(\n client: CloudDeviceClient,\n signal: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined> {\n if (\n this.relayReservationClient === client &&\n this.relayReservation &&\n this.relayReservation.expiresAt > this.now() + this.relayTokenSafetyMarginMs\n ) {\n return undefined;\n }\n const relayReservation = await client.createRelayReservation(\n { peerId: this.options.identity.peerId },\n signal,\n fence,\n );\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.network.configureRelayReservation(relayReservation, signal, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.relayReservation = relayReservation;\n this.relayReservationClient = client;\n });\n },\n };\n }\n\n public async heartbeat(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<undefined> {\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const unsigned = {\n peerId: this.options.identity.peerId,\n timestamp: this.now(),\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n };\n const proof = await this.options.signHeartbeat({ ...unsigned, signal });\n throwIfAborted(signal);\n const heartbeat = { ...unsigned, ...proof };\n void buildDeviceHeartbeatMessage({ ...unsigned, nonce: proof.nonce });\n if (!boundedProofSignature(heartbeat.signature)) {\n throw new Error('invalid device heartbeat signature');\n }\n let result: Awaited<ReturnType<CloudDeviceClient['heartbeat']>>;\n try {\n result = await client.heartbeat(heartbeat, signal);\n } catch (error) {\n if (isHeartbeatRegistrationInvalid(error)) {\n throw new DeviceCloudRegistrationInvalidError(error);\n }\n throw error;\n }\n if (!result.ok) throw new DeviceCloudRegistrationInvalidError();\n return undefined;\n }\n\n public async dispose(client: CloudDeviceClient, signal: AbortSignal): Promise<void> {\n this.relayReservation = undefined;\n this.relayReservationClient = undefined;\n this.backgroundSyncPeerIds = [];\n const errors: unknown[] = [];\n await bestEffortCleanup(\n () => this.options.clearConnectionGrantPublicKey(signal),\n errors,\n );\n await bestEffortCleanup(\n () => this.options.network.clearRelayReservation(signal),\n errors,\n );\n await bestEffortCleanup(\n async () => {\n await reconcileCloudDeviceDirectory({\n cloudDevices: [],\n liveDirectory: this.options.liveDirectory,\n logger: this.options.directoryLogger,\n now: this.now,\n trustStore: this.options.trustStore,\n });\n },\n errors,\n );\n await bestEffortCleanup(\n () => this.options.clearTokenCache(client, signal),\n errors,\n );\n if (errors.length > 0) {\n throw new AggregateError(errors, 'device cloud generation cleanup failed');\n }\n }\n\n public async syncDirectory(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult> {\n const cloudDevices = await client.listDevices(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.commitCloudDirectorySnapshot({\n cloudDevices,\n excludePeerIds: [this.options.identity.peerId],\n freshnessMs: this.options.directoryFreshnessMs,\n now: this.now(),\n }, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.backgroundSyncPeerIds = cloudDevices\n .filter(device => device.peerId !== this.options.identity.peerId && device.revokedAt === undefined)\n .map(device => device.peerId);\n });\n },\n };\n }\n\n public listBackgroundSyncPeerIds(\n _client: CloudDeviceClient,\n signal: AbortSignal,\n ): readonly string[] {\n signal.throwIfAborted();\n return this.options.syncDevice ? [...this.backgroundSyncPeerIds] : [];\n }\n\n public syncDevice(\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult> {\n signal.throwIfAborted();\n if (!this.options.syncDevice) throw new Error('background_device_sync_not_configured');\n return this.options.syncDevice(client, peerId, signal);\n }\n\n public classifyError(error: unknown): 'offline' | 'error' | 'registration-invalid' {\n if (error instanceof DeviceCloudRegistrationInvalidError) return 'registration-invalid';\n if (error instanceof CloudDeviceFetchError) {\n return error.code === 'cloud_request_failed' ? 'offline' : 'error';\n }\n return 'offline';\n }\n\n private currentRelayReservations(): string[] {\n const active = this.options.network.getMultiaddrs()\n .filter(address => address.includes('/p2p-circuit'));\n return active.length > 0 ? [...active] : [...(this.relayReservation?.relayMultiaddrs ?? [])];\n }\n}\n\nfunction isHeartbeatRegistrationInvalid(error: unknown): boolean {\n if (!(error instanceof CloudDeviceFetchError) || error.code !== 'cloud_http_error') {\n return false;\n }\n if (error.status === 404) return true;\n return error.status === 401 && hasExplicitRegistrationInvalidCode(error.responseBody);\n}\n\nfunction hasExplicitRegistrationInvalidCode(responseBody: string | undefined): boolean {\n const body = responseBody?.trim();\n if (!body) return false;\n let value: unknown;\n try {\n value = JSON.parse(body) as unknown;\n } catch {\n return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(body));\n }\n return registrationInvalidCodeFromValue(value);\n}\n\nfunction registrationInvalidCodeFromValue(value: unknown): boolean {\n if (typeof value === 'string') {\n return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(value));\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return registrationInvalidCodeFromValue(record.code) ||\n registrationInvalidCodeFromValue(record.errorCode) ||\n registrationInvalidCodeFromValue(record.error);\n}\n\nfunction normalizeErrorCode(value: string): string {\n return value.trim().toLowerCase().replaceAll('-', '_');\n}\n\nfunction toPublicDeviceIdentity(identity: LocalDeviceIdentity): PublicDeviceIdentity {\n return {\n peerId: identity.peerId,\n publicKeyMultibase: identity.publicKeyMultibase,\n createdAt: identity.createdAt,\n deviceName: identity.deviceName,\n platform: identity.platform,\n };\n}\n\n/**\n * True only when another device can dial a complete direct transport address.\n *\n * Merely finding a public-looking host is insufficient: `/ip4/8.8.8.8`,\n * `tcp/0`, and an unknown transport are not usable paths and must not let a\n * host report `online` without a relay. The optional PeerId pins advertised\n * addresses to the local identity while retaining the standalone classifier\n * used by hosts that append `/p2p/<peerId>` later.\n */\nexport function hasValidDirectCloudDeviceAddress(\n addresses: readonly string[],\n expectedPeerId?: string,\n): boolean {\n return addresses.some(address => isDialableDirectMultiaddr(address, expectedPeerId));\n}\n\nfunction isDialableDirectMultiaddr(address: string, expectedPeerId?: string): boolean {\n if (\n address.length === 0 || address.length > 4_096 || address !== address.trim() ||\n !address.startsWith('/') || address.endsWith('/') || address.includes('//') ||\n address.includes('/p2p-circuit')\n ) return false;\n const parts = address.split('/').slice(1);\n if (parts.some(part => part.length === 0 || containsAsciiControlOrSpace(part))) return false;\n\n const hostProtocol = parts[0];\n const host = parts[1]?.toLowerCase();\n if (\n host === undefined ||\n (hostProtocol !== 'ip4' && hostProtocol !== 'ip6' && hostProtocol !== 'dns' &&\n hostProtocol !== 'dns4' && hostProtocol !== 'dns6')\n ) return false;\n const publicHost = hostProtocol === 'ip4'\n ? isPublicIpv4(host)\n : hostProtocol === 'ip6'\n ? isPublicIpv6(host)\n : isPlausiblePublicDnsHost(host);\n if (!publicHost) return false;\n\n const transport = parts[2];\n const port = parsePort(parts[3]);\n if (transport !== 'tcp' || port === undefined) return false;\n let index = 4;\n if (parts[index] === 'ws' || parts[index] === 'wss') index += 1;\n\n if (parts[index] === 'p2p') {\n const peerId = parts[index + 1];\n if (!peerId || containsAsciiControlOrSpace(peerId)) return false;\n if (expectedPeerId !== undefined && peerId !== expectedPeerId) return false;\n index += 2;\n }\n return index === parts.length;\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n if (value === undefined || !/^\\d{1,5}$/u.test(value)) return undefined;\n const port = Number(value);\n return port >= 1 && port <= 65_535 ? port : undefined;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n\nfunction isPublicIpv4(host: string): boolean {\n const octets = host.split('.').map(part => Number(part));\n if (octets.length !== 4 || octets.some(octet => !Number.isInteger(octet) || octet < 0 || octet > 255)) {\n return false;\n }\n const [first, second] = octets as [number, number, number, number];\n return first !== 0 && first !== 10 && first !== 127 && first < 224 &&\n !(first === 100 && second >= 64 && second <= 127) &&\n !(first === 169 && second === 254) &&\n !(first === 172 && second >= 16 && second <= 31) &&\n !(first === 192 && second === 0 && octets[2] === 0) &&\n !(first === 192 && second === 0 && octets[2] === 2) &&\n !(first === 192 && second === 88 && octets[2] === 99) &&\n !(first === 192 && second === 168) &&\n !(first === 198 && (second === 18 || second === 19)) &&\n !(first === 198 && second === 51 && octets[2] === 100) &&\n !(first === 203 && second === 0 && octets[2] === 113);\n}\n\nfunction isPublicIpv6(host: string): boolean {\n const groups = parseIpv6(host);\n if (!groups) return false;\n const [first, second] = groups;\n if ((first & 0xe000) !== 0x2000) return false;\n // Documentation-only addresses are valid syntax but never direct public paths.\n return !(first === 0x2001 && second === 0x0db8);\n}\n\nfunction parseIpv6(host: string): number[] | undefined {\n const normalized = host.toLowerCase();\n if (normalized.includes('%') || normalized.includes('.')) return undefined;\n const halves = normalized.split('::');\n if (halves.length > 2) return undefined;\n const parseHalf = (half: string): number[] | undefined => {\n if (half === '') return [];\n const parts = half.split(':');\n if (parts.some(part => !/^[0-9a-f]{1,4}$/u.test(part))) return undefined;\n return parts.map(part => Number.parseInt(part, 16));\n };\n const left = parseHalf(halves[0] ?? '');\n const right = parseHalf(halves[1] ?? '');\n if (!left || !right) return undefined;\n if (halves.length === 1) return left.length === 8 ? left : undefined;\n const missing = 8 - left.length - right.length;\n if (missing < 1) return undefined;\n return [...left, ...Array.from({ length: missing }, () => 0), ...right];\n}\n\nfunction isPlausiblePublicDnsHost(host: string): boolean {\n const normalized = host.endsWith('.') ? host.slice(0, -1) : host;\n if (isIpv4Syntax(normalized)) return isPublicIpv4(normalized);\n if (normalized.includes(':')) return isPublicIpv6(normalized);\n const specialUseSuffixes = [\n 'example',\n 'home.arpa',\n 'internal',\n 'invalid',\n 'local',\n 'localhost',\n 'onion',\n 'test',\n ];\n if (specialUseSuffixes.some(suffix => normalized === suffix || normalized.endsWith(`.${suffix}`))) return false;\n const labels = normalized.split('.');\n return labels.length > 1 && labels.every(label =>\n label.length > 0 && label.length <= 63 &&\n /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label)\n );\n}\n\nfunction isIpv4Syntax(host: string): boolean {\n return /^\\d{1,3}(?:\\.\\d{1,3}){3}$/u.test(host);\n}\n\nfunction boundedProofSignature(signature: unknown): signature is string {\n if (\n typeof signature !== 'string' || signature.length === 0 ||\n signature.length > DEVICE_HEARTBEAT_LIMITS.signatureCharacters ||\n signature !== signature.trim()\n ) {\n return false;\n }\n for (let index = 0; index < signature.length; index += 1) {\n const code = signature.charCodeAt(index);\n if (code <= 31 || code === 127) return false;\n }\n return true;\n}\n\nasync function bestEffortCleanup(\n operation: () => Awaitable<void>,\n errors: unknown[],\n): Promise<void> {\n try {\n await operation();\n } catch (error) {\n errors.push(error);\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (!signal.aborted) return;\n throw signal.reason instanceof Error ? signal.reason : new Error('device_cloud_operation_aborted');\n}\n"],"mappings":"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","names":["compareCodeUnits","candidate","hasOnlyKeys","hasOnlyKeys","text","copied","throwIfAborted","hasOnlyKeys","containsAsciiControlOrSpace","peerId","throwIfAborted","fence","containsAsciiControlOrSpace"]}