@tearleads/client-sdk 0.1.44 → 0.1.46

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 (133) hide show
  1. package/client/Tearleads.js +3 -0
  2. package/client/Tearleads.js.map +1 -1
  3. package/client/userIdentities.d.ts +11 -1
  4. package/client/userIdentities.js +26 -8
  5. package/client/userIdentities.js.map +1 -1
  6. package/client/workflowRuntime.d.ts +2 -1
  7. package/client/workflowRuntime.js +1 -0
  8. package/client/workflowRuntime.js.map +1 -1
  9. package/data/persistence/container-contents/containerContentsPersistence.js +2 -3
  10. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  11. package/data/persistence/container-contents/containerCreateIntentSettlement.js +16 -16
  12. package/data/persistence/container-contents/containerCreateIntentSettlement.js.map +1 -1
  13. package/data/persistence/container-contents/containerDeletionPersistence.js +5 -11
  14. package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerDocumentReassignment.js +13 -13
  16. package/data/persistence/container-contents/containerDocumentReassignment.js.map +1 -1
  17. package/data/persistence/container-contents/containerHydrationPersistence.js +7 -4
  18. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  19. package/data/persistence/container-contents/containerIntentPersistence.js +43 -42
  20. package/data/persistence/container-contents/containerIntentPersistence.js.map +1 -1
  21. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +15 -20
  22. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  23. package/data/persistence/container-contents/containerMoveAbandonPersistence.js +1 -6
  24. package/data/persistence/container-contents/containerMoveAbandonPersistence.js.map +1 -1
  25. package/data/persistence/container-contents/containerMoveIntentRows.js +9 -8
  26. package/data/persistence/container-contents/containerMoveIntentRows.js.map +1 -1
  27. package/data/persistence/container-contents/containerReconcilePersistence.js +4 -8
  28. package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
  29. package/data/persistence/container-contents/containerRecoveryPersistence.js +20 -19
  30. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  31. package/data/persistence/container-contents/containerRemovalWork.js +10 -10
  32. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  33. package/data/persistence/container-contents/containerStructuralRepair.js +21 -44
  34. package/data/persistence/container-contents/containerStructuralRepair.js.map +1 -1
  35. package/data/persistence/container-contents/documentLinkRemovalRepair.js +12 -11
  36. package/data/persistence/container-contents/documentLinkRemovalRepair.js.map +1 -1
  37. package/data/persistence/container-contents/documentMoveIntentPersistence.js +53 -28
  38. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  39. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +9 -8
  40. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
  41. package/data/persistence/container-contents/documentPurgePlacement.js +6 -6
  42. package/data/persistence/container-contents/documentPurgePlacement.js.map +1 -1
  43. package/data/persistence/container-contents/dormantContainerMetadata.js +1 -5
  44. package/data/persistence/container-contents/dormantContainerMetadata.js.map +1 -1
  45. package/data/persistence/container-contents/pendingContainerCreate.js +5 -5
  46. package/data/persistence/container-contents/pendingContainerCreate.js.map +1 -1
  47. package/data/persistence/containers/containerPersistence.js +10 -27
  48. package/data/persistence/containers/containerPersistence.js.map +1 -1
  49. package/data/persistence/containers/documentContainerProjectionPersistence.js +2 -2
  50. package/data/persistence/containers/documentContainerProjectionPersistence.js.map +1 -1
  51. package/data/persistence/containers/documentPlacement.js +10 -10
  52. package/data/persistence/containers/documentPlacement.js.map +1 -1
  53. package/data/persistence/documents/internal/discardDocument.js +5 -5
  54. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  55. package/data/persistence/documents/internal/documentDeletionPersistence.js +7 -9
  56. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  57. package/data/persistence/documents/internal/documentMutationPersistence.js +6 -8
  58. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  59. package/data/persistence/documents/internal/ensureDocumentsSchema.js +2 -2
  60. package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
  61. package/data/persistence/documents/internal/orphanSideRows.js +3 -22
  62. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  63. package/data/persistence/organizations/organizationDataUsagePersistence.js +31 -64
  64. package/data/persistence/organizations/organizationDataUsagePersistence.js.map +1 -1
  65. package/data/persistence/organizations/organizationReadModelPurge.js +1 -5
  66. package/data/persistence/organizations/organizationReadModelPurge.js.map +1 -1
  67. package/data/persistence/principalCurrentAcknowledgementPersistence.js +24 -17
  68. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  69. package/data/persistence/principalHistoryIncompleteRetention.js +3 -9
  70. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -1
  71. package/data/persistence/principalHistoryStagePersistence.d.ts +3 -9
  72. package/data/persistence/principalHistoryStagePersistence.js +15 -25
  73. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  74. package/data/persistence/principalHistoryStageRetention.js +16 -15
  75. package/data/persistence/principalHistoryStageRetention.js.map +1 -1
  76. package/data/persistence/principalHistoryUnpublishedRetention.js +6 -13
  77. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -1
  78. package/data/sqlite/containerSchema.d.ts +84 -180
  79. package/data/sqlite/containerSchema.js +14 -23
  80. package/data/sqlite/containerSchema.js.map +1 -1
  81. package/data/sqlite/documentPlacementIntentSchema.js +3 -50
  82. package/data/sqlite/documentPlacementIntentSchema.js.map +1 -1
  83. package/data/sqlite/documentSyncFailurePersistence.d.ts +16 -6
  84. package/data/sqlite/documentSyncFailurePersistence.js +44 -54
  85. package/data/sqlite/documentSyncFailurePersistence.js.map +1 -1
  86. package/data/sqlite/{documentPlacementIntentSchema.d.ts → localIntentSchema.d.ts} +162 -88
  87. package/data/sqlite/localIntentSchema.js +90 -0
  88. package/data/sqlite/localIntentSchema.js.map +1 -0
  89. package/data/sqlite/organizationDataUsageSchema.js +11 -17
  90. package/data/sqlite/organizationDataUsageSchema.js.map +1 -1
  91. package/data/sqlite/principalHistoryRetentionSchema.js +0 -15
  92. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -1
  93. package/data/sqlite/principalHistoryStageSchema.d.ts +44 -2
  94. package/data/sqlite/principalHistoryStageSchema.js +14 -2
  95. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  96. package/data/sqlite/schema.d.ts +947 -2112
  97. package/data/sqlite/schema.js +26 -134
  98. package/data/sqlite/schema.js.map +1 -1
  99. package/data/trustedUserIdentity/identityLink.d.ts +12 -0
  100. package/data/trustedUserIdentity/identityLink.js +117 -0
  101. package/data/trustedUserIdentity/identityLink.js.map +1 -0
  102. package/data/trustedUserIdentity/index.d.ts +2 -1
  103. package/data/trustedUserIdentity/index.js +1 -0
  104. package/data/trustedUserIdentity/index.js.map +1 -1
  105. package/data/trustedUserIdentity/service.js +48 -2
  106. package/data/trustedUserIdentity/service.js.map +1 -1
  107. package/data/trustedUserIdentity/types.d.ts +3 -0
  108. package/data/trustedUserIdentity/types.js.map +1 -1
  109. package/index.js +1 -1
  110. package/index.js.map +1 -1
  111. package/package.json +1 -1
  112. package/workflows/container-contents/documentPriming.js +6 -10
  113. package/workflows/container-contents/documentPriming.js.map +1 -1
  114. package/workflows/container-contents/documentQueries/sql.js +11 -10
  115. package/workflows/container-contents/documentQueries/sql.js.map +1 -1
  116. package/workflows/container-contents/documentQueries.js +2 -2
  117. package/workflows/container-contents/documentQueries.js.map +1 -1
  118. package/workflows/container-contents/pendingDownloads.js +2 -5
  119. package/workflows/container-contents/pendingDownloads.js.map +1 -1
  120. package/workflows/container-contents/pendingWrites/deferredTails.js +3 -11
  121. package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
  122. package/workflows/container-contents/pendingWrites/sources.js +56 -80
  123. package/workflows/container-contents/pendingWrites/sources.js.map +1 -1
  124. package/workflows/container-contents/pendingWrites.js +6 -4
  125. package/workflows/container-contents/pendingWrites.js.map +1 -1
  126. package/workflows/container-contents/remoteContainerState.js +2 -1
  127. package/workflows/container-contents/remoteContainerState.js.map +1 -1
  128. package/workflows/sync/remoteReset.js +16 -23
  129. package/workflows/sync/remoteReset.js.map +1 -1
  130. package/workflows/sync/remoteResetPrincipalScope.js +1 -2
  131. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  132. package/workflows/sync/remoteResetScope.js +15 -8
  133. package/workflows/sync/remoteResetScope.js.map +1 -1
