@tearleads/client-sdk 0.1.82 → 0.1.84

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 (157) hide show
  1. package/data/documents/documentSync.js.map +1 -1
  2. package/data/documents/shared/crypto.js.map +1 -1
  3. package/data/documents/shared/types.d.ts +1 -1
  4. package/data/documents/shared/types.js.map +1 -1
  5. package/data/persistence/container-contents/containerContentsPersistence.js +2 -2
  6. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  7. package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +1 -1
  8. package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
  9. package/data/persistence/container-contents/containerDeletionPersistence.js +1 -1
  10. package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
  11. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +3 -3
  12. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  13. package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js +1 -1
  14. package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerMetadataRows.js +1 -1
  16. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  17. package/data/persistence/container-contents/containerPendingUpdatePersistence.js +2 -2
  18. package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
  19. package/data/persistence/container-contents/containerReconcilePersistence.js +1 -1
  20. package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
  21. package/data/persistence/container-contents/containerRemovalWork.js +1 -1
  22. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  23. package/data/persistence/documents/documentDiscoveryReset.d.ts +6 -0
  24. package/data/persistence/documents/documentsPersistence.js +2 -2
  25. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  26. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js +1 -1
  27. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js.map +1 -1
  28. package/data/persistence/documents/internal/discardDocument.js +2 -2
  29. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  30. package/data/persistence/documents/internal/documentDeletionPersistence.js +2 -2
  31. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  32. package/data/persistence/documents/internal/documentMutationPersistence.js +3 -3
  33. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  34. package/data/persistence/documents/internal/documentPullContinuationPersistence.js +1 -1
  35. package/data/persistence/documents/internal/documentPullContinuationPersistence.js.map +1 -1
  36. package/data/persistence/documents/internal/documentRecordIdentity.js.map +1 -1
  37. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  38. package/data/persistence/documents/internal/ensureDocumentsSchema.js +1 -1
  39. package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
  40. package/data/persistence/documents/internal/orphanSideRows.js +1 -1
  41. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  42. package/data/persistence/documents/internal/rowQueryPersistence.js +1 -1
  43. package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
  44. package/data/persistence/documents/internal/syncQueuePersistence.js +2 -2
  45. package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
  46. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.d.ts +1 -1
  47. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentHistoryPersistence.js +5 -5
  48. package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -0
  49. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.d.ts +2 -2
  50. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPendingUpdatePersistence.js +2 -2
  51. package/data/persistence/documents/records/documentPendingUpdatePersistence.js.map +1 -0
  52. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.d.ts +2 -2
  53. package/data/persistence/documents/records/documentPersistenceTypes.js.map +1 -0
  54. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.d.ts +1 -1
  55. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentRecordPersistence.js +4 -4
  56. package/data/persistence/documents/records/documentRecordPersistence.js.map +1 -0
  57. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.d.ts +2 -2
  58. package/data/{sqlite/documentPersistence → persistence/documents/records}/documentSyncFailurePersistence.js +3 -3
  59. package/data/persistence/documents/records/documentSyncFailurePersistence.js.map +1 -0
  60. package/data/{sqlite/documentPersistence → persistence/documents/records}/index.d.ts +2 -2
  61. package/data/{sqlite/documentPersistence → persistence/documents/records}/index.js +4 -4
  62. package/data/persistence/documents/records/index.js.map +1 -0
  63. package/data/persistence/documents/types.d.ts +2 -2
  64. package/data/persistence/documents/types.js.map +1 -1
  65. package/{workflows/sync/remoteResetPrincipalScope.d.ts → data/persistence/principalPolicy/principalPolicyRemoteReset.d.ts} +1 -1
  66. package/{workflows/sync/remoteResetPrincipalScope.js → data/persistence/principalPolicy/principalPolicyRemoteReset.js} +7 -7
  67. package/data/persistence/principalPolicy/principalPolicyRemoteReset.js.map +1 -0
  68. package/data/persistence/verifiedManifestBundlePersistence.d.ts +2 -0
  69. package/data/persistence/verifiedManifestBundlePersistence.js +7 -0
  70. package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -1
  71. package/data/sqlite/{documentPersistence/documentOrphanBlobReclaims.js → schema/documentOrphanBlobReclaimSchema.js} +1 -1
  72. package/data/sqlite/schema/documentOrphanBlobReclaimSchema.js.map +1 -0
  73. package/data/sqlite/schema/index.js +1 -1
  74. package/data/sqlite/schema/index.js.map +1 -1
  75. package/data/sqlite/sqliteBindBudget.js +12 -0
  76. package/data/sqlite/sqliteBindBudget.js.map +1 -1
  77. package/package.json +1 -1
  78. package/workflows/container-contents/container-state/create/createIntentSeed.js.map +1 -1
  79. package/workflows/container-contents/container-state/create/createWithMetadataPlan.js.map +1 -1
  80. package/workflows/container-contents/container-state/types.js.map +1 -1
  81. package/workflows/container-contents/metadata/index.js.map +1 -1
  82. package/workflows/container-contents/metadata/metadataEvents.d.ts +1 -1
  83. package/workflows/container-contents/metadata/metadataEvents.js.map +1 -1
  84. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js +1 -1
  85. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -1
  86. package/workflows/container-contents/metadata/metadataRemoteSync.d.ts +1 -1
  87. package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -1
  88. package/workflows/container-contents/pendingWrites/index.js +1 -1
  89. package/workflows/container-contents/pendingWrites/index.js.map +1 -1
  90. package/workflows/container-contents/recovery/accessRestoration.js +1 -1
  91. package/workflows/container-contents/recovery/accessRestoration.js.map +1 -1
  92. package/workflows/container-contents/remoteReset/containerRemoteReset.d.ts +185 -0
  93. package/workflows/container-contents/remoteReset/containerRemoteReset.js +174 -0
  94. package/workflows/container-contents/remoteReset/containerRemoteReset.js.map +1 -0
  95. package/workflows/container-contents/remoteReset/remoteResetCursorScope.d.ts +14 -0
  96. package/workflows/{sync → container-contents/remoteReset}/remoteResetCursorScope.js +2 -2
  97. package/workflows/container-contents/remoteReset/remoteResetCursorScope.js.map +1 -0
  98. package/workflows/documents/create/documentCreationPersistence.js.map +1 -1
  99. package/workflows/documents/create/index.d.ts +1 -1
  100. package/workflows/documents/create/index.js.map +1 -1
  101. package/workflows/documents/documentMutationCommit.d.ts +1 -1
  102. package/workflows/documents/documentMutationCommit.js.map +1 -1
  103. package/workflows/documents/index.d.ts +2 -2
  104. package/workflows/documents/index.js +2 -2
  105. package/workflows/documents/index.js.map +1 -1
  106. package/workflows/documents/remoteReset/documentRemoteReset.d.ts +56 -0
  107. package/workflows/documents/remoteReset/documentRemoteReset.js +135 -0
  108. package/workflows/documents/remoteReset/documentRemoteReset.js.map +1 -0
  109. package/workflows/{sync → documents/remoteReset}/remoteResetAttachments.js +3 -3
  110. package/workflows/documents/remoteReset/remoteResetAttachments.js.map +1 -0
  111. package/workflows/{sync → documents/remoteReset}/remoteResetPlans.d.ts +1 -1
  112. package/workflows/{sync → documents/remoteReset}/remoteResetPlans.js +7 -7
  113. package/workflows/documents/remoteReset/remoteResetPlans.js.map +1 -0
  114. package/workflows/documents/sync/index.js.map +1 -1
  115. package/workflows/documents/sync/initialSync.d.ts +1 -1
  116. package/workflows/documents/sync/initialSync.js.map +1 -1
  117. package/workflows/documents/sync/readOnlySync.d.ts +1 -1
  118. package/workflows/documents/sync/readOnlySync.js.map +1 -1
  119. package/workflows/documents/sync/syncAttemptPlanning.js.map +1 -1
  120. package/workflows/documents/sync/syncAttemptState.d.ts +1 -1
  121. package/workflows/documents/sync/syncAttemptState.js.map +1 -1
  122. package/workflows/documents/sync/syncResponseResult.js.map +1 -1
  123. package/workflows/documents/sync/syncSubmittedResult.js.map +1 -1
  124. package/workflows/documents/syncFailures/index.js.map +1 -1
  125. package/workflows/documents/syncPlan/syncContentKeys.d.ts +1 -1
  126. package/workflows/documents/syncPlan/syncContentKeys.js.map +1 -1
  127. package/workflows/documents/syncPlan/syncPlanMaterial.js.map +1 -1
  128. package/workflows/documents/syncPlan/syncPlanRequestBounds.js.map +1 -1
  129. package/workflows/documents/syncRekeys/syncContainerRekeys.js.map +1 -1
  130. package/workflows/documents/syncRekeys/syncRecoveryRekey.d.ts +1 -1
  131. package/workflows/documents/syncRekeys/syncRecoveryRekey.js +1 -1
  132. package/workflows/documents/syncRekeys/syncRecoveryRekey.js.map +1 -1
  133. package/workflows/organizations/readModel/listLocalOrganizations.js +1 -1
  134. package/workflows/organizations/readModel/listLocalOrganizations.js.map +1 -1
  135. package/workflows/organizations/readModel/organizationRemoteReset.js +25 -0
  136. package/workflows/organizations/readModel/organizationRemoteReset.js.map +1 -0
  137. package/workflows/registration/persistRegistrationBootstrap.d.ts +1 -1
  138. package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
  139. package/workflows/sync/remoteReset.js +60 -229
  140. package/workflows/sync/remoteReset.js.map +1 -1
  141. package/workflows/sync/remoteResetScope.d.ts +7 -10
  142. package/workflows/sync/remoteResetScope.js +26 -108
  143. package/workflows/sync/remoteResetScope.js.map +1 -1
  144. package/data/sqlite/documentPersistence/documentHistoryPersistence.js.map +0 -1
  145. package/data/sqlite/documentPersistence/documentOrphanBlobReclaims.js.map +0 -1
  146. package/data/sqlite/documentPersistence/documentPendingUpdatePersistence.js.map +0 -1
  147. package/data/sqlite/documentPersistence/documentPersistenceTypes.js.map +0 -1
  148. package/data/sqlite/documentPersistence/documentRecordPersistence.js.map +0 -1
  149. package/data/sqlite/documentPersistence/documentSyncFailurePersistence.js.map +0 -1
  150. package/data/sqlite/documentPersistence/index.js.map +0 -1
  151. package/workflows/sync/remoteResetAttachments.js.map +0 -1
  152. package/workflows/sync/remoteResetBatches.js +0 -13
  153. package/workflows/sync/remoteResetBatches.js.map +0 -1
  154. package/workflows/sync/remoteResetCursorScope.js.map +0 -1
  155. package/workflows/sync/remoteResetPlans.js.map +0 -1
  156. package/workflows/sync/remoteResetPrincipalScope.js.map +0 -1
  157. /package/data/{sqlite/documentPersistence → persistence/documents/records}/documentPersistenceTypes.js +0 -0
