@tearleads/client-sdk 0.1.76 → 0.1.77

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 (115) hide show
  1. package/data/{containers → persistence/container-contents}/containerBinding.js +1 -1
  2. package/data/persistence/container-contents/containerContentsPersistence.js +2 -2
  3. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  4. package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +2 -2
  5. package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
  6. package/data/persistence/container-contents/containerDeletionPersistence.js +2 -2
  7. package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
  8. package/data/persistence/container-contents/containerHydrationPersistence.js +2 -2
  9. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  10. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +2 -2
  11. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  12. package/data/persistence/container-contents/containerMetadataRows.js +1 -1
  13. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  14. package/data/persistence/container-contents/containerRebindPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerReconcilePersistence.js +2 -2
  16. package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
  17. package/data/persistence/container-contents/containerStructuralRepair.js +1 -1
  18. package/data/persistence/container-contents/containerStructuralRepair.js.map +1 -1
  19. package/data/persistence/container-contents/dormantMetadataSweep.js +1 -1
  20. package/data/persistence/container-contents/dormantMetadataSweep.js.map +1 -1
  21. package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js +1 -1
  22. package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js.map +1 -1
  23. package/data/persistence/documents/internal/containerDocumentTombstones.js +1 -1
  24. package/data/persistence/documents/internal/containerDocumentTombstones.js.map +1 -1
  25. package/data/persistence/documents/internal/discoveredDocumentPlacement.js +1 -1
  26. package/data/persistence/documents/internal/discoveredDocumentPlacement.js.map +1 -1
  27. package/package.json +1 -1
  28. package/stores/container-contents/systemContainers/systemContainerIcon.js +1 -1
  29. package/stores/container-contents/systemContainers/systemContainerIcon.js.map +1 -1
  30. package/workflows/container-contents/container-state/create/createChild.js +1 -1
  31. package/workflows/container-contents/container-state/create/createChild.js.map +1 -1
  32. package/workflows/container-contents/container-state/purge/purgeTree.js +1 -1
  33. package/workflows/container-contents/container-state/purge/purgeTree.js.map +1 -1
  34. package/workflows/container-contents/container-state/types.js.map +1 -1
  35. package/workflows/container-contents/containerPersistence.d.ts +3 -3
  36. package/workflows/container-contents/containerPersistence.js +1 -1
  37. package/workflows/container-contents/containerPersistence.js.map +1 -1
  38. package/workflows/container-contents/documentLinks/documentLinkIntent.js +1 -1
  39. package/workflows/container-contents/documentLinks/documentLinkIntent.js.map +1 -1
  40. package/workflows/container-contents/documentLinks/index.js +1 -1
  41. package/workflows/container-contents/documentLinks/index.js.map +1 -1
  42. package/workflows/container-contents/documentMove/documentMoveIntent.js +1 -1
  43. package/workflows/container-contents/documentMove/documentMoveIntent.js.map +1 -1
  44. package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js +2 -2
  45. package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js.map +1 -1
  46. package/workflows/container-contents/documentQueries/documentSubtreeQueries.js +1 -1
  47. package/workflows/container-contents/documentQueries/documentSubtreeQueries.js.map +1 -1
  48. package/workflows/container-contents/documentQueries/index.js +3 -3
  49. package/workflows/container-contents/documentQueries/index.js.map +1 -1
  50. package/workflows/container-contents/documentQueries/pendingDownloads.js +1 -1
  51. package/workflows/container-contents/documentQueries/pendingDownloads.js.map +1 -1
  52. package/workflows/container-contents/index.d.ts +1 -1
  53. package/workflows/container-contents/index.js +1 -1
  54. package/workflows/container-contents/index.js.map +1 -1
  55. package/workflows/container-contents/info/blobInfo.js +1 -1
  56. package/workflows/container-contents/info/blobInfo.js.map +1 -1
  57. package/workflows/container-contents/info/containerInfo.js +2 -2
  58. package/workflows/container-contents/info/containerInfo.js.map +1 -1
  59. package/{data/containers → workflows/container-contents/metadata}/containerMetadataDocument.d.ts +1 -1
  60. package/{data/containers → workflows/container-contents/metadata}/containerMetadataDocument.js +2 -2
  61. package/workflows/container-contents/metadata/containerMetadataDocument.js.map +1 -0
  62. package/workflows/container-contents/metadata/metadataMutationPreparation.js +1 -1
  63. package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -1
  64. package/workflows/container-contents/metadata/metadataPersistence.js +1 -1
  65. package/workflows/container-contents/metadata/metadataPersistence.js.map +1 -1
  66. package/workflows/container-contents/metadata/metadataRecord.js.map +1 -1
  67. package/workflows/container-contents/metadata/metadataStateIsolation.js +1 -1
  68. package/workflows/container-contents/metadata/metadataStateIsolation.js.map +1 -1
  69. package/workflows/container-contents/metadata/metadataSyncSettlement.js +1 -1
  70. package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -1
  71. package/workflows/container-contents/metadata/metadataTypes.d.ts +2 -2
  72. package/workflows/container-contents/metadata/metadataTypes.js.map +1 -1
  73. package/workflows/container-contents/recovery/folderRecovery.js +1 -1
  74. package/workflows/container-contents/recovery/folderRecovery.js.map +1 -1
  75. package/workflows/container-contents/remoteHydration/destination/replacementBinding.js +1 -1
  76. package/workflows/container-contents/remoteHydration/destination/replacementBinding.js.map +1 -1
  77. package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js +1 -1
  78. package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js.map +1 -1
  79. package/workflows/container-contents/remoteHydration/heldContainerRebind.js +1 -1
  80. package/workflows/container-contents/remoteHydration/heldContainerRebind.js.map +1 -1
  81. package/workflows/container-contents/remoteHydration/reattachMetadata.js +1 -1
  82. package/workflows/container-contents/remoteHydration/reattachMetadata.js.map +1 -1
  83. package/workflows/container-contents/remoteHydration/remoteContainers/insertRemoteContainer.js +2 -2
  84. package/workflows/container-contents/remoteHydration/remoteContainers/insertRemoteContainer.js.map +1 -1
  85. package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerState.js +1 -1
  86. package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerState.js.map +1 -1
  87. package/workflows/container-contents/remoteHydration/types.d.ts +1 -1
  88. package/workflows/container-contents/remoteHydration/types.js.map +1 -1
  89. package/workflows/container-contents/storedContainerState.js +1 -1
  90. package/workflows/container-contents/storedContainerState.js.map +1 -1
  91. package/workflows/organizations/groupMetadata/groupMetadataAccess.js +1 -1
  92. package/workflows/organizations/groupMetadata/groupMetadataAccess.js.map +1 -1
  93. package/workflows/organizations/readModel/localReadModelDetails.js +1 -1
  94. package/workflows/organizations/readModel/localReadModelDetails.js.map +1 -1
  95. package/workflows/registration/bootstrapRootContainer.js +1 -1
  96. package/workflows/registration/bootstrapRootContainer.js.map +1 -1
  97. package/workflows/registration/provisioningBootstrapBuilders.js +1 -1
  98. package/workflows/registration/provisioningBootstrapBuilders.js.map +1 -1
  99. package/workflows/registration/rootMetadataBootstrap.js +1 -1
  100. package/workflows/registration/rootMetadataBootstrap.js.map +1 -1
  101. package/workflows/sync/remoteReset.js +1 -1
  102. package/workflows/sync/remoteReset.js.map +1 -1
  103. package/data/containers/containerMetadataDocument.js.map +0 -1
  104. /package/data/{containers → persistence/container-contents}/containerBinding.d.ts +0 -0
  105. /package/data/{containers → persistence/container-contents}/containerBinding.js.map +0 -0
  106. /package/data/persistence/{containers → container-contents}/containerPersistence.d.ts +0 -0
  107. /package/data/persistence/{containers → container-contents}/containerPersistence.js +0 -0
  108. /package/data/persistence/{containers → container-contents}/containerPersistence.js.map +0 -0
  109. /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.d.ts +0 -0
  110. /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.js +0 -0
  111. /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.js.map +0 -0
  112. /package/data/persistence/{containers → container-contents}/documentContainerProjectionPersistence.js +0 -0
  113. /package/data/persistence/{containers → container-contents}/documentContainerProjectionPersistence.js.map +0 -0
  114. /package/data/persistence/{containers → container-contents}/documentPlacement.js +0 -0
  115. /package/data/persistence/{containers → container-contents}/documentPlacement.js.map +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"containerInfo.js","sourceRoot":"","sources":["containerInfo.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerAccessLevel,\n ContainerGrantSubjectType,\n} from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport { ensureContainerTables } from \"../../../data/persistence/containers/containerPersistence\";\nimport {\n type ContainerSyncWatermarkLane,\n containerContentsSyncLane,\n containerParentSyncLane,\n containerSyncWatermarkLaneKey,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../../data/persistence/containers/containerSyncWatermarkPersistence\";\nimport { containers } from \"../../../data/sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { OrganizationGroupSummary } from \"../../organizations/readModel\";\n\nexport type ContainerShareAccessLevel = ContainerAccessLevel;\n\nexport interface ContainerInfoGrant {\n accessLevel: ContainerAccessLevel;\n subjectId: string;\n subjectType: ContainerGrantSubjectType;\n}\n\nexport interface ContainerInfoGrantRow extends ContainerInfoGrant {\n inherited: boolean;\n sourceContainerId: string;\n}\n\nexport interface ContainerInfoSyncCursor {\n label: string;\n laneId: string;\n laneKind: string;\n savedAt: string | null;\n watermarkId: string | null;\n watermarkUpdatedAt: string | null;\n}\n\nexport interface ContainerInfoPathEntry {\n containerId: string;\n containerKeyEpoch: number;\n containerKeyEpochId: string;\n directGrantCount: number;\n eventHash: string;\n keyEpochHash: string;\n keyTargetHash: string;\n manifestHash: string;\n manifestHistoryCount: number;\n parentContainerId: string | null;\n parentManifestHash: string | null;\n recipientTargetCount: number;\n referencedPrincipalCount: number;\n wrapCount: number;\n}\n\nexport interface ContainerInfoSecurityDetails {\n currentContainerKeyEpoch: number;\n currentContainerKeyEpochId: string;\n currentManifestHash: string;\n currentManifestHistoryCount: number;\n currentParentContainerKeyEpochId: string | null;\n currentReferencedPrincipalCount: number;\n path: ContainerInfoPathEntry[];\n pathLength: number;\n}\n\nexport interface ContainerInfoRemoteDetails {\n grantRows: ContainerInfoGrantRow[];\n grants: ContainerInfoGrant[];\n groups: OrganizationGroupSummary[];\n security?: ContainerInfoSecurityDetails;\n syncCursors: ContainerInfoSyncCursor[];\n}\n\nexport interface ContainerInfoLocalDetails {\n createdAt: string | null;\n updatedAt: string | null;\n}\n\nexport interface ContainerInfo {\n local: ContainerInfoLocalDetails;\n remoteInfo: ContainerInfoRemoteDetails | null;\n}\n\ninterface ContainerInfoApi {\n getContainerWriterProjection: (\n containerId: string,\n ) => Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport type ContainerInfoRemoteMode = \"always\" | \"if-synced\" | \"never\";\n\ninterface LocalContainerInfoRecord {\n hasSyncedContainer: boolean;\n localCreatedAt: string | null;\n localUpdatedAt: string | null;\n organizationId: string | null;\n parentId: string | null;\n}\n\nfunction sortContainerInfoGrants<T extends ContainerInfoGrant>(\n grants: readonly T[],\n): T[] {\n return [...grants].sort((left, right) =>\n `${left.subjectType}:${left.subjectId}`.localeCompare(\n `${right.subjectType}:${right.subjectId}`,\n ),\n );\n}\n\nfunction toContainerInfoGrant(grant: ContainerInfoGrant): ContainerInfoGrant {\n return {\n accessLevel: grant.accessLevel,\n subjectId: grant.subjectId,\n subjectType: grant.subjectType,\n };\n}\n\nfunction getContainerInfoGrantRows(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoGrantRow[] {\n const rows = projection.path.flatMap((bundle) => {\n const state = readContainerState(bundle);\n\n return state.directGrants.map((grant) => ({\n ...toContainerInfoGrant(grant),\n inherited: state.containerId !== projection.containerId,\n sourceContainerId: state.containerId,\n }));\n });\n\n return sortContainerInfoGrants(rows);\n}\n\nfunction getContainerInfoPathEntries(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoPathEntry[] {\n return projection.path.map((bundle, index) => {\n const state = readContainerState(bundle);\n const kek = projection.containerKeks[index];\n if (!kek) {\n throw new Error(\"Container projection path and KEKs are inconsistent\");\n }\n\n return {\n containerId: state.containerId,\n containerKeyEpoch: kek.containerKeyEpoch,\n containerKeyEpochId: kek.containerKeyEpochId,\n directGrantCount: state.directGrants.length,\n eventHash: state.eventHash,\n keyEpochHash: kek.keyEpochHash,\n keyTargetHash: kek.keyTargetHash,\n manifestHash: bundle.manifestHash,\n manifestHistoryCount: kek.containerManifestHistory.length,\n parentContainerId: state.parentContainerId,\n parentManifestHash: state.parentManifestHash,\n recipientTargetCount: kek.recipientTargets.length,\n referencedPrincipalCount: state.referencedPrincipalHeads.length,\n wrapCount: kek.wraps.length,\n };\n });\n}\n\nfunction getContainerInfoSecurityDetails(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoSecurityDetails {\n const path = getContainerInfoPathEntries(projection);\n const targetPathEntry = path.at(-1);\n const targetKek = projection.containerKeks.at(-1);\n if (!targetPathEntry || !targetKek) {\n throw new Error(\"Container projection is empty\");\n }\n\n return {\n currentContainerKeyEpoch: targetPathEntry.containerKeyEpoch,\n currentContainerKeyEpochId: targetPathEntry.containerKeyEpochId,\n currentManifestHash: targetPathEntry.manifestHash,\n currentManifestHistoryCount: targetPathEntry.manifestHistoryCount,\n currentParentContainerKeyEpochId: targetKek.parentContainerKeyEpochId,\n currentReferencedPrincipalCount: targetPathEntry.referencedPrincipalCount,\n path,\n pathLength: path.length,\n };\n}\n\ninterface ContainerInfoSyncCursorDefinition {\n label: string;\n lane: ContainerSyncWatermarkLane;\n}\n\nfunction getContainerSyncCursorDefinitions(input: {\n containerId: string;\n parentId: string | null;\n}): ContainerInfoSyncCursorDefinition[] {\n return [\n {\n label: \"Parent Listing\",\n lane: containerParentSyncLane(input.parentId),\n },\n {\n label: \"Child Containers\",\n lane: containerParentSyncLane(input.containerId),\n },\n {\n label: \"Documents\",\n lane: containerContentsSyncLane(input.containerId),\n },\n ];\n}\n\nasync function loadContainerSyncCursors(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<ContainerInfoSyncCursor[]> {\n const cursorDefinitions = getContainerSyncCursorDefinitions(input);\n let records: Awaited<\n ReturnType<typeof sqlContainerSyncWatermarkPersistence.loadWatermarkRecords>\n > = [];\n if (input.execSql) {\n await sqlContainerSyncWatermarkPersistence.ensureSchema(input.execSql);\n records = await sqlContainerSyncWatermarkPersistence.loadWatermarkRecords(\n input.execSql,\n cursorDefinitions.map(({ lane }) => lane),\n );\n }\n\n return cursorDefinitions.map((definition, index) => {\n const { laneId, laneKind } = containerSyncWatermarkLaneKey(definition.lane);\n const record = records[index] ?? null;\n\n return {\n label: definition.label,\n laneId,\n laneKind,\n savedAt: record?.updatedAt ?? null,\n watermarkId: record?.watermark.id ?? null,\n watermarkUpdatedAt: record?.watermark.updatedAt ?? null,\n };\n });\n}\n\nasync function loadLocalContainerInfoRecord(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<LocalContainerInfoRecord> {\n const fallback: LocalContainerInfoRecord = {\n hasSyncedContainer: false,\n localCreatedAt: null,\n localUpdatedAt: null,\n organizationId: null,\n parentId: input.parentId,\n };\n\n if (!input.execSql) {\n return fallback;\n }\n\n await ensureContainerTables(input.execSql);\n\n const { db } = getClientSQLitePersistenceRuntime(input.execSql);\n const rows = await db\n .select({\n localCreatedAt: containers.localCreatedAt,\n localUpdatedAt: containers.localUpdatedAt,\n metadataDocumentId: containers.metadataDocumentId,\n organizationId: containers.organizationId,\n parentId: containers.parentId,\n })\n .from(containers)\n .where(eq(containers.id, input.containerId))\n .limit(1);\n const row = rows[0];\n\n if (!row) {\n return fallback;\n }\n\n return {\n hasSyncedContainer:\n typeof row.metadataDocumentId === \"string\" &&\n row.metadataDocumentId.length > 0,\n localCreatedAt: row.localCreatedAt,\n localUpdatedAt: row.localUpdatedAt,\n organizationId: row.organizationId,\n parentId: row.parentId,\n };\n}\n\nfunction shouldLoadRemoteContainerInfo(input: {\n localContainerInfo: LocalContainerInfoRecord;\n remoteInfoMode: ContainerInfoRemoteMode;\n}): boolean {\n switch (input.remoteInfoMode) {\n case \"always\":\n return true;\n case \"if-synced\":\n return input.localContainerInfo.hasSyncedContainer;\n case \"never\":\n return false;\n }\n}\n\nexport async function loadContainerInfo(input: {\n apiClient: ContainerInfoApi;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | null | undefined;\n execSql?: ExecSql | null;\n loadOrganizationGroups: () => Promise<\n ReadonlyArray<OrganizationGroupSummary>\n >;\n parentId?: string | null;\n remoteInfoMode?: ContainerInfoRemoteMode | undefined;\n}): Promise<ContainerInfo> {\n const localContainerInfo = await loadLocalContainerInfoRecord({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: input.parentId ?? null,\n });\n const local = {\n createdAt: localContainerInfo.localCreatedAt,\n updatedAt: localContainerInfo.localUpdatedAt,\n };\n\n if (\n !shouldLoadRemoteContainerInfo({\n localContainerInfo,\n remoteInfoMode: input.remoteInfoMode ?? \"always\",\n })\n ) {\n return {\n local,\n remoteInfo: null,\n };\n }\n\n const [projection, groups, syncCursors] = await Promise.all([\n input.containerProjection\n ? Promise.resolve(input.containerProjection)\n : input.apiClient.getContainerWriterProjection(input.containerId),\n input.loadOrganizationGroups(),\n loadContainerSyncCursors({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: localContainerInfo.parentId,\n }),\n ]);\n\n if (!projection) {\n throw new Error(\"Container info could not be loaded.\");\n }\n\n const target = getTargetContainerContext(projection);\n const state = readContainerState(target.manifest);\n\n return {\n local,\n remoteInfo: {\n grantRows: getContainerInfoGrantRows(projection),\n grants: sortContainerInfoGrants(\n state.directGrants.map(toContainerInfoGrant),\n ),\n groups: [...groups],\n security: getContainerInfoSecurityDetails(projection),\n syncCursors,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"containerInfo.js","sourceRoot":"","sources":["containerInfo.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerAccessLevel,\n ContainerGrantSubjectType,\n} from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport { ensureContainerTables } from \"../../../data/persistence/container-contents/containerPersistence\";\nimport {\n type ContainerSyncWatermarkLane,\n containerContentsSyncLane,\n containerParentSyncLane,\n containerSyncWatermarkLaneKey,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../../data/persistence/container-contents/containerSyncWatermarkPersistence\";\nimport { containers } from \"../../../data/sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { OrganizationGroupSummary } from \"../../organizations/readModel\";\n\nexport type ContainerShareAccessLevel = ContainerAccessLevel;\n\nexport interface ContainerInfoGrant {\n accessLevel: ContainerAccessLevel;\n subjectId: string;\n subjectType: ContainerGrantSubjectType;\n}\n\nexport interface ContainerInfoGrantRow extends ContainerInfoGrant {\n inherited: boolean;\n sourceContainerId: string;\n}\n\nexport interface ContainerInfoSyncCursor {\n label: string;\n laneId: string;\n laneKind: string;\n savedAt: string | null;\n watermarkId: string | null;\n watermarkUpdatedAt: string | null;\n}\n\nexport interface ContainerInfoPathEntry {\n containerId: string;\n containerKeyEpoch: number;\n containerKeyEpochId: string;\n directGrantCount: number;\n eventHash: string;\n keyEpochHash: string;\n keyTargetHash: string;\n manifestHash: string;\n manifestHistoryCount: number;\n parentContainerId: string | null;\n parentManifestHash: string | null;\n recipientTargetCount: number;\n referencedPrincipalCount: number;\n wrapCount: number;\n}\n\nexport interface ContainerInfoSecurityDetails {\n currentContainerKeyEpoch: number;\n currentContainerKeyEpochId: string;\n currentManifestHash: string;\n currentManifestHistoryCount: number;\n currentParentContainerKeyEpochId: string | null;\n currentReferencedPrincipalCount: number;\n path: ContainerInfoPathEntry[];\n pathLength: number;\n}\n\nexport interface ContainerInfoRemoteDetails {\n grantRows: ContainerInfoGrantRow[];\n grants: ContainerInfoGrant[];\n groups: OrganizationGroupSummary[];\n security?: ContainerInfoSecurityDetails;\n syncCursors: ContainerInfoSyncCursor[];\n}\n\nexport interface ContainerInfoLocalDetails {\n createdAt: string | null;\n updatedAt: string | null;\n}\n\nexport interface ContainerInfo {\n local: ContainerInfoLocalDetails;\n remoteInfo: ContainerInfoRemoteDetails | null;\n}\n\ninterface ContainerInfoApi {\n getContainerWriterProjection: (\n containerId: string,\n ) => Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport type ContainerInfoRemoteMode = \"always\" | \"if-synced\" | \"never\";\n\ninterface LocalContainerInfoRecord {\n hasSyncedContainer: boolean;\n localCreatedAt: string | null;\n localUpdatedAt: string | null;\n organizationId: string | null;\n parentId: string | null;\n}\n\nfunction sortContainerInfoGrants<T extends ContainerInfoGrant>(\n grants: readonly T[],\n): T[] {\n return [...grants].sort((left, right) =>\n `${left.subjectType}:${left.subjectId}`.localeCompare(\n `${right.subjectType}:${right.subjectId}`,\n ),\n );\n}\n\nfunction toContainerInfoGrant(grant: ContainerInfoGrant): ContainerInfoGrant {\n return {\n accessLevel: grant.accessLevel,\n subjectId: grant.subjectId,\n subjectType: grant.subjectType,\n };\n}\n\nfunction getContainerInfoGrantRows(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoGrantRow[] {\n const rows = projection.path.flatMap((bundle) => {\n const state = readContainerState(bundle);\n\n return state.directGrants.map((grant) => ({\n ...toContainerInfoGrant(grant),\n inherited: state.containerId !== projection.containerId,\n sourceContainerId: state.containerId,\n }));\n });\n\n return sortContainerInfoGrants(rows);\n}\n\nfunction getContainerInfoPathEntries(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoPathEntry[] {\n return projection.path.map((bundle, index) => {\n const state = readContainerState(bundle);\n const kek = projection.containerKeks[index];\n if (!kek) {\n throw new Error(\"Container projection path and KEKs are inconsistent\");\n }\n\n return {\n containerId: state.containerId,\n containerKeyEpoch: kek.containerKeyEpoch,\n containerKeyEpochId: kek.containerKeyEpochId,\n directGrantCount: state.directGrants.length,\n eventHash: state.eventHash,\n keyEpochHash: kek.keyEpochHash,\n keyTargetHash: kek.keyTargetHash,\n manifestHash: bundle.manifestHash,\n manifestHistoryCount: kek.containerManifestHistory.length,\n parentContainerId: state.parentContainerId,\n parentManifestHash: state.parentManifestHash,\n recipientTargetCount: kek.recipientTargets.length,\n referencedPrincipalCount: state.referencedPrincipalHeads.length,\n wrapCount: kek.wraps.length,\n };\n });\n}\n\nfunction getContainerInfoSecurityDetails(\n projection: ContainerWriterProjectionResponse,\n): ContainerInfoSecurityDetails {\n const path = getContainerInfoPathEntries(projection);\n const targetPathEntry = path.at(-1);\n const targetKek = projection.containerKeks.at(-1);\n if (!targetPathEntry || !targetKek) {\n throw new Error(\"Container projection is empty\");\n }\n\n return {\n currentContainerKeyEpoch: targetPathEntry.containerKeyEpoch,\n currentContainerKeyEpochId: targetPathEntry.containerKeyEpochId,\n currentManifestHash: targetPathEntry.manifestHash,\n currentManifestHistoryCount: targetPathEntry.manifestHistoryCount,\n currentParentContainerKeyEpochId: targetKek.parentContainerKeyEpochId,\n currentReferencedPrincipalCount: targetPathEntry.referencedPrincipalCount,\n path,\n pathLength: path.length,\n };\n}\n\ninterface ContainerInfoSyncCursorDefinition {\n label: string;\n lane: ContainerSyncWatermarkLane;\n}\n\nfunction getContainerSyncCursorDefinitions(input: {\n containerId: string;\n parentId: string | null;\n}): ContainerInfoSyncCursorDefinition[] {\n return [\n {\n label: \"Parent Listing\",\n lane: containerParentSyncLane(input.parentId),\n },\n {\n label: \"Child Containers\",\n lane: containerParentSyncLane(input.containerId),\n },\n {\n label: \"Documents\",\n lane: containerContentsSyncLane(input.containerId),\n },\n ];\n}\n\nasync function loadContainerSyncCursors(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<ContainerInfoSyncCursor[]> {\n const cursorDefinitions = getContainerSyncCursorDefinitions(input);\n let records: Awaited<\n ReturnType<typeof sqlContainerSyncWatermarkPersistence.loadWatermarkRecords>\n > = [];\n if (input.execSql) {\n await sqlContainerSyncWatermarkPersistence.ensureSchema(input.execSql);\n records = await sqlContainerSyncWatermarkPersistence.loadWatermarkRecords(\n input.execSql,\n cursorDefinitions.map(({ lane }) => lane),\n );\n }\n\n return cursorDefinitions.map((definition, index) => {\n const { laneId, laneKind } = containerSyncWatermarkLaneKey(definition.lane);\n const record = records[index] ?? null;\n\n return {\n label: definition.label,\n laneId,\n laneKind,\n savedAt: record?.updatedAt ?? null,\n watermarkId: record?.watermark.id ?? null,\n watermarkUpdatedAt: record?.watermark.updatedAt ?? null,\n };\n });\n}\n\nasync function loadLocalContainerInfoRecord(input: {\n containerId: string;\n execSql: ExecSql | null;\n parentId: string | null;\n}): Promise<LocalContainerInfoRecord> {\n const fallback: LocalContainerInfoRecord = {\n hasSyncedContainer: false,\n localCreatedAt: null,\n localUpdatedAt: null,\n organizationId: null,\n parentId: input.parentId,\n };\n\n if (!input.execSql) {\n return fallback;\n }\n\n await ensureContainerTables(input.execSql);\n\n const { db } = getClientSQLitePersistenceRuntime(input.execSql);\n const rows = await db\n .select({\n localCreatedAt: containers.localCreatedAt,\n localUpdatedAt: containers.localUpdatedAt,\n metadataDocumentId: containers.metadataDocumentId,\n organizationId: containers.organizationId,\n parentId: containers.parentId,\n })\n .from(containers)\n .where(eq(containers.id, input.containerId))\n .limit(1);\n const row = rows[0];\n\n if (!row) {\n return fallback;\n }\n\n return {\n hasSyncedContainer:\n typeof row.metadataDocumentId === \"string\" &&\n row.metadataDocumentId.length > 0,\n localCreatedAt: row.localCreatedAt,\n localUpdatedAt: row.localUpdatedAt,\n organizationId: row.organizationId,\n parentId: row.parentId,\n };\n}\n\nfunction shouldLoadRemoteContainerInfo(input: {\n localContainerInfo: LocalContainerInfoRecord;\n remoteInfoMode: ContainerInfoRemoteMode;\n}): boolean {\n switch (input.remoteInfoMode) {\n case \"always\":\n return true;\n case \"if-synced\":\n return input.localContainerInfo.hasSyncedContainer;\n case \"never\":\n return false;\n }\n}\n\nexport async function loadContainerInfo(input: {\n apiClient: ContainerInfoApi;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | null | undefined;\n execSql?: ExecSql | null;\n loadOrganizationGroups: () => Promise<\n ReadonlyArray<OrganizationGroupSummary>\n >;\n parentId?: string | null;\n remoteInfoMode?: ContainerInfoRemoteMode | undefined;\n}): Promise<ContainerInfo> {\n const localContainerInfo = await loadLocalContainerInfoRecord({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: input.parentId ?? null,\n });\n const local = {\n createdAt: localContainerInfo.localCreatedAt,\n updatedAt: localContainerInfo.localUpdatedAt,\n };\n\n if (\n !shouldLoadRemoteContainerInfo({\n localContainerInfo,\n remoteInfoMode: input.remoteInfoMode ?? \"always\",\n })\n ) {\n return {\n local,\n remoteInfo: null,\n };\n }\n\n const [projection, groups, syncCursors] = await Promise.all([\n input.containerProjection\n ? Promise.resolve(input.containerProjection)\n : input.apiClient.getContainerWriterProjection(input.containerId),\n input.loadOrganizationGroups(),\n loadContainerSyncCursors({\n containerId: input.containerId,\n execSql: input.execSql ?? null,\n parentId: localContainerInfo.parentId,\n }),\n ]);\n\n if (!projection) {\n throw new Error(\"Container info could not be loaded.\");\n }\n\n const target = getTargetContainerContext(projection);\n const state = readContainerState(target.manifest);\n\n return {\n local,\n remoteInfo: {\n grantRows: getContainerInfoGrantRows(projection),\n grants: sortContainerInfoGrants(\n state.directGrants.map(toContainerInfoGrant),\n ),\n groups: [...groups],\n security: getContainerInfoSecurityDetails(projection),\n syncCursors,\n },\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { createDocument } from "../../internal/loro/index.js";