@@ -1,9 +1,7 @@
1
+ import { LOCAL_INTENT_LANES } from "../../../data/sqlite/schema.js";
1
2
  import { getContainerDisplayNameSql, getContainerOrganizationAttributionSql, } from "../documentQueries/sql.js";
2
3
  import { readNumber, readString } from "./rowReaders.js";
3
- const CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({
4
- containerAlias: "container",
5
- projectionAlias: "container_projection",
6
- });
4
+ const CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql("container");
7
5
  const DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({
8
6
  containerAlias: "container",
9
7
  projectionAlias: "projection",
@@ -35,8 +33,8 @@ const PENDING_WRITE_SOURCE_SQL = `
35
33
  updates.updated_at AS updated_at,
36
34
  NULL AS target_container_id,
37
35
  'pending' AS operation_status,
38
- failure.message AS last_error,
39
- failure.attempted_at AS last_attempted_at,
36
+ stored.sync_failure_message AS last_error,
37
+ stored.sync_failure_attempted_at AS last_attempted_at,
40
38
  'always' AS inclusion
41
39
  FROM pending_update_groups updates
42
40
  LEFT JOIN documents stored
@@ -46,9 +44,6 @@ const PENDING_WRITE_SOURCE_SQL = `
46
44
  ON projection.local_id = updates.local_id
47
45
  LEFT JOIN containers container
48
46
  ON container.id = projection.container_id
49
- LEFT JOIN document_sync_failures failure
50
- ON failure.app_kind = 'documents'
51
- AND failure.local_id = updates.local_id
52
47
  WHERE updates.app_kind = 'documents'
53
48
 
54
49
  UNION ALL
@@ -62,7 +57,7 @@ const PENDING_WRITE_SOURCE_SQL = `
62
57
  SELECT
63
58
  'document' AS object_kind,
64
59
  NULL AS namespace,
65
- failure.local_id AS local_id,
60
+ stored.local_id AS local_id,
66
61
  stored.document_id AS remote_id,
67
62
  projection.title AS name,
68
63
  projection.container_id AS container_id,
@@ -70,22 +65,20 @@ const PENDING_WRITE_SOURCE_SQL = `
70
65
  'revalidation' AS operation_kind,
71
66
  0 AS operation_count,
72
67
  0 AS byte_length,
73
- failure.attempted_at AS created_at,
74
- failure.attempted_at AS updated_at,
68
+ stored.sync_failure_attempted_at AS created_at,
69
+ stored.sync_failure_attempted_at AS updated_at,
75
70
  NULL AS target_container_id,
76
71
  'pending' AS operation_status,
77
- failure.message AS last_error,
78
- failure.attempted_at AS last_attempted_at,
72
+ stored.sync_failure_message AS last_error,
73
+ stored.sync_failure_attempted_at AS last_attempted_at,
79
74
  'unless-item-covered' AS inclusion
80
- FROM document_sync_failures failure
81
- LEFT JOIN documents stored
82
- ON stored.app_kind = failure.app_kind
83
- AND stored.local_id = failure.local_id
75
+ FROM documents stored
84
76
  LEFT JOIN document_projection projection
85
- ON projection.local_id = failure.local_id
77
+ ON projection.local_id = stored.local_id
86
78
  LEFT JOIN containers container
87
79
  ON container.id = projection.container_id
88
- WHERE failure.app_kind = 'documents'
80
+ WHERE stored.app_kind = 'documents'
81
+ AND stored.sync_failure_message IS NOT NULL
89
82
 
90
83
  UNION ALL
91
84
 
@@ -104,16 +97,14 @@ const PENDING_WRITE_SOURCE_SQL = `
104
97
  updates.updated_at AS updated_at,
105
98
  NULL AS target_container_id,
106
99
  'pending' AS operation_status,
107
- failure.message AS last_error,
108
- failure.attempted_at AS last_attempted_at,
100
+ metadata.sync_failure_message AS last_error,
101
+ metadata.sync_failure_attempted_at AS last_attempted_at,
109
102
  'always' AS inclusion
110
103
  FROM pending_update_groups updates
111
104
  LEFT JOIN containers container ON container.id = updates.local_id
112
- LEFT JOIN container_projection
113
- ON container_projection.container_id = updates.local_id
114
- LEFT JOIN document_sync_failures failure
115
- ON failure.app_kind = 'container-metadata'
116
- AND failure.local_id = updates.local_id
105
+ LEFT JOIN documents metadata
106
+ ON metadata.app_kind = 'container-metadata'
107
+ AND metadata.local_id = updates.local_id
117
108
  WHERE updates.app_kind = 'container-metadata'
118
109
  -- Dormant retained metadata (container tombstoned access_revoked, row 4)
119
110
  -- has no containers row; keep it unsurfaced until rehydration re-attaches
@@ -128,7 +119,7 @@ const PENDING_WRITE_SOURCE_SQL = `
128
119
  SELECT
129
120
  'container' AS object_kind,
130
121
  NULL AS namespace,
131
- failure.local_id AS local_id,
122
+ metadata.local_id AS local_id,
132
123
  CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,
133
124
  ${CONTAINER_DISPLAY_NAME_SQL} AS name,
134
125
  container.id AS container_id,
@@ -136,18 +127,17 @@ const PENDING_WRITE_SOURCE_SQL = `
136
127
  'revalidation' AS operation_kind,
137
128
  0 AS operation_count,
138
129
  0 AS byte_length,
139
- failure.attempted_at AS created_at,
140
- failure.attempted_at AS updated_at,
130
+ metadata.sync_failure_attempted_at AS created_at,
131
+ metadata.sync_failure_attempted_at AS updated_at,
141
132
  NULL AS target_container_id,
142
133
  'pending' AS operation_status,
143
- failure.message AS last_error,
144
- failure.attempted_at AS last_attempted_at,
134
+ metadata.sync_failure_message AS last_error,
135
+ metadata.sync_failure_attempted_at AS last_attempted_at,
145
136
  'unless-item-covered' AS inclusion
146
- FROM document_sync_failures failure
147
- JOIN containers container ON container.id = failure.local_id
148
- LEFT JOIN container_projection
149
- ON container_projection.container_id = failure.local_id
150
- WHERE failure.app_kind = 'container-metadata'
137
+ FROM documents metadata
138
+ JOIN containers container ON container.id = metadata.local_id
139
+ WHERE metadata.app_kind = 'container-metadata'
140
+ AND metadata.sync_failure_message IS NOT NULL
151
141
 
152
142
  UNION ALL
153
143
 
@@ -166,16 +156,13 @@ const PENDING_WRITE_SOURCE_SQL = `
166
156
  updates.updated_at AS updated_at,
167
157
  NULL AS target_container_id,
168
158
  'pending' AS operation_status,
169
- failure.message AS last_error,
170
- failure.attempted_at AS last_attempted_at,
159
+ stored.sync_failure_message AS last_error,
160
+ stored.sync_failure_attempted_at AS last_attempted_at,
171
161
  'always' AS inclusion
172
162
  FROM pending_update_groups updates
173
163
  LEFT JOIN documents stored
174
164
  ON stored.app_kind = updates.app_kind
175
165
  AND stored.local_id = updates.local_id
176
- LEFT JOIN document_sync_failures failure
177
- ON failure.app_kind = updates.app_kind
178
- AND failure.local_id = updates.local_id
179
166
  WHERE updates.app_kind NOT IN ('documents', 'container-metadata')
180
167
 
181
168
  UNION ALL
@@ -195,8 +182,8 @@ const PENDING_WRITE_SOURCE_SQL = `
195
182
  MAX(attachment.created_at) AS updated_at,
196
183
  NULL AS target_container_id,
197
184
  'pending' AS operation_status,
198
- failure.message AS last_error,
199
- failure.attempted_at AS last_attempted_at,
185
+ stored.sync_failure_message AS last_error,
186
+ stored.sync_failure_attempted_at AS last_attempted_at,
200
187
  'always' AS inclusion
201
188
  FROM document_pending_attachments attachment
202
189
  LEFT JOIN documents stored
@@ -206,9 +193,6 @@ const PENDING_WRITE_SOURCE_SQL = `
206
193
  ON projection.local_id = attachment.local_id
207
194
  LEFT JOIN containers container
208
195
  ON container.id = projection.container_id
209
- LEFT JOIN document_sync_failures failure
210
- ON failure.app_kind = 'documents'
211
- AND failure.local_id = attachment.local_id
212
196
  GROUP BY attachment.local_id
213
197
 
214
198
  UNION ALL
@@ -216,26 +200,25 @@ const PENDING_WRITE_SOURCE_SQL = `
216
200
  SELECT
217
201
  'container' AS object_kind,
218
202
  NULL AS namespace,
219
- intent.container_id AS local_id,
203
+ intent.subject_id AS local_id,
220
204
  COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,
221
205
  ${CONTAINER_DISPLAY_NAME_SQL} AS name,
222
- intent.container_id AS container_id,
206
+ intent.subject_id AS container_id,
223
207
  NULLIF(container.organization_id, '') AS organization_id,
224
208
  'create' AS operation_kind,
225
209
  1 AS operation_count,
226
210
  0 AS byte_length,
227
211
  intent.created_at AS created_at,
228
212
  intent.updated_at AS updated_at,
229
- intent.parent_container_id AS target_container_id,
213
+ intent.target_container_id AS target_container_id,
230
214
  'pending' AS operation_status,
231
215
  intent.last_error AS last_error,
232
216
  intent.last_attempted_at AS last_attempted_at,
233
217
  'always' AS inclusion
234
- FROM container_create_intents intent
235
- LEFT JOIN containers container ON container.id = intent.container_id
236
- LEFT JOIN container_projection
237
- ON container_projection.container_id = intent.container_id
238
- WHERE intent.intent_type = 'container.create'
218
+ FROM local_intents intent
219
+ LEFT JOIN containers container ON container.id = intent.subject_id
220
+ WHERE intent.lane = '${LOCAL_INTENT_LANES.containerCreate}'
221
+ AND intent.intent_type = 'container.create'
239
222
  AND intent.sync_status = 'pending'
240
223
 
241
224
  UNION ALL
@@ -243,26 +226,25 @@ const PENDING_WRITE_SOURCE_SQL = `
243
226
  SELECT
244
227
  'container' AS object_kind,
245
228
  NULL AS namespace,
246
- intent.container_id AS local_id,
229
+ intent.subject_id AS local_id,
247
230
  CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,
248
231
  ${CONTAINER_DISPLAY_NAME_SQL} AS name,
249
- intent.container_id AS container_id,
232
+ intent.subject_id AS container_id,
250
233
  NULLIF(container.organization_id, '') AS organization_id,
251
234
  'move' AS operation_kind,
252
235
  1 AS operation_count,
253
236
  0 AS byte_length,
254
237
  intent.created_at AS created_at,
255
238
  intent.updated_at AS updated_at,
256
- intent.parent_container_id AS target_container_id,
239
+ intent.target_container_id AS target_container_id,
257
240
  CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,
258
241
  intent.last_error AS last_error,
259
242
  intent.last_attempted_at AS last_attempted_at,
260
243
  'always' AS inclusion
261
- FROM container_move_intents intent
262
- LEFT JOIN containers container ON container.id = intent.container_id
263
- LEFT JOIN container_projection
264
- ON container_projection.container_id = intent.container_id
265
- WHERE intent.intent_type = 'container.move'
244
+ FROM local_intents intent
245
+ LEFT JOIN containers container ON container.id = intent.subject_id
246
+ WHERE intent.lane = '${LOCAL_INTENT_LANES.containerMove}'
247
+ AND intent.intent_type = 'container.move'
266
248
 
267
249
  UNION ALL
268
250
 
@@ -270,7 +252,7 @@ const PENDING_WRITE_SOURCE_SQL = `
270
252
  'document' AS object_kind,
271
253
  NULL AS namespace,
272
254
  intent.local_id AS local_id,
273
- intent.document_id AS remote_id,
255
+ intent.subject_id AS remote_id,
274
256
  projection.title AS name,
275
257
  COALESCE(projection.container_id, intent.target_container_id) AS container_id,
276
258
  ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,
@@ -281,18 +263,19 @@ const PENDING_WRITE_SOURCE_SQL = `
281
263
  intent.updated_at AS updated_at,
282
264
  intent.target_container_id AS target_container_id,
283
265
  CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,
284
- COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,
285
- COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,
266
+ COALESCE(NULLIF(intent.last_error, ''), stored.sync_failure_message) AS last_error,
267
+ COALESCE(intent.last_attempted_at, stored.sync_failure_attempted_at) AS last_attempted_at,
286
268
  'always' AS inclusion
287
- FROM document_move_intents intent
269
+ FROM local_intents intent
270
+ LEFT JOIN documents stored
271
+ ON stored.app_kind = 'documents'
272
+ AND stored.local_id = intent.local_id
288
273
  LEFT JOIN document_projection projection
289
274
  ON projection.local_id = intent.local_id
290
275
  LEFT JOIN containers container
291
276
  ON container.id = COALESCE(projection.container_id, intent.target_container_id)
292
- LEFT JOIN document_sync_failures failure
293
- ON failure.app_kind = 'documents'
294
- AND failure.local_id = intent.local_id
295
- WHERE intent.intent_type IN ('document.move', 'document.link')
277
+ WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'
278
+ AND intent.intent_type IN ('document.move', 'document.link')
296
279
 
297
280
  UNION ALL
298
281
 
@@ -311,17 +294,14 @@ const PENDING_WRITE_SOURCE_SQL = `
311
294
  stored.updated_at AS updated_at,
312
295
  projection.container_id AS target_container_id,
313
296
  'pending' AS operation_status,
314
- failure.message AS last_error,
315
- failure.attempted_at AS last_attempted_at,
297
+ stored.sync_failure_message AS last_error,
298
+ stored.sync_failure_attempted_at AS last_attempted_at,
316
299
  'unless-operation-covered' AS inclusion
317
300
  FROM documents stored
318
301
  LEFT JOIN document_projection projection
319
302
  ON projection.local_id = stored.local_id
320
303
  LEFT JOIN containers container
321
304
  ON container.id = projection.container_id
322
- LEFT JOIN document_sync_failures failure
323
- ON failure.app_kind = 'documents'
324
- AND failure.local_id = stored.local_id
325
305
  WHERE stored.app_kind = 'documents'
326
306
  AND stored.document_id IS NULL
327
307
 
@@ -346,8 +326,6 @@ const PENDING_WRITE_SOURCE_SQL = `
346
326
  NULL AS last_attempted_at,
347
327
  'unless-operation-covered' AS inclusion
348
328
  FROM containers container
349
- LEFT JOIN container_projection
350
- ON container_projection.container_id = container.id
351
329
  LEFT JOIN documents metadata
352
330
  ON metadata.app_kind = 'container-metadata'
353
331
  AND metadata.local_id = container.id
@@ -376,8 +354,6 @@ const PENDING_WRITE_SOURCE_SQL = `
376
354
  NULL AS last_attempted_at,
377
355
  'unless-item-covered' AS inclusion
378
356
  FROM containers container
379
- LEFT JOIN container_projection
380
- ON container_projection.container_id = container.id
381
357
  WHERE container.local_updated_at IS NOT NULL
382
358
  AND (
383
359
  container.server_updated_at IS NULL
@@ -1 +1 @@
1
- {"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({\n containerAlias: \"container\",\n projectionAlias: \"container_projection\",\n});\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_history_updates\n WHERE update_id IS NOT NULL\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n LEFT JOIN documents stored\n ON stored.app_kind = failure.app_kind\n AND stored.local_id = failure.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = failure.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE failure.app_kind = 'documents'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'container-metadata'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n JOIN containers container ON container.id = failure.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = failure.local_id\n WHERE failure.app_kind = 'container-metadata'\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = updates.app_kind\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = attachment.local_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_create_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_move_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.document_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,\n COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM document_move_intents intent\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = intent.local_id\n WHERE intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import { LOCAL_INTENT_LANES } from \"../../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql(\"container\");\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_history_updates\n WHERE update_id IS NOT NULL\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n stored.sync_failure_message AS last_error,\n stored.sync_failure_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n stored.sync_failure_attempted_at AS created_at,\n stored.sync_failure_attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n stored.sync_failure_message AS last_error,\n stored.sync_failure_attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE stored.app_kind = 'documents'\n AND stored.sync_failure_message IS NOT NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n metadata.sync_failure_message AS last_error,\n metadata.sync_failure_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n metadata.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n metadata.sync_failure_attempted_at AS created_at,\n metadata.sync_failure_attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n metadata.sync_failure_message AS last_error,\n metadata.sync_failure_attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM documents metadata\n JOIN containers container ON container.id = metadata.local_id\n WHERE metadata.app_kind = 'container-metadata'\n AND metadata.sync_failure_message IS NOT NULL\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n stored.sync_failure_message AS last_error,\n stored.sync_failure_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n stored.sync_failure_message AS last_error,\n stored.sync_failure_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.subject_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.subject_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM local_intents intent\n LEFT JOIN containers container ON container.id = intent.subject_id\n WHERE intent.lane = '${LOCAL_INTENT_LANES.containerCreate}'\n AND intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.subject_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.subject_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM local_intents intent\n LEFT JOIN containers container ON container.id = intent.subject_id\n WHERE intent.lane = '${LOCAL_INTENT_LANES.containerMove}'\n AND intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.subject_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), stored.sync_failure_message) AS last_error,\n COALESCE(intent.last_attempted_at, stored.sync_failure_attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM local_intents intent\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = intent.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'\n AND intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n stored.sync_failure_message AS last_error,\n stored.sync_failure_attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
@@ -3,7 +3,7 @@ import { sqlDocumentMoveIntentPersistence } from "../../data/persistence/contain
3
3
  import { sqlDocumentsPersistence } from "../../data/persistence/documents/documentsPersistence.js";
4
4
  import { DOCUMENTS_APP_KIND } from "../../data/persistence/documents/internal/constants.js";
5
5
  import { clearDocumentSyncFailure, resetDocumentPendingUpdateRekeyBudget, } from "../../data/sqlite/documentPersistence.js";
6
- import { documentMoveIntentTables, documentTables, } from "../../data/sqlite/schema.js";
6
+ import { documentPlacementIntentTables, documentTables, LOCAL_INTENT_LANES, } from "../../data/sqlite/schema.js";
7
7
  import { ensureSqlTables } from "../../data/sqlite/sqlSchema.js";
8
8
  import { defaultContainerContentsPersistence } from "./containerPersistence.js";
9
9
  import { groupPendingWriteCandidates } from "./pendingWrites/aggregation.js";
@@ -74,7 +74,7 @@ export async function resetPendingWriteRetryState(execSql, input) {
74
74
  async function hasQueuedScopeWork(execSql, scope) {
75
75
  await ensureSqlTables(execSql, [
76
76
  ...documentTables,
77
- ...documentMoveIntentTables,
77
+ ...documentPlacementIntentTables,
78
78
  ]);
79
79
  const rows = await execSql(`SELECT 1 AS present
80
80
  WHERE EXISTS (
@@ -87,8 +87,10 @@ async function hasQueuedScopeWork(execSql, scope) {
87
87
  WHERE attachment.local_id = ?
88
88
  )
89
89
  OR EXISTS (
90
- SELECT 1 FROM document_move_intents intent
91
- WHERE intent.local_id = ? AND intent.intent_type IN ('document.move', 'document.link')
90
+ SELECT 1 FROM local_intents intent
91
+ WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'
92
+ AND intent.local_id = ?
93
+ AND intent.intent_type IN ('document.move', 'document.link')
92
94
  )
93
95
  OR EXISTS (
94
96
  SELECT 1 FROM documents stored
@@ -1 +1 @@
1
- {"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"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","sourcesContent":["import { CONTAINER_METADATA_APP_KIND } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport { DOCUMENTS_APP_KIND } from \"../../data/persistence/documents/internal/constants\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../data/sqlite/documentPersistence\";\nimport {\n documentMoveIntentTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"./containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./pendingWrites/aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./pendingWrites/deferredTails\";\nimport { listPersistedPendingWriteCandidates } from \"./pendingWrites/sources\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_history_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM document_move_intents intent\n WHERE intent.local_id = ? AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
1
+ {"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"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","sourcesContent":["import { CONTAINER_METADATA_APP_KIND } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport { DOCUMENTS_APP_KIND } from \"../../data/persistence/documents/internal/constants\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../data/sqlite/documentPersistence\";\nimport {\n documentPlacementIntentTables,\n documentTables,\n LOCAL_INTENT_LANES,\n} from \"../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"./containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./pendingWrites/aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./pendingWrites/deferredTails\";\nimport { listPersistedPendingWriteCandidates } from \"./pendingWrites/sources\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentPlacementIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_history_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM local_intents intent\n WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'\n AND intent.local_id = ?\n AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
@@ -18,7 +18,8 @@ import { verifyRemoteContainerDestination } from "./remoteHydration/verifiedDest
18
18
  // move — one whose destination parent has not synced yet, the common boot-time
19
19
  // case — is protected too. Pending *metadata*
20
20
  // updates are handled separately (listRemoteContainerIdsWithPendingMetadataUpdates);
21
- // these live in dedicated create/move intent tables that that query does not cover.
21
+ // structural intents live in the local outbox's container lanes, which that
22
+ // query does not cover.
22
23
  export async function listRemoteContainerIdsWithPendingStructuralIntents(input) {
23
24
  if (input.remoteContainers.length === 0) {
24
25
  return new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"remoteContainerState.js","sourceRoot":"","sources":["remoteContainerState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessManifestCheckpoint } from \"@tearleads/crypto\";\nimport {\n heldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../data/containers/containerBinding\";\nimport {\n isKeyingVerificationError,\n runWithSecurityIncidentReporting,\n} from \"../../data/keyingProjectionVerification/error\";\nimport { isProjectionVerificationCancelledError } from \"../../data/keyingProjectionVerification/types\";\nimport type { ContainerHydrationTombstone } from \"./containerPersistence\";\nimport { installContainerMetadataRecord } from \"./metadataPersistence\";\nimport { projectionGeneration } from \"./projectionGeneration\";\nimport {\n moveIndexedContainerChild,\n removeIndexedContainerChild,\n} from \"./remoteHydration/childIndex\";\nimport type { PrefetchedDestinationProjection } from \"./remoteHydration/destinationPrefetch\";\nimport { rebindReHomedContainer } from \"./remoteHydration/heldContainerRebind\";\nimport { insertRemoteContainerState } from \"./remoteHydration/insertRemoteContainer\";\nimport {\n reconcileLocalOnlyRootContainers,\n reconcileLocalOnlySystemContainers,\n} from \"./remoteHydration/reconciliation\";\nimport {\n applyRemoteContainerTimestamps,\n remoteContainerHydrationSaveOptions,\n resolveRemoteContainerHydrationLocalUpdatedAt,\n} from \"./remoteHydration/remoteContainerTimestamps\";\nimport type {\n ContainerChildIndex,\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationHost,\n RemoteContainerHydrationState,\n} from \"./remoteHydration/types\";\nimport { verifyRemoteContainerDestination } from \"./remoteHydration/verifiedDestination\";\n\n// Container ids (restricted to the inbound page) that carry an unsynced local\n// create or move intent. Such a container's parent and local-edit timestamp are\n// owned by its structural-intent lane until that lane reconciles, so inbound\n// hydration must not revert parentId to the server value nor collapse\n// localUpdatedAt — doing so silently undoes a queued move and falsely reads\n// \"synced\". Move intents are read via listUnsyncedMoveIntents so a blocked\n// move — one whose destination parent has not synced yet, the common boot-time\n// case — is protected too. Pending *metadata*\n// updates are handled separately (listRemoteContainerIdsWithPendingMetadataUpdates);\n// these live in dedicated create/move intent tables that that query does not cover.\nexport async function listRemoteContainerIdsWithPendingStructuralIntents(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n if (input.remoteContainers.length === 0) {\n return new Set();\n }\n const remoteContainerIds = new Set(\n input.remoteContainers.map((remoteContainer) => remoteContainer.id),\n );\n\n const execSql = input.state.runtime.infra.execSql;\n const [pendingCreateIntents, unsyncedMoveIntents] = await Promise.all([\n input.state.persistence.listPendingCreateIntents(execSql),\n input.state.persistence.listUnsyncedMoveIntents(execSql),\n ]);\n const containerIdsWithPendingStructuralIntents = new Set<string>();\n for (const intent of pendingCreateIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n for (const intent of unsyncedMoveIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n return containerIdsWithPendingStructuralIntents;\n}\n\nexport async function listRemoteContainerIdsWithPendingMetadataUpdates(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n const containerIds = input.remoteContainers.flatMap((remoteContainer) => {\n const previousLocalUpdatedAt = input.state.containersById.get(\n remoteContainer.id,\n )?.container.localUpdatedAt;\n\n return previousLocalUpdatedAt &&\n previousLocalUpdatedAt.localeCompare(remoteContainer.updatedAt) > 0\n ? [remoteContainer.id]\n : [];\n });\n if (containerIds.length === 0) {\n return new Set();\n }\n\n const execSql = input.state.runtime.infra.execSql;\n return new Set(\n await input.state.persistence.listContainerIdsWithPendingUpdates(\n execSql,\n containerIds,\n ),\n );\n}\n\nfunction removeMissingHydratedContainer(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n existingState: ContainerState;\n host: RemoteContainerHydrationHost;\n previousParentId: string | null;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): void {\n const { existingState, remoteContainer, state } = input;\n if (state.containersById.get(remoteContainer.id) !== existingState) {\n return;\n }\n\n state.containersById.delete(remoteContainer.id);\n if (input.childIdsByParentId) {\n removeIndexedContainerChild(\n input.childIdsByParentId,\n remoteContainer.id,\n input.previousParentId,\n );\n input.childIdsByParentId.delete(remoteContainer.id);\n }\n input.host.updateSnapshot();\n}\n\nfunction createUpdatedRemoteContainerState(\n existingState: ContainerState,\n remoteContainer: RemoteContainer,\n): ContainerState {\n return {\n ...existingState,\n container: applyRemoteContainerTimestamps(\n existingState.container,\n remoteContainer,\n ),\n containerWriterProjection: null,\n metadataReferencedPrincipals: remoteContainer.metadataReferencedPrincipals,\n };\n}\n\nfunction installUpdatedRemoteContainerState(\n existingState: ContainerState,\n nextState: ContainerState,\n host: RemoteContainerHydrationHost,\n): void {\n const wasLocalOnly = existingState.container.serverCreatedAt == null;\n existingState.container = nextState.container;\n existingState.containerWriterProjection = nextState.containerWriterProjection;\n existingState.metadataReferencedPrincipals =\n nextState.metadataReferencedPrincipals;\n // The snapshot copied the live generation when it was taken; a hint that\n // landed during the persist leaves the live metadata projection dropped.\n if (projectionGeneration(existingState) === projectionGeneration(nextState))\n existingState.metadataWriterProjection = nextState.metadataWriterProjection;\n installContainerMetadataRecord(existingState, nextState.record);\n // A document pass may have deferred while this root was awaiting proof.\n // The first durable remote acknowledgement makes its pending creates runnable.\n if (wasLocalOnly && existingState.container.serverCreatedAt != null)\n host.requestDocumentPriming?.();\n}\n\nasync function updateExistingRemoteContainerState(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n isCurrent?: (() => boolean) | undefined;\n existingState: ContainerState;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): Promise<ContainerState | null> {\n const { childIdsByParentId, existingState, host, remoteContainer, state } =\n input;\n const previousParentId = existingState.container.parentId;\n const previousLocalUpdatedAt = existingState.container.localUpdatedAt;\n // A queued, not-yet-synced local move/create owns this container's parent\n // until its intent lane reconciles. Omit the remote parent when the page scan\n // saw one; persistence also rechecks the intent transactionally so a move\n // created after that scan wins. Both paths preserve the durable local clock.\n const hasPendingStructuralIntent =\n input.containerIdsWithPendingStructuralIntents.has(remoteContainer.id);\n const nextParentId = hasPendingStructuralIntent\n ? undefined\n : remoteContainer.parentId;\n const localUpdatedAt = resolveRemoteContainerHydrationLocalUpdatedAt({\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n hasPendingStructuralIntent,\n previousLocalUpdatedAt,\n remoteContainer,\n });\n const nextState = createUpdatedRemoteContainerState(\n existingState,\n remoteContainer,\n );\n const persistenceResult = await host.persistContainerState(\n nextState,\n {\n accessEpoch: remoteContainer.metadataAccessEpoch,\n accessStateHash: remoteContainer.metadataAccessStateHash,\n documentId: remoteContainer.metadataDocumentId,\n effectiveAccessLevel: remoteContainer.effectiveAccessLevel,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n systemSlot: remoteContainer.systemSlot ?? null,\n organizationId: remoteContainer.organizationId,\n ...(nextParentId !== undefined ? { parentId: nextParentId } : {}),\n },\n false,\n remoteContainerHydrationSaveOptions({\n localUpdatedAt,\n remoteContainer,\n }),\n {\n preserveDurableStructureWhenPending: true,\n },\n );\n if (persistenceResult.status === \"missing\") {\n // Hydration persists a detached candidate so an in-flight response cannot\n // mutate mapped state before its guards settle. Retire the exact state this\n // hydration read because store-level reference cleanup cannot see the clone.\n removeMissingHydratedContainer({\n childIdsByParentId,\n existingState,\n host,\n previousParentId,\n remoteContainer,\n state,\n });\n return null;\n }\n if (persistenceResult.status !== \"persisted\") return null;\n const { record: nextRecord } = persistenceResult;\n installContainerMetadataRecord(nextState, nextRecord);\n if (input.isCurrent?.() === false) {\n return existingState;\n }\n nextState.container = {\n ...nextState.container,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n organizationId: remoteContainer.organizationId,\n parentId: nextState.container.parentId,\n };\n\n installUpdatedRemoteContainerState(existingState, nextState, host);\n moveIndexedContainerChild(\n childIdsByParentId,\n remoteContainer.id,\n previousParentId,\n existingState.container.parentId,\n );\n await reconcileLocalOnlyRootContainers({\n childIdsByParentId,\n isCurrent: input.isCurrent,\n remoteRootState: existingState,\n requestDocumentPriming: host.requestDocumentPriming,\n state,\n });\n return existingState;\n}\n\ninterface UpsertRemoteContainerStateInput {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n expectedHydrationTombstone?: ContainerHydrationTombstone | null | undefined;\n isCurrent?: (() => boolean) | undefined;\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}\n\nexport async function upsertRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n let expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n const heldState = input.state.containersById.get(input.remoteContainer.id);\n const heldBinding = heldState\n ? heldContainerBinding(heldState)\n : await input.state.persistence.loadHeldContainerBinding(\n input.state.runtime.infra.execSql,\n input.remoteContainer.id,\n );\n const listed = input.remoteContainer;\n // A folder re-homed away from the listed organization never returns there,\n // whatever binding (possibly none, after a reset) the device holds now.\n const supersededListing =\n !listingRepeatsHeldOrdinaryBinding(heldBinding, listed) &&\n (await input.state.persistence.isSupersededContainerBinding(\n input.state.runtime.infra.execSql,\n { containerId: listed.id, organizationId: listed.organizationId },\n ));\n if (input.isCurrent?.() === false) return null;\n const verified = await verifyRemoteContainerDestination({\n ...input,\n heldBinding,\n supersededListing,\n refresh: !!input.expectedHydrationTombstone,\n onVerifiedCheckpoint: (checkpoint) => {\n expectedPlacementCheckpoint = checkpoint;\n },\n });\n if (!verified || input.isCurrent?.() === false) return null;\n input = { ...input, remoteContainer: verified };\n const existingState = input.state.containersById.get(\n input.remoteContainer.id,\n );\n const remoteState = await runWithSecurityIncidentReporting(\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: verified.id,\n objectKind: \"container\",\n operation: \"container.binding.persist\",\n organizationId: verified.organizationId,\n },\n async () =>\n (await rebindReHomedContainer({\n existingState,\n heldBinding,\n isCurrent: input.isCurrent,\n state: input.state,\n verified,\n }))\n ? persistVerifiedRemoteContainer({\n ...input,\n existingState,\n expectedPlacementCheckpoint,\n })\n : null,\n );\n if (!remoteState) {\n return null;\n }\n await reconcileLocalOnlySystemContainers({\n childIdsByParentId: input.childIdsByParentId,\n isCurrent: input.isCurrent,\n requestDocumentPriming: input.host.requestDocumentPriming,\n remoteSystemState: remoteState,\n state: input.state,\n });\n return remoteState;\n}\n\n/**\n * Upsert one listed folder, isolating a rejected proof or binding. The refusal\n * was already reported; returning no state leaves the item unapplied without\n * blocking independent folders.\n */\nexport async function upsertIsolatedRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n try {\n return await upsertRemoteContainerState(input);\n } catch (error) {\n if (\n !isKeyingVerificationError(error) &&\n !isProjectionVerificationCancelledError(error)\n )\n throw error;\n return null;\n }\n}\n\nfunction persistVerifiedRemoteContainer(\n input: UpsertRemoteContainerStateInput & {\n existingState: ContainerState | undefined;\n expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n },\n): Promise<ContainerState | null> {\n const { existingState, expectedPlacementCheckpoint } = input;\n return existingState\n ? updateExistingRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n containerIdsWithPendingStructuralIntents:\n input.containerIdsWithPendingStructuralIntents,\n existingState,\n host: input.host,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n })\n : insertRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n host: input.host,\n expectedHydrationTombstone: input.expectedHydrationTombstone ?? null,\n expectedPlacementCheckpoint,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n });\n}\n"]}
1
+ {"version":3,"file":"remoteContainerState.js","sourceRoot":"","sources":["remoteContainerState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessManifestCheckpoint } from \"@tearleads/crypto\";\nimport {\n heldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../data/containers/containerBinding\";\nimport {\n isKeyingVerificationError,\n runWithSecurityIncidentReporting,\n} from \"../../data/keyingProjectionVerification/error\";\nimport { isProjectionVerificationCancelledError } from \"../../data/keyingProjectionVerification/types\";\nimport type { ContainerHydrationTombstone } from \"./containerPersistence\";\nimport { installContainerMetadataRecord } from \"./metadataPersistence\";\nimport { projectionGeneration } from \"./projectionGeneration\";\nimport {\n moveIndexedContainerChild,\n removeIndexedContainerChild,\n} from \"./remoteHydration/childIndex\";\nimport type { PrefetchedDestinationProjection } from \"./remoteHydration/destinationPrefetch\";\nimport { rebindReHomedContainer } from \"./remoteHydration/heldContainerRebind\";\nimport { insertRemoteContainerState } from \"./remoteHydration/insertRemoteContainer\";\nimport {\n reconcileLocalOnlyRootContainers,\n reconcileLocalOnlySystemContainers,\n} from \"./remoteHydration/reconciliation\";\nimport {\n applyRemoteContainerTimestamps,\n remoteContainerHydrationSaveOptions,\n resolveRemoteContainerHydrationLocalUpdatedAt,\n} from \"./remoteHydration/remoteContainerTimestamps\";\nimport type {\n ContainerChildIndex,\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationHost,\n RemoteContainerHydrationState,\n} from \"./remoteHydration/types\";\nimport { verifyRemoteContainerDestination } from \"./remoteHydration/verifiedDestination\";\n\n// Container ids (restricted to the inbound page) that carry an unsynced local\n// create or move intent. Such a container's parent and local-edit timestamp are\n// owned by its structural-intent lane until that lane reconciles, so inbound\n// hydration must not revert parentId to the server value nor collapse\n// localUpdatedAt — doing so silently undoes a queued move and falsely reads\n// \"synced\". Move intents are read via listUnsyncedMoveIntents so a blocked\n// move — one whose destination parent has not synced yet, the common boot-time\n// case — is protected too. Pending *metadata*\n// updates are handled separately (listRemoteContainerIdsWithPendingMetadataUpdates);\n// structural intents live in the local outbox's container lanes, which that\n// query does not cover.\nexport async function listRemoteContainerIdsWithPendingStructuralIntents(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n if (input.remoteContainers.length === 0) {\n return new Set();\n }\n const remoteContainerIds = new Set(\n input.remoteContainers.map((remoteContainer) => remoteContainer.id),\n );\n\n const execSql = input.state.runtime.infra.execSql;\n const [pendingCreateIntents, unsyncedMoveIntents] = await Promise.all([\n input.state.persistence.listPendingCreateIntents(execSql),\n input.state.persistence.listUnsyncedMoveIntents(execSql),\n ]);\n const containerIdsWithPendingStructuralIntents = new Set<string>();\n for (const intent of pendingCreateIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n for (const intent of unsyncedMoveIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n return containerIdsWithPendingStructuralIntents;\n}\n\nexport async function listRemoteContainerIdsWithPendingMetadataUpdates(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n const containerIds = input.remoteContainers.flatMap((remoteContainer) => {\n const previousLocalUpdatedAt = input.state.containersById.get(\n remoteContainer.id,\n )?.container.localUpdatedAt;\n\n return previousLocalUpdatedAt &&\n previousLocalUpdatedAt.localeCompare(remoteContainer.updatedAt) > 0\n ? [remoteContainer.id]\n : [];\n });\n if (containerIds.length === 0) {\n return new Set();\n }\n\n const execSql = input.state.runtime.infra.execSql;\n return new Set(\n await input.state.persistence.listContainerIdsWithPendingUpdates(\n execSql,\n containerIds,\n ),\n );\n}\n\nfunction removeMissingHydratedContainer(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n existingState: ContainerState;\n host: RemoteContainerHydrationHost;\n previousParentId: string | null;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): void {\n const { existingState, remoteContainer, state } = input;\n if (state.containersById.get(remoteContainer.id) !== existingState) {\n return;\n }\n\n state.containersById.delete(remoteContainer.id);\n if (input.childIdsByParentId) {\n removeIndexedContainerChild(\n input.childIdsByParentId,\n remoteContainer.id,\n input.previousParentId,\n );\n input.childIdsByParentId.delete(remoteContainer.id);\n }\n input.host.updateSnapshot();\n}\n\nfunction createUpdatedRemoteContainerState(\n existingState: ContainerState,\n remoteContainer: RemoteContainer,\n): ContainerState {\n return {\n ...existingState,\n container: applyRemoteContainerTimestamps(\n existingState.container,\n remoteContainer,\n ),\n containerWriterProjection: null,\n metadataReferencedPrincipals: remoteContainer.metadataReferencedPrincipals,\n };\n}\n\nfunction installUpdatedRemoteContainerState(\n existingState: ContainerState,\n nextState: ContainerState,\n host: RemoteContainerHydrationHost,\n): void {\n const wasLocalOnly = existingState.container.serverCreatedAt == null;\n existingState.container = nextState.container;\n existingState.containerWriterProjection = nextState.containerWriterProjection;\n existingState.metadataReferencedPrincipals =\n nextState.metadataReferencedPrincipals;\n // The snapshot copied the live generation when it was taken; a hint that\n // landed during the persist leaves the live metadata projection dropped.\n if (projectionGeneration(existingState) === projectionGeneration(nextState))\n existingState.metadataWriterProjection = nextState.metadataWriterProjection;\n installContainerMetadataRecord(existingState, nextState.record);\n // A document pass may have deferred while this root was awaiting proof.\n // The first durable remote acknowledgement makes its pending creates runnable.\n if (wasLocalOnly && existingState.container.serverCreatedAt != null)\n host.requestDocumentPriming?.();\n}\n\nasync function updateExistingRemoteContainerState(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n isCurrent?: (() => boolean) | undefined;\n existingState: ContainerState;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): Promise<ContainerState | null> {\n const { childIdsByParentId, existingState, host, remoteContainer, state } =\n input;\n const previousParentId = existingState.container.parentId;\n const previousLocalUpdatedAt = existingState.container.localUpdatedAt;\n // A queued, not-yet-synced local move/create owns this container's parent\n // until its intent lane reconciles. Omit the remote parent when the page scan\n // saw one; persistence also rechecks the intent transactionally so a move\n // created after that scan wins. Both paths preserve the durable local clock.\n const hasPendingStructuralIntent =\n input.containerIdsWithPendingStructuralIntents.has(remoteContainer.id);\n const nextParentId = hasPendingStructuralIntent\n ? undefined\n : remoteContainer.parentId;\n const localUpdatedAt = resolveRemoteContainerHydrationLocalUpdatedAt({\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n hasPendingStructuralIntent,\n previousLocalUpdatedAt,\n remoteContainer,\n });\n const nextState = createUpdatedRemoteContainerState(\n existingState,\n remoteContainer,\n );\n const persistenceResult = await host.persistContainerState(\n nextState,\n {\n accessEpoch: remoteContainer.metadataAccessEpoch,\n accessStateHash: remoteContainer.metadataAccessStateHash,\n documentId: remoteContainer.metadataDocumentId,\n effectiveAccessLevel: remoteContainer.effectiveAccessLevel,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n systemSlot: remoteContainer.systemSlot ?? null,\n organizationId: remoteContainer.organizationId,\n ...(nextParentId !== undefined ? { parentId: nextParentId } : {}),\n },\n false,\n remoteContainerHydrationSaveOptions({\n localUpdatedAt,\n remoteContainer,\n }),\n {\n preserveDurableStructureWhenPending: true,\n },\n );\n if (persistenceResult.status === \"missing\") {\n // Hydration persists a detached candidate so an in-flight response cannot\n // mutate mapped state before its guards settle. Retire the exact state this\n // hydration read because store-level reference cleanup cannot see the clone.\n removeMissingHydratedContainer({\n childIdsByParentId,\n existingState,\n host,\n previousParentId,\n remoteContainer,\n state,\n });\n return null;\n }\n if (persistenceResult.status !== \"persisted\") return null;\n const { record: nextRecord } = persistenceResult;\n installContainerMetadataRecord(nextState, nextRecord);\n if (input.isCurrent?.() === false) {\n return existingState;\n }\n nextState.container = {\n ...nextState.container,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n organizationId: remoteContainer.organizationId,\n parentId: nextState.container.parentId,\n };\n\n installUpdatedRemoteContainerState(existingState, nextState, host);\n moveIndexedContainerChild(\n childIdsByParentId,\n remoteContainer.id,\n previousParentId,\n existingState.container.parentId,\n );\n await reconcileLocalOnlyRootContainers({\n childIdsByParentId,\n isCurrent: input.isCurrent,\n remoteRootState: existingState,\n requestDocumentPriming: host.requestDocumentPriming,\n state,\n });\n return existingState;\n}\n\ninterface UpsertRemoteContainerStateInput {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n expectedHydrationTombstone?: ContainerHydrationTombstone | null | undefined;\n isCurrent?: (() => boolean) | undefined;\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}\n\nexport async function upsertRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n let expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n const heldState = input.state.containersById.get(input.remoteContainer.id);\n const heldBinding = heldState\n ? heldContainerBinding(heldState)\n : await input.state.persistence.loadHeldContainerBinding(\n input.state.runtime.infra.execSql,\n input.remoteContainer.id,\n );\n const listed = input.remoteContainer;\n // A folder re-homed away from the listed organization never returns there,\n // whatever binding (possibly none, after a reset) the device holds now.\n const supersededListing =\n !listingRepeatsHeldOrdinaryBinding(heldBinding, listed) &&\n (await input.state.persistence.isSupersededContainerBinding(\n input.state.runtime.infra.execSql,\n { containerId: listed.id, organizationId: listed.organizationId },\n ));\n if (input.isCurrent?.() === false) return null;\n const verified = await verifyRemoteContainerDestination({\n ...input,\n heldBinding,\n supersededListing,\n refresh: !!input.expectedHydrationTombstone,\n onVerifiedCheckpoint: (checkpoint) => {\n expectedPlacementCheckpoint = checkpoint;\n },\n });\n if (!verified || input.isCurrent?.() === false) return null;\n input = { ...input, remoteContainer: verified };\n const existingState = input.state.containersById.get(\n input.remoteContainer.id,\n );\n const remoteState = await runWithSecurityIncidentReporting(\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: verified.id,\n objectKind: \"container\",\n operation: \"container.binding.persist\",\n organizationId: verified.organizationId,\n },\n async () =>\n (await rebindReHomedContainer({\n existingState,\n heldBinding,\n isCurrent: input.isCurrent,\n state: input.state,\n verified,\n }))\n ? persistVerifiedRemoteContainer({\n ...input,\n existingState,\n expectedPlacementCheckpoint,\n })\n : null,\n );\n if (!remoteState) {\n return null;\n }\n await reconcileLocalOnlySystemContainers({\n childIdsByParentId: input.childIdsByParentId,\n isCurrent: input.isCurrent,\n requestDocumentPriming: input.host.requestDocumentPriming,\n remoteSystemState: remoteState,\n state: input.state,\n });\n return remoteState;\n}\n\n/**\n * Upsert one listed folder, isolating a rejected proof or binding. The refusal\n * was already reported; returning no state leaves the item unapplied without\n * blocking independent folders.\n */\nexport async function upsertIsolatedRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n try {\n return await upsertRemoteContainerState(input);\n } catch (error) {\n if (\n !isKeyingVerificationError(error) &&\n !isProjectionVerificationCancelledError(error)\n )\n throw error;\n return null;\n }\n}\n\nfunction persistVerifiedRemoteContainer(\n input: UpsertRemoteContainerStateInput & {\n existingState: ContainerState | undefined;\n expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n },\n): Promise<ContainerState | null> {\n const { existingState, expectedPlacementCheckpoint } = input;\n return existingState\n ? updateExistingRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n containerIdsWithPendingStructuralIntents:\n input.containerIdsWithPendingStructuralIntents,\n existingState,\n host: input.host,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n })\n : insertRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n host: input.host,\n expectedHydrationTombstone: input.expectedHydrationTombstone ?? null,\n expectedPlacementCheckpoint,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n });\n}\n"]}