@@ -1,247 +1,78 @@
1
- import { and, eq, inArray, or } from "drizzle-orm";
2
- import { deleteDocumentPlacementRowsByContainerIds, deleteDocumentPlacementRowsByDocumentIds, } from "../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
3
- import { recordSupersededContainerBindingsInTransaction } from "../../data/persistence/container-contents/supersededContainerBindings.js";
4
- import { clearDocumentDiscoveryEvidenceOnRemoteReset } from "../../data/persistence/documents/documentDiscoveryReset.js";
5
- import { queuedUpdateRow, unqueueDocumentScopesInTransaction, } from "../../data/sqlite/documentPersistence/documentPendingUpdatePersistence.js";
6
- import { CLEARED_DOCUMENT_SYNC_FAILURE } from "../../data/sqlite/documentPersistence/documentSyncFailurePersistence.js";
7
- import { clientSqlTables, containerHydrationTombstones, containers, documentAttachmentBlobProjection, documentHistoryUpdates, documentPendingAttachments, documentProjection, documents, dormantContainerMetadata, dormantMetadataSweepRequests, inContainerIntentLanes, inLocalIntentLane, LOCAL_INTENT_LANES, localIntents, } from "../../data/sqlite/schema/index.js";
8
- import { documentIntentLinkTargets } from "../../data/sqlite/schema/documentPlacementIntentSchema.js";
9
- import { organizationDataUsageSnapshots } from "../../data/sqlite/schema/organizationDataUsageSchema.js";
10
- import { organizationPresentationDenials, organizationReadModelContainerGrants, organizationReadModelDirectoryUsers, organizationReadModelGroupMembers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../data/sqlite/schema/organizationReadModelSchema.js";
11
- import { verifiedAccessManifestBundles } from "../../data/sqlite/schema/verifiedManifestBundleSchema.js";
1
+ import { clearRemoteResetPrincipalRows } from "../../data/persistence/principalPolicy/principalPolicyRemoteReset.js";
2
+ import { deleteVerifiedManifestBundlesForOrganization } from "../../data/persistence/verifiedManifestBundlePersistence.js";
3
+ import { clientSqlTables } from "../../data/sqlite/schema/index.js";
12
4
  import { getClientSQLitePersistenceRuntime, } from "../../data/sqlite/sqlitePersistenceRuntime.js";
13
5
  import { ensureSqlTables } from "../../data/sqlite/sqlTableSchema.js";
14
- import { runOrganizationPresentationReset } from "../organizations/readModel/organizationPresentationAccessState.js";
15
- import { clearResetPendingAttachments } from "./remoteResetAttachments.js";
16
- import { remoteResetBatches } from "./remoteResetBatches.js";
17
- import { clearRemoteResetSyncCursors } from "./remoteResetCursorScope.js";
18
- import { buildResetPlans, } from "./remoteResetPlans.js";
19
- import { clearRemoteResetPrincipalRows } from "./remoteResetPrincipalScope.js";
6
+ import { clearContainerRowsForRemoteReset, clearDocumentPlacementsForRemoteReset, clearDormantContainerMetadataForRemoteReset, clearRemoteResetSyncCursors, queueContainerCreatesForRemoteReset, resetContainerServerIdentity, } from "../container-contents/remoteReset/containerRemoteReset.js";
7
+ import { buildResetPlans, clearDocumentDiscoveryEvidenceOnRemoteReset, clearDocumentRowsForRemoteReset, queueAttachmentReuploadsForRemoteReset, queueDocumentRepublishForRemoteReset, resetDocumentServerIdentity, } from "../documents/remoteReset/documentRemoteReset.js";
8
+ import { clearOrganizationReadModelsForRemoteReset, runOrganizationPresentationReset, } from "../organizations/readModel/organizationRemoteReset.js";
20
9
  import { readRemoteSyncStateSnapshot, } from "./remoteResetScope.js";
21
- const CONTAINER_CREATE_INTENT_TYPE = "container.create";
22
- async function clearOrganizationPresentationRows(tx, organizationId) {
23
- for (const table of [
24
- organizationDataUsageSnapshots,
25
- organizationReadModelContainerGrants,
26
- organizationReadModelGroupMembers,
27
- organizationReadModelDirectoryUsers,
28
- organizationReadModelGroups,
29
- organizationReadModelRequesters,
30
- organizationReadModelState,
31
- organizationPresentationDenials,
32
- ]) {
33
- await tx
34
- .delete(table)
35
- .where(eq(table.organizationId, organizationId))
36
- .run();
37
- }
38
- }
39
- async function clearScopedContainerRows(input) {
40
- for (const containerBatch of remoteResetBatches(input.snapshot.containerIds)) {
41
- await deleteDocumentPlacementRowsByContainerIds(input.tx, containerBatch);
42
- await input.tx
43
- .delete(localIntents)
44
- .where(and(inContainerIntentLanes(), inArray(localIntents.subjectId, containerBatch)))
45
- .run();
46
- await input.tx
47
- .delete(containerHydrationTombstones)
48
- .where(inArray(containerHydrationTombstones.containerId, containerBatch))
49
- .run();
50
- }
51
- }
52
- async function clearScopedDocumentRows(input) {
53
- const { snapshot, tx } = input;
54
- for (const documentIdBatch of remoteResetBatches(snapshot.oldDocumentIds)) {
55
- await deleteDocumentPlacementRowsByDocumentIds(tx, documentIdBatch);
56
- }
57
- await clearResetPendingAttachments({
58
- attachmentUploads: input.attachmentUploads,
10
+ // Each subsystem resets its own tables; this runs their steps in one
11
+ // transaction. Steps on different tables are independent, and each subsystem
12
+ // clears its rows before it queues new ones.
13
+ async function clearRemoteSyncStateInTransaction(input) {
14
+ const now = new Date().toISOString();
15
+ const { plans, reset, snapshot, tx } = input;
16
+ const { organizationId } = reset;
17
+ // Forget what the server told this device about the organization.
18
+ await clearOrganizationReadModelsForRemoteReset(tx, organizationId);
19
+ await clearDormantContainerMetadataForRemoteReset(tx, organizationId);
20
+ await deleteVerifiedManifestBundlesForOrganization(tx, organizationId);
21
+ await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {
22
+ containerIds: snapshot.containerIds,
23
+ documentIds: snapshot.oldDocumentIds,
24
+ });
25
+ await clearRemoteResetPrincipalRows({ organizationId, snapshot, tx });
26
+ await clearContainerRowsForRemoteReset({
27
+ containerIds: snapshot.containerIds,
28
+ tx,
29
+ });
30
+ await clearDocumentPlacementsForRemoteReset({
59
31
  documentLocalIds: snapshot.documentLocalIds,
32
+ oldDocumentIds: snapshot.oldDocumentIds,
60
33
  tx,
61
34
  });
62
- for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {
63
- const placementIntents = and(inLocalIntentLane(LOCAL_INTENT_LANES.documentPlacement), inArray(localIntents.localId, localIdBatch));
64
- await tx
65
- .delete(documentIntentLinkTargets)
66
- .where(inArray(documentIntentLinkTargets.intentId, tx
67
- .select({ id: localIntents.id })
68
- .from(localIntents)
69
- .where(placementIntents)))
70
- .run();
71
- await tx.delete(localIntents).where(placementIntents).run();
72
- }
73
- // Sync failures clear with the document columns in resetRemoteColumns.
74
- for (const documentBatch of remoteResetBatches(snapshot.documentRows)) {
75
- await unqueueDocumentScopesInTransaction(tx, documentBatch);
76
- }
77
- }
78
- async function clearScopedRemoteRows(input) {
79
- const { organizationId, tx } = input;
80
- await clearOrganizationPresentationRows(tx, organizationId);
81
- for (const table of [
82
- dormantContainerMetadata,
83
- dormantMetadataSweepRequests,
84
- verifiedAccessManifestBundles,
85
- ]) {
86
- await tx
87
- .delete(table)
88
- .where(eq(table.organizationId, organizationId))
89
- .run();
90
- }
91
- await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {
92
- containerIds: input.snapshot.containerIds,
93
- documentIds: input.snapshot.oldDocumentIds,
35
+ await clearDocumentRowsForRemoteReset({
36
+ attachmentUploads: plans.attachmentUploads,
37
+ documentLocalIds: snapshot.documentLocalIds,
38
+ documentRows: snapshot.documentRows,
39
+ tx,
94
40
  });
95
- await clearRemoteResetPrincipalRows(input);
96
- await clearScopedContainerRows(input);
97
- await clearScopedDocumentRows(input);
98
41
  await clearRemoteResetSyncCursors({
99
- containerIds: input.snapshot.containerIds,
42
+ containerIds: snapshot.containerIds,
100
43
  tx,
101
44
  });
102
- }
103
- async function resetRemoteColumns(input) {
104
- const { now, reset, snapshot, tx } = input;
105
- for (const row of snapshot.documentRows) {
106
- await tx
107
- .update(documents)
108
- .set({
109
- accessEpoch: 1,
110
- accessStateHash: null,
111
- contentKeyBundle: null,
112
- documentId: null,
113
- documentKekTargets: null,
114
- documentManifestBundle: null,
115
- lastCommitLsn: null,
116
- pullContinuation: null,
117
- recoveryDocumentId: row.documentId ?? row.recoveryDocumentId,
118
- ...CLEARED_DOCUMENT_SYNC_FAILURE,
119
- updatedAt: now,
120
- })
121
- .where(and(eq(documents.appKind, row.appKind), eq(documents.localId, row.localId)))
122
- .run();
123
- }
124
- for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {
125
- await tx
126
- .update(documentProjection)
127
- .set({
128
- documentId: null,
129
- organizationId: reset.replacement?.organizationId ?? reset.organizationId,
130
- })
131
- .where(inArray(documentProjection.localId, localIdBatch))
132
- .run();
133
- }
134
- // Replacement re-homes folders under their ids; the purged organization
135
- // can never bind them again on this device.
136
- for (const containerIds of reset.replacement
137
- ? remoteResetBatches(snapshot.containerIds)
138
- : []) {
139
- await recordSupersededContainerBindingsInTransaction(tx, {
140
- containerIds,
141
- organizationId: reset.organizationId,
142
- supersededAt: now,
143
- });
144
- }
145
- for (const row of snapshot.containerRows) {
146
- await tx
147
- .update(containers)
148
- .set({
149
- metadataDocumentId: null,
150
- organizationId: reset.replacement?.organizationId ?? reset.organizationId,
151
- parentId: reset.replacement && row.parentId === null
152
- ? reset.replacement.rootContainerId
153
- : row.parentId,
154
- serverCreatedAt: null,
155
- serverUpdatedAt: null,
156
- ...(reset.replacement ? { systemSlot: null } : {}),
157
- localUpdatedAt: now,
158
- })
159
- .where(eq(containers.id, row.id))
160
- .run();
161
- }
162
- }
163
- async function queueResetDocumentUpdates(input) {
164
- for (const updateBatch of remoteResetBatches(input.documentUpdates)) {
165
- await input.tx
166
- .insert(documentHistoryUpdates)
167
- .values(updateBatch.map((update) => queuedUpdateRow({
168
- createdAt: input.now,
169
- origin: "outbox",
170
- pendingUpdate: update,
171
- scope: update,
172
- updateId: crypto.randomUUID(),
173
- })))
174
- .run();
175
- }
176
- }
177
- async function queueResetContainerCreates(input) {
178
- const rows = input.snapshot.containerRows.flatMap((row) => {
179
- const parentId = row.parentId ?? input.reset.replacement?.rootContainerId ?? null;
180
- return parentId ? [{ id: row.id, parentId }] : [];
45
+ // Strip server identity from the rows the device keeps.
46
+ await resetDocumentServerIdentity({
47
+ documentLocalIds: snapshot.documentLocalIds,
48
+ documentRows: snapshot.documentRows,
49
+ now,
50
+ organizationId: reset.replacement?.organizationId ?? organizationId,
51
+ tx,
181
52
  });
182
- if (rows.length === 0)
183
- return 0;
184
- for (const rowBatch of remoteResetBatches(rows)) {
185
- await input.tx
186
- .insert(localIntents)
187
- .values(rowBatch.map((row) => ({
188
- id: crypto.randomUUID(),
189
- lane: LOCAL_INTENT_LANES.containerCreate,
190
- subjectId: row.id,
191
- targetContainerId: row.parentId,
192
- intentType: CONTAINER_CREATE_INTENT_TYPE,
193
- syncStatus: "pending",
194
- remoteContainerId: null,
195
- remoteMetadataAccessStateHash: null,
196
- remoteMetadataDocumentId: null,
197
- lastError: null,
198
- createdAt: input.now,
199
- updatedAt: input.now,
200
- })))
201
- .run();
202
- }
203
- return rows.length;
204
- }
205
- async function queueResetAttachmentUploads(input) {
206
- for (const attachmentBatch of remoteResetBatches(input.attachmentUploads)) {
207
- await input.tx
208
- .insert(documentPendingAttachments)
209
- .values(attachmentBatch.map((attachment) => ({
210
- ...attachment,
211
- createdAt: input.now,
212
- })))
213
- .run();
214
- await input.tx
215
- .delete(documentAttachmentBlobProjection)
216
- .where(or(...attachmentBatch.map((attachment) => and(eq(documentAttachmentBlobProjection.localId, attachment.localId), eq(documentAttachmentBlobProjection.slotId, attachment.slotId)))))
217
- .run();
218
- }
219
- }
220
- async function clearRemoteSyncStateInTransaction(input) {
221
- const now = new Date().toISOString();
222
- const { snapshot } = input;
223
- await clearScopedRemoteRows({
224
- attachmentUploads: input.plans.attachmentUploads,
225
- organizationId: input.reset.organizationId,
226
- snapshot,
227
- tx: input.tx,
53
+ await resetContainerServerIdentity({
54
+ containerIds: snapshot.containerIds,
55
+ containerRows: snapshot.containerRows,
56
+ now,
57
+ reset,
58
+ tx,
228
59
  });
229
- await resetRemoteColumns({ now, reset: input.reset, snapshot, tx: input.tx });
230
- await queueResetDocumentUpdates({
231
- documentUpdates: input.plans.documentUpdates,
60
+ // Queue the local content to be published again.
61
+ await queueDocumentRepublishForRemoteReset({
62
+ documentUpdates: plans.documentUpdates,
232
63
  now,
233
- tx: input.tx,
64
+ tx,
234
65
  });
235
- const queuedContainerCreateCount = await queueResetContainerCreates({
66
+ const queuedContainerCreateCount = await queueContainerCreatesForRemoteReset({
67
+ containerRows: snapshot.containerRows,
236
68
  now,
237
- reset: input.reset,
238
- snapshot,
239
- tx: input.tx,
69
+ reset,
70
+ tx,
240
71
  });
241
- await queueResetAttachmentUploads({
242
- attachmentUploads: input.plans.attachmentUploads,
72
+ await queueAttachmentReuploadsForRemoteReset({
73
+ attachmentUploads: plans.attachmentUploads,
243
74
  now,
244
- tx: input.tx,
75
+ tx,
245
76
  });
246
77
  return {
247
78
  clearedContainerCreateIntentCount: snapshot.clearedContainerCreateIntentCount,
@@ -249,9 +80,9 @@ async function clearRemoteSyncStateInTransaction(input) {
249
80
  clearedDocumentMoveIntentCount: snapshot.clearedDocumentMoveIntentCount,
250
81
  clearedPrincipalPolicyCount: snapshot.clearedPrincipalPolicyCount,
251
82
  clearedSyncCursorCount: snapshot.clearedSyncCursorCount,
252
- queuedAttachmentUploadCount: input.plans.attachmentUploads.length,
83
+ queuedAttachmentUploadCount: plans.attachmentUploads.length,
253
84
  queuedContainerCreateCount,
254
- queuedDocumentUpdateCount: input.plans.documentUpdates.length,
85
+ queuedDocumentUpdateCount: plans.documentUpdates.length,
255
86
  resetContainerCount: snapshot.containerRows.length,
256
87
  resetDocumentCount: snapshot.documentRows.length,
257
88
  };
@@ -1 +1 @@
1
- {"version":3,"file":"remoteReset.js","sourceRoot":"","sources":["remoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray, or } from \"drizzle-orm\";\nimport {\n deleteDocumentPlacementRowsByContainerIds,\n deleteDocumentPlacementRowsByDocumentIds,\n} from \"../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport { recordSupersededContainerBindingsInTransaction } from \"../../data/persistence/container-contents/supersededContainerBindings\";\nimport { clearDocumentDiscoveryEvidenceOnRemoteReset } from \"../../data/persistence/documents/documentDiscoveryReset\";\nimport {\n queuedUpdateRow,\n unqueueDocumentScopesInTransaction,\n} from \"../../data/sqlite/documentPersistence/documentPendingUpdatePersistence\";\nimport { CLEARED_DOCUMENT_SYNC_FAILURE } from \"../../data/sqlite/documentPersistence/documentSyncFailurePersistence\";\nimport {\n clientSqlTables,\n containerHydrationTombstones,\n containers,\n documentAttachmentBlobProjection,\n documentHistoryUpdates,\n documentPendingAttachments,\n documentProjection,\n documents,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n inContainerIntentLanes,\n inLocalIntentLane,\n LOCAL_INTENT_LANES,\n localIntents,\n} from \"../../data/sqlite/schema\";\nimport { documentIntentLinkTargets } from \"../../data/sqlite/schema/documentPlacementIntentSchema\";\nimport { organizationDataUsageSnapshots } from \"../../data/sqlite/schema/organizationDataUsageSchema\";\nimport {\n organizationPresentationDenials,\n organizationReadModelContainerGrants,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../data/sqlite/schema/organizationReadModelSchema\";\nimport { verifiedAccessManifestBundles } from \"../../data/sqlite/schema/verifiedManifestBundleSchema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlTableSchema\";\nimport { runOrganizationPresentationReset } from \"../organizations/readModel/organizationPresentationAccessState\";\nimport { clearResetPendingAttachments } from \"./remoteResetAttachments\";\nimport { remoteResetBatches } from \"./remoteResetBatches\";\nimport { clearRemoteResetSyncCursors } from \"./remoteResetCursorScope\";\nimport {\n buildResetPlans,\n type ResetAttachmentUpload,\n type ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\nimport { clearRemoteResetPrincipalRows } from \"./remoteResetPrincipalScope\";\nimport {\n type RemoteResetInput,\n type RemoteSyncStateSnapshot,\n readRemoteSyncStateSnapshot,\n} from \"./remoteResetScope\";\n\nexport type {\n RemoteResetInput,\n RemoteResetReplacement,\n} from \"./remoteResetScope\";\n\nconst CONTAINER_CREATE_INTENT_TYPE = \"container.create\";\n\nexport interface ClearRemoteSyncStateResult {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly queuedAttachmentUploadCount: number;\n readonly queuedContainerCreateCount: number;\n readonly queuedDocumentUpdateCount: number;\n readonly resetContainerCount: number;\n readonly resetDocumentCount: number;\n}\n\nasync function clearOrganizationPresentationRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<void> {\n for (const table of [\n organizationDataUsageSnapshots,\n organizationReadModelContainerGrants,\n organizationReadModelGroupMembers,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n organizationPresentationDenials,\n ] as const) {\n await tx\n .delete(table)\n .where(eq(table.organizationId, organizationId))\n .run();\n }\n}\n\ninterface ScopedRemoteRowsInput {\n attachmentUploads: readonly ResetAttachmentUpload[];\n organizationId: string;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}\n\nasync function clearScopedContainerRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n for (const containerBatch of remoteResetBatches(\n input.snapshot.containerIds,\n )) {\n await deleteDocumentPlacementRowsByContainerIds(input.tx, containerBatch);\n await input.tx\n .delete(localIntents)\n .where(\n and(\n inContainerIntentLanes(),\n inArray(localIntents.subjectId, containerBatch),\n ),\n )\n .run();\n await input.tx\n .delete(containerHydrationTombstones)\n .where(inArray(containerHydrationTombstones.containerId, containerBatch))\n .run();\n }\n}\n\nasync function clearScopedDocumentRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n const { snapshot, tx } = input;\n for (const documentIdBatch of remoteResetBatches(snapshot.oldDocumentIds)) {\n await deleteDocumentPlacementRowsByDocumentIds(tx, documentIdBatch);\n }\n await clearResetPendingAttachments({\n attachmentUploads: input.attachmentUploads,\n documentLocalIds: snapshot.documentLocalIds,\n tx,\n });\n for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {\n const placementIntents = and(\n inLocalIntentLane(LOCAL_INTENT_LANES.documentPlacement),\n inArray(localIntents.localId, localIdBatch),\n );\n await tx\n .delete(documentIntentLinkTargets)\n .where(\n inArray(\n documentIntentLinkTargets.intentId,\n tx\n .select({ id: localIntents.id })\n .from(localIntents)\n .where(placementIntents),\n ),\n )\n .run();\n await tx.delete(localIntents).where(placementIntents).run();\n }\n // Sync failures clear with the document columns in resetRemoteColumns.\n for (const documentBatch of remoteResetBatches(snapshot.documentRows)) {\n await unqueueDocumentScopesInTransaction(tx, documentBatch);\n }\n}\n\nasync function clearScopedRemoteRows(\n input: ScopedRemoteRowsInput,\n): Promise<void> {\n const { organizationId, tx } = input;\n await clearOrganizationPresentationRows(tx, organizationId);\n for (const table of [\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n verifiedAccessManifestBundles,\n ] as const) {\n await tx\n .delete(table)\n .where(eq(table.organizationId, organizationId))\n .run();\n }\n await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {\n containerIds: input.snapshot.containerIds,\n documentIds: input.snapshot.oldDocumentIds,\n });\n await clearRemoteResetPrincipalRows(input);\n await clearScopedContainerRows(input);\n await clearScopedDocumentRows(input);\n await clearRemoteResetSyncCursors({\n containerIds: input.snapshot.containerIds,\n tx,\n });\n}\n\nasync function resetRemoteColumns(input: {\n now: string;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { now, reset, snapshot, tx } = input;\n for (const row of snapshot.documentRows) {\n await tx\n .update(documents)\n .set({\n accessEpoch: 1,\n accessStateHash: null,\n contentKeyBundle: null,\n documentId: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n lastCommitLsn: null,\n pullContinuation: null,\n recoveryDocumentId: row.documentId ?? row.recoveryDocumentId,\n ...CLEARED_DOCUMENT_SYNC_FAILURE,\n updatedAt: now,\n })\n .where(\n and(\n eq(documents.appKind, row.appKind),\n eq(documents.localId, row.localId),\n ),\n )\n .run();\n }\n for (const localIdBatch of remoteResetBatches(snapshot.documentLocalIds)) {\n await tx\n .update(documentProjection)\n .set({\n documentId: null,\n organizationId:\n reset.replacement?.organizationId ?? reset.organizationId,\n })\n .where(inArray(documentProjection.localId, localIdBatch))\n .run();\n }\n // Replacement re-homes folders under their ids; the purged organization\n // can never bind them again on this device.\n for (const containerIds of reset.replacement\n ? remoteResetBatches(snapshot.containerIds)\n : []) {\n await recordSupersededContainerBindingsInTransaction(tx, {\n containerIds,\n organizationId: reset.organizationId,\n supersededAt: now,\n });\n }\n for (const row of snapshot.containerRows) {\n await tx\n .update(containers)\n .set({\n metadataDocumentId: null,\n organizationId:\n reset.replacement?.organizationId ?? reset.organizationId,\n parentId:\n reset.replacement && row.parentId === null\n ? reset.replacement.rootContainerId\n : row.parentId,\n serverCreatedAt: null,\n serverUpdatedAt: null,\n ...(reset.replacement ? { systemSlot: null } : {}),\n localUpdatedAt: now,\n })\n .where(eq(containers.id, row.id))\n .run();\n }\n}\n\nasync function queueResetDocumentUpdates(input: {\n documentUpdates: readonly ResetDocumentUpdate[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const updateBatch of remoteResetBatches(input.documentUpdates)) {\n await input.tx\n .insert(documentHistoryUpdates)\n .values(\n updateBatch.map((update) =>\n queuedUpdateRow({\n createdAt: input.now,\n origin: \"outbox\",\n pendingUpdate: update,\n scope: update,\n updateId: crypto.randomUUID(),\n }),\n ),\n )\n .run();\n }\n}\n\nasync function queueResetContainerCreates(input: {\n now: string;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<number> {\n const rows = input.snapshot.containerRows.flatMap((row) => {\n const parentId =\n row.parentId ?? input.reset.replacement?.rootContainerId ?? null;\n return parentId ? [{ id: row.id, parentId }] : [];\n });\n if (rows.length === 0) return 0;\n for (const rowBatch of remoteResetBatches(rows)) {\n await input.tx\n .insert(localIntents)\n .values(\n rowBatch.map((row) => ({\n id: crypto.randomUUID(),\n lane: LOCAL_INTENT_LANES.containerCreate,\n subjectId: row.id,\n targetContainerId: row.parentId,\n intentType: CONTAINER_CREATE_INTENT_TYPE,\n syncStatus: \"pending\" as const,\n remoteContainerId: null,\n remoteMetadataAccessStateHash: null,\n remoteMetadataDocumentId: null,\n lastError: null,\n createdAt: input.now,\n updatedAt: input.now,\n })),\n )\n .run();\n }\n return rows.length;\n}\n\nasync function queueResetAttachmentUploads(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const attachmentBatch of remoteResetBatches(input.attachmentUploads)) {\n await input.tx\n .insert(documentPendingAttachments)\n .values(\n attachmentBatch.map((attachment) => ({\n ...attachment,\n createdAt: input.now,\n })),\n )\n .run();\n await input.tx\n .delete(documentAttachmentBlobProjection)\n .where(\n or(\n ...attachmentBatch.map((attachment) =>\n and(\n eq(documentAttachmentBlobProjection.localId, attachment.localId),\n eq(documentAttachmentBlobProjection.slotId, attachment.slotId),\n ),\n ),\n ),\n )\n .run();\n }\n}\n\nasync function clearRemoteSyncStateInTransaction(input: {\n plans: Awaited<ReturnType<typeof buildResetPlans>>;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<ClearRemoteSyncStateResult> {\n const now = new Date().toISOString();\n const { snapshot } = input;\n await clearScopedRemoteRows({\n attachmentUploads: input.plans.attachmentUploads,\n organizationId: input.reset.organizationId,\n snapshot,\n tx: input.tx,\n });\n await resetRemoteColumns({ now, reset: input.reset, snapshot, tx: input.tx });\n await queueResetDocumentUpdates({\n documentUpdates: input.plans.documentUpdates,\n now,\n tx: input.tx,\n });\n const queuedContainerCreateCount = await queueResetContainerCreates({\n now,\n reset: input.reset,\n snapshot,\n tx: input.tx,\n });\n await queueResetAttachmentUploads({\n attachmentUploads: input.plans.attachmentUploads,\n now,\n tx: input.tx,\n });\n return {\n clearedContainerCreateIntentCount:\n snapshot.clearedContainerCreateIntentCount,\n clearedContainerMoveIntentCount: snapshot.clearedContainerMoveIntentCount,\n clearedDocumentMoveIntentCount: snapshot.clearedDocumentMoveIntentCount,\n clearedPrincipalPolicyCount: snapshot.clearedPrincipalPolicyCount,\n clearedSyncCursorCount: snapshot.clearedSyncCursorCount,\n queuedAttachmentUploadCount: input.plans.attachmentUploads.length,\n queuedContainerCreateCount,\n queuedDocumentUpdateCount: input.plans.documentUpdates.length,\n resetContainerCount: snapshot.containerRows.length,\n resetDocumentCount: snapshot.documentRows.length,\n };\n}\n\nexport async function clearRemoteSyncState(\n execSql: ExecSql,\n reset: RemoteResetInput,\n canCommit?: (() => boolean) | undefined,\n): Promise<ClearRemoteSyncStateResult> {\n return runOrganizationPresentationReset(\n execSql,\n reset.organizationId,\n async () => {\n await ensureSqlTables(execSql, clientSqlTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const resetInTransaction = async (tx: ClientSQLiteTransactionScope) => {\n if (canCommit && !canCommit()) {\n throw new Error(\n \"Remote sync reset aborted: session identity changed\",\n );\n }\n const snapshot = await readRemoteSyncStateSnapshot(\n tx,\n reset.organizationId,\n );\n const plans = await buildResetPlans(tx, snapshot.documentRows);\n return clearRemoteSyncStateInTransaction({\n plans,\n reset,\n snapshot,\n tx,\n });\n };\n if (!canCommit) {\n return runtime.transaction(resetInTransaction);\n }\n const outcome = await runtime.guardedTransaction(\n resetInTransaction,\n canCommit,\n );\n if (!outcome.committed || !outcome.result) {\n throw new Error(\"Remote sync reset aborted: session identity changed\");\n }\n return outcome.result;\n },\n );\n}\n"]}
1
+ {"version":3,"file":"remoteReset.js","sourceRoot":"","sources":["remoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { clearRemoteResetPrincipalRows } from \"../../data/persistence/principalPolicy/principalPolicyRemoteReset\";\nimport { deleteVerifiedManifestBundlesForOrganization } from \"../../data/persistence/verifiedManifestBundlePersistence\";\nimport { clientSqlTables } from \"../../data/sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlTableSchema\";\nimport {\n clearContainerRowsForRemoteReset,\n clearDocumentPlacementsForRemoteReset,\n clearDormantContainerMetadataForRemoteReset,\n clearRemoteResetSyncCursors,\n queueContainerCreatesForRemoteReset,\n resetContainerServerIdentity,\n} from \"../container-contents/remoteReset/containerRemoteReset\";\nimport {\n buildResetPlans,\n clearDocumentDiscoveryEvidenceOnRemoteReset,\n clearDocumentRowsForRemoteReset,\n queueAttachmentReuploadsForRemoteReset,\n queueDocumentRepublishForRemoteReset,\n resetDocumentServerIdentity,\n} from \"../documents/remoteReset/documentRemoteReset\";\nimport {\n clearOrganizationReadModelsForRemoteReset,\n runOrganizationPresentationReset,\n} from \"../organizations/readModel/organizationRemoteReset\";\nimport {\n type RemoteResetInput,\n type RemoteSyncStateSnapshot,\n readRemoteSyncStateSnapshot,\n} from \"./remoteResetScope\";\n\nexport type {\n RemoteResetInput,\n RemoteResetReplacement,\n} from \"./remoteResetScope\";\n\nexport interface ClearRemoteSyncStateResult {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly queuedAttachmentUploadCount: number;\n readonly queuedContainerCreateCount: number;\n readonly queuedDocumentUpdateCount: number;\n readonly resetContainerCount: number;\n readonly resetDocumentCount: number;\n}\n\n// Each subsystem resets its own tables; this runs their steps in one\n// transaction. Steps on different tables are independent, and each subsystem\n// clears its rows before it queues new ones.\nasync function clearRemoteSyncStateInTransaction(input: {\n plans: Awaited<ReturnType<typeof buildResetPlans>>;\n reset: RemoteResetInput;\n snapshot: RemoteSyncStateSnapshot;\n tx: ClientSQLiteTransactionScope;\n}): Promise<ClearRemoteSyncStateResult> {\n const now = new Date().toISOString();\n const { plans, reset, snapshot, tx } = input;\n const { organizationId } = reset;\n\n // Forget what the server told this device about the organization.\n await clearOrganizationReadModelsForRemoteReset(tx, organizationId);\n await clearDormantContainerMetadataForRemoteReset(tx, organizationId);\n await deleteVerifiedManifestBundlesForOrganization(tx, organizationId);\n await clearDocumentDiscoveryEvidenceOnRemoteReset(tx, {\n containerIds: snapshot.containerIds,\n documentIds: snapshot.oldDocumentIds,\n });\n await clearRemoteResetPrincipalRows({ organizationId, snapshot, tx });\n await clearContainerRowsForRemoteReset({\n containerIds: snapshot.containerIds,\n tx,\n });\n await clearDocumentPlacementsForRemoteReset({\n documentLocalIds: snapshot.documentLocalIds,\n oldDocumentIds: snapshot.oldDocumentIds,\n tx,\n });\n await clearDocumentRowsForRemoteReset({\n attachmentUploads: plans.attachmentUploads,\n documentLocalIds: snapshot.documentLocalIds,\n documentRows: snapshot.documentRows,\n tx,\n });\n await clearRemoteResetSyncCursors({\n containerIds: snapshot.containerIds,\n tx,\n });\n\n // Strip server identity from the rows the device keeps.\n await resetDocumentServerIdentity({\n documentLocalIds: snapshot.documentLocalIds,\n documentRows: snapshot.documentRows,\n now,\n organizationId: reset.replacement?.organizationId ?? organizationId,\n tx,\n });\n await resetContainerServerIdentity({\n containerIds: snapshot.containerIds,\n containerRows: snapshot.containerRows,\n now,\n reset,\n tx,\n });\n\n // Queue the local content to be published again.\n await queueDocumentRepublishForRemoteReset({\n documentUpdates: plans.documentUpdates,\n now,\n tx,\n });\n const queuedContainerCreateCount = await queueContainerCreatesForRemoteReset({\n containerRows: snapshot.containerRows,\n now,\n reset,\n tx,\n });\n await queueAttachmentReuploadsForRemoteReset({\n attachmentUploads: plans.attachmentUploads,\n now,\n tx,\n });\n return {\n clearedContainerCreateIntentCount:\n snapshot.clearedContainerCreateIntentCount,\n clearedContainerMoveIntentCount: snapshot.clearedContainerMoveIntentCount,\n clearedDocumentMoveIntentCount: snapshot.clearedDocumentMoveIntentCount,\n clearedPrincipalPolicyCount: snapshot.clearedPrincipalPolicyCount,\n clearedSyncCursorCount: snapshot.clearedSyncCursorCount,\n queuedAttachmentUploadCount: plans.attachmentUploads.length,\n queuedContainerCreateCount,\n queuedDocumentUpdateCount: plans.documentUpdates.length,\n resetContainerCount: snapshot.containerRows.length,\n resetDocumentCount: snapshot.documentRows.length,\n };\n}\n\nexport async function clearRemoteSyncState(\n execSql: ExecSql,\n reset: RemoteResetInput,\n canCommit?: (() => boolean) | undefined,\n): Promise<ClearRemoteSyncStateResult> {\n return runOrganizationPresentationReset(\n execSql,\n reset.organizationId,\n async () => {\n await ensureSqlTables(execSql, clientSqlTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const resetInTransaction = async (tx: ClientSQLiteTransactionScope) => {\n if (canCommit && !canCommit()) {\n throw new Error(\n \"Remote sync reset aborted: session identity changed\",\n );\n }\n const snapshot = await readRemoteSyncStateSnapshot(\n tx,\n reset.organizationId,\n );\n const plans = await buildResetPlans(tx, snapshot.documentRows);\n return clearRemoteSyncStateInTransaction({\n plans,\n reset,\n snapshot,\n tx,\n });\n };\n if (!canCommit) {\n return runtime.transaction(resetInTransaction);\n }\n const outcome = await runtime.guardedTransaction(\n resetInTransaction,\n canCommit,\n );\n if (!outcome.committed || !outcome.result) {\n throw new Error(\"Remote sync reset aborted: session identity changed\");\n }\n return outcome.result;\n },\n );\n}\n"]}
@@ -1,6 +1,7 @@
1
+ import { type RemoteResetPrincipalKey } from "../../data/persistence/principalPolicy/principalPolicyRemoteReset.js";
1
2
  import type { ClientSQLiteTransactionScope } from "../../data/sqlite/sqlitePersistenceRuntime.js";
2
- import type { ResetDocumentScope } from "./remoteResetPlans.js";
3
- import { type RemoteResetPrincipalKey } from "./remoteResetPrincipalScope.js";
3
+ import { type ResetContainerRow } from "../container-contents/remoteReset/containerRemoteReset.js";
4
+ import { type ResetDocumentRow } from "../documents/remoteReset/documentRemoteReset.js";
4
5
  export interface RemoteResetReplacement {
5
6
  readonly organizationId: string;
6
7
  readonly rootContainerId: string;
@@ -9,14 +10,6 @@ export interface RemoteResetInput {
9
10
  readonly organizationId: string;
10
11
  readonly replacement?: RemoteResetReplacement | undefined;
11
12
  }
12
- export interface ResetContainerRow {
13
- readonly id: string;
14
- readonly parentId: string | null;
15
- }
16
- export interface ResetDocumentRow extends ResetDocumentScope {
17
- readonly documentId: string | null;
18
- readonly recoveryDocumentId: string | null;
19
- }
20
13
  export interface RemoteSyncStateSnapshot {
21
14
  readonly clearedContainerCreateIntentCount: number;
22
15
  readonly clearedContainerMoveIntentCount: number;
@@ -30,4 +23,8 @@ export interface RemoteSyncStateSnapshot {
30
23
  readonly oldDocumentIds: readonly string[];
31
24
  readonly principalKeys: readonly RemoteResetPrincipalKey[];
32
25
  }
26
+ /**
27
+ * Reads what a reset of the organization covers, from each subsystem that owns
28
+ * part of it: folders, then the documents in them, then principal policies.
29
+ */
33
30
  export declare function readRemoteSyncStateSnapshot(tx: ClientSQLiteTransactionScope, organizationId: string): Promise<RemoteSyncStateSnapshot>;
@@ -1,121 +1,39 @@
1
- import { eq } from "drizzle-orm";
2
- import { containerSyncWatermarks, containers, documentContainerProjection, documentProjection, documents, dormantContainerMetadata, LOCAL_INTENT_LANES, localIntents, } from "../../data/sqlite/schema/index.js";
3
- import { isRemoteResetSyncCursor } from "./remoteResetCursorScope.js";
4
- import { loadRemoteResetPrincipalScope, } from "./remoteResetPrincipalScope.js";
1
+ import { loadRemoteResetPrincipalScope, } from "../../data/persistence/principalPolicy/principalPolicyRemoteReset.js";
2
+ import { countContainerResetIntents, countRemoteResetSyncCursors, listDocumentPlacementRows, loadContainerResetScope, } from "../container-contents/remoteReset/containerRemoteReset.js";
3
+ import { loadDocumentResetScope, } from "../documents/remoteReset/documentRemoteReset.js";
5
4
  function principalKeyOfRow(row) {
6
5
  return `${row.principalType}\0${row.principalId}`;
7
6
  }
8
- function scopeKey(scope) {
9
- return `${scope.appKind}\0${scope.localId}`;
10
- }
11
- async function loadContainerScope(tx, organizationId) {
12
- const liveContainerRows = (await tx
13
- .select({ id: containers.id, parentId: containers.parentId })
14
- .from(containers)
15
- .where(eq(containers.organizationId, organizationId))).flatMap((row) => (row.id ? [{ id: row.id, parentId: row.parentId }] : []));
16
- const dormantContainerRows = await tx
17
- .select({ id: dormantContainerMetadata.containerId })
18
- .from(dormantContainerMetadata)
19
- .where(eq(dormantContainerMetadata.organizationId, organizationId));
20
- const containerRows = liveContainerRows;
21
- return {
22
- containerIds: [
23
- ...new Set([
24
- ...containerRows.map((row) => row.id),
25
- ...dormantContainerRows.map((row) => row.id),
26
- ]),
27
- ],
28
- containerRows,
29
- };
30
- }
31
- async function loadDocumentScope(input) {
32
- const { organizationId, tx } = input;
33
- const containerIdSet = new Set(input.containerIds);
34
- const [allDocuments, projectionRows, linkRows] = await loadDocumentAssociationRows(tx);
35
- const linkedDocumentIds = new Set(linkRows
36
- .filter((row) => containerIdSet.has(row.containerId))
37
- .map((row) => row.documentId));
38
- const projectedLocalIds = new Set(projectionRows
39
- .filter((row) => (row.containerId !== null && containerIdSet.has(row.containerId)) ||
40
- row.organizationId === organizationId ||
41
- (row.documentId !== null && linkedDocumentIds.has(row.documentId)))
42
- .flatMap((row) => (row.localId ? [row.localId] : [])));
43
- const documentRows = allDocuments.filter((row) => (row.appKind === "container-metadata" &&
44
- containerIdSet.has(row.localId)) ||
45
- (row.appKind === "documents" && projectedLocalIds.has(row.localId)) ||
46
- (row.documentId !== null && linkedDocumentIds.has(row.documentId)));
47
- return {
48
- documentLocalIds: [
49
- ...new Set(documentRows
50
- .filter((row) => row.appKind === "documents")
51
- .map((row) => row.localId)),
52
- ],
53
- documentRows,
54
- oldDocumentIds: [
55
- ...new Set(documentRows.flatMap((row) => (row.documentId ? [row.documentId] : []))),
56
- ],
57
- };
58
- }
59
- function loadDocumentAssociationRows(tx) {
60
- return Promise.all([
61
- tx
62
- .select({
63
- appKind: documents.appKind,
64
- documentId: documents.documentId,
65
- localId: documents.localId,
66
- recoveryDocumentId: documents.recoveryDocumentId,
67
- })
68
- .from(documents),
69
- tx.select().from(documentProjection),
70
- tx.select().from(documentContainerProjection),
71
- ]);
72
- }
73
- async function loadSnapshotCounts(input) {
74
- const { organizationId, tx } = input;
75
- const containerIdSet = new Set(input.containerIds);
76
- const documentScopeKeys = new Set(input.documentRows.map(scopeKey));
77
- const [principalScope, intents] = await Promise.all([
78
- loadRemoteResetPrincipalScope(tx, organizationId),
79
- tx
80
- .select({
81
- lane: localIntents.lane,
82
- localId: localIntents.localId,
83
- subjectId: localIntents.subjectId,
84
- })
85
- .from(localIntents),
86
- ]);
87
- const containerIntentCount = (lane) => intents.filter((row) => row.lane === lane && containerIdSet.has(row.subjectId)).length;
88
- const principalKeys = principalScope.principalKeys;
89
- const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));
90
- const scopedContainerIds = new Set(input.containerIds);
91
- const syncLanes = await tx.select().from(containerSyncWatermarks);
92
- return {
93
- clearedContainerCreateIntentCount: containerIntentCount(LOCAL_INTENT_LANES.containerCreate),
94
- clearedContainerMoveIntentCount: containerIntentCount(LOCAL_INTENT_LANES.containerMove),
95
- clearedDocumentMoveIntentCount: intents.filter((row) => row.lane === LOCAL_INTENT_LANES.documentPlacement &&
96
- row.localId !== null &&
97
- documentScopeKeys.has(scopeKey({ appKind: "documents", localId: row.localId }))).length,
98
- clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) => principalKeySet.has(`${row.type}\0${row.id}`)).length,
99
- clearedSyncCursorCount: syncLanes.filter((row) => isRemoteResetSyncCursor({
100
- containerIds: scopedContainerIds,
101
- row,
102
- })).length,
103
- principalKeys,
104
- };
105
- }
7
+ /**
8
+ * Reads what a reset of the organization covers, from each subsystem that owns
9
+ * part of it: folders, then the documents in them, then principal policies.
10
+ */
106
11
  export async function readRemoteSyncStateSnapshot(tx, organizationId) {
107
- const containerScope = await loadContainerScope(tx, organizationId);
108
- const documentScope = await loadDocumentScope({
12
+ const containerScope = await loadContainerResetScope(tx, organizationId);
13
+ const documentScope = await loadDocumentResetScope({
109
14
  containerIds: containerScope.containerIds,
110
15
  organizationId,
16
+ placementRows: await listDocumentPlacementRows(tx),
111
17
  tx,
112
18
  });
113
- const counts = await loadSnapshotCounts({
19
+ const principalScope = await loadRemoteResetPrincipalScope(tx, organizationId);
20
+ const intentCounts = await countContainerResetIntents({
114
21
  containerIds: containerScope.containerIds,
115
- documentRows: documentScope.documentRows,
116
- organizationId,
22
+ documentLocalIds: documentScope.documentLocalIds,
117
23
  tx,
118
24
  });
119
- return { ...containerScope, ...documentScope, ...counts };
25
+ const principalKeys = principalScope.principalKeys;
26
+ const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));
27
+ return {
28
+ ...containerScope,
29
+ ...documentScope,
30
+ ...intentCounts,
31
+ clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) => principalKeySet.has(`${row.type}\0${row.id}`)).length,
32
+ clearedSyncCursorCount: await countRemoteResetSyncCursors({
33
+ containerIds: containerScope.containerIds,
34
+ tx,
35
+ }),
36
+ principalKeys,
37
+ };
120
38
  }
121
39
  //# sourceMappingURL=remoteResetScope.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remoteResetScope.js","sourceRoot":"","sources":["remoteResetScope.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport {\n containerSyncWatermarks,\n containers,\n documentContainerProjection,\n documentProjection,\n documents,\n dormantContainerMetadata,\n LOCAL_INTENT_LANES,\n localIntents,\n} from \"../../data/sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport { isRemoteResetSyncCursor } from \"./remoteResetCursorScope\";\nimport type { ResetDocumentScope } from \"./remoteResetPlans\";\nimport {\n loadRemoteResetPrincipalScope,\n type RemoteResetPrincipalKey,\n} from \"./remoteResetPrincipalScope\";\n\nexport interface RemoteResetReplacement {\n readonly organizationId: string;\n readonly rootContainerId: string;\n}\n\nexport interface RemoteResetInput {\n readonly organizationId: string;\n readonly replacement?: RemoteResetReplacement | undefined;\n}\n\nexport interface ResetContainerRow {\n readonly id: string;\n readonly parentId: string | null;\n}\n\nexport interface ResetDocumentRow extends ResetDocumentScope {\n readonly documentId: string | null;\n readonly recoveryDocumentId: string | null;\n}\n\nexport interface RemoteSyncStateSnapshot {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly containerIds: readonly string[];\n readonly containerRows: readonly ResetContainerRow[];\n readonly documentLocalIds: readonly string[];\n readonly documentRows: readonly ResetDocumentRow[];\n readonly oldDocumentIds: readonly string[];\n readonly principalKeys: readonly RemoteResetPrincipalKey[];\n}\n\nfunction principalKeyOfRow(row: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${row.principalType}\\0${row.principalId}`;\n}\n\nfunction scopeKey(scope: ResetDocumentScope): string {\n return `${scope.appKind}\\0${scope.localId}`;\n}\n\nasync function loadContainerScope(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<{\n containerIds: string[];\n containerRows: ResetContainerRow[];\n}> {\n const liveContainerRows = (\n await tx\n .select({ id: containers.id, parentId: containers.parentId })\n .from(containers)\n .where(eq(containers.organizationId, organizationId))\n ).flatMap((row) => (row.id ? [{ id: row.id, parentId: row.parentId }] : []));\n const dormantContainerRows = await tx\n .select({ id: dormantContainerMetadata.containerId })\n .from(dormantContainerMetadata)\n .where(eq(dormantContainerMetadata.organizationId, organizationId));\n const containerRows = liveContainerRows;\n return {\n containerIds: [\n ...new Set([\n ...containerRows.map((row) => row.id),\n ...dormantContainerRows.map((row) => row.id),\n ]),\n ],\n containerRows,\n };\n}\n\nasync function loadDocumentScope(input: {\n containerIds: readonly string[];\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<{\n documentLocalIds: string[];\n documentRows: ResetDocumentRow[];\n oldDocumentIds: string[];\n}> {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const [allDocuments, projectionRows, linkRows] =\n await loadDocumentAssociationRows(tx);\n const linkedDocumentIds = new Set(\n linkRows\n .filter((row) => containerIdSet.has(row.containerId))\n .map((row) => row.documentId),\n );\n const projectedLocalIds = new Set(\n projectionRows\n .filter(\n (row) =>\n (row.containerId !== null && containerIdSet.has(row.containerId)) ||\n row.organizationId === organizationId ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n )\n .flatMap((row) => (row.localId ? [row.localId] : [])),\n );\n const documentRows = allDocuments.filter(\n (row) =>\n (row.appKind === \"container-metadata\" &&\n containerIdSet.has(row.localId)) ||\n (row.appKind === \"documents\" && projectedLocalIds.has(row.localId)) ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n );\n return {\n documentLocalIds: [\n ...new Set(\n documentRows\n .filter((row) => row.appKind === \"documents\")\n .map((row) => row.localId),\n ),\n ],\n documentRows,\n oldDocumentIds: [\n ...new Set(\n documentRows.flatMap((row) => (row.documentId ? [row.documentId] : [])),\n ),\n ],\n };\n}\n\nfunction loadDocumentAssociationRows(tx: ClientSQLiteTransactionScope) {\n return Promise.all([\n tx\n .select({\n appKind: documents.appKind,\n documentId: documents.documentId,\n localId: documents.localId,\n recoveryDocumentId: documents.recoveryDocumentId,\n })\n .from(documents),\n tx.select().from(documentProjection),\n tx.select().from(documentContainerProjection),\n ]);\n}\n\nasync function loadSnapshotCounts(input: {\n containerIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}) {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const documentScopeKeys = new Set(input.documentRows.map(scopeKey));\n const [principalScope, intents] = await Promise.all([\n loadRemoteResetPrincipalScope(tx, organizationId),\n tx\n .select({\n lane: localIntents.lane,\n localId: localIntents.localId,\n subjectId: localIntents.subjectId,\n })\n .from(localIntents),\n ]);\n const containerIntentCount = (lane: string) =>\n intents.filter(\n (row) => row.lane === lane && containerIdSet.has(row.subjectId),\n ).length;\n const principalKeys = principalScope.principalKeys;\n const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));\n const scopedContainerIds = new Set(input.containerIds);\n const syncLanes = await tx.select().from(containerSyncWatermarks);\n\n return {\n clearedContainerCreateIntentCount: containerIntentCount(\n LOCAL_INTENT_LANES.containerCreate,\n ),\n clearedContainerMoveIntentCount: containerIntentCount(\n LOCAL_INTENT_LANES.containerMove,\n ),\n clearedDocumentMoveIntentCount: intents.filter(\n (row) =>\n row.lane === LOCAL_INTENT_LANES.documentPlacement &&\n row.localId !== null &&\n documentScopeKeys.has(\n scopeKey({ appKind: \"documents\", localId: row.localId }),\n ),\n ).length,\n clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) =>\n principalKeySet.has(`${row.type}\\0${row.id}`),\n ).length,\n clearedSyncCursorCount: syncLanes.filter((row) =>\n isRemoteResetSyncCursor({\n containerIds: scopedContainerIds,\n row,\n }),\n ).length,\n principalKeys,\n };\n}\n\nexport async function readRemoteSyncStateSnapshot(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<RemoteSyncStateSnapshot> {\n const containerScope = await loadContainerScope(tx, organizationId);\n const documentScope = await loadDocumentScope({\n containerIds: containerScope.containerIds,\n organizationId,\n tx,\n });\n const counts = await loadSnapshotCounts({\n containerIds: containerScope.containerIds,\n documentRows: documentScope.documentRows,\n organizationId,\n tx,\n });\n return { ...containerScope, ...documentScope, ...counts };\n}\n"]}
1
+ {"version":3,"file":"remoteResetScope.js","sourceRoot":"","sources":["remoteResetScope.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,GAE9B,MAAM,mEAAmE,CAAC;AAE3E,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,GAExB,MAAM,wDAAwD,CAAC;AAChE,OAAO,EACL,sBAAsB,GAEvB,MAAM,8CAA8C,CAAC;AA0BtD,SAAS,iBAAiB,CAAC,GAG1B;IACC,OAAO,GAAG,GAAG,CAAC,aAAa,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,EAAgC,EAChC,cAAsB;IAEtB,MAAM,cAAc,GAAG,MAAM,uBAAuB,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC;QACjD,YAAY,EAAE,cAAc,CAAC,YAAY;QACzC,cAAc;QACd,aAAa,EAAE,MAAM,yBAAyB,CAAC,EAAE,CAAC;QAClD,EAAE;KACH,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,MAAM,6BAA6B,CACxD,EAAE,EACF,cAAc,CACf,CAAC;IACF,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC;QACpD,YAAY,EAAE,cAAc,CAAC,YAAY;QACzC,gBAAgB,EAAE,aAAa,CAAC,gBAAgB;QAChD,EAAE;KACH,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;IACnD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,OAAO;QACL,GAAG,cAAc;QACjB,GAAG,aAAa;QAChB,GAAG,YAAY;QACf,2BAA2B,EAAE,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACpE,eAAe,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAC9C,CAAC,MAAM;QACR,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;YACxD,YAAY,EAAE,cAAc,CAAC,YAAY;YACzC,EAAE;SACH,CAAC;QACF,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["import {\n loadRemoteResetPrincipalScope,\n type RemoteResetPrincipalKey,\n} from \"../../data/persistence/principalPolicy/principalPolicyRemoteReset\";\nimport type { ClientSQLiteTransactionScope } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport {\n countContainerResetIntents,\n countRemoteResetSyncCursors,\n listDocumentPlacementRows,\n loadContainerResetScope,\n type ResetContainerRow,\n} from \"../container-contents/remoteReset/containerRemoteReset\";\nimport {\n loadDocumentResetScope,\n type ResetDocumentRow,\n} from \"../documents/remoteReset/documentRemoteReset\";\n\nexport interface RemoteResetReplacement {\n readonly organizationId: string;\n readonly rootContainerId: string;\n}\n\nexport interface RemoteResetInput {\n readonly organizationId: string;\n readonly replacement?: RemoteResetReplacement | undefined;\n}\n\nexport interface RemoteSyncStateSnapshot {\n readonly clearedContainerCreateIntentCount: number;\n readonly clearedContainerMoveIntentCount: number;\n readonly clearedDocumentMoveIntentCount: number;\n readonly clearedPrincipalPolicyCount: number;\n readonly clearedSyncCursorCount: number;\n readonly containerIds: readonly string[];\n readonly containerRows: readonly ResetContainerRow[];\n readonly documentLocalIds: readonly string[];\n readonly documentRows: readonly ResetDocumentRow[];\n readonly oldDocumentIds: readonly string[];\n readonly principalKeys: readonly RemoteResetPrincipalKey[];\n}\n\nfunction principalKeyOfRow(row: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${row.principalType}\\0${row.principalId}`;\n}\n\n/**\n * Reads what a reset of the organization covers, from each subsystem that owns\n * part of it: folders, then the documents in them, then principal policies.\n */\nexport async function readRemoteSyncStateSnapshot(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<RemoteSyncStateSnapshot> {\n const containerScope = await loadContainerResetScope(tx, organizationId);\n const documentScope = await loadDocumentResetScope({\n containerIds: containerScope.containerIds,\n organizationId,\n placementRows: await listDocumentPlacementRows(tx),\n tx,\n });\n const principalScope = await loadRemoteResetPrincipalScope(\n tx,\n organizationId,\n );\n const intentCounts = await countContainerResetIntents({\n containerIds: containerScope.containerIds,\n documentLocalIds: documentScope.documentLocalIds,\n tx,\n });\n const principalKeys = principalScope.principalKeys;\n const principalKeySet = new Set(principalKeys.map(principalKeyOfRow));\n return {\n ...containerScope,\n ...documentScope,\n ...intentCounts,\n clearedPrincipalPolicyCount: principalScope.policyRows.filter((row) =>\n principalKeySet.has(`${row.type}\\0${row.id}`),\n ).length,\n clearedSyncCursorCount: await countRemoteResetSyncCursors({\n containerIds: containerScope.containerIds,\n tx,\n }),\n principalKeys,\n };\n}\n"]}