codex-overleaf-link 2.2.1 → 2.3.0

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 (71) hide show
  1. package/README.md +25 -23
  2. package/extension/bootstrap/manifest.template.json +1 -1
  3. package/extension/runtime-manifest.json +5 -71
  4. package/extension/src/background.js +53 -69
  5. package/extension/src/backgroundUpdateCoordinator.js +128 -66
  6. package/extension/src/content/applyResultFormatters.js +2 -3
  7. package/extension/src/content/contentRuntime.js +650 -1449
  8. package/extension/src/content/contextTray.js +4 -6
  9. package/extension/src/content/diagnosticsController.js +1 -2
  10. package/extension/src/content/diffReviewPanel.js +14 -13
  11. package/extension/src/content/generated/content.bundle.js +41370 -0
  12. package/extension/src/content/generated/content.bundle.meta.json +102 -0
  13. package/extension/src/content/legacyGlobalRegistry.js +129 -0
  14. package/extension/src/content/markdownText.js +5 -7
  15. package/extension/src/content/modelPicker.js +1 -1
  16. package/extension/src/content/modelPickerSupport.js +10 -5
  17. package/extension/src/content/moduleRegistryKernel.js +125 -0
  18. package/extension/src/content/nativeCompatibilityController.js +313 -0
  19. package/extension/src/content/otWarmMirror.js +7 -5
  20. package/extension/src/content/pageBridgeClient.js +224 -0
  21. package/extension/src/content/panelMaintenance.js +8 -3
  22. package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
  23. package/extension/src/content/projectProviderSelection.js +4 -12
  24. package/extension/src/content/projectSessionCleanup.js +3 -3
  25. package/extension/src/content/providerSettingsCoordinator.js +59 -26
  26. package/extension/src/content/providerSettingsDialog.js +30 -18
  27. package/extension/src/content/recentProjects.js +15 -23
  28. package/extension/src/content/runGuidanceController.js +1 -1
  29. package/extension/src/content/runQueueScheduler.js +129 -29
  30. package/extension/src/content/runSettlementPersistence.js +51 -0
  31. package/extension/src/content/runTimelineView.js +11 -8
  32. package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
  33. package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
  34. package/extension/src/content/scopedPersistencePanelState.js +111 -0
  35. package/extension/src/content/sessionManager.js +15 -12
  36. package/extension/src/content/sessionPersistence.js +67 -8
  37. package/extension/src/content/updateNotice.js +10 -4
  38. package/extension/src/content/writebackOrchestrator.js +91 -23
  39. package/extension/src/contentScript.js +5 -1
  40. package/extension/src/page/trackedChangesLifecycle.js +6 -1
  41. package/extension/src/pageBridge.js +47 -98
  42. package/extension/src/shared/agentTranscript.js +8 -5
  43. package/extension/src/shared/compatibility.js +1 -1
  44. package/extension/src/shared/governanceRules.js +1 -1
  45. package/extension/src/shared/managedUpdateProjection.js +337 -0
  46. package/extension/src/shared/nativeRequestIdentity.js +60 -0
  47. package/extension/src/shared/otText.js +0 -19
  48. package/extension/src/shared/pageRpcContract.js +136 -0
  49. package/extension/src/shared/runExecutionSnapshot.js +177 -0
  50. package/extension/src/shared/runExecutionSnapshotCodec.js +168 -0
  51. package/extension/src/shared/runInputQueue.js +81 -34
  52. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
  53. package/extension/src/shared/scopedPersistenceQueuePolicy.js +181 -0
  54. package/extension/src/shared/scopedPersistenceTransaction.js +238 -0
  55. package/extension/src/shared/sessionState.js +64 -48
  56. package/extension/src/shared/settlementFacts.js +351 -0
  57. package/extension/src/shared/storageDb.js +19 -5
  58. package/extension/src/shared/storageMigration.js +275 -61
  59. package/extension/src/shared/storageSessionClaims.js +60 -0
  60. package/extension/src/shared/updateConsent.js +4 -0
  61. package/extension/src/shared/updateRevocationIntent.js +109 -0
  62. package/extension/src/shared/writebackEvidenceProjection.js +150 -0
  63. package/extension/src/shared/writebackOperationEvidence.js +143 -0
  64. package/extension/src/shared/writebackSettlement.js +705 -0
  65. package/native-host/src/codexRuntimeIdentity.js +1 -1
  66. package/native-host/src/codexSessionRunner.js +7 -13
  67. package/native-host/src/index.js +3 -69
  68. package/native-host/src/managedInstall.js +50 -8
  69. package/native-host/src/nativeTransportEnvelope.js +148 -0
  70. package/native-host/src/taskRunnerRuntime.js +3 -3
  71. package/package.json +13 -5