1
+ import { createDocument } from "../../../internal/loro/index.js";
2
2
  interface ContainerMetadataValue {
3
3
  icon: string | null;
4
4
  name: string;
@@ -1,5 +1,5 @@
1
- import { createDocument, exportAllUpdates } from "../../internal/loro/index.js";
2
- import { getScopedPeerSeed } from "../sync/crdtPeerSeed.js";
1
+ import { createDocument, exportAllUpdates } from "../../../internal/loro/index.js";
2
+ import { getScopedPeerSeed } from "../../../data/sync/crdtPeerSeed.js";
3
3
  export function getDefaultContainerName(parentId) {
4
4
  return parentId === null ? "/" : "Untitled";
5
5
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerMetadataDocument.js","sourceRoot":"","sources":["containerMetadataDocument.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAWpE,MAAM,UAAU,uBAAuB,CAAC,QAAuB;IAC7D,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,YAAoB;IAEpB,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,cAAc,CAAC,MAAM,iBAAiB,CAAC,oBAAoB,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0CAA0C,CAC9D,WAAmB,EACnB,KAA6B;IAK7B,MAAM,GAAG,GAAG,MAAM,+BAA+B,CAAC,WAAW,CAAC,CAAC;IAC/D,2BAA2B,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAExC,OAAO;QACL,GAAG;QACH,aAAa,EAAE,gBAAgB,CAAC,GAAG,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,GAA8B,EAC9B,WAAmB;IAEnB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAExC,OAAO;QACL,IAAI,EACF,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YACrD,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,IAAI;QACV,IAAI,EACF,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAC5D,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,WAAW;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,GAA8B,EAC9B,KAA6B;IAE7B,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEzC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["import { createDocument, exportAllUpdates } from \"@tearleads/loro\";\nimport { getScopedPeerSeed } from \"../../../data/sync/crdtPeerSeed\";\n\ninterface ContainerMetadataValue {\n icon: string | null;\n name: string;\n}\n\nexport type ContainerMetadataDocument = Awaited<\n ReturnType<typeof createDocument>\n>;\n\nexport function getDefaultContainerName(parentId: string | null): string {\n return parentId === null ? \"/\" : \"Untitled\";\n}\n\nexport async function createContainerMetadataDocument(\n _containerId: string,\n): Promise<ContainerMetadataDocument> {\n // A single static scope for all container-metadata docs: they are separate\n // CRDTs, so they can share one device peer, and a per-container scope would\n // hold a distinct device-peer lock (and cache entry) per container for the\n // tab's lifetime, accumulating without bound as containers are browsed.\n return createDocument(await getScopedPeerSeed(\"container-metadata\"));\n}\n\nexport async function createInitializedContainerMetadataDocument(\n containerId: string,\n value: ContainerMetadataValue,\n): Promise<{\n doc: ContainerMetadataDocument;\n initialUpdate: Uint8Array;\n}> {\n const doc = await createContainerMetadataDocument(containerId);\n writeContainerMetadataValue(doc, value);\n\n return {\n doc,\n initialUpdate: exportAllUpdates(doc),\n };\n}\n\nexport function readContainerMetadataValue(\n doc: ContainerMetadataDocument,\n defaultName: string,\n): ContainerMetadataValue {\n const metadata = doc.getMap(\"container\");\n const storedName = metadata.get(\"name\");\n const storedIcon = metadata.get(\"icon\");\n\n return {\n icon:\n typeof storedIcon === \"string\" && storedIcon.length > 0\n ? storedIcon\n : null,\n name:\n typeof storedName === \"string\" && storedName.trim().length > 0\n ? storedName\n : defaultName,\n };\n}\n\nexport function writeContainerMetadataValue(\n doc: ContainerMetadataDocument,\n value: ContainerMetadataValue,\n): void {\n const metadata = doc.getMap(\"container\");\n\n metadata.set(\"name\", value.name);\n\n if (value.icon) {\n metadata.set(\"icon\", value.icon);\n return;\n }\n\n metadata.delete(\"icon\");\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { base64ToBytes } from "../../../internal/encoding/index.js";
2
2
  import { encodeVersionVector, exportUpdatesSince, importUpdates, } from "../../../internal/loro/index.js";
3
- import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
4
3
  import { documentSyncPullContinuationsEqual } from "../../../data/documents/shared/sync/syncPagination.js";
5
4
  import { canWriteEffectiveAccessLevel } from "../../../data/keying/accessLevel.js";
5
+ import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "./containerMetadataDocument.js";
6
6
  import { metadataSyncSecurityContextMatches, replaceSupersededMetadataIdentity, sameNullableMetadataValue, } from "./metadataSyncSettlement.js";
7
7
  export function currentMetadataPullContinuation(metadataState) {
8
8
  return Object.hasOwn(metadataState, "pullContinuation")
@@ -1 +1 @@
1
- {"version":3,"file":"metadataMutationPreparation.js","sourceRoot":"","sources":["metadataMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n exportUpdatesSince,\n importUpdates,\n} from \"@tearleads/loro\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { documentSyncPullContinuationsEqual } from \"../../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../../data/keying/accessLevel\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n sameNullableMetadataValue,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport interface PersistContainerMetadataStateInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n clearSyncFailure?: boolean | undefined;\n execSql: ExecSql;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n localMetadataPatch?:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n localUpdate?: Uint8Array | undefined;\n metadataState: ContainerMetadataState;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n patch?: Partial<ContainerMetadataPatch> | undefined;\n persistence: ContainerContentsPersistence;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?:\n | Parameters<ContainerContentsPersistence[\"saveContainer\"]>[3]\n | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport function currentMetadataPullContinuation(\n metadataState: ContainerMetadataState,\n) {\n return Object.hasOwn(metadataState, \"pullContinuation\")\n ? (metadataState.pullContinuation ?? null)\n : (metadataState.record.pullContinuation ?? null);\n}\n\nexport function resolveMetadataSecurityContext(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const currentDocumentId = metadataState.record.documentId ?? null;\n const documentId =\n patch.documentId !== undefined ? patch.documentId : currentDocumentId;\n const accessEpoch = patch.accessEpoch ?? metadataState.record.accessEpoch;\n const documentIdChanged = documentId !== currentDocumentId;\n\n return {\n accessEpoch,\n changed:\n documentIdChanged || accessEpoch !== metadataState.record.accessEpoch,\n documentId,\n documentIdChanged,\n };\n}\n\nfunction mergeDurableMetadataCheckpoint(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): void {\n const { durableRecord, metadataState, securityContext } = input;\n if (\n !durableRecord?.metadataUpdates ||\n durableRecord.documentId !== metadataState.record.documentId ||\n durableRecord.documentId !== securityContext.documentId ||\n durableRecord.accessEpoch !== metadataState.record.accessEpoch ||\n durableRecord.accessEpoch !== securityContext.accessEpoch\n ) {\n return;\n }\n\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n}\n\nexport async function loadAuthoritativeContainerMetadataState(input: {\n containerId: string;\n execSql: ExecSql;\n persistence: ContainerContentsPersistence;\n}) {\n const stored = await input.persistence.loadContainerMetadataState(\n input.execSql,\n input.containerId,\n );\n return stored?.record\n ? { container: stored.container, record: stored.record }\n : null;\n}\n\nfunction localMetadataWriteAccessWasRevoked(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n mutationInput: PersistContainerMetadataStateInput;\n}): boolean {\n return (\n input.mutationInput.expectedSyncState === undefined &&\n input.mutationInput.localUpdate !== undefined &&\n canWriteEffectiveAccessLevel(\n input.mutationInput.metadataState.container.effectiveAccessLevel,\n ) &&\n !canWriteEffectiveAccessLevel(\n input.authoritativeState.container.effectiveAccessLevel,\n )\n );\n}\n\nasync function prepareRebasedLocalMetadataMutation(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n metadataState: ContainerMetadataState;\n localMetadataPatch:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n patch: Partial<ContainerMetadataPatch>;\n}) {\n const { authoritativeState, metadataState, patch } = input;\n const replacementVersion = encodeVersionVector(metadataState.doc);\n const replacementMetadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(authoritativeState.container.parentId),\n );\n writeContainerMetadataValue(metadataState.doc, {\n ...replacementMetadata,\n ...input.localMetadataPatch,\n });\n const rebasedMetadataState = {\n ...metadataState,\n container: authoritativeState.container,\n pullContinuation: authoritativeState.record.pullContinuation ?? null,\n record: authoritativeState.record,\n };\n return {\n durableRecord: authoritativeState.record,\n mutationContainer: authoritativeState.container,\n mutationMetadataState: rebasedMetadataState,\n mutationPatch: patch,\n pendingLocalUpdate: exportUpdatesSince(\n metadataState.doc,\n replacementVersion,\n ),\n pullContinuationSuperseded: false,\n securityContext: resolveMetadataSecurityContext(\n rebasedMetadataState,\n patch,\n ),\n securityContextMatches: true,\n };\n}\n\nfunction resolveMetadataSettlementMatch(\n expectedSyncState: ExpectedContainerMetadataSyncState | undefined,\n durableRecord: DocumentRecord | null,\n) {\n if (!expectedSyncState) {\n return {\n contentStateSuperseded: false,\n pullContinuationSuperseded: false,\n securityContextMatches: true,\n };\n }\n const securityContextMatches = metadataSyncSecurityContextMatches(\n durableRecord,\n expectedSyncState.record,\n );\n const progressStateMatches =\n securityContextMatches &&\n sameNullableMetadataValue(\n durableRecord?.lastCommitLsn,\n expectedSyncState.record.lastCommitLsn,\n ) &&\n Boolean(durableRecord?.pullContinuationRecoveryRequired) ===\n Boolean(expectedSyncState.record.pullContinuationRecoveryRequired) &&\n documentSyncPullContinuationsEqual(\n durableRecord?.pullContinuation,\n expectedSyncState.pullContinuation,\n );\n const contentStateMatches =\n progressStateMatches &&\n sameNullableMetadataValue(\n durableRecord?.metadataUpdates,\n expectedSyncState.record.metadataUpdates,\n ) &&\n sameNullableMetadataValue(\n durableRecord?.snapshotEndVersion,\n expectedSyncState.record.snapshotEndVersion,\n );\n return {\n contentStateSuperseded: progressStateMatches && !contentStateMatches,\n pullContinuationSuperseded: !progressStateMatches,\n securityContextMatches,\n };\n}\n\nexport async function prepareContainerMetadataMutation(\n input: PersistContainerMetadataStateInput,\n execSql: ExecSql,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const { metadataState, persistence } = input;\n const authoritativeState = await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql,\n persistence,\n });\n if (!authoritativeState) {\n return {\n authoritativeState: null,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n if (\n localMetadataWriteAccessWasRevoked({\n authoritativeState,\n mutationInput: input,\n })\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n const durableRecord = authoritativeState.record;\n const mutationMetadataState = durableRecord\n ? {\n ...metadataState,\n pullContinuation: durableRecord.pullContinuation ?? null,\n record: durableRecord,\n }\n : metadataState;\n const capturedSecurityContextMatches =\n durableRecord !== null &&\n metadataSyncSecurityContextMatches(durableRecord, metadataState.record);\n const {\n contentStateSuperseded,\n pullContinuationSuperseded,\n securityContextMatches,\n } = resolveMetadataSettlementMatch(input.expectedSyncState, durableRecord);\n\n if (\n input.expectedSyncState === undefined &&\n !capturedSecurityContextMatches\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n if (input.localUpdate === undefined) {\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n return prepareRebasedLocalMetadataMutation({\n authoritativeState,\n localMetadataPatch: input.localMetadataPatch,\n metadataState,\n patch,\n });\n }\n const mutationPatch = pullContinuationSuperseded ? {} : patch;\n const securityContext = resolveMetadataSecurityContext(\n mutationMetadataState,\n mutationPatch,\n );\n if (\n securityContextMatches &&\n (input.expectedSyncState === undefined || contentStateSuperseded)\n ) {\n mergeDurableMetadataCheckpoint({\n durableRecord,\n metadataState,\n securityContext,\n });\n }\n return {\n durableRecord,\n mutationContainer: authoritativeState.container,\n mutationMetadataState,\n mutationPatch,\n pendingLocalUpdate: input.localUpdate,\n pullContinuationSuperseded,\n securityContext,\n securityContextMatches,\n };\n}\n"]}
1
+ {"version":3,"file":"metadataMutationPreparation.js","sourceRoot":"","sources":["metadataMutationPreparation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kCAAkC,EAAE,MAAM,oDAAoD,CAAC;AACxG,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAIhF,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,kCAAkC,EAClC,iCAAiC,EACjC,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AA+BlC,MAAM,UAAU,+BAA+B,CAC7C,aAAqC;IAErC,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,kBAAkB,CAAC;QACrD,CAAC,CAAC,CAAC,aAAa,CAAC,gBAAgB,IAAI,IAAI,CAAC;QAC1C,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,aAAqC,EACrC,KAAsC;IAEtC,MAAM,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC;IAClE,MAAM,UAAU,GACd,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACxE,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC;IAC1E,MAAM,iBAAiB,GAAG,UAAU,KAAK,iBAAiB,CAAC;IAE3D,OAAO;QACL,WAAW;QACX,OAAO,EACL,iBAAiB,IAAI,WAAW,KAAK,aAAa,CAAC,MAAM,CAAC,WAAW;QACvE,UAAU;QACV,iBAAiB;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,8BAA8B,CAAC,KAIvC;IACC,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAChE,IACE,CAAC,aAAa,EAAE,eAAe;QAC/B,aAAa,CAAC,UAAU,KAAK,aAAa,CAAC,MAAM,CAAC,UAAU;QAC5D,aAAa,CAAC,UAAU,KAAK,eAAe,CAAC,UAAU;QACvD,aAAa,CAAC,WAAW,KAAK,aAAa,CAAC,MAAM,CAAC,WAAW;QAC9D,aAAa,CAAC,WAAW,KAAK,eAAe,CAAC,WAAW,EACzD,CAAC;QACD,OAAO;IACT,CAAC;IAED,aAAa,CAAC,aAAa,CAAC,GAAG,EAAE;QAC/B,aAAa,CAAC,aAAa,CAAC,eAAe,CAAC;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uCAAuC,CAAC,KAI7D;IACC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,0BAA0B,CAC/D,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,WAAW,CAClB,CAAC;IACF,OAAO,MAAM,EAAE,MAAM;QACnB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QACxD,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,kCAAkC,CAAC,KAK3C;IACC,OAAO,CACL,KAAK,CAAC,aAAa,CAAC,iBAAiB,KAAK,SAAS;QACnD,KAAK,CAAC,aAAa,CAAC,WAAW,KAAK,SAAS;QAC7C,4BAA4B,CAC1B,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,oBAAoB,CACjE;QACD,CAAC,4BAA4B,CAC3B,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,oBAAoB,CACxD,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mCAAmC,CAAC,KASlD;IACC,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC3D,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,mBAAmB,GAAG,0BAA0B,CACpD,aAAa,CAAC,GAAG,EACjB,uBAAuB,CAAC,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAC/D,CAAC;IACF,2BAA2B,CAAC,aAAa,CAAC,GAAG,EAAE;QAC7C,GAAG,mBAAmB;QACtB,GAAG,KAAK,CAAC,kBAAkB;KAC5B,CAAC,CAAC;IACH,MAAM,oBAAoB,GAAG;QAC3B,GAAG,aAAa;QAChB,SAAS,EAAE,kBAAkB,CAAC,SAAS;QACvC,gBAAgB,EAAE,kBAAkB,CAAC,MAAM,CAAC,gBAAgB,IAAI,IAAI;QACpE,MAAM,EAAE,kBAAkB,CAAC,MAAM;KAClC,CAAC;IACF,OAAO;QACL,aAAa,EAAE,kBAAkB,CAAC,MAAM;QACxC,iBAAiB,EAAE,kBAAkB,CAAC,SAAS;QAC/C,qBAAqB,EAAE,oBAAoB;QAC3C,aAAa,EAAE,KAAK;QACpB,kBAAkB,EAAE,kBAAkB,CACpC,aAAa,CAAC,GAAG,EACjB,kBAAkB,CACnB;QACD,0BAA0B,EAAE,KAAK;QACjC,eAAe,EAAE,8BAA8B,CAC7C,oBAAoB,EACpB,KAAK,CACN;QACD,sBAAsB,EAAE,IAAI;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,8BAA8B,CACrC,iBAAiE,EACjE,aAAoC;IAEpC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,OAAO;YACL,sBAAsB,EAAE,KAAK;YAC7B,0BAA0B,EAAE,KAAK;YACjC,sBAAsB,EAAE,IAAI;SAC7B,CAAC;IACJ,CAAC;IACD,MAAM,sBAAsB,GAAG,kCAAkC,CAC/D,aAAa,EACb,iBAAiB,CAAC,MAAM,CACzB,CAAC;IACF,MAAM,oBAAoB,GACxB,sBAAsB;QACtB,yBAAyB,CACvB,aAAa,EAAE,aAAa,EAC5B,iBAAiB,CAAC,MAAM,CAAC,aAAa,CACvC;QACD,OAAO,CAAC,aAAa,EAAE,gCAAgC,CAAC;YACtD,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,gCAAgC,CAAC;QACpE,kCAAkC,CAChC,aAAa,EAAE,gBAAgB,EAC/B,iBAAiB,CAAC,gBAAgB,CACnC,CAAC;IACJ,MAAM,mBAAmB,GACvB,oBAAoB;QACpB,yBAAyB,CACvB,aAAa,EAAE,eAAe,EAC9B,iBAAiB,CAAC,MAAM,CAAC,eAAe,CACzC;QACD,yBAAyB,CACvB,aAAa,EAAE,kBAAkB,EACjC,iBAAiB,CAAC,MAAM,CAAC,kBAAkB,CAC5C,CAAC;IACJ,OAAO;QACL,sBAAsB,EAAE,oBAAoB,IAAI,CAAC,mBAAmB;QACpE,0BAA0B,EAAE,CAAC,oBAAoB;QACjD,sBAAsB;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,KAAyC,EACzC,OAAgB,EAChB,KAAsC;IAEtC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,kBAAkB,GAAG,MAAM,uCAAuC,CAAC;QACvE,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE;QACvC,OAAO;QACP,WAAW;KACZ,CAAC,CAAC;IACH,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,OAAO;YACL,kBAAkB,EAAE,IAAI;YACxB,0BAA0B,EAAE,IAAI;YAChC,sBAAsB,EAAE,KAAK;SAC9B,CAAC;IACJ,CAAC;IACD,IACE,kCAAkC,CAAC;QACjC,kBAAkB;QAClB,aAAa,EAAE,KAAK;KACrB,CAAC,EACF,CAAC;QACD,MAAM,iCAAiC,CAAC;YACtC,aAAa,EAAE,kBAAkB,CAAC,MAAM;YACxC,aAAa;SACd,CAAC,CAAC;QACH,OAAO;YACL,kBAAkB;YAClB,0BAA0B,EAAE,IAAI;YAChC,sBAAsB,EAAE,KAAK;SAC9B,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC;IAChD,MAAM,qBAAqB,GAAG,aAAa;QACzC,CAAC,CAAC;YACE,GAAG,aAAa;YAChB,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,IAAI,IAAI;YACxD,MAAM,EAAE,aAAa;SACtB;QACH,CAAC,CAAC,aAAa,CAAC;IAClB,MAAM,8BAA8B,GAClC,aAAa,KAAK,IAAI;QACtB,kCAAkC,CAAC,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1E,MAAM,EACJ,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,GACvB,GAAG,8BAA8B,CAAC,KAAK,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAE3E,IACE,KAAK,CAAC,iBAAiB,KAAK,SAAS;QACrC,CAAC,8BAA8B,EAC/B,CAAC;QACD,MAAM,iCAAiC,CAAC;YACtC,aAAa,EAAE,kBAAkB,CAAC,MAAM;YACxC,aAAa;SACd,CAAC,CAAC;QACH,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO;gBACL,kBAAkB;gBAClB,0BAA0B,EAAE,IAAI;gBAChC,sBAAsB,EAAE,KAAK;aAC9B,CAAC;QACJ,CAAC;QACD,OAAO,mCAAmC,CAAC;YACzC,kBAAkB;YAClB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,aAAa;YACb,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IACD,MAAM,aAAa,GAAG,0BAA0B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9D,MAAM,eAAe,GAAG,8BAA8B,CACpD,qBAAqB,EACrB,aAAa,CACd,CAAC;IACF,IACE,sBAAsB;QACtB,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS,IAAI,sBAAsB,CAAC,EACjE,CAAC;QACD,8BAA8B,CAAC;YAC7B,aAAa;YACb,aAAa;YACb,eAAe;SAChB,CAAC,CAAC;IACL,CAAC;IACD,OAAO;QACL,aAAa;QACb,iBAAiB,EAAE,kBAAkB,CAAC,SAAS;QAC/C,qBAAqB;QACrB,aAAa;QACb,kBAAkB,EAAE,KAAK,CAAC,WAAW;QACrC,0BAA0B;QAC1B,eAAe;QACf,sBAAsB;KACvB,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n exportUpdatesSince,\n importUpdates,\n} from \"@tearleads/loro\";\nimport { documentSyncPullContinuationsEqual } from \"../../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../../data/keying/accessLevel\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"./containerMetadataDocument\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n sameNullableMetadataValue,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport interface PersistContainerMetadataStateInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n clearSyncFailure?: boolean | undefined;\n execSql: ExecSql;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n localMetadataPatch?:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n localUpdate?: Uint8Array | undefined;\n metadataState: ContainerMetadataState;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n patch?: Partial<ContainerMetadataPatch> | undefined;\n persistence: ContainerContentsPersistence;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?:\n | Parameters<ContainerContentsPersistence[\"saveContainer\"]>[3]\n | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport function currentMetadataPullContinuation(\n metadataState: ContainerMetadataState,\n) {\n return Object.hasOwn(metadataState, \"pullContinuation\")\n ? (metadataState.pullContinuation ?? null)\n : (metadataState.record.pullContinuation ?? null);\n}\n\nexport function resolveMetadataSecurityContext(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const currentDocumentId = metadataState.record.documentId ?? null;\n const documentId =\n patch.documentId !== undefined ? patch.documentId : currentDocumentId;\n const accessEpoch = patch.accessEpoch ?? metadataState.record.accessEpoch;\n const documentIdChanged = documentId !== currentDocumentId;\n\n return {\n accessEpoch,\n changed:\n documentIdChanged || accessEpoch !== metadataState.record.accessEpoch,\n documentId,\n documentIdChanged,\n };\n}\n\nfunction mergeDurableMetadataCheckpoint(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): void {\n const { durableRecord, metadataState, securityContext } = input;\n if (\n !durableRecord?.metadataUpdates ||\n durableRecord.documentId !== metadataState.record.documentId ||\n durableRecord.documentId !== securityContext.documentId ||\n durableRecord.accessEpoch !== metadataState.record.accessEpoch ||\n durableRecord.accessEpoch !== securityContext.accessEpoch\n ) {\n return;\n }\n\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n}\n\nexport async function loadAuthoritativeContainerMetadataState(input: {\n containerId: string;\n execSql: ExecSql;\n persistence: ContainerContentsPersistence;\n}) {\n const stored = await input.persistence.loadContainerMetadataState(\n input.execSql,\n input.containerId,\n );\n return stored?.record\n ? { container: stored.container, record: stored.record }\n : null;\n}\n\nfunction localMetadataWriteAccessWasRevoked(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n mutationInput: PersistContainerMetadataStateInput;\n}): boolean {\n return (\n input.mutationInput.expectedSyncState === undefined &&\n input.mutationInput.localUpdate !== undefined &&\n canWriteEffectiveAccessLevel(\n input.mutationInput.metadataState.container.effectiveAccessLevel,\n ) &&\n !canWriteEffectiveAccessLevel(\n input.authoritativeState.container.effectiveAccessLevel,\n )\n );\n}\n\nasync function prepareRebasedLocalMetadataMutation(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n metadataState: ContainerMetadataState;\n localMetadataPatch:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n patch: Partial<ContainerMetadataPatch>;\n}) {\n const { authoritativeState, metadataState, patch } = input;\n const replacementVersion = encodeVersionVector(metadataState.doc);\n const replacementMetadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(authoritativeState.container.parentId),\n );\n writeContainerMetadataValue(metadataState.doc, {\n ...replacementMetadata,\n ...input.localMetadataPatch,\n });\n const rebasedMetadataState = {\n ...metadataState,\n container: authoritativeState.container,\n pullContinuation: authoritativeState.record.pullContinuation ?? null,\n record: authoritativeState.record,\n };\n return {\n durableRecord: authoritativeState.record,\n mutationContainer: authoritativeState.container,\n mutationMetadataState: rebasedMetadataState,\n mutationPatch: patch,\n pendingLocalUpdate: exportUpdatesSince(\n metadataState.doc,\n replacementVersion,\n ),\n pullContinuationSuperseded: false,\n securityContext: resolveMetadataSecurityContext(\n rebasedMetadataState,\n patch,\n ),\n securityContextMatches: true,\n };\n}\n\nfunction resolveMetadataSettlementMatch(\n expectedSyncState: ExpectedContainerMetadataSyncState | undefined,\n durableRecord: DocumentRecord | null,\n) {\n if (!expectedSyncState) {\n return {\n contentStateSuperseded: false,\n pullContinuationSuperseded: false,\n securityContextMatches: true,\n };\n }\n const securityContextMatches = metadataSyncSecurityContextMatches(\n durableRecord,\n expectedSyncState.record,\n );\n const progressStateMatches =\n securityContextMatches &&\n sameNullableMetadataValue(\n durableRecord?.lastCommitLsn,\n expectedSyncState.record.lastCommitLsn,\n ) &&\n Boolean(durableRecord?.pullContinuationRecoveryRequired) ===\n Boolean(expectedSyncState.record.pullContinuationRecoveryRequired) &&\n documentSyncPullContinuationsEqual(\n durableRecord?.pullContinuation,\n expectedSyncState.pullContinuation,\n );\n const contentStateMatches =\n progressStateMatches &&\n sameNullableMetadataValue(\n durableRecord?.metadataUpdates,\n expectedSyncState.record.metadataUpdates,\n ) &&\n sameNullableMetadataValue(\n durableRecord?.snapshotEndVersion,\n expectedSyncState.record.snapshotEndVersion,\n );\n return {\n contentStateSuperseded: progressStateMatches && !contentStateMatches,\n pullContinuationSuperseded: !progressStateMatches,\n securityContextMatches,\n };\n}\n\nexport async function prepareContainerMetadataMutation(\n input: PersistContainerMetadataStateInput,\n execSql: ExecSql,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const { metadataState, persistence } = input;\n const authoritativeState = await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql,\n persistence,\n });\n if (!authoritativeState) {\n return {\n authoritativeState: null,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n if (\n localMetadataWriteAccessWasRevoked({\n authoritativeState,\n mutationInput: input,\n })\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n const durableRecord = authoritativeState.record;\n const mutationMetadataState = durableRecord\n ? {\n ...metadataState,\n pullContinuation: durableRecord.pullContinuation ?? null,\n record: durableRecord,\n }\n : metadataState;\n const capturedSecurityContextMatches =\n durableRecord !== null &&\n metadataSyncSecurityContextMatches(durableRecord, metadataState.record);\n const {\n contentStateSuperseded,\n pullContinuationSuperseded,\n securityContextMatches,\n } = resolveMetadataSettlementMatch(input.expectedSyncState, durableRecord);\n\n if (\n input.expectedSyncState === undefined &&\n !capturedSecurityContextMatches\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n if (input.localUpdate === undefined) {\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n return prepareRebasedLocalMetadataMutation({\n authoritativeState,\n localMetadataPatch: input.localMetadataPatch,\n metadataState,\n patch,\n });\n }\n const mutationPatch = pullContinuationSuperseded ? {} : patch;\n const securityContext = resolveMetadataSecurityContext(\n mutationMetadataState,\n mutationPatch,\n );\n if (\n securityContextMatches &&\n (input.expectedSyncState === undefined || contentStateSuperseded)\n ) {\n mergeDurableMetadataCheckpoint({\n durableRecord,\n metadataState,\n securityContext,\n });\n }\n return {\n durableRecord,\n mutationContainer: authoritativeState.container,\n mutationMetadataState,\n mutationPatch,\n pendingLocalUpdate: input.localUpdate,\n pullContinuationSuperseded,\n securityContext,\n securityContextMatches,\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { encodeVersionVector, exportUpdatesSince } from "../../../internal/loro/index.js";
2
- import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
3
2
  import { createPendingUpdateFields } from "../../../data/documents/documentSync.js";
4
3
  import { runSerializedSqlMutation, } from "../../../data/sqlite/sqlSchema.js";
4
+ import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "./containerMetadataDocument.js";
5
5
  import { currentMetadataPullContinuation, loadAuthoritativeContainerMetadataState, prepareContainerMetadataMutation, } from "./metadataMutationPreparation.js";
6
6
  import { buildContainerMetadataRecord, resolveContainerSystemSlot, resolveMetadataDocumentId, } from "./metadataRecord.js";
7
7
  import { installContainerMetadataRecord } from "./metadataStateInstallation.js";
@@ -1 +1 @@
1
- {"version":3,"file":"metadataPersistence.js","sourceRoot":"","sources":["metadataPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeVersionVector, exportUpdatesSince } from \"@tearleads/loro\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { createPendingUpdateFields } from \"../../../data/documents/documentSync\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\nimport {\n type ExecSql,\n runSerializedSqlMutation,\n} from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport type { ContainerContentsWorkflowSqlRuntime } from \"../runtime\";\nimport {\n currentMetadataPullContinuation,\n loadAuthoritativeContainerMetadataState,\n type PersistContainerMetadataStateInput,\n prepareContainerMetadataMutation,\n} from \"./metadataMutationPreparation\";\nimport {\n buildContainerMetadataRecord,\n resolveContainerSystemSlot,\n resolveMetadataDocumentId,\n} from \"./metadataRecord\";\nimport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n PersistedContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype ContainerMetadataPersistenceRuntime = ContainerContentsWorkflowSqlRuntime;\nconst MAX_METADATA_MUTATION_COMMIT_ATTEMPTS = 8;\ntype SaveContainerOptions = Parameters<\n ContainerContentsPersistence[\"saveContainer\"]\n>[3];\n\nexport { hasCurrentContainerMetadataReadState } from \"./metadataReadState\";\nexport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nexport { currentMetadataPullContinuation };\n\nfunction invalidateMetadataWriterProjection(\n metadataState: ContainerMetadataState,\n securityContextChanged: boolean,\n): void {\n if (securityContextChanged) {\n metadataState.metadataWriterProjection = null;\n }\n}\ntype PreparedContainerMetadataMutation = Awaited<\n ReturnType<typeof prepareContainerMetadataMutation>\n>;\ntype ApplicableContainerMetadataMutation = Exclude<\n PreparedContainerMetadataMutation,\n { authoritativeState: unknown }\n>;\nasync function settleSupersededMetadataMutation(input: {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n execSql: ExecSql;\n expectedRecord?: DocumentRecord | undefined;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n prepared: PreparedContainerMetadataMutation;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { metadataState, persistence, prepared } = input;\n const settledState = input.expectedRecord\n ? await persistence.settleAcceptedMetadataPendingUpdates(input.execSql, {\n containerId: metadataState.container.id,\n expectedRecord: input.expectedRecord,\n pendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n stillCurrent: input.stillCurrent,\n })\n : undefined;\n if (\"authoritativeState\" in prepared) {\n const authoritativeState = settledState ?? prepared.authoritativeState;\n if (!authoritativeState?.record) return null;\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n syncIdentitySuperseded: true,\n };\n }\n const authoritativeState =\n settledState ??\n (await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql: input.execSql,\n persistence,\n }));\n if (!authoritativeState?.record) return null;\n // The rejected response may already have mutated the live Loro document.\n // Rebuild from the authoritative durable snapshot instead of merging into\n // that losing document, which would retain non-overlapping rejected fields.\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n ...(!prepared.securityContextMatches\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistPreparedMetadataMutation(input: {\n clearSyncFailure?: boolean | undefined;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n persistence: ContainerContentsPersistence;\n prepared: ApplicableContainerMetadataMutation;\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?: SaveContainerOptions;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | PersistedContainerMetadataState\n | {\n conflict: true;\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n staleServerState?: true;\n }\n> {\n const { metadataState, persistence, prepared } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(prepared.mutationContainer.parentId),\n );\n const nextContainer: ContainerRecord = {\n ...prepared.mutationContainer,\n ...(prepared.mutationPatch.effectiveAccessLevel !== undefined\n ? {\n effectiveAccessLevel: prepared.mutationPatch.effectiveAccessLevel,\n }\n : {}),\n organizationId:\n prepared.mutationPatch.organizationId ??\n prepared.mutationContainer.organizationId,\n parentId:\n prepared.mutationPatch.parentId ?? prepared.mutationContainer.parentId,\n metadataDocumentId: resolveMetadataDocumentId(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n systemSlot: resolveContainerSystemSlot(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n name: prepared.mutationPatch.name ?? metadata.name,\n icon:\n prepared.mutationPatch.icon !== undefined\n ? prepared.mutationPatch.icon\n : metadata.icon,\n };\n const nextRecord = buildContainerMetadataRecord({\n metadataState: prepared.mutationMetadataState,\n patch: prepared.mutationPatch,\n securityContext: prepared.securityContext,\n });\n const pendingUpdate = prepared.pendingLocalUpdate\n ? (createPendingUpdateFields(prepared.pendingLocalUpdate) ?? undefined)\n : undefined;\n const committed = await persistence.commitMetadataMutation(input.execSql, {\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n clearSyncFailure: input.clearSyncFailure,\n container: nextContainer,\n createIntentSettlement: input.createIntentSettlement,\n expectedContainer: prepared.mutationContainer,\n expectedRecord: prepared.durableRecord,\n moveIntentSettlement: input.moveIntentSettlement,\n pendingUpdate,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n record: nextRecord,\n saveOptions: input.saveOptions,\n settleAcceptedPendingOnConflict:\n input.acceptedPendingUpdateIds !== undefined,\n stillCurrent: input.stillCurrent,\n });\n if (!committed.committed) {\n return {\n conflict: true,\n currentState: committed.currentState,\n ...(committed.staleServerState\n ? { staleServerState: true as const }\n : {}),\n };\n }\n invalidateMetadataWriterProjection(\n metadataState,\n prepared.securityContext.changed,\n );\n return {\n container: committed.container,\n record: nextRecord,\n ...(committed.createIntentSettled\n ? { createIntentSettled: true as const }\n : {}),\n ...(committed.moveIntentSettled\n ? { moveIntentSettled: true as const }\n : {}),\n };\n}\nasync function adoptMetadataCommitConflict(input: {\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n expectedRecord: DocumentRecord;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n metadataState: ContainerMetadataState;\n staleServerState?: true | undefined;\n}): Promise<PersistedContainerMetadataState | null | \"retry\"> {\n if (!input.staleServerState && input.expectedSyncState === undefined) {\n return \"retry\";\n }\n if (!input.currentState?.record) return null;\n await replaceSupersededMetadataIdentity({\n durableRecord: input.currentState.record,\n metadataState: input.metadataState,\n });\n input.metadataState.container = input.currentState.container;\n installContainerMetadataRecord(\n input.metadataState,\n input.currentState.record,\n );\n return {\n container: input.currentState.container,\n pullContinuationSuperseded: true,\n record: input.currentState.record,\n ...(input.staleServerState ? { mutationSuperseded: true as const } : {}),\n ...(!metadataSyncSecurityContextMatches(\n input.currentState.record,\n input.expectedSyncState?.record ?? input.expectedRecord,\n )\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistContainerMetadataState(\n input: PersistContainerMetadataStateInput,\n): Promise<PersistedContainerMetadataState | null> {\n const patch = input.patch ?? {};\n const prepareMutation = prepareContainerMetadataMutation;\n return runSerializedSqlMutation(input.execSql, async (lockedExecSql) => {\n for (\n let attempt = 0;\n attempt < MAX_METADATA_MUTATION_COMMIT_ATTEMPTS;\n attempt += 1\n ) {\n const prepared = await prepareMutation(input, lockedExecSql, patch);\n if (input.stillCurrent?.() === false) return null;\n if (\n \"authoritativeState\" in prepared ||\n prepared.pullContinuationSuperseded\n ) {\n return settleSupersededMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n execSql: lockedExecSql,\n expectedRecord: input.expectedSyncState?.record,\n metadataState: input.metadataState,\n persistence: input.persistence,\n prepared,\n stillCurrent: input.stillCurrent,\n });\n }\n const persisted = await persistPreparedMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n clearSyncFailure: input.clearSyncFailure,\n createIntentSettlement: input.createIntentSettlement,\n execSql: lockedExecSql,\n metadataState: input.metadataState,\n moveIntentSettlement: input.moveIntentSettlement,\n persistence: input.persistence,\n prepared,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n saveOptions: input.saveOptions,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n if (!(\"conflict\" in persisted)) return persisted;\n const conflict = await adoptMetadataCommitConflict({\n currentState: persisted.currentState,\n expectedRecord: prepared.durableRecord,\n expectedSyncState: input.expectedSyncState,\n metadataState: input.metadataState,\n staleServerState: persisted.staleServerState,\n });\n if (conflict !== \"retry\") return conflict;\n }\n throw new Error(\n `Container metadata mutation commit gave up after ${MAX_METADATA_MUTATION_COMMIT_ATTEMPTS} concurrent conflicts`,\n );\n });\n}\ntype PersistContainerMetadataStateRuntimeInput = Omit<\n PersistContainerMetadataStateInput,\n \"execSql\"\n> & {\n onDurableStateNeedsReload?: (() => void) | undefined;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n};\n\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState: ExpectedContainerMetadataSyncState;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState?: undefined;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport async function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput,\n): Promise<PersistedContainerMetadataState | null> {\n const { onDurableStateNeedsReload, runtime, ...persistenceInput } = input;\n const execSql = runtime.infra.execSql;\n const persisted = await persistContainerMetadataState({\n ...persistenceInput,\n execSql,\n });\n if (input.stillCurrent?.() === false) {\n onDurableStateNeedsReload?.();\n return null;\n }\n return persisted;\n}\n\nasync function writeContainerMetadataPatch(input: {\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n patch: Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>;\n persistence: ContainerContentsPersistence;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { execSql, metadataState, patch, persistence } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(metadataState.container.parentId),\n );\n const previousVersion = encodeVersionVector(metadataState.doc);\n writeContainerMetadataValue(metadataState.doc, { ...metadata, ...patch });\n const update = exportUpdatesSince(metadataState.doc, previousVersion);\n\n return persistContainerMetadataState({\n execSql,\n localMetadataPatch: patch,\n localUpdate: update,\n metadataState,\n patch,\n persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function renameContainerMetadataStateFromRuntime(input: {\n metadataState: ContainerMetadataState;\n name: string;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const trimmedName = input.name.trim();\n if (!trimmedName) {\n return null;\n }\n\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { name: trimmedName },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function setContainerIconMetadataStateFromRuntime(input: {\n icon: string | null;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { icon: input.icon?.trim() || null },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
1
+ {"version":3,"file":"metadataPersistence.js","sourceRoot":"","sources":["metadataPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeVersionVector, exportUpdatesSince } from \"@tearleads/loro\";\nimport { createPendingUpdateFields } from \"../../../data/documents/documentSync\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/container-contents/containerPersistence\";\nimport {\n type ExecSql,\n runSerializedSqlMutation,\n} from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport type { ContainerContentsWorkflowSqlRuntime } from \"../runtime\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"./containerMetadataDocument\";\nimport {\n currentMetadataPullContinuation,\n loadAuthoritativeContainerMetadataState,\n type PersistContainerMetadataStateInput,\n prepareContainerMetadataMutation,\n} from \"./metadataMutationPreparation\";\nimport {\n buildContainerMetadataRecord,\n resolveContainerSystemSlot,\n resolveMetadataDocumentId,\n} from \"./metadataRecord\";\nimport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n PersistedContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype ContainerMetadataPersistenceRuntime = ContainerContentsWorkflowSqlRuntime;\nconst MAX_METADATA_MUTATION_COMMIT_ATTEMPTS = 8;\ntype SaveContainerOptions = Parameters<\n ContainerContentsPersistence[\"saveContainer\"]\n>[3];\n\nexport { hasCurrentContainerMetadataReadState } from \"./metadataReadState\";\nexport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nexport { currentMetadataPullContinuation };\n\nfunction invalidateMetadataWriterProjection(\n metadataState: ContainerMetadataState,\n securityContextChanged: boolean,\n): void {\n if (securityContextChanged) {\n metadataState.metadataWriterProjection = null;\n }\n}\ntype PreparedContainerMetadataMutation = Awaited<\n ReturnType<typeof prepareContainerMetadataMutation>\n>;\ntype ApplicableContainerMetadataMutation = Exclude<\n PreparedContainerMetadataMutation,\n { authoritativeState: unknown }\n>;\nasync function settleSupersededMetadataMutation(input: {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n execSql: ExecSql;\n expectedRecord?: DocumentRecord | undefined;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n prepared: PreparedContainerMetadataMutation;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { metadataState, persistence, prepared } = input;\n const settledState = input.expectedRecord\n ? await persistence.settleAcceptedMetadataPendingUpdates(input.execSql, {\n containerId: metadataState.container.id,\n expectedRecord: input.expectedRecord,\n pendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n stillCurrent: input.stillCurrent,\n })\n : undefined;\n if (\"authoritativeState\" in prepared) {\n const authoritativeState = settledState ?? prepared.authoritativeState;\n if (!authoritativeState?.record) return null;\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n syncIdentitySuperseded: true,\n };\n }\n const authoritativeState =\n settledState ??\n (await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql: input.execSql,\n persistence,\n }));\n if (!authoritativeState?.record) return null;\n // The rejected response may already have mutated the live Loro document.\n // Rebuild from the authoritative durable snapshot instead of merging into\n // that losing document, which would retain non-overlapping rejected fields.\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n ...(!prepared.securityContextMatches\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistPreparedMetadataMutation(input: {\n clearSyncFailure?: boolean | undefined;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n persistence: ContainerContentsPersistence;\n prepared: ApplicableContainerMetadataMutation;\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?: SaveContainerOptions;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | PersistedContainerMetadataState\n | {\n conflict: true;\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n staleServerState?: true;\n }\n> {\n const { metadataState, persistence, prepared } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(prepared.mutationContainer.parentId),\n );\n const nextContainer: ContainerRecord = {\n ...prepared.mutationContainer,\n ...(prepared.mutationPatch.effectiveAccessLevel !== undefined\n ? {\n effectiveAccessLevel: prepared.mutationPatch.effectiveAccessLevel,\n }\n : {}),\n organizationId:\n prepared.mutationPatch.organizationId ??\n prepared.mutationContainer.organizationId,\n parentId:\n prepared.mutationPatch.parentId ?? prepared.mutationContainer.parentId,\n metadataDocumentId: resolveMetadataDocumentId(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n systemSlot: resolveContainerSystemSlot(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n name: prepared.mutationPatch.name ?? metadata.name,\n icon:\n prepared.mutationPatch.icon !== undefined\n ? prepared.mutationPatch.icon\n : metadata.icon,\n };\n const nextRecord = buildContainerMetadataRecord({\n metadataState: prepared.mutationMetadataState,\n patch: prepared.mutationPatch,\n securityContext: prepared.securityContext,\n });\n const pendingUpdate = prepared.pendingLocalUpdate\n ? (createPendingUpdateFields(prepared.pendingLocalUpdate) ?? undefined)\n : undefined;\n const committed = await persistence.commitMetadataMutation(input.execSql, {\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n clearSyncFailure: input.clearSyncFailure,\n container: nextContainer,\n createIntentSettlement: input.createIntentSettlement,\n expectedContainer: prepared.mutationContainer,\n expectedRecord: prepared.durableRecord,\n moveIntentSettlement: input.moveIntentSettlement,\n pendingUpdate,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n record: nextRecord,\n saveOptions: input.saveOptions,\n settleAcceptedPendingOnConflict:\n input.acceptedPendingUpdateIds !== undefined,\n stillCurrent: input.stillCurrent,\n });\n if (!committed.committed) {\n return {\n conflict: true,\n currentState: committed.currentState,\n ...(committed.staleServerState\n ? { staleServerState: true as const }\n : {}),\n };\n }\n invalidateMetadataWriterProjection(\n metadataState,\n prepared.securityContext.changed,\n );\n return {\n container: committed.container,\n record: nextRecord,\n ...(committed.createIntentSettled\n ? { createIntentSettled: true as const }\n : {}),\n ...(committed.moveIntentSettled\n ? { moveIntentSettled: true as const }\n : {}),\n };\n}\nasync function adoptMetadataCommitConflict(input: {\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n expectedRecord: DocumentRecord;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n metadataState: ContainerMetadataState;\n staleServerState?: true | undefined;\n}): Promise<PersistedContainerMetadataState | null | \"retry\"> {\n if (!input.staleServerState && input.expectedSyncState === undefined) {\n return \"retry\";\n }\n if (!input.currentState?.record) return null;\n await replaceSupersededMetadataIdentity({\n durableRecord: input.currentState.record,\n metadataState: input.metadataState,\n });\n input.metadataState.container = input.currentState.container;\n installContainerMetadataRecord(\n input.metadataState,\n input.currentState.record,\n );\n return {\n container: input.currentState.container,\n pullContinuationSuperseded: true,\n record: input.currentState.record,\n ...(input.staleServerState ? { mutationSuperseded: true as const } : {}),\n ...(!metadataSyncSecurityContextMatches(\n input.currentState.record,\n input.expectedSyncState?.record ?? input.expectedRecord,\n )\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistContainerMetadataState(\n input: PersistContainerMetadataStateInput,\n): Promise<PersistedContainerMetadataState | null> {\n const patch = input.patch ?? {};\n const prepareMutation = prepareContainerMetadataMutation;\n return runSerializedSqlMutation(input.execSql, async (lockedExecSql) => {\n for (\n let attempt = 0;\n attempt < MAX_METADATA_MUTATION_COMMIT_ATTEMPTS;\n attempt += 1\n ) {\n const prepared = await prepareMutation(input, lockedExecSql, patch);\n if (input.stillCurrent?.() === false) return null;\n if (\n \"authoritativeState\" in prepared ||\n prepared.pullContinuationSuperseded\n ) {\n return settleSupersededMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n execSql: lockedExecSql,\n expectedRecord: input.expectedSyncState?.record,\n metadataState: input.metadataState,\n persistence: input.persistence,\n prepared,\n stillCurrent: input.stillCurrent,\n });\n }\n const persisted = await persistPreparedMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n clearSyncFailure: input.clearSyncFailure,\n createIntentSettlement: input.createIntentSettlement,\n execSql: lockedExecSql,\n metadataState: input.metadataState,\n moveIntentSettlement: input.moveIntentSettlement,\n persistence: input.persistence,\n prepared,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n saveOptions: input.saveOptions,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n if (!(\"conflict\" in persisted)) return persisted;\n const conflict = await adoptMetadataCommitConflict({\n currentState: persisted.currentState,\n expectedRecord: prepared.durableRecord,\n expectedSyncState: input.expectedSyncState,\n metadataState: input.metadataState,\n staleServerState: persisted.staleServerState,\n });\n if (conflict !== \"retry\") return conflict;\n }\n throw new Error(\n `Container metadata mutation commit gave up after ${MAX_METADATA_MUTATION_COMMIT_ATTEMPTS} concurrent conflicts`,\n );\n });\n}\ntype PersistContainerMetadataStateRuntimeInput = Omit<\n PersistContainerMetadataStateInput,\n \"execSql\"\n> & {\n onDurableStateNeedsReload?: (() => void) | undefined;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n};\n\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState: ExpectedContainerMetadataSyncState;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState?: undefined;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport async function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput,\n): Promise<PersistedContainerMetadataState | null> {\n const { onDurableStateNeedsReload, runtime, ...persistenceInput } = input;\n const execSql = runtime.infra.execSql;\n const persisted = await persistContainerMetadataState({\n ...persistenceInput,\n execSql,\n });\n if (input.stillCurrent?.() === false) {\n onDurableStateNeedsReload?.();\n return null;\n }\n return persisted;\n}\n\nasync function writeContainerMetadataPatch(input: {\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n patch: Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>;\n persistence: ContainerContentsPersistence;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { execSql, metadataState, patch, persistence } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(metadataState.container.parentId),\n );\n const previousVersion = encodeVersionVector(metadataState.doc);\n writeContainerMetadataValue(metadataState.doc, { ...metadata, ...patch });\n const update = exportUpdatesSince(metadataState.doc, previousVersion);\n\n return persistContainerMetadataState({\n execSql,\n localMetadataPatch: patch,\n localUpdate: update,\n metadataState,\n patch,\n persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function renameContainerMetadataStateFromRuntime(input: {\n metadataState: ContainerMetadataState;\n name: string;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const trimmedName = input.name.trim();\n if (!trimmedName) {\n return null;\n }\n\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { name: trimmedName },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function setContainerIconMetadataStateFromRuntime(input: {\n icon: string | null;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { icon: input.icon?.trim() || null },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"metadataRecord.js","sourceRoot":"","sources":["metadataRecord.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport { exportAllUpdates } from \"@tearleads/loro\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n currentMetadataPullContinuation,\n type resolveMetadataSecurityContext,\n} from \"./metadataMutationPreparation\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype NullableContainerMetadataDocumentField =\n | \"accessStateHash\"\n | \"lastCommitLsn\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\";\n\nexport function resolveContainerSystemSlot(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): NonNullable<ContainerRecord[\"systemSlot\"]> | null {\n return patch.systemSlot ?? container.systemSlot ?? null;\n}\n\nexport function resolveMetadataDocumentId(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): ContainerRecord[\"metadataDocumentId\"] {\n return (\n patch.metadataDocumentId ?? patch.documentId ?? container.metadataDocumentId\n );\n}\n\nfunction resolveNullableContainerMetadataDocumentField(\n patch: Partial<ContainerMetadataPatch>,\n key: NullableContainerMetadataDocumentField,\n currentValue: string | null | undefined,\n resetWhenUnpatched = false,\n): string | null {\n if (Object.hasOwn(patch, key)) return patch[key] ?? null;\n return resetWhenUnpatched ? null : (currentValue ?? null);\n}\n\nfunction resolveMetadataPullState(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n securityContextChanged: boolean,\n): Pick<\n DocumentRecord,\n \"pullContinuation\" | \"pullContinuationRecoveryRequired\"\n> {\n if (Object.hasOwn(patch, \"pullContinuation\")) {\n return { pullContinuation: patch.pullContinuation ?? null };\n }\n if (securityContextChanged) return { pullContinuation: null };\n if (metadataState.record.pullContinuationRecoveryRequired) {\n return { pullContinuationRecoveryRequired: true };\n }\n return { pullContinuation: currentMetadataPullContinuation(metadataState) };\n}\n\nexport function buildContainerMetadataRecord(input: {\n metadataState: ContainerMetadataState;\n patch: Partial<ContainerMetadataPatch>;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): DocumentRecord {\n const { metadataState, patch, securityContext } = input;\n return {\n id: metadataState.container.id,\n documentId: securityContext.documentId,\n metadataUpdates:\n patch.metadataUpdates ??\n bytesToBase64(exportAllUpdates(metadataState.doc)),\n snapshotEndVersion: \"\",\n accessEpoch: securityContext.accessEpoch,\n accessStateHash: resolveNullableContainerMetadataDocumentField(\n patch,\n \"accessStateHash\",\n metadataState.record.accessStateHash,\n securityContext.changed,\n ),\n lastCommitLsn: resolveNullableContainerMetadataDocumentField(\n patch,\n \"lastCommitLsn\",\n metadataState.record.lastCommitLsn,\n securityContext.documentIdChanged,\n ),\n contentKeyBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"contentKeyBundle\",\n metadataState.record.contentKeyBundle,\n securityContext.changed,\n ),\n documentKekTargets: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentKekTargets\",\n metadataState.record.documentKekTargets,\n securityContext.changed,\n ),\n documentManifestBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentManifestBundle\",\n metadataState.record.documentManifestBundle,\n securityContext.changed,\n ),\n ...resolveMetadataPullState(metadataState, patch, securityContext.changed),\n };\n}\n"]}
1
+ {"version":3,"file":"metadataRecord.js","sourceRoot":"","sources":["metadataRecord.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport { exportAllUpdates } from \"@tearleads/loro\";\nimport type { ContainerRecord } from \"../../../data/persistence/container-contents/containerPersistence\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n currentMetadataPullContinuation,\n type resolveMetadataSecurityContext,\n} from \"./metadataMutationPreparation\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype NullableContainerMetadataDocumentField =\n | \"accessStateHash\"\n | \"lastCommitLsn\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\";\n\nexport function resolveContainerSystemSlot(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): NonNullable<ContainerRecord[\"systemSlot\"]> | null {\n return patch.systemSlot ?? container.systemSlot ?? null;\n}\n\nexport function resolveMetadataDocumentId(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): ContainerRecord[\"metadataDocumentId\"] {\n return (\n patch.metadataDocumentId ?? patch.documentId ?? container.metadataDocumentId\n );\n}\n\nfunction resolveNullableContainerMetadataDocumentField(\n patch: Partial<ContainerMetadataPatch>,\n key: NullableContainerMetadataDocumentField,\n currentValue: string | null | undefined,\n resetWhenUnpatched = false,\n): string | null {\n if (Object.hasOwn(patch, key)) return patch[key] ?? null;\n return resetWhenUnpatched ? null : (currentValue ?? null);\n}\n\nfunction resolveMetadataPullState(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n securityContextChanged: boolean,\n): Pick<\n DocumentRecord,\n \"pullContinuation\" | \"pullContinuationRecoveryRequired\"\n> {\n if (Object.hasOwn(patch, \"pullContinuation\")) {\n return { pullContinuation: patch.pullContinuation ?? null };\n }\n if (securityContextChanged) return { pullContinuation: null };\n if (metadataState.record.pullContinuationRecoveryRequired) {\n return { pullContinuationRecoveryRequired: true };\n }\n return { pullContinuation: currentMetadataPullContinuation(metadataState) };\n}\n\nexport function buildContainerMetadataRecord(input: {\n metadataState: ContainerMetadataState;\n patch: Partial<ContainerMetadataPatch>;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): DocumentRecord {\n const { metadataState, patch, securityContext } = input;\n return {\n id: metadataState.container.id,\n documentId: securityContext.documentId,\n metadataUpdates:\n patch.metadataUpdates ??\n bytesToBase64(exportAllUpdates(metadataState.doc)),\n snapshotEndVersion: \"\",\n accessEpoch: securityContext.accessEpoch,\n accessStateHash: resolveNullableContainerMetadataDocumentField(\n patch,\n \"accessStateHash\",\n metadataState.record.accessStateHash,\n securityContext.changed,\n ),\n lastCommitLsn: resolveNullableContainerMetadataDocumentField(\n patch,\n \"lastCommitLsn\",\n metadataState.record.lastCommitLsn,\n securityContext.documentIdChanged,\n ),\n contentKeyBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"contentKeyBundle\",\n metadataState.record.contentKeyBundle,\n securityContext.changed,\n ),\n documentKekTargets: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentKekTargets\",\n metadataState.record.documentKekTargets,\n securityContext.changed,\n ),\n documentManifestBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentManifestBundle\",\n metadataState.record.documentManifestBundle,\n securityContext.changed,\n ),\n ...resolveMetadataPullState(metadataState, patch, securityContext.changed),\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { encodeVersionVector, exportAllUpdates, exportFullHistorySnapshot, importSnapshot, importUpdates, satisfiesVersionVector, } from "../../../internal/loro/index.js";
2
- import { createContainerMetadataDocument, getDefaultContainerName, readContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
3
2
  import { projectionGeneration } from "../projectionGeneration.js";
3
+ import { createContainerMetadataDocument, getDefaultContainerName, readContainerMetadataValue, } from "./containerMetadataDocument.js";
4
4
  import { metadataSyncSecurityContextMatches } from "./metadataSyncSettlement.js";
5
5
  function mergeConcurrentMetadataRecord(liveRecord, candidateRecord) {
6
6
  if (metadataSyncSecurityContextMatches(liveRecord, candidateRecord)) {
@@ -1 +1 @@
1
- {"version":3,"file":"metadataStateIsolation.js","sourceRoot":"","sources":["metadataStateIsolation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n encodeVersionVector,\n exportAllUpdates,\n exportFullHistorySnapshot,\n importSnapshot,\n importUpdates,\n satisfiesVersionVector,\n} from \"@tearleads/loro\";\nimport {\n createContainerMetadataDocument,\n getDefaultContainerName,\n readContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { projectionGeneration } from \"../projectionGeneration\";\nimport { metadataSyncSecurityContextMatches } from \"./metadataSyncSettlement\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface DetachedContainerMetadataState extends ContainerMetadataState {\n readonly detachedSource: {\n readonly metadataVersion: string;\n /** The live state's `writerProjectionGeneration` when it was detached. */\n readonly writerProjectionGeneration: number;\n };\n}\n\ninterface DetachedContainerMetadataInstallOptions {\n readonly candidateRecord?: ContainerMetadataState[\"record\"];\n readonly preserveConcurrentMetadataEdit?: boolean;\n}\n\nfunction mergeConcurrentMetadataRecord(\n liveRecord: ContainerMetadataState[\"record\"],\n candidateRecord: ContainerMetadataState[\"record\"],\n): ContainerMetadataState[\"record\"] {\n if (metadataSyncSecurityContextMatches(liveRecord, candidateRecord)) {\n return liveRecord;\n }\n\n // The live document owns the concurrent CRDT frontier, but the candidate\n // owns the newly committed remote identity. Carry only the fields that\n // describe the live CRDT history across that identity boundary.\n return {\n ...candidateRecord,\n metadataUpdates: liveRecord.metadataUpdates,\n snapshotEndVersion: liveRecord.snapshotEndVersion,\n ...(liveRecord.pendingBaseVersion === undefined\n ? {}\n : { pendingBaseVersion: liveRecord.pendingBaseVersion }),\n };\n}\n\n/**\n * Gives an asynchronous sync pass its own mutable metadata projection. Durable\n * settlement can then repair or replace the candidate without changing the\n * live store until the caller has rechecked its lifecycle generation.\n */\nexport async function createDetachedContainerMetadataState(\n metadataState: ContainerMetadataState,\n options: {\n /**\n * The live generation captured when the surrounding operation began, for\n * callers that awaited (a request, a policy warm-up) before detaching.\n */\n readonly writerProjectionGeneration?: number | undefined;\n } = {},\n): Promise<DetachedContainerMetadataState> {\n const doc = await createContainerMetadataDocument(metadataState.container.id);\n importSnapshot(doc, exportFullHistorySnapshot(metadataState.doc));\n return {\n ...metadataState,\n container: { ...metadataState.container },\n detachedSource: {\n metadataVersion: encodeVersionVector(metadataState.doc),\n writerProjectionGeneration:\n options.writerProjectionGeneration ??\n projectionGeneration(metadataState),\n },\n doc,\n record: { ...metadataState.record },\n };\n}\n\nexport function installDetachedContainerMetadataState(\n target: ContainerMetadataState,\n candidate: DetachedContainerMetadataState,\n options: DetachedContainerMetadataInstallOptions = {},\n): void {\n const candidateRecord = options.candidateRecord ?? candidate.record;\n const liveMetadataVersion = encodeVersionVector(target.doc);\n const candidateMetadataVersion = encodeVersionVector(candidate.doc);\n const liveRecord = target.record;\n const livePullContinuation = target.pullContinuation;\n const preserveConcurrentLiveMetadata =\n options.preserveConcurrentMetadataEdit === true &&\n liveMetadataVersion !== candidate.detachedSource.metadataVersion &&\n !satisfiesVersionVector(candidateMetadataVersion, liveMetadataVersion);\n const installedRecord = preserveConcurrentLiveMetadata\n ? mergeConcurrentMetadataRecord(liveRecord, candidateRecord)\n : candidateRecord;\n\n if (preserveConcurrentLiveMetadata) {\n importUpdates(target.doc, [exportAllUpdates(candidate.doc)]);\n const metadata = readContainerMetadataValue(\n target.doc,\n getDefaultContainerName(candidate.container.parentId),\n );\n target.container = {\n ...candidate.container,\n icon: metadata.icon,\n name: metadata.name,\n };\n } else {\n target.container = candidate.container;\n target.doc = candidate.doc;\n }\n // A hint invalidated the live projections while this candidate was out;\n // its copy may cite a pre-hint manifest, so the live slot stays as the hint\n // left it and the next metadata write fetches a fresh projection.\n if (\n projectionGeneration(target) ===\n candidate.detachedSource.writerProjectionGeneration\n )\n target.metadataWriterProjection = candidate.metadataWriterProjection;\n target.pullContinuation = preserveConcurrentLiveMetadata\n ? metadataSyncSecurityContextMatches(liveRecord, candidateRecord)\n ? livePullContinuation\n : (candidateRecord.pullContinuation ?? null)\n : (candidateRecord.pullContinuation ?? null);\n target.record = installedRecord;\n target.rekeyOnlyPassCount = candidate.rekeyOnlyPassCount;\n}\n"]}
1
+ {"version":3,"file":"metadataStateIsolation.js","sourceRoot":"","sources":["metadataStateIsolation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n encodeVersionVector,\n exportAllUpdates,\n exportFullHistorySnapshot,\n importSnapshot,\n importUpdates,\n satisfiesVersionVector,\n} from \"@tearleads/loro\";\nimport { projectionGeneration } from \"../projectionGeneration\";\nimport {\n createContainerMetadataDocument,\n getDefaultContainerName,\n readContainerMetadataValue,\n} from \"./containerMetadataDocument\";\nimport { metadataSyncSecurityContextMatches } from \"./metadataSyncSettlement\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface DetachedContainerMetadataState extends ContainerMetadataState {\n readonly detachedSource: {\n readonly metadataVersion: string;\n /** The live state's `writerProjectionGeneration` when it was detached. */\n readonly writerProjectionGeneration: number;\n };\n}\n\ninterface DetachedContainerMetadataInstallOptions {\n readonly candidateRecord?: ContainerMetadataState[\"record\"];\n readonly preserveConcurrentMetadataEdit?: boolean;\n}\n\nfunction mergeConcurrentMetadataRecord(\n liveRecord: ContainerMetadataState[\"record\"],\n candidateRecord: ContainerMetadataState[\"record\"],\n): ContainerMetadataState[\"record\"] {\n if (metadataSyncSecurityContextMatches(liveRecord, candidateRecord)) {\n return liveRecord;\n }\n\n // The live document owns the concurrent CRDT frontier, but the candidate\n // owns the newly committed remote identity. Carry only the fields that\n // describe the live CRDT history across that identity boundary.\n return {\n ...candidateRecord,\n metadataUpdates: liveRecord.metadataUpdates,\n snapshotEndVersion: liveRecord.snapshotEndVersion,\n ...(liveRecord.pendingBaseVersion === undefined\n ? {}\n : { pendingBaseVersion: liveRecord.pendingBaseVersion }),\n };\n}\n\n/**\n * Gives an asynchronous sync pass its own mutable metadata projection. Durable\n * settlement can then repair or replace the candidate without changing the\n * live store until the caller has rechecked its lifecycle generation.\n */\nexport async function createDetachedContainerMetadataState(\n metadataState: ContainerMetadataState,\n options: {\n /**\n * The live generation captured when the surrounding operation began, for\n * callers that awaited (a request, a policy warm-up) before detaching.\n */\n readonly writerProjectionGeneration?: number | undefined;\n } = {},\n): Promise<DetachedContainerMetadataState> {\n const doc = await createContainerMetadataDocument(metadataState.container.id);\n importSnapshot(doc, exportFullHistorySnapshot(metadataState.doc));\n return {\n ...metadataState,\n container: { ...metadataState.container },\n detachedSource: {\n metadataVersion: encodeVersionVector(metadataState.doc),\n writerProjectionGeneration:\n options.writerProjectionGeneration ??\n projectionGeneration(metadataState),\n },\n doc,\n record: { ...metadataState.record },\n };\n}\n\nexport function installDetachedContainerMetadataState(\n target: ContainerMetadataState,\n candidate: DetachedContainerMetadataState,\n options: DetachedContainerMetadataInstallOptions = {},\n): void {\n const candidateRecord = options.candidateRecord ?? candidate.record;\n const liveMetadataVersion = encodeVersionVector(target.doc);\n const candidateMetadataVersion = encodeVersionVector(candidate.doc);\n const liveRecord = target.record;\n const livePullContinuation = target.pullContinuation;\n const preserveConcurrentLiveMetadata =\n options.preserveConcurrentMetadataEdit === true &&\n liveMetadataVersion !== candidate.detachedSource.metadataVersion &&\n !satisfiesVersionVector(candidateMetadataVersion, liveMetadataVersion);\n const installedRecord = preserveConcurrentLiveMetadata\n ? mergeConcurrentMetadataRecord(liveRecord, candidateRecord)\n : candidateRecord;\n\n if (preserveConcurrentLiveMetadata) {\n importUpdates(target.doc, [exportAllUpdates(candidate.doc)]);\n const metadata = readContainerMetadataValue(\n target.doc,\n getDefaultContainerName(candidate.container.parentId),\n );\n target.container = {\n ...candidate.container,\n icon: metadata.icon,\n name: metadata.name,\n };\n } else {\n target.container = candidate.container;\n target.doc = candidate.doc;\n }\n // A hint invalidated the live projections while this candidate was out;\n // its copy may cite a pre-hint manifest, so the live slot stays as the hint\n // left it and the next metadata write fetches a fresh projection.\n if (\n projectionGeneration(target) ===\n candidate.detachedSource.writerProjectionGeneration\n )\n target.metadataWriterProjection = candidate.metadataWriterProjection;\n target.pullContinuation = preserveConcurrentLiveMetadata\n ? metadataSyncSecurityContextMatches(liveRecord, candidateRecord)\n ? livePullContinuation\n : (candidateRecord.pullContinuation ?? null)\n : (candidateRecord.pullContinuation ?? null);\n target.record = installedRecord;\n target.rekeyOnlyPassCount = candidate.rekeyOnlyPassCount;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { base64ToBytes } from "../../../internal/encoding/index.js";
2
2
  import { importUpdates } from "../../../internal/loro/index.js";
3
- import { createContainerMetadataDocument } from "../../../data/containers/containerMetadataDocument.js";
3
+ import { createContainerMetadataDocument } from "./containerMetadataDocument.js";
4
4
  export function sameNullableMetadataValue(left, right) {
5
5
  return (left ?? null) === (right ?? null);
6
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"metadataSyncSettlement.js","sourceRoot":"","sources":["metadataSyncSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,MAAM,oDAAoD,CAAC;AAUrG,MAAM,UAAU,yBAAyB,CACvC,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,OAA8B,EAC9B,QAAwB;IAExB,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,yBAAyB,CACvB,OAAO,CAAC,eAAe,EACvB,QAAQ,CAAC,eAAe,CACzB;QACD,yBAAyB,CACvB,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,yBAAyB,CACvB,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,yBAAyB,CACvB,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,cAAc,GAAG,MAAM,+BAA+B,CAC1D,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CACjC,CAAC;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC;QACzC,aAAa,CAAC,cAAc,EAAE;YAC5B,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC;IACzC,KAAK,CAAC,aAAa,CAAC,wBAAwB,GAAG,IAAI,CAAC;AACtD,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport { createContainerMetadataDocument } from \"../../../data/containers/containerMetadataDocument\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/sync/syncPagination\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface ExpectedContainerMetadataSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: DocumentRecord;\n}\n\nexport function sameNullableMetadataValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function metadataSyncSecurityContextMatches(\n current: DocumentRecord | null,\n expected: DocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableMetadataValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n sameNullableMetadataValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableMetadataValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableMetadataValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nexport async function replaceSupersededMetadataIdentity(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n}): Promise<void> {\n const replacementDoc = await createContainerMetadataDocument(\n input.metadataState.container.id,\n );\n if (input.durableRecord?.metadataUpdates) {\n importUpdates(replacementDoc, [\n base64ToBytes(input.durableRecord.metadataUpdates),\n ]);\n }\n input.metadataState.doc = replacementDoc;\n input.metadataState.metadataWriterProjection = null;\n}\n"]}
1
+ {"version":3,"file":"metadataSyncSettlement.js","sourceRoot":"","sources":["metadataSyncSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAQ9E,MAAM,UAAU,yBAAyB,CACvC,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,OAA8B,EAC9B,QAAwB;IAExB,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,yBAAyB,CACvB,OAAO,CAAC,eAAe,EACvB,QAAQ,CAAC,eAAe,CACzB;QACD,yBAAyB,CACvB,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,yBAAyB,CACvB,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,yBAAyB,CACvB,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,cAAc,GAAG,MAAM,+BAA+B,CAC1D,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CACjC,CAAC;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC;QACzC,aAAa,CAAC,cAAc,EAAE;YAC5B,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC;IACzC,KAAK,CAAC,aAAa,CAAC,wBAAwB,GAAG,IAAI,CAAC;AACtD,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/sync/syncPagination\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport { createContainerMetadataDocument } from \"./containerMetadataDocument\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface ExpectedContainerMetadataSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: DocumentRecord;\n}\n\nexport function sameNullableMetadataValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function metadataSyncSecurityContextMatches(\n current: DocumentRecord | null,\n expected: DocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableMetadataValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n sameNullableMetadataValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableMetadataValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableMetadataValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nexport async function replaceSupersededMetadataIdentity(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n}): Promise<void> {\n const replacementDoc = await createContainerMetadataDocument(\n input.metadataState.container.id,\n );\n if (input.durableRecord?.metadataUpdates) {\n importUpdates(replacementDoc, [\n base64ToBytes(input.durableRecord.metadataUpdates),\n ]);\n }\n input.metadataState.doc = replacementDoc;\n input.metadataState.metadataWriterProjection = null;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import type { DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
2
- import type { ContainerMetadataDocument } from "../../../data/containers/containerMetadataDocument.js";
3
2
  import type { DocumentSyncPullContinuation } from "../../../data/documents/shared/sync/syncPagination.js";
4
3
  import type { ContainerMetadataRecord } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
5
- import type { ContainerRecord } from "../../../data/persistence/containers/containerPersistence.js";
4
+ import type { ContainerRecord } from "../../../data/persistence/container-contents/containerPersistence.js";
5
+ import type { ContainerMetadataDocument } from "./containerMetadataDocument.js";
6
6
  export interface ContainerMetadataState {
7
7
  container: ContainerRecord;
8
8
  doc: ContainerMetadataDocument;
@@ -1 +1 @@
1
- {"version":3,"file":"metadataTypes.js","sourceRoot":"","sources":["metadataTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { ContainerMetadataDocument } from \"../../../data/containers/containerMetadataDocument\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/sync/syncPagination\";\nimport type { ContainerMetadataRecord } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\n\nexport interface ContainerMetadataState {\n container: ContainerRecord;\n doc: ContainerMetadataDocument;\n metadataWriterProjection?:\n | DocumentWriterProjectionResponse\n | null\n | undefined;\n /** See `ContainerState.writerProjectionGeneration`; shared by both caches. */\n writerProjectionGeneration?: number | undefined;\n /** Durable continuation mirrored from the metadata document record. */\n pullContinuation?: DocumentSyncPullContinuation | null | undefined;\n record: ContainerMetadataRecord;\n /**\n * Consecutive completed sync passes that re-keyed conflicted pending updates\n * without settling anything; bounds the rekey-driven follow-up sync. See\n * shouldReArmAfterOutgoingSettlement.\n */\n rekeyOnlyPassCount?: number | undefined;\n}\n\nexport interface ContainerMetadataPatch {\n accessEpoch: number;\n accessStateHash: string | null;\n effectiveAccessLevel: ContainerRecord[\"effectiveAccessLevel\"];\n documentId: string | null;\n icon: string | null;\n lastCommitLsn: string | null;\n metadataDocumentId: string | null;\n systemSlot: ContainerRecord[\"systemSlot\"];\n metadataUpdates: string;\n name: string;\n organizationId: string;\n parentId: string | null;\n pullContinuation: DocumentSyncPullContinuation | null;\n contentKeyBundle: string | null;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n}\n\nexport interface PersistedContainerMetadataState {\n container: ContainerRecord;\n createIntentSettled?: true;\n moveIntentSettled?: true;\n mutationSuperseded?: true;\n pullContinuationSuperseded?: true;\n record: ContainerMetadataRecord;\n syncIdentitySuperseded?: true;\n}\n\nexport interface SyncedContainerMetadataState\n extends PersistedContainerMetadataState {\n shouldRequestFollowupSync: boolean;\n}\n\nexport interface MissingContainerMetadataState {\n missing: true;\n}\n"]}
1
+ {"version":3,"file":"metadataTypes.js","sourceRoot":"","sources":["metadataTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/sync/syncPagination\";\nimport type { ContainerMetadataRecord } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/container-contents/containerPersistence\";\nimport type { ContainerMetadataDocument } from \"./containerMetadataDocument\";\n\nexport interface ContainerMetadataState {\n container: ContainerRecord;\n doc: ContainerMetadataDocument;\n metadataWriterProjection?:\n | DocumentWriterProjectionResponse\n | null\n | undefined;\n /** See `ContainerState.writerProjectionGeneration`; shared by both caches. */\n writerProjectionGeneration?: number | undefined;\n /** Durable continuation mirrored from the metadata document record. */\n pullContinuation?: DocumentSyncPullContinuation | null | undefined;\n record: ContainerMetadataRecord;\n /**\n * Consecutive completed sync passes that re-keyed conflicted pending updates\n * without settling anything; bounds the rekey-driven follow-up sync. See\n * shouldReArmAfterOutgoingSettlement.\n */\n rekeyOnlyPassCount?: number | undefined;\n}\n\nexport interface ContainerMetadataPatch {\n accessEpoch: number;\n accessStateHash: string | null;\n effectiveAccessLevel: ContainerRecord[\"effectiveAccessLevel\"];\n documentId: string | null;\n icon: string | null;\n lastCommitLsn: string | null;\n metadataDocumentId: string | null;\n systemSlot: ContainerRecord[\"systemSlot\"];\n metadataUpdates: string;\n name: string;\n organizationId: string;\n parentId: string | null;\n pullContinuation: DocumentSyncPullContinuation | null;\n contentKeyBundle: string | null;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n}\n\nexport interface PersistedContainerMetadataState {\n container: ContainerRecord;\n createIntentSettled?: true;\n moveIntentSettled?: true;\n mutationSuperseded?: true;\n pullContinuationSuperseded?: true;\n record: ContainerMetadataRecord;\n syncIdentitySuperseded?: true;\n}\n\nexport interface SyncedContainerMetadataState\n extends PersistedContainerMetadataState {\n shouldRequestFollowupSync: boolean;\n}\n\nexport interface MissingContainerMetadataState {\n missing: true;\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { base64ToBytes } from "../../../internal/encoding/index.js";
2
2
  import { importUpdates } from "../../../internal/loro/index.js";
3
- import { createContainerMetadataDocument, readContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
4
3
  import { discardRetainedContainerMetadata, listRecoveryFolderMoveIds, listRetainedContainerMetadata, } from "../../../data/persistence/container-contents/containerRecoveryPersistence.js";
4
+ import { createContainerMetadataDocument, readContainerMetadataValue, } from "../metadata/containerMetadataDocument.js";
5
5
  export function createFolderRecoveryQueries(execSql) {
6
6
  return {
7
7
  listRecoveryFolderMoveIds(input) {
@@ -1 +1 @@
1
- {"version":3,"file":"folderRecovery.js","sourceRoot":"","sources":["folderRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,2EAA2E,CAAC;AAanF,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,OAAO;QACL,yBAAyB,CAAC,KAEzB;YACC,OAAO,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,mBAAmB,CAAC,KAEzB;YACC,MAAM,OAAO,GAAG,MAAM,6BAA6B,CACjD,OAAO,EACP,KAAK,CAAC,qBAAqB,CAC5B,CAAC;YACF,OAAO,OAAO,CAAC,GAAG,CAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE;gBACnD,MAAM,GAAG,GAAG,MAAM,+BAA+B,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACtE,IAAI,CAAC;oBACH,IAAI,eAAe;wBACjB,aAAa,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;oBACvD,OAAO;wBACL,GAAG,MAAM;wBACT,GAAG,0BAA0B,CAAC,GAAG,EAAE,iBAAiB,CAAC;qBACtD,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,CAAC;YACH,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QACD,qBAAqB,CACnB,KAGC;YAED,OAAO,gCAAgC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport {\n createContainerMetadataDocument,\n readContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport {\n discardRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n listRetainedContainerMetadata,\n} from \"../../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\n\nexport interface RecoveryFolder {\n containerId: string;\n organizationId: string;\n name: string;\n icon: string | null;\n pendingUpdateCount: number;\n hasStructuralIntent: boolean;\n revision: string;\n}\n\nexport function createFolderRecoveryQueries(execSql: ExecSql) {\n return {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]> {\n return listRecoveryFolderMoveIds(execSql, input.currentOrganizationId);\n },\n async listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]> {\n const records = await listRetainedContainerMetadata(\n execSql,\n input.currentOrganizationId,\n );\n return Promise.all(\n records.map(async ({ metadataUpdates, ...record }) => {\n const doc = await createContainerMetadataDocument(record.containerId);\n try {\n if (metadataUpdates)\n importUpdates(doc, [base64ToBytes(metadataUpdates)]);\n return {\n ...record,\n ...readContainerMetadataValue(doc, \"Untitled folder\"),\n };\n } finally {\n doc.free();\n }\n }),\n );\n },\n discardRecoveryFolder(\n input: Pick<\n RecoveryFolder,\n \"containerId\" | \"organizationId\" | \"revision\"\n >,\n ): Promise<boolean> {\n return discardRetainedContainerMetadata(execSql, input);\n },\n };\n}\n"]}
1
+ {"version":3,"file":"folderRecovery.js","sourceRoot":"","sources":["folderRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,2EAA2E,CAAC;AAEnF,OAAO,EACL,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,uCAAuC,CAAC;AAY/C,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,OAAO;QACL,yBAAyB,CAAC,KAEzB;YACC,OAAO,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,mBAAmB,CAAC,KAEzB;YACC,MAAM,OAAO,GAAG,MAAM,6BAA6B,CACjD,OAAO,EACP,KAAK,CAAC,qBAAqB,CAC5B,CAAC;YACF,OAAO,OAAO,CAAC,GAAG,CAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE;gBACnD,MAAM,GAAG,GAAG,MAAM,+BAA+B,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACtE,IAAI,CAAC;oBACH,IAAI,eAAe;wBACjB,aAAa,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;oBACvD,OAAO;wBACL,GAAG,MAAM;wBACT,GAAG,0BAA0B,CAAC,GAAG,EAAE,iBAAiB,CAAC;qBACtD,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,CAAC;YACH,CAAC,CAAC,CACH,CAAC;QACJ,CAAC;QACD,qBAAqB,CACnB,KAGC;YAED,OAAO,gCAAgC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport {\n discardRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n listRetainedContainerMetadata,\n} from \"../../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n createContainerMetadataDocument,\n readContainerMetadataValue,\n} from \"../metadata/containerMetadataDocument\";\n\nexport interface RecoveryFolder {\n containerId: string;\n organizationId: string;\n name: string;\n icon: string | null;\n pendingUpdateCount: number;\n hasStructuralIntent: boolean;\n revision: string;\n}\n\nexport function createFolderRecoveryQueries(execSql: ExecSql) {\n return {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]> {\n return listRecoveryFolderMoveIds(execSql, input.currentOrganizationId);\n },\n async listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]> {\n const records = await listRetainedContainerMetadata(\n execSql,\n input.currentOrganizationId,\n );\n return Promise.all(\n records.map(async ({ metadataUpdates, ...record }) => {\n const doc = await createContainerMetadataDocument(record.containerId);\n try {\n if (metadataUpdates)\n importUpdates(doc, [base64ToBytes(metadataUpdates)]);\n return {\n ...record,\n ...readContainerMetadataValue(doc, \"Untitled folder\"),\n };\n } finally {\n doc.free();\n }\n }),\n );\n },\n discardRecoveryFolder(\n input: Pick<\n RecoveryFolder,\n \"containerId\" | \"organizationId\" | \"revision\"\n >,\n ): Promise<boolean> {\n return discardRetainedContainerMetadata(execSql, input);\n },\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { KeyingVerificationError, verifyOrganizationReplacementAuthorization, } from "../../../../internal/crypto/index.js";
2
- import { assertHeldContainerBinding, } from "../../../../data/containers/containerBinding.js";
3
2
  import { ProjectionDependencyUnavailableError } from "../../../../data/keyingProjectionVerification/dependencyUnavailable.js";
3
+ import { assertHeldContainerBinding, } from "../../../../data/persistence/container-contents/containerBinding.js";
4
4
  import { persistOrganizationReplacementCheckpoints } from "../../../../data/persistence/keyingCheckpoints/organizationReplacementCheckpointPersistence.js";
5
5
  import { loadOrganizationFounder } from "../../../../data/persistence/organizationFounderPersistence.js";
6
6
  async function acceptsSharedReplacement(input, oldOrganizationId) {
@@ -1 +1 @@
1
- {"version":3,"file":"replacementBinding.js","sourceRoot":"","sources":["replacementBinding.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n verifyOrganizationReplacementAuthorization,\n} from \"@tearleads/crypto\";\nimport {\n assertHeldContainerBinding,\n type HeldContainerBinding,\n} from \"../../../../data/containers/containerBinding\";\nimport { ProjectionDependencyUnavailableError } from \"../../../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { persistOrganizationReplacementCheckpoints } from \"../../../../data/persistence/keyingCheckpoints/organizationReplacementCheckpointPersistence\";\nimport { loadOrganizationFounder } from \"../../../../data/persistence/organizationFounderPersistence\";\nimport type { RemoteContainer, RemoteContainerHydrationState } from \"../types\";\nimport type { DestinationRole } from \"./destinationRoleCache\";\n\nexport interface BindingInput {\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly heldBinding: HeldContainerBinding | null;\n readonly listed: Pick<RemoteContainer, \"id\" | \"organizationId\">;\n readonly role: DestinationRole;\n readonly runtime: RemoteContainerHydrationState[\"runtime\"];\n}\n\nasync function acceptsSharedReplacement(\n input: BindingInput,\n oldOrganizationId: string,\n): Promise<boolean> {\n const { listed, role, runtime } = input;\n const founder = await loadOrganizationFounder(\n runtime.infra.execSql,\n oldOrganizationId,\n );\n if (!founder || role.createSignerUserId !== founder.userId) return false;\n const identity = await runtime.resolveTrustedUserIdentity(founder.userId);\n if (!identity)\n throw new ProjectionDependencyUnavailableError(\n \"Replacement founder identity is unavailable\",\n );\n if (identity.signingKeyFingerprint !== founder.signingKeyFingerprint)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Replacement founder differs from the held organization's pinned identity\",\n );\n const response =\n await runtime.apiClient.getContainerReplacementAuthorizationsResult(\n listed.id,\n oldOrganizationId,\n );\n if (!response.ok) {\n if (response.status === 404) return false;\n throw new ProjectionDependencyUnavailableError(response.message);\n }\n const last = verifyReplacementLineage(\n response.data.authorizations,\n oldOrganizationId,\n founder.userId,\n identity.signingPublicKey,\n );\n const replacementFounder = await loadOrganizationFounder(\n runtime.infra.execSql,\n listed.organizationId,\n );\n if (\n last?.organizationId !== listed.organizationId ||\n replacementFounder?.userId !== founder.userId ||\n replacementFounder.signingKeyFingerprint !==\n founder.signingKeyFingerprint ||\n replacementFounder.genesisStateHash !== last.organizationStateHash ||\n role.rootContainerId !== last.rootContainerId ||\n role.rootCreateManifestHash !== last.rootManifestHash ||\n role.rootMetadataDocumentId !== last.rootMetadataDocumentId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Replacement authorization does not bind the destination genesis\",\n );\n // The founder also commits the reserved groups' genesis. Pin those even\n // when the readable folder's projection does not cite both groups yet.\n await persistOrganizationReplacementCheckpoints({\n authorization: last,\n execSql: runtime.infra.execSql,\n stillCurrent: input.stillCurrent,\n });\n return true;\n}\n\nfunction verifyReplacementLineage(\n authorizations: readonly unknown[],\n oldOrganizationId: string,\n userId: string,\n signingPublicKey: Uint8Array,\n) {\n let expected = oldOrganizationId;\n const visited = new Set([expected]);\n let last:\n | ReturnType<typeof verifyOrganizationReplacementAuthorization>\n | undefined;\n for (const candidate of authorizations) {\n const proof = verifyOrganizationReplacementAuthorization(\n candidate,\n signingPublicKey,\n );\n if (\n proof.replacesOrganizationId !== expected ||\n proof.userId !== userId ||\n visited.has(proof.organizationId)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Replacement authorization lineage does not extend the held organization\",\n );\n expected = proof.organizationId;\n visited.add(expected);\n last = proof;\n }\n return last;\n}\n\n/** A foreign creator needs the held organization's pinned founder to authorize rehome. */\nexport async function assertPermittedDestinationBinding(\n input: BindingInput,\n): Promise<void> {\n const { heldBinding: held, listed, role, runtime } = input;\n if (role.createSignerUserId === runtime.auth.userId) return;\n if (held?.metadataDocumentId === null)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"a local folder can bind only to its own signed create\",\n );\n if (\n held?.organizationId &&\n held.organizationId !== listed.organizationId &&\n role.systemSlot === null &&\n (await acceptsSharedReplacement(input, held.organizationId))\n )\n return;\n assertHeldContainerBinding(held, {\n organizationId: listed.organizationId,\n metadataDocumentIds: [role.metadataDocumentId],\n });\n}\n"]}
1
+ {"version":3,"file":"replacementBinding.js","sourceRoot":"","sources":["replacementBinding.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,0CAA0C,GAC3C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oCAAoC,EAAE,MAAM,qEAAqE,CAAC;AAC3H,OAAO,EACL,0BAA0B,GAE3B,MAAM,kEAAkE,CAAC;AAC1E,OAAO,EAAE,yCAAyC,EAAE,MAAM,6FAA6F,CAAC;AACxJ,OAAO,EAAE,uBAAuB,EAAE,MAAM,6DAA6D,CAAC;AAYtG,KAAK,UAAU,wBAAwB,CACrC,KAAmB,EACnB,iBAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAC3C,OAAO,CAAC,KAAK,CAAC,OAAO,EACrB,iBAAiB,CAClB,CAAC;IACF,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,kBAAkB,KAAK,OAAO,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,IAAI,CAAC,QAAQ;QACX,MAAM,IAAI,oCAAoC,CAC5C,6CAA6C,CAC9C,CAAC;IACJ,IAAI,QAAQ,CAAC,qBAAqB,KAAK,OAAO,CAAC,qBAAqB;QAClE,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,0EAA0E,CAC3E,CAAC;IACJ,MAAM,QAAQ,GACZ,MAAM,OAAO,CAAC,SAAS,CAAC,2CAA2C,CACjE,MAAM,CAAC,EAAE,EACT,iBAAiB,CAClB,CAAC;IACJ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QAC1C,MAAM,IAAI,oCAAoC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,IAAI,GAAG,wBAAwB,CACnC,QAAQ,CAAC,IAAI,CAAC,cAAc,EAC5B,iBAAiB,EACjB,OAAO,CAAC,MAAM,EACd,QAAQ,CAAC,gBAAgB,CAC1B,CAAC;IACF,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CACtD,OAAO,CAAC,KAAK,CAAC,OAAO,EACrB,MAAM,CAAC,cAAc,CACtB,CAAC;IACF,IACE,IAAI,EAAE,cAAc,KAAK,MAAM,CAAC,cAAc;QAC9C,kBAAkB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM;QAC7C,kBAAkB,CAAC,qBAAqB;YACtC,OAAO,CAAC,qBAAqB;QAC/B,kBAAkB,CAAC,gBAAgB,KAAK,IAAI,CAAC,qBAAqB;QAClE,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,eAAe;QAC7C,IAAI,CAAC,sBAAsB,KAAK,IAAI,CAAC,gBAAgB;QACrD,IAAI,CAAC,sBAAsB,KAAK,IAAI,CAAC,sBAAsB;QAE3D,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,iEAAiE,CAClE,CAAC;IACJ,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,yCAAyC,CAAC;QAC9C,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,wBAAwB,CAC/B,cAAkC,EAClC,iBAAyB,EACzB,MAAc,EACd,gBAA4B;IAE5B,IAAI,QAAQ,GAAG,iBAAiB,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpC,IAAI,IAES,CAAC;IACd,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,0CAA0C,CACtD,SAAS,EACT,gBAAgB,CACjB,CAAC;QACF,IACE,KAAK,CAAC,sBAAsB,KAAK,QAAQ;YACzC,KAAK,CAAC,MAAM,KAAK,MAAM;YACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC;YAEjC,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,yEAAyE,CAC1E,CAAC;QACJ,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,IAAI,GAAG,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,KAAmB;IAEnB,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC3D,IAAI,IAAI,CAAC,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO;IAC5D,IAAI,IAAI,EAAE,kBAAkB,KAAK,IAAI;QACnC,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,uDAAuD,CACxD,CAAC;IACJ,IACE,IAAI,EAAE,cAAc;QACpB,IAAI,CAAC,cAAc,KAAK,MAAM,CAAC,cAAc;QAC7C,IAAI,CAAC,UAAU,KAAK,IAAI;QACxB,CAAC,MAAM,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAE5D,OAAO;IACT,0BAA0B,CAAC,IAAI,EAAE;QAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,mBAAmB,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC;KAC/C,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n verifyOrganizationReplacementAuthorization,\n} from \"@tearleads/crypto\";\nimport { ProjectionDependencyUnavailableError } from \"../../../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport {\n assertHeldContainerBinding,\n type HeldContainerBinding,\n} from \"../../../../data/persistence/container-contents/containerBinding\";\nimport { persistOrganizationReplacementCheckpoints } from \"../../../../data/persistence/keyingCheckpoints/organizationReplacementCheckpointPersistence\";\nimport { loadOrganizationFounder } from \"../../../../data/persistence/organizationFounderPersistence\";\nimport type { RemoteContainer, RemoteContainerHydrationState } from \"../types\";\nimport type { DestinationRole } from \"./destinationRoleCache\";\n\nexport interface BindingInput {\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly heldBinding: HeldContainerBinding | null;\n readonly listed: Pick<RemoteContainer, \"id\" | \"organizationId\">;\n readonly role: DestinationRole;\n readonly runtime: RemoteContainerHydrationState[\"runtime\"];\n}\n\nasync function acceptsSharedReplacement(\n input: BindingInput,\n oldOrganizationId: string,\n): Promise<boolean> {\n const { listed, role, runtime } = input;\n const founder = await loadOrganizationFounder(\n runtime.infra.execSql,\n oldOrganizationId,\n );\n if (!founder || role.createSignerUserId !== founder.userId) return false;\n const identity = await runtime.resolveTrustedUserIdentity(founder.userId);\n if (!identity)\n throw new ProjectionDependencyUnavailableError(\n \"Replacement founder identity is unavailable\",\n );\n if (identity.signingKeyFingerprint !== founder.signingKeyFingerprint)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Replacement founder differs from the held organization's pinned identity\",\n );\n const response =\n await runtime.apiClient.getContainerReplacementAuthorizationsResult(\n listed.id,\n oldOrganizationId,\n );\n if (!response.ok) {\n if (response.status === 404) return false;\n throw new ProjectionDependencyUnavailableError(response.message);\n }\n const last = verifyReplacementLineage(\n response.data.authorizations,\n oldOrganizationId,\n founder.userId,\n identity.signingPublicKey,\n );\n const replacementFounder = await loadOrganizationFounder(\n runtime.infra.execSql,\n listed.organizationId,\n );\n if (\n last?.organizationId !== listed.organizationId ||\n replacementFounder?.userId !== founder.userId ||\n replacementFounder.signingKeyFingerprint !==\n founder.signingKeyFingerprint ||\n replacementFounder.genesisStateHash !== last.organizationStateHash ||\n role.rootContainerId !== last.rootContainerId ||\n role.rootCreateManifestHash !== last.rootManifestHash ||\n role.rootMetadataDocumentId !== last.rootMetadataDocumentId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Replacement authorization does not bind the destination genesis\",\n );\n // The founder also commits the reserved groups' genesis. Pin those even\n // when the readable folder's projection does not cite both groups yet.\n await persistOrganizationReplacementCheckpoints({\n authorization: last,\n execSql: runtime.infra.execSql,\n stillCurrent: input.stillCurrent,\n });\n return true;\n}\n\nfunction verifyReplacementLineage(\n authorizations: readonly unknown[],\n oldOrganizationId: string,\n userId: string,\n signingPublicKey: Uint8Array,\n) {\n let expected = oldOrganizationId;\n const visited = new Set([expected]);\n let last:\n | ReturnType<typeof verifyOrganizationReplacementAuthorization>\n | undefined;\n for (const candidate of authorizations) {\n const proof = verifyOrganizationReplacementAuthorization(\n candidate,\n signingPublicKey,\n );\n if (\n proof.replacesOrganizationId !== expected ||\n proof.userId !== userId ||\n visited.has(proof.organizationId)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Replacement authorization lineage does not extend the held organization\",\n );\n expected = proof.organizationId;\n visited.add(expected);\n last = proof;\n }\n return last;\n}\n\n/** A foreign creator needs the held organization's pinned founder to authorize rehome. */\nexport async function assertPermittedDestinationBinding(\n input: BindingInput,\n): Promise<void> {\n const { heldBinding: held, listed, role, runtime } = input;\n if (role.createSignerUserId === runtime.auth.userId) return;\n if (held?.metadataDocumentId === null)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"a local folder can bind only to its own signed create\",\n );\n if (\n held?.organizationId &&\n held.organizationId !== listed.organizationId &&\n role.systemSlot === null &&\n (await acceptsSharedReplacement(input, held.organizationId))\n )\n return;\n assertHeldContainerBinding(held, {\n organizationId: listed.organizationId,\n metadataDocumentIds: [role.metadataDocumentId],\n });\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  import { KeyingVerificationError, } from "../../../../internal/crypto/index.js";
2
2
  import { deriveOrganizationMetadataContainerSystemSlot } from "../../../../internal/validators/containerSystemSlot.js";
3
- import { listingRepeatsHeldOrdinaryBinding, } from "../../../../data/containers/containerBinding.js";
4
3
  import { verifiedContainerCreateManifest } from "../../../../data/keyingProjectionVerification/container/containerCreateManifest.js";
5
4
  import { verifyContainerDestinationProjection } from "../../../../data/keyingProjectionVerification/container/containerDestinationVerification.js";
6
5
  import { verifyContainerWriterProjection } from "../../../../data/keyingProjectionVerification/container/containerProjectionVerification.js";
7
6
  import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, runWithSecurityIncidentReporting, } from "../../../../data/keyingProjectionVerification/error.js";
7
+ import { listingRepeatsHeldOrdinaryBinding, } from "../../../../data/persistence/container-contents/containerBinding.js";
8
8
  import { verifyRuntimeGroupMetadataAuthority } from "../../../organizations/groupMetadata/runtimeGroupMetadataAuthority.js";
9
9
  import { createRuntimePrincipalPolicyWarmer } from "../../../principals/runtimePolicyWarmer.js";
10
10
  import { cachedDestinationRole, rememberDestinationRole, } from "./destinationRoleCache.js";