@@ -1,10 +1,10 @@
1
1
  (function initStorageMigration(root, factory) {
2
2
  if (typeof module === 'object' && module.exports) {
3
- module.exports = factory();
3
+ module.exports = factory(require('./storageDb'));
4
4
  } else {
5
- root.CodexOverleafStorageMigration = factory();
5
+ root.CodexOverleafModuleRegistry.define('StorageMigration', ['StorageDb'], factory);
6
6
  }
7
- })(typeof globalThis !== 'undefined' ? globalThis : window, function storageMigrationFactory() {
7
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function storageMigrationFactory(StorageDb) {
8
8
  'use strict';
9
9
 
10
10
  var PREFS_KEY = 'codexOverleafPrefs';
@@ -13,74 +13,249 @@
13
13
  var MAX_DELETED_SESSION_IDS_PER_PROJECT = 100;
14
14
  var CUSTOM_INSTRUCTIONS_MAX_CHARS = 12000;
15
15
  var PROJECT_PREF_KEY_MAX_CHARS = 160;
16
+ var PROJECT_SCOPED_PREF_MAPS = [
17
+ 'activeSessionByProject',
18
+ 'experimentalOtByProject',
19
+ 'customInstructionsByProject',
20
+ 'governanceRulesByProject',
21
+ 'selectedLocalSkillIdsByProject'
22
+ ];
23
+ var projectPreferenceLockTails = {};
16
24
 
17
- function runMigrationIfNeeded(projectId, legacyStorageKey) {
18
- var StorageDb = (typeof window !== 'undefined' && window.CodexOverleafStorageDb)
19
- ? window.CodexOverleafStorageDb
20
- : require('./storageDb');
21
- return chrome.storage.local.get(null).then(function (stored) {
22
- var prefs = normalizePrefs(stored[PREFS_KEY] || {});
23
- var tombstones = collectSessionTombstones(stored);
24
- var deletedSessionIds = getDeletedSessionIds(tombstones, projectId);
25
- var schemaVersion = prefs.storageSchemaVersion || 0;
26
-
27
- if (schemaVersion >= StorageDb.TARGET_SCHEMA_VERSION) {
28
- var activeSessionByProject = prefs.activeSessionByProject || {};
29
- var activeSessionId = activeSessionByProject[projectId] || '';
30
- return StorageDb.getAllByIndex('sessions', 'projectId', projectId).then(function (sessions) {
31
- var visibleSessions = sessions.filter(function (session) {
32
- return deletedSessionIds.indexOf(session && session.id) === -1;
33
- });
34
- return { prefs: prefs, sessions: visibleSessions, activeSessionId: activeSessionId, migrated: false };
35
- });
25
+ function buildScopedProjectPreferenceKey(accountScopeId, projectId) {
26
+ var account = compactScopePart(accountScopeId);
27
+ var project = compactScopePart(projectId);
28
+ return account && project ? 'account:' + account + ':project:' + project : '';
29
+ }
30
+
31
+ function compactScopePart(value) {
32
+ var text = normalizeTextField(value, PROJECT_PREF_KEY_MAX_CHARS);
33
+ if (!text) {
34
+ return '';
35
+ }
36
+ var encoded = encodeURIComponent(text);
37
+ if (encoded.length <= 64) {
38
+ return encoded;
39
+ }
40
+ return encoded.slice(0, 48) + '-' + hashText(encoded);
41
+ }
42
+
43
+ function hashText(value) {
44
+ var hash = 2166136261;
45
+ for (var i = 0; i < value.length; i++) {
46
+ hash ^= value.charCodeAt(i);
47
+ hash = Math.imul(hash, 16777619);
48
+ }
49
+ return (hash >>> 0).toString(36);
50
+ }
51
+
52
+ function withProjectPreferenceLock(projectId, work) {
53
+ var lockName = 'codex-overleaf-project-prefs:' + compactScopePart(projectId);
54
+ var lockManager = typeof navigator !== 'undefined' && navigator && navigator.locks;
55
+ if (lockManager && typeof lockManager.request === 'function') {
56
+ return lockManager.request(lockName, work);
57
+ }
58
+ var previous = projectPreferenceLockTails[lockName] || Promise.resolve();
59
+ var current = previous.then(work, work);
60
+ projectPreferenceLockTails[lockName] = current;
61
+ return current.finally(function () {
62
+ if (projectPreferenceLockTails[lockName] === current) {
63
+ delete projectPreferenceLockTails[lockName];
36
64
  }
65
+ });
66
+ }
37
67
 
38
- // Migration v0 → v1
39
- var legacyBlob = stored[legacyStorageKey] || {};
40
- var legacySessions = Array.isArray(legacyBlob.sessions) ? legacyBlob.sessions : [];
41
- var migratedSessions = [];
42
-
43
- for (var i = 0; i < legacySessions.length; i++) {
44
- var legacy = legacySessions[i];
45
- if (!legacy || !legacy.id) { continue; }
46
- if (deletedSessionIds.indexOf(legacy.id) !== -1) { continue; }
47
- var record = StorageDb.buildSessionRecord(
48
- buildLegacySessionRecordInput(projectId, legacyBlob, legacy)
49
- );
50
- migratedSessions.push(record);
68
+ function copyPreferenceValue(value) {
69
+ if (!value || typeof value !== 'object') {
70
+ return value;
71
+ }
72
+ try {
73
+ return JSON.parse(JSON.stringify(value));
74
+ } catch (_error) {
75
+ return value;
76
+ }
77
+ }
78
+
79
+ function claimLegacyProjectPreferences(prefs, accountScopeId, projectId) {
80
+ var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
81
+ var next = normalizePrefs(prefs);
82
+ var changed = false;
83
+ PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
84
+ var source = next[mapName] && typeof next[mapName] === 'object'
85
+ ? Object.assign({}, next[mapName])
86
+ : {};
87
+ if (Object.prototype.hasOwnProperty.call(source, projectId)) {
88
+ if (!Object.prototype.hasOwnProperty.call(source, scopedKey)) {
89
+ source[scopedKey] = copyPreferenceValue(source[projectId]);
90
+ }
91
+ delete source[projectId];
92
+ changed = true;
93
+ }
94
+ next[mapName] = source;
95
+ });
96
+ return { prefs: next, changed: changed };
97
+ }
98
+
99
+ function buildProjectPreferenceView(prefs, accountScopeId, projectId) {
100
+ var source = normalizePrefs(prefs);
101
+ var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
102
+ var view = Object.assign({}, source);
103
+ PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
104
+ var sourceMap = source[mapName] && typeof source[mapName] === 'object'
105
+ ? source[mapName]
106
+ : {};
107
+ var projectMap = {};
108
+ if (Object.prototype.hasOwnProperty.call(sourceMap, scopedKey)) {
109
+ projectMap[projectId] = copyPreferenceValue(sourceMap[scopedKey]);
51
110
  }
111
+ view[mapName] = projectMap;
112
+ });
113
+ return normalizePrefs(view);
114
+ }
52
115
 
53
- var putPromise = migratedSessions.length
54
- ? StorageDb.putRecords('sessions', migratedSessions)
55
- : Promise.resolve([]);
116
+ function mergeScopedProjectPreferences(existingPrefs, incomingPrefs, accountScopeId, projectId) {
117
+ var existing = normalizePrefs(existingPrefs);
118
+ var incoming = normalizePrefs(incomingPrefs);
119
+ var scopedKey = buildScopedProjectPreferenceKey(accountScopeId, projectId);
120
+ var next = Object.assign({}, existing, incoming);
121
+ PROJECT_SCOPED_PREF_MAPS.forEach(function (mapName) {
122
+ var storedMap = existing[mapName] && typeof existing[mapName] === 'object'
123
+ ? Object.assign({}, existing[mapName])
124
+ : {};
125
+ var incomingMap = incoming[mapName] && typeof incoming[mapName] === 'object'
126
+ ? incoming[mapName]
127
+ : {};
128
+ if (Object.prototype.hasOwnProperty.call(incomingMap, projectId)) {
129
+ storedMap[scopedKey] = copyPreferenceValue(incomingMap[projectId]);
130
+ }
131
+ delete storedMap[projectId];
132
+ next[mapName] = storedMap;
133
+ });
134
+ return normalizePrefs(next);
135
+ }
56
136
 
57
- return putPromise.then(function () {
58
- var newPrefs = StorageDb.extractLightweightPrefs(legacyBlob, projectId);
59
- newPrefs.activeSessionByProject = StorageDb.buildActiveSessionByProject(
60
- {},
61
- projectId,
62
- legacyBlob.activeSessionId || (migratedSessions.length ? migratedSessions[migratedSessions.length - 1].id : '')
137
+ function runMigrationIfNeeded(projectId, legacyStorageKey, accountScopeId) {
138
+ projectId = normalizeProjectPrefKey(projectId);
139
+ var normalizedAccountScopeId = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
140
+ if (!normalizedAccountScopeId || !projectId) {
141
+ return Promise.resolve({
142
+ prefs: normalizePrefs({}),
143
+ sessions: [],
144
+ activeSessionId: '',
145
+ migrated: false,
146
+ reason: 'account_scope_unavailable'
147
+ });
148
+ }
149
+ return withProjectPreferenceLock(projectId, function () {
150
+ return chrome.storage.local.get(null).then(function (stored) {
151
+ var claimed = claimLegacyProjectPreferences(
152
+ stored[PREFS_KEY] || {},
153
+ normalizedAccountScopeId,
154
+ projectId
63
155
  );
64
- newPrefs = normalizePrefs(newPrefs);
65
-
66
- return chrome.storage.local.set({ [PREFS_KEY]: newPrefs }).then(function () {
67
- return chrome.storage.local.remove(legacyStorageKey).catch(function () {});
68
- }).then(function () {
69
- return {
70
- prefs: newPrefs,
71
- sessions: migratedSessions,
72
- activeSessionId: newPrefs.activeSessionByProject[projectId] || '',
73
- migrated: true
74
- };
156
+ var storedPrefs = claimed.prefs;
157
+ var persistClaim = claimed.changed
158
+ ? chrome.storage.local.set({ [PREFS_KEY]: storedPrefs })
159
+ : Promise.resolve();
160
+ return persistClaim.then(function () {
161
+ var prefs = buildProjectPreferenceView(
162
+ storedPrefs,
163
+ normalizedAccountScopeId,
164
+ projectId
165
+ );
166
+ var tombstones = collectSessionTombstones(stored);
167
+ var deletedSessionIds = getDeletedSessionIds(tombstones, projectId);
168
+ var schemaVersion = prefs.storageSchemaVersion || 0;
169
+
170
+ if (schemaVersion >= StorageDb.TARGET_SCHEMA_VERSION) {
171
+ var activeSessionByProject = prefs.activeSessionByProject || {};
172
+ var activeSessionId = activeSessionByProject[projectId] || '';
173
+ if (typeof StorageDb.claimSessionsForAccount !== 'function') {
174
+ return Promise.reject(Object.assign(
175
+ new Error('Atomic legacy-session claiming is unavailable.'),
176
+ { code: 'scoped_claim_unavailable' }
177
+ ));
178
+ }
179
+ return StorageDb.claimSessionsForAccount(
180
+ projectId,
181
+ normalizedAccountScopeId,
182
+ deletedSessionIds
183
+ ).then(function (visibleSessions) {
184
+ var visibleActiveSessionId = visibleSessions.some(function (session) {
185
+ return session && session.id === activeSessionId;
186
+ })
187
+ ? activeSessionId
188
+ : visibleSessions.length
189
+ ? visibleSessions[visibleSessions.length - 1].id
190
+ : '';
191
+ return {
192
+ prefs: prefs,
193
+ sessions: visibleSessions,
194
+ activeSessionId: visibleActiveSessionId,
195
+ migrated: false
196
+ };
197
+ });
198
+ }
199
+
200
+ // Migration v0 → v1
201
+ var legacyBlob = stored[legacyStorageKey] || {};
202
+ var legacySessions = Array.isArray(legacyBlob.sessions) ? legacyBlob.sessions : [];
203
+ var migratedSessions = [];
204
+
205
+ for (var i = 0; i < legacySessions.length; i++) {
206
+ var legacy = legacySessions[i];
207
+ if (!legacy || !legacy.id) { continue; }
208
+ if (deletedSessionIds.indexOf(legacy.id) !== -1) { continue; }
209
+ var record = StorageDb.buildSessionRecord(
210
+ buildLegacySessionRecordInput(projectId, legacyBlob, legacy, normalizedAccountScopeId)
211
+ );
212
+ migratedSessions.push(record);
213
+ }
214
+
215
+ var putPromise = migratedSessions.length
216
+ ? StorageDb.putRecords('sessions', migratedSessions)
217
+ : Promise.resolve([]);
218
+
219
+ return putPromise.then(function () {
220
+ var newPrefs = StorageDb.extractLightweightPrefs(legacyBlob, projectId);
221
+ newPrefs.activeSessionByProject = StorageDb.buildActiveSessionByProject(
222
+ {},
223
+ projectId,
224
+ legacyBlob.activeSessionId || (migratedSessions.length ? migratedSessions[migratedSessions.length - 1].id : '')
225
+ );
226
+ var mergedPrefs = mergeScopedProjectPreferences(
227
+ storedPrefs,
228
+ newPrefs,
229
+ normalizedAccountScopeId,
230
+ projectId
231
+ );
232
+ var prefsView = buildProjectPreferenceView(
233
+ mergedPrefs,
234
+ normalizedAccountScopeId,
235
+ projectId
236
+ );
237
+
238
+ return chrome.storage.local.set({ [PREFS_KEY]: mergedPrefs }).then(function () {
239
+ return chrome.storage.local.remove(legacyStorageKey).catch(function () {});
240
+ }).then(function () {
241
+ return {
242
+ prefs: prefsView,
243
+ sessions: migratedSessions,
244
+ activeSessionId: prefsView.activeSessionByProject[projectId] || '',
245
+ migrated: true
246
+ };
247
+ });
248
+ });
75
249
  });
76
250
  });
77
251
  });
78
252
  }
79
253
 
80
- function buildLegacySessionRecordInput(projectId, legacyBlob, legacy) {
254
+ function buildLegacySessionRecordInput(projectId, legacyBlob, legacy, accountScopeId) {
81
255
  return {
82
256
  id: legacy.id,
83
257
  projectId: projectId,
258
+ accountScopeId: accountScopeId,
84
259
  title: legacy.title || '',
85
260
  titleSource: legacy.titleSource === 'manual' ? 'manual' : 'auto',
86
261
  codexThreadId: '',
@@ -100,13 +275,51 @@
100
275
  };
101
276
  }
102
277
 
103
- function savePrefs(prefs) {
104
- return chrome.storage.local.set({ [PREFS_KEY]: normalizePrefs(prefs) });
278
+ function savePrefs(prefs, accountScopeId, projectId) {
279
+ var account = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
280
+ var project = normalizeProjectPrefKey(projectId);
281
+ if (!account && !project) {
282
+ return chrome.storage.local.set({ [PREFS_KEY]: normalizePrefs(prefs) });
283
+ }
284
+ if (!account || !project) {
285
+ return Promise.reject(Object.assign(
286
+ new Error('Scoped project preferences require account and project identity.'),
287
+ { code: 'account_scope_unavailable' }
288
+ ));
289
+ }
290
+ return withProjectPreferenceLock(project, function () {
291
+ return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
292
+ var claimed = claimLegacyProjectPreferences(stored[PREFS_KEY] || {}, account, project);
293
+ var next = mergeScopedProjectPreferences(claimed.prefs, prefs, account, project);
294
+ return chrome.storage.local.set({ [PREFS_KEY]: next });
295
+ });
296
+ });
105
297
  }
106
298
 
107
- function loadPrefs() {
108
- return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
109
- return normalizePrefs(stored[PREFS_KEY] || {});
299
+ function loadPrefs(accountScopeId, projectId) {
300
+ var account = normalizeTextField(accountScopeId, PROJECT_PREF_KEY_MAX_CHARS);
301
+ var project = normalizeProjectPrefKey(projectId);
302
+ if (!account && !project) {
303
+ return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
304
+ return normalizePrefs(stored[PREFS_KEY] || {});
305
+ });
306
+ }
307
+ if (!account || !project) {
308
+ return Promise.reject(Object.assign(
309
+ new Error('Scoped project preferences require account and project identity.'),
310
+ { code: 'account_scope_unavailable' }
311
+ ));
312
+ }
313
+ return withProjectPreferenceLock(project, function () {
314
+ return chrome.storage.local.get([PREFS_KEY]).then(function (stored) {
315
+ var claimed = claimLegacyProjectPreferences(stored[PREFS_KEY] || {}, account, project);
316
+ var persisted = claimed.changed
317
+ ? chrome.storage.local.set({ [PREFS_KEY]: claimed.prefs })
318
+ : Promise.resolve();
319
+ return persisted.then(function () {
320
+ return buildProjectPreferenceView(claimed.prefs, account, project);
321
+ });
322
+ });
110
323
  });
111
324
  }
112
325
 
@@ -278,6 +491,7 @@
278
491
  return {
279
492
  PREFS_KEY: PREFS_KEY,
280
493
  SESSION_TOMBSTONES_KEY: SESSION_TOMBSTONES_KEY,
494
+ buildScopedProjectPreferenceKey: buildScopedProjectPreferenceKey,
281
495
  runMigrationIfNeeded: runMigrationIfNeeded,
282
496
  savePrefs: savePrefs,
283
497
  loadPrefs: loadPrefs,
@@ -0,0 +1,60 @@
1
+ (function initStorageSessionClaims(root, factory) {
2
+ var api = factory();
3
+ if (typeof module === 'object' && module.exports) module.exports = api;
4
+ if (root) root.CodexOverleafStorageSessionClaims = api;
5
+ })(typeof globalThis !== 'undefined' ? globalThis : this, function storageSessionClaimsFactory() {
6
+ 'use strict';
7
+
8
+ function createSessionClaimer(openDb, getKeyRange) {
9
+ return function claimSessionsForAccount(projectId, accountScopeId, deletedSessionIds) {
10
+ var normalizedProjectId = typeof projectId === 'string' ? projectId.trim() : '';
11
+ var normalizedAccountScopeId = typeof accountScopeId === 'string' ? accountScopeId.trim() : '';
12
+ if (!normalizedProjectId || !normalizedAccountScopeId) {
13
+ return Promise.reject(Object.assign(
14
+ new Error('A project and account scope are required to claim legacy sessions.'),
15
+ { code: !normalizedAccountScopeId ? 'account_scope_unavailable' : 'project_scope_unavailable' }
16
+ ));
17
+ }
18
+ var deleted = {};
19
+ (Array.isArray(deletedSessionIds) ? deletedSessionIds : []).forEach(function (id) {
20
+ if (typeof id === 'string' && id) deleted[id] = true;
21
+ });
22
+ return openDb().then(function (db) {
23
+ return new Promise(function (resolve, reject) {
24
+ var visible = [];
25
+ var tx = db.transaction('sessions', 'readwrite');
26
+ var store = tx.objectStore('sessions');
27
+ var index = store.index('projectId');
28
+ var request = index.openCursor(getKeyRange().only(normalizedProjectId));
29
+ request.onsuccess = function (event) {
30
+ var cursor = event.target.result;
31
+ if (!cursor) return;
32
+ var record = cursor.value;
33
+ if (record && !deleted[record.id]) {
34
+ var recordScopeId = typeof record.accountScopeId === 'string'
35
+ ? record.accountScopeId.trim()
36
+ : '';
37
+ if (recordScopeId === normalizedAccountScopeId) {
38
+ visible.push(record);
39
+ } else if (!recordScopeId) {
40
+ var claimed = Object.assign({}, record, {
41
+ accountScopeId: normalizedAccountScopeId,
42
+ accountScopeUnavailable: false
43
+ });
44
+ cursor.update(claimed);
45
+ visible.push(claimed);
46
+ }
47
+ }
48
+ cursor.continue();
49
+ };
50
+ request.onerror = function (event) { reject(event.target.error); };
51
+ tx.oncomplete = function () { resolve(visible); };
52
+ tx.onerror = function (event) { reject(event.target.error || tx.error); };
53
+ tx.onabort = function (event) { reject(event.target.error || tx.error); };
54
+ });
55
+ });
56
+ };
57
+ }
58
+
59
+ return Object.freeze({ createSessionClaimer: createSessionClaimer });
60
+ });
@@ -87,6 +87,10 @@
87
87
  authorizedVersion: safeVersion(value.authorizedVersion),
88
88
  authorizationId: safeId(value.authorizationId),
89
89
  authorizedAt: finiteNumber(value.authorizedAt),
90
+ revokingAuthorizationId: safeId(value.revokingAuthorizationId),
91
+ revokingVersion: safeVersion(value.revokingVersion),
92
+ revokingTransactionId: safeId(value.revokingTransactionId),
93
+ revokingAt: finiteNumber(value.revokingAt),
90
94
  lastPromptedVersion: safeVersion(value.lastPromptedVersion),
91
95
  lastPromptedAt: finiteNumber(value.lastPromptedAt)
92
96
  };
@@ -0,0 +1,109 @@
1
+ (function initUpdateRevocationIntent(root, factory) {
2
+ const api = factory();
3
+ if (typeof module === "object" && module.exports) {
4
+ module.exports = api;
5
+ }
6
+ if (root) {
7
+ root.CodexOverleafUpdateRevocation = api;
8
+ }
9
+ })(typeof globalThis !== "undefined" ? globalThis : this, function createUpdateRevocationIntent() {
10
+ "use strict";
11
+
12
+ function safeString(value) {
13
+ return typeof value === "string" ? value.trim() : "";
14
+ }
15
+
16
+ function safeTime(value, fallback = 0) {
17
+ return Number.isFinite(value) && value >= 0 ? value : fallback;
18
+ }
19
+
20
+ function begin(consentState, updateState, now = Date.now()) {
21
+ const consent = consentState && typeof consentState === "object" ? consentState : {};
22
+ const update = updateState && typeof updateState === "object" ? updateState : {};
23
+ return {
24
+ ...consent,
25
+ revokingAuthorizationId: safeString(consent.authorizationId),
26
+ revokingVersion:
27
+ safeString(consent.authorizedVersion) || safeString(update.latestVersion),
28
+ revokingTransactionId: safeString(update.transactionId),
29
+ revokingAt: safeTime(now)
30
+ };
31
+ }
32
+
33
+ function prepareAuthorization(consentState, authorizationId, targetVersion, now = Date.now()) {
34
+ const consent = consentState && typeof consentState === "object" ? consentState : {};
35
+ return {
36
+ ...consent,
37
+ revokingAuthorizationId: safeString(authorizationId),
38
+ revokingVersion: safeString(targetVersion),
39
+ revokingTransactionId: "",
40
+ revokingAt: safeTime(now)
41
+ };
42
+ }
43
+
44
+ function hasPending(consentState) {
45
+ const consent = consentState && typeof consentState === "object" ? consentState : {};
46
+ return Boolean(
47
+ safeString(consent.revokingAuthorizationId) &&
48
+ safeString(consent.revokingVersion)
49
+ );
50
+ }
51
+
52
+ function clear(consentState) {
53
+ const consent = consentState && typeof consentState === "object" ? consentState : {};
54
+ return {
55
+ ...consent,
56
+ revokingAuthorizationId: "",
57
+ revokingVersion: "",
58
+ revokingTransactionId: "",
59
+ revokingAt: 0
60
+ };
61
+ }
62
+
63
+ function complete(updateState, consentState, options = {}) {
64
+ const update = updateState && typeof updateState === "object" ? updateState : {};
65
+ const consent = consentState && typeof consentState === "object" ? consentState : {};
66
+ const now = safeTime(options.now, Date.now());
67
+ const snoozeMs = safeTime(options.snoozeMs);
68
+ const version =
69
+ safeString(consent.revokingVersion) ||
70
+ safeString(consent.authorizedVersion) ||
71
+ safeString(update.latestVersion);
72
+ return {
73
+ updateState: {
74
+ ...update,
75
+ state: "update_available",
76
+ transactionId: "",
77
+ stagedPath: "",
78
+ stagedAt: 0,
79
+ applyingAt: 0,
80
+ awaitingHealthAt: 0,
81
+ blocker: "",
82
+ blockers: [],
83
+ blockingReason: "",
84
+ code: "",
85
+ message: "",
86
+ error: null,
87
+ postponeUntil: safeTime(options.postponeUntil),
88
+ postponeGuardVersion: version
89
+ },
90
+ consentState: clear({
91
+ ...consent,
92
+ mode: "snoozed",
93
+ snoozedVersion: version,
94
+ snoozedUntil: now + snoozeMs,
95
+ authorizedVersion: "",
96
+ authorizationId: "",
97
+ authorizedAt: 0
98
+ })
99
+ };
100
+ }
101
+
102
+ return Object.freeze({
103
+ begin,
104
+ prepareAuthorization,
105
+ hasPending,
106
+ clear,
107
+ complete
108
+ });
109
+ });