@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 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EACL,gCAAgC,EAChC,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAM3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { createApiUserIdentitySource } from \"./apiAdapter\";\nexport { requireTrustedUserIdentityResolver } from \"./requiredResolver\";\nexport {\n createTrustedUserIdentityService,\n loadPinnedUserIdentity,\n} from \"./service\";\nexport { resolveIdentityTrustDomain } from \"./trustDomain\";\nexport type {\n LocalUserIdentityCandidate,\n TrustedUserIdentity,\n TrustedUserIdentityResolver,\n} from \"./types\";\nexport { validateUserIdentityKeys } from \"./validation\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EACL,gCAAgC,EAChC,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAO3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { createApiUserIdentitySource } from \"./apiAdapter\";\nexport { parseIdentityLink } from \"./identityLink\";\nexport { requireTrustedUserIdentityResolver } from \"./requiredResolver\";\nexport {\n createTrustedUserIdentityService,\n loadPinnedUserIdentity,\n} from \"./service\";\nexport { resolveIdentityTrustDomain } from \"./trustDomain\";\nexport type {\n LocalUserIdentityCandidate,\n TrustedUserIdentity,\n TrustedUserIdentityResolver,\n TrustedUserIdentityService,\n} from \"./types\";\nexport { validateUserIdentityKeys } from \"./validation\";\n"]}
@@ -3,13 +3,18 @@ import { base64ToBytes, bytesToBase64 } from "../../internal/encoding/index.js";
3
3
  import { compareOrInsertTrustedUserIdentityPin, loadTrustedUserIdentityPin, loadTrustedUserIdForSigningKey, TrustedUserIdentityPinCorruptError, TrustedUserIdentityPinMismatchError, } from "../persistence/trustedUserIdentityPinPersistence.js";
4
4
  import { TrustedUserIdentityPinContentionError } from "../persistence/trustedUserIdentityPinTransaction.js";
5
5
  import { DatabaseUnavailableError } from "../sync/databaseUnavailable.js";
6
+ import { assertIdentityLinkMatches, createIdentityLink, parseIdentityLink, } from "./identityLink.js";
6
7
  import { brandTrustedUserIdentity, TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE, TRUSTED_USER_IDENTITY_FORMAT_VERSION, TRUSTED_USER_IDENTITY_SIGNING_SUITE, } from "./types.js";
7
8
  import { assertTrustedUserIdentityUserId, validateLocalUserIdentity, validateRemoteUserIdentity, validateUserIdentityKeys, } from "./validation.js";
8
- function requireTrustStore(dependencies) {
9
+ function requireTrustDomain(dependencies) {
9
10
  // A missing trust domain is a static misconfiguration and must stay loud.
10
11
  if (!dependencies.identityTrustDomain) {
11
12
  throw new KeyingVerificationError("missing_dependency", "Trusted user identity resolution requires a stable API trust domain");
12
13
  }
14
+ return dependencies.identityTrustDomain;
15
+ }
16
+ function requireTrustStore(dependencies) {
17
+ const identityTrustDomain = requireTrustDomain(dependencies);
13
18
  // An absent trust store is not: getExecSql() returns null exactly while the
14
19
  // database is not ready, which happens routinely when the runtime is swapped
15
20
  // under in-flight sync work. Callers that tolerate a vanishing database
@@ -18,7 +23,7 @@ function requireTrustStore(dependencies) {
18
23
  if (!execSql) {
19
24
  throw new DatabaseUnavailableError("Trusted user identity resolution requires a ready SQLite trust store");
20
25
  }
21
- return { execSql, identityTrustDomain: dependencies.identityTrustDomain };
26
+ return { execSql, identityTrustDomain };
22
27
  }
23
28
  async function compareWithDurablePin(input) {
24
29
  try {
@@ -111,6 +116,47 @@ export async function loadPinnedUserIdentity(input) {
111
116
  }
112
117
  export function createTrustedUserIdentityService(dependencies) {
113
118
  return {
119
+ async resolvePinned(userId) {
120
+ const { execSql, identityTrustDomain } = requireTrustStore(dependencies);
121
+ return loadPinnedUserIdentity({ execSql, identityTrustDomain, userId });
122
+ },
123
+ async createLink(appUrl) {
124
+ const identityTrustDomain = requireTrustDomain(dependencies);
125
+ const userId = dependencies.getLocalUserId();
126
+ const candidate = userId ? dependencies.getLocalIdentity(userId) : null;
127
+ if (!userId || !candidate) {
128
+ throw new Error("Sign in before sharing your identity link.");
129
+ }
130
+ const identity = await validateLocalUserIdentity({
131
+ candidate,
132
+ identityTrustDomain,
133
+ userId,
134
+ });
135
+ return createIdentityLink(identity, appUrl);
136
+ },
137
+ async verifyLink(link) {
138
+ const expectation = parseIdentityLink(link);
139
+ const { execSql, identityTrustDomain } = requireTrustStore(dependencies);
140
+ if (expectation.identityTrustDomain !== identityTrustDomain) {
141
+ throw new Error("This identity link belongs to a different Tearleads service.");
142
+ }
143
+ const localUserId = dependencies.getLocalUserId();
144
+ try {
145
+ const identity = await resolveCandidate(dependencies, expectation.userId, identityTrustDomain);
146
+ if (!identity)
147
+ throw new Error("The identity in this link is unavailable.");
148
+ await assertIdentityLinkMatches(expectation, identity);
149
+ if (dependencies.getExecSql() !== execSql ||
150
+ dependencies.getLocalUserId() !== localUserId) {
151
+ throw new DatabaseUnavailableError("The active identity changed. Open the identity link again.");
152
+ }
153
+ return await pinIdentity({ dependencies, execSql, identity });
154
+ }
155
+ catch (error) {
156
+ dependencies.remoteSource.invalidate(expectation.userId);
157
+ throw error;
158
+ }
159
+ },
114
160
  async boundUserId(signingKeyFingerprint) {
115
161
  const { execSql, identityTrustDomain } = requireTrustStore(dependencies);
116
162
  return loadTrustedUserIdForSigningKey({
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EACL,qCAAqC,EACrC,0BAA0B,EAC1B,8BAA8B,EAC9B,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,qCAAqC,EAAE,MAAM,kDAAkD,CAAC;AAEzG,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACL,wBAAwB,EACxB,yCAAyC,EACzC,oCAAoC,EACpC,mCAAmC,GAKpC,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAEtB,SAAS,iBAAiB,CACxB,YAAoD;IAOpD,0EAA0E;IAC1E,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;QACtC,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,qEAAqE,CACtE,CAAC;IACJ,CAAC;IACD,4EAA4E;IAC5E,6EAA6E;IAC7E,wEAAwE;IACxE,yEAAyE;IACzE,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,wBAAwB,CAChC,sEAAsE,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,YAAY,CAAC,mBAAmB,EAAE,CAAC;AAC5E,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,KAMpC;IACC,IAAI,CAAC;QACH,MAAM,qCAAqC,CAAC;YAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,EAAE;gBACH,2BAA2B,EAAE,KAAK,CAAC,QAAQ,CAAC,2BAA2B;gBACvE,sBAAsB,EAAE,aAAa,CACnC,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CACtC;gBACD,kBAAkB,EAAE,yCAAyC;gBAC7D,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,aAAa,EAAE,oCAAoC;gBACnD,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,mBAAmB;gBACvD,qBAAqB,EAAE,KAAK,CAAC,QAAQ,CAAC,qBAAqB;gBAC3D,gBAAgB,EAAE,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAChE,YAAY,EAAE,mCAAmC;gBACjD,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;aAC9B;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,mCAAmC,EAAE,CAAC;YACzD,MAAM,IAAI,uBAAuB,CAC/B,cAAc,EACd,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,MAAM;gBAC9C,CAAC,CAAC,mBAAmB,KAAK,CAAC,QAAQ,CAAC,MAAM,wBAAwB,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;gBACzF,CAAC,CAAC,qCAAqC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CACjE,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,YAAY,kCAAkC,EAAE,CAAC;YACxD,MAAM,IAAI,uBAAuB,CAC/B,eAAe,EACf,4CAA4C,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,YAAY,qCAAqC,EAAE,CAAC;YAC3D,sEAAsE;YACtE,yEAAyE;YACzE,MAAM,IAAI,wBAAwB,CAChC,+CAA+C,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CACvE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,YAAoD,EACpD,MAAc,EACd,mBAA2B;IAE3B,MAAM,WAAW,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC;IAClD,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,YAAY,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,mDAAmD,CACpD,CAAC;QACJ,CAAC;QACD,OAAO,yBAAyB,CAAC;YAC/B,SAAS,EAAE,aAAa;YACxB,mBAAmB;YACnB,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpE,OAAO,cAAc;QACnB,CAAC,CAAC,0BAA0B,CAAC;YACzB,SAAS,EAAE,cAAc;YACzB,mBAAmB;YACnB,eAAe,EAAE,MAAM;SACxB,CAAC;QACJ,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,KAM1B;IACC,MAAM,qBAAqB,CAAC;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE;QACrE,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IACH,OAAO,wBAAwB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAI5C;IACC,+BAA+B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;QAC1C,SAAS,EAAE;YACT,sBAAsB,EAAE,aAAa,CAAC,GAAG,CAAC,sBAAsB,CAAC;YACjE,qBAAqB,EAAE,GAAG,CAAC,qBAAqB;YAChD,gBAAgB,EAAE,aAAa,CAAC,GAAG,CAAC,gBAAgB,CAAC;SACtD;QACD,2BAA2B,EAAE,GAAG,CAAC,2BAA2B;KAC7D,CAAC,CAAC;IACH,OAAO,wBAAwB,CAAC;QAC9B,GAAG,IAAI;QACP,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;QAC9C,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,YAAoD;IAEpD,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,qBAAqB;YACrC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACzE,OAAO,8BAA8B,CAAC;gBACpC,OAAO;gBACP,mBAAmB;gBACnB,qBAAqB;aACtB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS;YAC9B,+BAA+B,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACzE,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAAC;gBAC/C,SAAS;gBACT,mBAAmB;gBACnB,MAAM;aACP,CAAC,CAAC;YACH,OAAO,WAAW,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,MAAM;YAClB,+BAA+B,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACzE,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,YAAY,EACZ,MAAM,EACN,mBAAmB,CACpB,CAAC;gBACF,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,MAAM,WAAW,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { base64ToBytes, bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n compareOrInsertTrustedUserIdentityPin,\n loadTrustedUserIdentityPin,\n loadTrustedUserIdForSigningKey,\n TrustedUserIdentityPinCorruptError,\n TrustedUserIdentityPinMismatchError,\n} from \"../persistence/trustedUserIdentityPinPersistence\";\nimport { TrustedUserIdentityPinContentionError } from \"../persistence/trustedUserIdentityPinTransaction\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { DatabaseUnavailableError } from \"../sync/databaseUnavailable\";\nimport {\n brandTrustedUserIdentity,\n TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE,\n TRUSTED_USER_IDENTITY_FORMAT_VERSION,\n TRUSTED_USER_IDENTITY_SIGNING_SUITE,\n type TrustedUserIdentity,\n type TrustedUserIdentityService,\n type TrustedUserIdentityServiceDependencies,\n type ValidatedUserIdentityCandidate,\n} from \"./types\";\nimport {\n assertTrustedUserIdentityUserId,\n validateLocalUserIdentity,\n validateRemoteUserIdentity,\n validateUserIdentityKeys,\n} from \"./validation\";\n\nfunction requireTrustStore(\n dependencies: TrustedUserIdentityServiceDependencies,\n): {\n readonly execSql: NonNullable<\n ReturnType<TrustedUserIdentityServiceDependencies[\"getExecSql\"]>\n >;\n readonly identityTrustDomain: string;\n} {\n // A missing trust domain is a static misconfiguration and must stay loud.\n if (!dependencies.identityTrustDomain) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Trusted user identity resolution requires a stable API trust domain\",\n );\n }\n // An absent trust store is not: getExecSql() returns null exactly while the\n // database is not ready, which happens routinely when the runtime is swapped\n // under in-flight sync work. Callers that tolerate a vanishing database\n // discriminate on the error type, so this must not share the code above.\n const execSql = dependencies.getExecSql();\n if (!execSql) {\n throw new DatabaseUnavailableError(\n \"Trusted user identity resolution requires a ready SQLite trust store\",\n );\n }\n return { execSql, identityTrustDomain: dependencies.identityTrustDomain };\n}\n\nasync function compareWithDurablePin(input: {\n readonly execSql: NonNullable<\n ReturnType<TrustedUserIdentityServiceDependencies[\"getExecSql\"]>\n >;\n readonly firstSeenAt: string;\n readonly identity: ValidatedUserIdentityCandidate;\n}): Promise<void> {\n try {\n await compareOrInsertTrustedUserIdentityPin({\n execSql: input.execSql,\n pin: {\n encapsulationKeyFingerprint: input.identity.encapsulationKeyFingerprint,\n encapsulationPublicKey: bytesToBase64(\n input.identity.encapsulationPublicKey,\n ),\n encapsulationSuite: TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE,\n firstSeenAt: input.firstSeenAt,\n formatVersion: TRUSTED_USER_IDENTITY_FORMAT_VERSION,\n identityTrustDomain: input.identity.identityTrustDomain,\n signingKeyFingerprint: input.identity.signingKeyFingerprint,\n signingPublicKey: bytesToBase64(input.identity.signingPublicKey),\n signingSuite: TRUSTED_USER_IDENTITY_SIGNING_SUITE,\n userId: input.identity.userId,\n },\n });\n } catch (error) {\n if (error instanceof TrustedUserIdentityPinMismatchError) {\n throw new KeyingVerificationError(\n \"equivocation\",\n error.existing.userId !== error.candidate.userId\n ? `Signing key for ${input.identity.userId} is already bound to ${error.existing.userId}`\n : `Trusted user identity changed for ${input.identity.userId}`,\n );\n }\n if (error instanceof TrustedUserIdentityPinCorruptError) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n `Trusted user identity pin is corrupt for ${input.identity.userId}`,\n );\n }\n if (error instanceof TrustedUserIdentityPinContentionError) {\n // Lock contention says nothing about the identity; the caller retries\n // once the trust store is free, so this must not be recordable evidence.\n throw new DatabaseUnavailableError(\n `Trusted user identity pin store is busy for ${input.identity.userId}`,\n );\n }\n throw error;\n }\n}\n\nasync function resolveCandidate(\n dependencies: TrustedUserIdentityServiceDependencies,\n userId: string,\n identityTrustDomain: string,\n): Promise<ValidatedUserIdentityCandidate | null> {\n const localUserId = dependencies.getLocalUserId();\n if (userId === localUserId) {\n const localIdentity = dependencies.getLocalIdentity(userId);\n if (!localIdentity) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Authoritative local identity keys are unavailable\",\n );\n }\n return validateLocalUserIdentity({\n candidate: localIdentity,\n identityTrustDomain,\n userId,\n });\n }\n\n const remoteIdentity = await dependencies.remoteSource.load(userId);\n return remoteIdentity\n ? validateRemoteUserIdentity({\n candidate: remoteIdentity,\n identityTrustDomain,\n requestedUserId: userId,\n })\n : null;\n}\n\nasync function pinIdentity(input: {\n readonly dependencies: TrustedUserIdentityServiceDependencies;\n readonly execSql: NonNullable<\n ReturnType<TrustedUserIdentityServiceDependencies[\"getExecSql\"]>\n >;\n readonly identity: ValidatedUserIdentityCandidate;\n}): Promise<TrustedUserIdentity> {\n await compareWithDurablePin({\n execSql: input.execSql,\n firstSeenAt: (input.dependencies.now?.() ?? new Date()).toISOString(),\n identity: input.identity,\n });\n return brandTrustedUserIdentity(input.identity);\n}\n\n/**\n * Read-only: the identity this trust store already pins for `userId`, or null.\n * The stored keys must still match their stored fingerprints. Never inserts,\n * compares against or replaces a pin.\n */\nexport async function loadPinnedUserIdentity(input: {\n readonly execSql: ExecSql;\n readonly identityTrustDomain: string;\n readonly userId: string;\n}): Promise<TrustedUserIdentity | null> {\n assertTrustedUserIdentityUserId(input.userId);\n const pin = await loadTrustedUserIdentityPin(input);\n if (!pin) return null;\n const keys = await validateUserIdentityKeys({\n candidate: {\n encapsulationPublicKey: base64ToBytes(pin.encapsulationPublicKey),\n signingKeyFingerprint: pin.signingKeyFingerprint,\n signingPublicKey: base64ToBytes(pin.signingPublicKey),\n },\n encapsulationKeyFingerprint: pin.encapsulationKeyFingerprint,\n });\n return brandTrustedUserIdentity({\n ...keys,\n identityTrustDomain: input.identityTrustDomain,\n userId: input.userId,\n });\n}\n\nexport function createTrustedUserIdentityService(\n dependencies: TrustedUserIdentityServiceDependencies,\n): TrustedUserIdentityService {\n return {\n async boundUserId(signingKeyFingerprint) {\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n return loadTrustedUserIdForSigningKey({\n execSql,\n identityTrustDomain,\n signingKeyFingerprint,\n });\n },\n async pinLocal(userId, candidate) {\n assertTrustedUserIdentityUserId(userId);\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n const identity = await validateLocalUserIdentity({\n candidate,\n identityTrustDomain,\n userId,\n });\n return pinIdentity({ dependencies, execSql, identity });\n },\n async resolve(userId) {\n assertTrustedUserIdentityUserId(userId);\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n try {\n const identity = await resolveCandidate(\n dependencies,\n userId,\n identityTrustDomain,\n );\n if (!identity) {\n return null;\n }\n return await pinIdentity({ dependencies, execSql, identity });\n } catch (error) {\n dependencies.remoteSource.invalidate(userId);\n throw error;\n }\n },\n };\n}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["service.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { base64ToBytes, bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n compareOrInsertTrustedUserIdentityPin,\n loadTrustedUserIdentityPin,\n loadTrustedUserIdForSigningKey,\n TrustedUserIdentityPinCorruptError,\n TrustedUserIdentityPinMismatchError,\n} from \"../persistence/trustedUserIdentityPinPersistence\";\nimport { TrustedUserIdentityPinContentionError } from \"../persistence/trustedUserIdentityPinTransaction\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { DatabaseUnavailableError } from \"../sync/databaseUnavailable\";\nimport {\n assertIdentityLinkMatches,\n createIdentityLink,\n parseIdentityLink,\n} from \"./identityLink\";\nimport {\n brandTrustedUserIdentity,\n TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE,\n TRUSTED_USER_IDENTITY_FORMAT_VERSION,\n TRUSTED_USER_IDENTITY_SIGNING_SUITE,\n type TrustedUserIdentity,\n type TrustedUserIdentityService,\n type TrustedUserIdentityServiceDependencies,\n type ValidatedUserIdentityCandidate,\n} from \"./types\";\nimport {\n assertTrustedUserIdentityUserId,\n validateLocalUserIdentity,\n validateRemoteUserIdentity,\n validateUserIdentityKeys,\n} from \"./validation\";\n\nfunction requireTrustDomain(\n dependencies: TrustedUserIdentityServiceDependencies,\n): string {\n // A missing trust domain is a static misconfiguration and must stay loud.\n if (!dependencies.identityTrustDomain) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Trusted user identity resolution requires a stable API trust domain\",\n );\n }\n return dependencies.identityTrustDomain;\n}\n\nfunction requireTrustStore(\n dependencies: TrustedUserIdentityServiceDependencies,\n) {\n const identityTrustDomain = requireTrustDomain(dependencies);\n // An absent trust store is not: getExecSql() returns null exactly while the\n // database is not ready, which happens routinely when the runtime is swapped\n // under in-flight sync work. Callers that tolerate a vanishing database\n // discriminate on the error type, so this must not share the code above.\n const execSql = dependencies.getExecSql();\n if (!execSql) {\n throw new DatabaseUnavailableError(\n \"Trusted user identity resolution requires a ready SQLite trust store\",\n );\n }\n return { execSql, identityTrustDomain };\n}\n\nasync function compareWithDurablePin(input: {\n readonly execSql: NonNullable<\n ReturnType<TrustedUserIdentityServiceDependencies[\"getExecSql\"]>\n >;\n readonly firstSeenAt: string;\n readonly identity: ValidatedUserIdentityCandidate;\n}): Promise<void> {\n try {\n await compareOrInsertTrustedUserIdentityPin({\n execSql: input.execSql,\n pin: {\n encapsulationKeyFingerprint: input.identity.encapsulationKeyFingerprint,\n encapsulationPublicKey: bytesToBase64(\n input.identity.encapsulationPublicKey,\n ),\n encapsulationSuite: TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE,\n firstSeenAt: input.firstSeenAt,\n formatVersion: TRUSTED_USER_IDENTITY_FORMAT_VERSION,\n identityTrustDomain: input.identity.identityTrustDomain,\n signingKeyFingerprint: input.identity.signingKeyFingerprint,\n signingPublicKey: bytesToBase64(input.identity.signingPublicKey),\n signingSuite: TRUSTED_USER_IDENTITY_SIGNING_SUITE,\n userId: input.identity.userId,\n },\n });\n } catch (error) {\n if (error instanceof TrustedUserIdentityPinMismatchError) {\n throw new KeyingVerificationError(\n \"equivocation\",\n error.existing.userId !== error.candidate.userId\n ? `Signing key for ${input.identity.userId} is already bound to ${error.existing.userId}`\n : `Trusted user identity changed for ${input.identity.userId}`,\n );\n }\n if (error instanceof TrustedUserIdentityPinCorruptError) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n `Trusted user identity pin is corrupt for ${input.identity.userId}`,\n );\n }\n if (error instanceof TrustedUserIdentityPinContentionError) {\n // Lock contention says nothing about the identity; the caller retries\n // once the trust store is free, so this must not be recordable evidence.\n throw new DatabaseUnavailableError(\n `Trusted user identity pin store is busy for ${input.identity.userId}`,\n );\n }\n throw error;\n }\n}\n\nasync function resolveCandidate(\n dependencies: TrustedUserIdentityServiceDependencies,\n userId: string,\n identityTrustDomain: string,\n): Promise<ValidatedUserIdentityCandidate | null> {\n const localUserId = dependencies.getLocalUserId();\n if (userId === localUserId) {\n const localIdentity = dependencies.getLocalIdentity(userId);\n if (!localIdentity) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Authoritative local identity keys are unavailable\",\n );\n }\n return validateLocalUserIdentity({\n candidate: localIdentity,\n identityTrustDomain,\n userId,\n });\n }\n\n const remoteIdentity = await dependencies.remoteSource.load(userId);\n return remoteIdentity\n ? validateRemoteUserIdentity({\n candidate: remoteIdentity,\n identityTrustDomain,\n requestedUserId: userId,\n })\n : null;\n}\n\nasync function pinIdentity(input: {\n readonly dependencies: TrustedUserIdentityServiceDependencies;\n readonly execSql: NonNullable<\n ReturnType<TrustedUserIdentityServiceDependencies[\"getExecSql\"]>\n >;\n readonly identity: ValidatedUserIdentityCandidate;\n}): Promise<TrustedUserIdentity> {\n await compareWithDurablePin({\n execSql: input.execSql,\n firstSeenAt: (input.dependencies.now?.() ?? new Date()).toISOString(),\n identity: input.identity,\n });\n return brandTrustedUserIdentity(input.identity);\n}\n\n/**\n * Read-only: the identity this trust store already pins for `userId`, or null.\n * The stored keys must still match their stored fingerprints. Never inserts,\n * compares against or replaces a pin.\n */\nexport async function loadPinnedUserIdentity(input: {\n readonly execSql: ExecSql;\n readonly identityTrustDomain: string;\n readonly userId: string;\n}): Promise<TrustedUserIdentity | null> {\n assertTrustedUserIdentityUserId(input.userId);\n const pin = await loadTrustedUserIdentityPin(input);\n if (!pin) return null;\n const keys = await validateUserIdentityKeys({\n candidate: {\n encapsulationPublicKey: base64ToBytes(pin.encapsulationPublicKey),\n signingKeyFingerprint: pin.signingKeyFingerprint,\n signingPublicKey: base64ToBytes(pin.signingPublicKey),\n },\n encapsulationKeyFingerprint: pin.encapsulationKeyFingerprint,\n });\n return brandTrustedUserIdentity({\n ...keys,\n identityTrustDomain: input.identityTrustDomain,\n userId: input.userId,\n });\n}\n\nexport function createTrustedUserIdentityService(\n dependencies: TrustedUserIdentityServiceDependencies,\n): TrustedUserIdentityService {\n return {\n async resolvePinned(userId) {\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n return loadPinnedUserIdentity({ execSql, identityTrustDomain, userId });\n },\n async createLink(appUrl) {\n const identityTrustDomain = requireTrustDomain(dependencies);\n const userId = dependencies.getLocalUserId();\n const candidate = userId ? dependencies.getLocalIdentity(userId) : null;\n if (!userId || !candidate) {\n throw new Error(\"Sign in before sharing your identity link.\");\n }\n const identity = await validateLocalUserIdentity({\n candidate,\n identityTrustDomain,\n userId,\n });\n return createIdentityLink(identity, appUrl);\n },\n async verifyLink(link) {\n const expectation = parseIdentityLink(link);\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n if (expectation.identityTrustDomain !== identityTrustDomain) {\n throw new Error(\n \"This identity link belongs to a different Tearleads service.\",\n );\n }\n const localUserId = dependencies.getLocalUserId();\n try {\n const identity = await resolveCandidate(\n dependencies,\n expectation.userId,\n identityTrustDomain,\n );\n if (!identity)\n throw new Error(\"The identity in this link is unavailable.\");\n await assertIdentityLinkMatches(expectation, identity);\n if (\n dependencies.getExecSql() !== execSql ||\n dependencies.getLocalUserId() !== localUserId\n ) {\n throw new DatabaseUnavailableError(\n \"The active identity changed. Open the identity link again.\",\n );\n }\n return await pinIdentity({ dependencies, execSql, identity });\n } catch (error) {\n dependencies.remoteSource.invalidate(expectation.userId);\n throw error;\n }\n },\n async boundUserId(signingKeyFingerprint) {\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n return loadTrustedUserIdForSigningKey({\n execSql,\n identityTrustDomain,\n signingKeyFingerprint,\n });\n },\n async pinLocal(userId, candidate) {\n assertTrustedUserIdentityUserId(userId);\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n const identity = await validateLocalUserIdentity({\n candidate,\n identityTrustDomain,\n userId,\n });\n return pinIdentity({ dependencies, execSql, identity });\n },\n async resolve(userId) {\n assertTrustedUserIdentityUserId(userId);\n const { execSql, identityTrustDomain } = requireTrustStore(dependencies);\n try {\n const identity = await resolveCandidate(\n dependencies,\n userId,\n identityTrustDomain,\n );\n if (!identity) {\n return null;\n }\n return await pinIdentity({ dependencies, execSql, identity });\n } catch (error) {\n dependencies.remoteSource.invalidate(userId);\n throw error;\n }\n },\n };\n}\n"]}
@@ -50,6 +50,9 @@ export interface LocalUserIdentityCandidate {
50
50
  readonly signingPublicKey: Uint8Array;
51
51
  }
52
52
  export interface TrustedUserIdentityService {
53
+ createLink(appUrl: string): Promise<string>;
54
+ verifyLink(link: string): Promise<TrustedUserIdentity>;
55
+ resolvePinned(userId: string): Promise<TrustedUserIdentity | null>;
53
56
  /** The user this device's trust store already binds a signing key to. */
54
57
  boundUserId(signingKeyFingerprint: string): Promise<string | null>;
55
58
  pinLocal(userId: string, candidate: LocalUserIdentityCandidate): Promise<TrustedUserIdentity>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,mCAAmC,GAAG,WAAW,CAAC;AAC/D,MAAM,CAAC,MAAM,yCAAyC,GAAG,aAAa,CAAC;AAEvE,MAAM,wBAAwB,GAAkB,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAC9E,MAAM,6BAA6B,GAAG,IAAI,CAAC;AA4E3C,MAAM,UAAU,wBAAwB,CACtC,KAAqC;IAErC,OAAO;QACL,GAAG,KAAK;QACR,CAAC,wBAAwB,CAAC,EAAE,6BAA6B;KAC1D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC;YAC1C,6BAA6B,CAChC,CAAC;AACJ,CAAC","sourcesContent":["import type { ExecSql } from \"../sqlite/sqlSchema\";\n\nexport const TRUSTED_USER_IDENTITY_FORMAT_VERSION = 1;\nexport const TRUSTED_USER_IDENTITY_SIGNING_SUITE = \"ML-DSA-87\";\nexport const TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE = \"ML-KEM-1024\";\n\nconst trustedUserIdentityBrand: unique symbol = Symbol(\"trustedUserIdentity\");\nconst trustedUserIdentityBrandValue = true;\n\n/**\n * A complete user identity bundle that has passed strict key validation and\n * the durable trust-on-first-use comparison for its trust domain.\n *\n * The nominal brand keeps raw API and organization response objects from being\n * accepted at cryptographic boundaries by structural typing. Its private\n * symbol and constructor remain package-private to the SDK trust gateway.\n */\nexport interface TrustedUserIdentity {\n readonly [trustedUserIdentityBrand]: true;\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: Uint8Array;\n readonly identityTrustDomain: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: Uint8Array;\n readonly userId: string;\n}\n\n/** Strictly decoded and self-consistent, but not yet accepted by durable TOFU. */\nexport interface ValidatedUserIdentityCandidate {\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: Uint8Array;\n readonly identityTrustDomain: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: Uint8Array;\n readonly userId: string;\n}\n\nexport interface RemoteUserIdentityCandidate {\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: string;\n readonly userId: string;\n}\n\nexport interface RemoteUserIdentitySource {\n invalidate(userId: string): void;\n /**\n * `null` only when the server asserts the user does not exist. A transport\n * or non-404 HTTP failure throws a retryable availability error instead.\n */\n load(userId: string): Promise<RemoteUserIdentityCandidate | null>;\n}\n\nexport interface LocalUserIdentityCandidate {\n readonly encapsulationPublicKey: Uint8Array;\n readonly signingKeyFingerprint?: string | null | undefined;\n readonly signingPublicKey: Uint8Array;\n}\n\nexport interface TrustedUserIdentityService {\n /** The user this device's trust store already binds a signing key to. */\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocal(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<TrustedUserIdentity>;\n resolve(userId: string): Promise<TrustedUserIdentity | null>;\n}\n\nexport type TrustedUserIdentityResolver = TrustedUserIdentityService[\"resolve\"];\n\nexport interface TrustedUserIdentityServiceDependencies {\n readonly getExecSql: () => ExecSql | null;\n readonly getLocalIdentity: (\n userId: string,\n ) => LocalUserIdentityCandidate | null;\n readonly getLocalUserId: () => string | null;\n readonly identityTrustDomain: string | null;\n readonly now?: (() => Date) | undefined;\n readonly remoteSource: RemoteUserIdentitySource;\n}\n\nexport function brandTrustedUserIdentity(\n input: ValidatedUserIdentityCandidate,\n): TrustedUserIdentity {\n return {\n ...input,\n [trustedUserIdentityBrand]: trustedUserIdentityBrandValue,\n };\n}\n\nexport function isTrustedUserIdentity(\n value: unknown,\n): value is TrustedUserIdentity {\n return (\n typeof value === \"object\" &&\n value !== null &&\n Reflect.get(value, trustedUserIdentityBrand) ===\n trustedUserIdentityBrandValue\n );\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,mCAAmC,GAAG,WAAW,CAAC;AAC/D,MAAM,CAAC,MAAM,yCAAyC,GAAG,aAAa,CAAC;AAEvE,MAAM,wBAAwB,GAAkB,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAC9E,MAAM,6BAA6B,GAAG,IAAI,CAAC;AA+E3C,MAAM,UAAU,wBAAwB,CACtC,KAAqC;IAErC,OAAO;QACL,GAAG,KAAK;QACR,CAAC,wBAAwB,CAAC,EAAE,6BAA6B;KAC1D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc;IAEd,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC;YAC1C,6BAA6B,CAChC,CAAC;AACJ,CAAC","sourcesContent":["import type { ExecSql } from \"../sqlite/sqlSchema\";\n\nexport const TRUSTED_USER_IDENTITY_FORMAT_VERSION = 1;\nexport const TRUSTED_USER_IDENTITY_SIGNING_SUITE = \"ML-DSA-87\";\nexport const TRUSTED_USER_IDENTITY_ENCAPSULATION_SUITE = \"ML-KEM-1024\";\n\nconst trustedUserIdentityBrand: unique symbol = Symbol(\"trustedUserIdentity\");\nconst trustedUserIdentityBrandValue = true;\n\n/**\n * A complete user identity bundle that has passed strict key validation and\n * the durable trust-on-first-use comparison for its trust domain.\n *\n * The nominal brand keeps raw API and organization response objects from being\n * accepted at cryptographic boundaries by structural typing. Its private\n * symbol and constructor remain package-private to the SDK trust gateway.\n */\nexport interface TrustedUserIdentity {\n readonly [trustedUserIdentityBrand]: true;\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: Uint8Array;\n readonly identityTrustDomain: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: Uint8Array;\n readonly userId: string;\n}\n\n/** Strictly decoded and self-consistent, but not yet accepted by durable TOFU. */\nexport interface ValidatedUserIdentityCandidate {\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: Uint8Array;\n readonly identityTrustDomain: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: Uint8Array;\n readonly userId: string;\n}\n\nexport interface RemoteUserIdentityCandidate {\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: string;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: string;\n readonly userId: string;\n}\n\nexport interface RemoteUserIdentitySource {\n invalidate(userId: string): void;\n /**\n * `null` only when the server asserts the user does not exist. A transport\n * or non-404 HTTP failure throws a retryable availability error instead.\n */\n load(userId: string): Promise<RemoteUserIdentityCandidate | null>;\n}\n\nexport interface LocalUserIdentityCandidate {\n readonly encapsulationPublicKey: Uint8Array;\n readonly signingKeyFingerprint?: string | null | undefined;\n readonly signingPublicKey: Uint8Array;\n}\n\nexport interface TrustedUserIdentityService {\n createLink(appUrl: string): Promise<string>;\n verifyLink(link: string): Promise<TrustedUserIdentity>;\n resolvePinned(userId: string): Promise<TrustedUserIdentity | null>;\n /** The user this device's trust store already binds a signing key to. */\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocal(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<TrustedUserIdentity>;\n resolve(userId: string): Promise<TrustedUserIdentity | null>;\n}\n\nexport type TrustedUserIdentityResolver = TrustedUserIdentityService[\"resolve\"];\n\nexport interface TrustedUserIdentityServiceDependencies {\n readonly getExecSql: () => ExecSql | null;\n readonly getLocalIdentity: (\n userId: string,\n ) => LocalUserIdentityCandidate | null;\n readonly getLocalUserId: () => string | null;\n readonly identityTrustDomain: string | null;\n readonly now?: (() => Date) | undefined;\n readonly remoteSource: RemoteUserIdentitySource;\n}\n\nexport function brandTrustedUserIdentity(\n input: ValidatedUserIdentityCandidate,\n): TrustedUserIdentity {\n return {\n ...input,\n [trustedUserIdentityBrand]: trustedUserIdentityBrandValue,\n };\n}\n\nexport function isTrustedUserIdentity(\n value: unknown,\n): value is TrustedUserIdentity {\n return (\n typeof value === \"object\" &&\n value !== null &&\n Reflect.get(value, trustedUserIdentityBrand) ===\n trustedUserIdentityBrandValue\n );\n}\n"]}
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // Current SDK contract: unified device-first handles and atomic revision checks.
1
+ // SDK: verified identity links, read-only pins and device-first handles.
2
2
  // Authority loaders take exact heads, including cached citations. Obsolete
3
3
  // adapters are excluded; authored policy journals survive restart. See workflows/README.md.
4
4
  export { ApiRequestMetrics, } from "./internal/api-client/index.js";
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["// Current SDK contract: unified device-first handles and atomic revision checks.\n// Authority loaders take exact heads, including cached citations. Obsolete\n// adapters are excluded; authored policy journals survive restart. See workflows/README.md.\nexport {\n type ApiRequestCounts,\n type ApiRequestEndpointCounts,\n ApiRequestMetrics,\n type ApiRequestMetricsSnapshot,\n} from \"@tearleads/api-client\";\nexport type {\n AbandonOrganizationPolicyMutationInput,\n AddOrganizationGroupUserInput,\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n BlobInfoSortDirection,\n BlobInfoSortKey,\n BrowserLocalKeyringOptions,\n ClientDatabaseOptions,\n ContainerContents,\n ContainerContentsContextValue,\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerDocumentLinkInput,\n ContainerDocumentLinks,\n ContainerDocumentObjectSyncState,\n ContainerDocumentObjectSyncStatus,\n ContainerDocumentQueries,\n ContainerDocumentSidebarRow,\n ContainerInfo,\n ContainerInfoInput,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n ContainerNode,\n ContainerShareAccessLevel,\n CreateOrganizationOptions,\n DatabaseListener,\n DatabaseOptions,\n DatabaseSnapshot,\n DatabaseStatus,\n DeviceFirst,\n DeviceFirstContainerContents,\n DiscardUnreadableOrganizationPolicyMutationInput,\n DocumentAttachmentStatus,\n DocumentAttachmentUpload,\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n DocumentContextValue,\n DocumentInfo,\n DocumentInfoInput,\n DocumentList,\n DocumentSort,\n DocumentSortDirection,\n DocumentSortKey,\n DocumentStore,\n DocumentSubscriptionOptions,\n Documents,\n DocumentsRuntime,\n DomainScope,\n FileSaver,\n Identity,\n IdentityGenerationResult,\n IdentityKeyPackage,\n IdentityListener,\n IdentityOptions,\n IdentitySnapshot,\n ImportedOrganizationUser,\n IndexedDbLocalKeyringManifestStoreOptions,\n IndexedDbWrappingKeyKeystoreOptions,\n LinkDocumentToContainerInput,\n ListDocumentsInput,\n LocalKeyPurpose,\n LocalKeyring,\n LocalKeyringManifest,\n LocalKeyringManifestFormat,\n LocalKeyringManifestStorage,\n LocalKeyringManifestStore,\n LocalKeyringOptions,\n LocalKeyringPinCode,\n LocalKeyringScope,\n LocalKeyringSession,\n LocalOrganizationSummary,\n LocalProjectionReconciledDelta,\n LocalProjectionSnapshot,\n LocalProjectionView,\n LocalSecretContext,\n LocalStorageLocalKeyringManifestStoreOptions,\n Logger,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n NetworkListener,\n NetworkMode,\n NetworkStatusSource,\n NormalizedLocalKeyringScope,\n OpenContainerDocumentInput,\n OpenDocumentInput,\n OpenDocumentOptions,\n OrganizationBilling,\n OrganizationBillingHistory,\n OrganizationBillingHistoryEntry,\n OrganizationBillingManagementUrl,\n OrganizationBillingView,\n OrganizationContainerGrant,\n OrganizationContainerGrants,\n OrganizationDataUsage,\n OrganizationDirectory,\n OrganizationDirectoryAndGroups,\n OrganizationDirectoryUser,\n OrganizationGrantRef,\n OrganizationGroupContainer,\n OrganizationGroupContainers,\n OrganizationGroupDetails,\n OrganizationGroupMember,\n OrganizationGroupMembers,\n OrganizationGroupMutationReceipt,\n OrganizationGroupPolicyHistory,\n OrganizationGroupSummary,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n /** Verified organization display page with an optional older-page cursor. */\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationProfile,\n Organizations,\n OrganizationUserDetail,\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n // Persistence notifications distinguish placement changes from content saves.\n PersistedDocumentListener,\n PinCodeBrowserLocalKeyringOptions,\n PinCodeWrappingKeyKeystoreOptions,\n PurgeDocumentInput,\n PurgeDocumentResult,\n ReconciliationService,\n RemoveOrganizationGroupUserInput,\n ResolvedUserIdentity,\n SaveFileRequest,\n SecurityIncident,\n SecurityIncidentListener,\n SecurityIncidentObjectKind,\n SecurityIncidents,\n Session,\n SessionContext,\n SessionCreateOrganizationResult,\n SessionListener,\n SessionRecoverOrganizationResult,\n SessionRegistrationRefusal,\n SessionRegistrationResult,\n SessionSnapshot,\n SetActiveDocumentContainerInput,\n SetLinkedContainerIdsForDocument,\n UnlinkDocumentFromContainerInput,\n UnwrapLocalSecretInput,\n UserIdentities,\n UserSession,\n WrapLocalSecretInput,\n WrappedLocalSecretEnvelope,\n WrappedLocalSecretFormat,\n WrappingKeyHandle,\n WrappingKeyKeystore,\n WrappingKeyMaterialStorage,\n} from \"./client\";\nexport {\n type BlobStoreFactory,\n Blobs,\n type ClientOptions,\n createBrowserLocalKeyring,\n createBrowserLocalKeyringManifestStore,\n createBrowserNetworkStatusSource,\n createContainerDocumentObjectSyncState,\n createDomainScope,\n createIndexedDbLocalKeyringManifestStore,\n createIndexedDbWrappingKeyKeystore,\n createLocalKeyring,\n createLocalStorageLocalKeyringManifestStore,\n createMemoryLocalKeyringManifestStore,\n createMemoryWrappingKeyKeystore,\n createPinCodeBrowserLocalKeyring,\n createPinCodeWrappingKeyKeystore,\n createRevenueCatPurchases,\n createUnavailableDirectCheckout,\n createUnavailablePurchases,\n createWebViewLocalKeyring,\n Database,\n DEFAULT_DOCUMENT_ID,\n type DirectCheckoutAppearance,\n type DirectCheckoutCapability,\n type DirectCheckoutConfirmation,\n type DirectCheckoutSession,\n DirectCheckoutUnavailableError,\n decodeLocalKeyringSqliteKey,\n Events,\n type EventsListener,\n type EventsSnapshot,\n encodeLocalKeyringSqliteKey,\n enqueueReconciliationForEvents,\n IDENTITY_KEY_PACKAGE_FORMAT,\n isPinCodeWrappedLocalSecretEnvelope,\n LOCAL_KEYRING_MANIFEST_FORMAT,\n localKeyringScopeKey,\n Network,\n normalizeLocalKeyringScope,\n type PrincipalHistoryKeyProvider,\n type PrincipalHistoryKeyScope,\n PurchaseAbortedError,\n PurchaseAlreadyOwnedError,\n PurchaseCancelledError,\n PurchaseIdentityPendingError,\n PurchaseProviderStalledError,\n type PurchasesCapability,\n PurchasesUnavailableError,\n PurgedOrganizationRecoveryBillingRequiredError,\n parseLocalKeyringManifest,\n type RevenueCatBackend,\n type RevenueCatCustomerInfo,\n type RevenueCatPackage,\n type RevenueCatPurchasesConfig,\n SyncBillingGate,\n type SyncBillingGateListener,\n type SyncPurchaseResult,\n type SyncSubscriptionOption,\n serializeLocalKeyringManifest,\n Tearleads,\n WRAPPED_LOCAL_SECRET_FORMAT,\n} from \"./client\";\nexport type {\n BlobByteSource,\n BlobByteSourceInput,\n BlobBytes,\n BlobStore,\n DiscoveredDocumentInput,\n DocumentAttachment,\n DocumentClientProjectionDefinition,\n DocumentClientProjectionDeleteInput,\n DocumentClientProjectionSaveInput,\n DocumentFieldValidationIssue,\n DocumentProjection,\n DocumentProjectorDefinition,\n DocumentProjectorInput,\n DocumentProjectorRegistry,\n DocumentProjectorRegistryInput,\n DocumentRow,\n DocumentRowSummary,\n DocumentSummary,\n StoredDocumentKind,\n StoredDocumentState,\n StructuredDocumentMap,\n StructuredDocumentShape,\n StructuredDocumentText,\n ValidatedDocumentFields,\n} from \"./documents\";\nexport {\n addDocumentAttachments,\n blobByteSourceInputLength,\n createBlobByteSource,\n createDocumentProjectorRegistry,\n createDocumentSignerDeviceId,\n DEFAULT_DOCUMENT_ACCESS_EPOCH,\n DEFAULT_DOCUMENT_KIND,\n defaultDocumentProjectorRegistry,\n deriveStoredDocumentTitle,\n ensureDocumentAttachmentStructure,\n getDocumentAttachments,\n getDocumentClientProjectionTables,\n getStoredDocumentTypeLabel,\n getUntitledDocumentTitle,\n initializeStoredDocumentKind,\n projectStoredDocumentState,\n readBlobByteSource,\n readStoredDocumentState,\n readStringDocumentField,\n resolveOpIdAttribution,\n sameDocumentAttachments,\n summarizeDocumentContributors,\n writerByPeerId,\n writeStoredDocumentFields,\n} from \"./documents\";\nexport type {\n ContainerContentsSnapshot,\n ContainerContentsStoreRuntime,\n ContainerContentsStoreState,\n ContainerContentsStoreSyncAgent,\n ContainerContentsStoreSyncState,\n ContainerState,\n PurgeOptions,\n PurgeProgress,\n} from \"./stores/container-contents\";\nexport {\n createContainerContentsStore,\n createContainerContentsStoreState,\n createContainerContentsStoreSyncAgent,\n getOrCreateContainerContentsStore,\n isSystemContainerNode,\n requestContainerContentsDocumentPriming,\n subscribeToContainerContentsStore,\n updateContainerContentsSnapshot,\n updateContainerContentsStoreRuntime,\n} from \"./stores/container-contents\";\nexport type {\n DocumentSnapshot,\n DocumentStoreFacade,\n DocumentStoreOpenOptions,\n DocumentStoreRelinkInput,\n DocumentStructuredFieldPatch,\n} from \"./stores/documents\";\nexport {\n createDocumentStore,\n discardRegisteredDocumentLocalState,\n getOrCreateDocumentStore,\n openDocumentStore,\n requestDomainDocumentSync,\n subscribeToPersistedDocuments,\n} from \"./stores/documents\";\nexport type {\n EncryptedBlobStoreCipher,\n EncryptedBlobStoreKey,\n EncryptedBlobStoreOptions,\n WrapEncryptedBlobStoreOptions,\n} from \"./workflows/blobs\";\nexport {\n createBlobStore,\n createEncryptedBlobStore,\n createLazyEncryptedBlobStore,\n createMemoryBlobStore,\n decryptDocumentAttachmentBlob,\n hydrateDocumentAttachmentBlobs,\n purgeOpfsBlobStore,\n uploadDocumentAttachment,\n wrapEncryptedBlobStore,\n} from \"./workflows/blobs\";\nexport type {\n ContainerContentsRootAdopter,\n ContainerContentsRootAdoptionInput,\n ContainerContentsStoreWorkflowRuntime,\n ContainerContentsWorkflowRuntime,\n // Distinct from the canonical `ContainerDocumentLinkInput` (./client); the\n // documentQueries variant has a different shape, so it keeps a disambiguating\n // alias on the public surface.\n ContainerDocumentLinkInput as ContainerDocumentQueriesLinkInput,\n ContainerSystemSlotDefinition,\n PendingDownloadQueueItem,\n RecoveryFolder,\n} from \"./workflows/container-contents\";\nexport {\n createContainerContentsDocumentsRuntime,\n createContainerContentsProjectionUserKeyResolver,\n createContainerContentsStoreWorkflowRuntime,\n createContainerContentsSyncLane,\n createContainerContentsWorkflowRuntime,\n createContainerParentSyncLane,\n createInitializedContainerMetadataDocument,\n defaultContainerContentsPersistence,\n deriveContainerSystemSlot,\n initializeDocumentLinksSchema,\n listBlobInfo,\n listDocumentLinkedContainerIds,\n loadContainerInfo,\n loadContainerSyncWatermark,\n loadDocumentAttributionRanges,\n loadDocumentInfo,\n replaceDocumentLinks,\n saveContainerSyncWatermark,\n syncedContainerDocumentObjectSyncState,\n} from \"./workflows/container-contents\";\nexport type {\n AggregatedContainerKekLog,\n ContainerMutationAuthor,\n ContainerReciteApi,\n ContainerWriteRefusal,\n KeyringRebuildResult,\n MaterializedContainerRekeyPlan,\n} from \"./workflows/containers\";\nexport {\n buildMaterializedContainerRekeyPlan,\n buildRootContainerCreatePlan,\n ContainerAuthorAccessError,\n ContainerKekRepairInaccessibleError,\n ContainerKekRepairRequiredError,\n ContainerKeyringOverrideStaleError,\n ContainerPathTooDeepError,\n classifyContainerWriteRefusal,\n containerWriterProjectionFromRekeyPlan,\n createRemoteContainer,\n fetchContainerKekLog,\n GroupShareNameMismatchError,\n HistoricalWrapUnavailableError,\n type HistoricalWrapUnavailableReason,\n isProjectionVerificationCancelledError,\n moveRemoteContainer,\n rebuildKeyringEntriesFromLog,\n recoverKeyringEntryFromWraps,\n rekeyRemoteContainer,\n revokeRemoteContainer,\n rootContainerWriterProjectionFromCreatePlan,\n shareRemoteContainer,\n shareRemoteContainerWithGroup,\n} from \"./workflows/containers\";\nexport type {\n DocumentRecord,\n DocumentSyncContainerRekeyBuilder,\n DocumentSyncPullContinuation,\n DocumentSyncUpdateIsolationError,\n DocumentsPersistence,\n DocumentsWorkflowRuntime,\n DocumentsWorkflowRuntimeInput,\n IncomingDocumentSyncUpdateValidator,\n LocalAttachmentRecord,\n PendingAttachmentRecord,\n PendingUpdateInsert,\n PendingUpdateRecord,\n SyncRemoteDocumentInput,\n} from \"./workflows/documents\";\nexport {\n buildMaterializedDocumentCreatePlan,\n createDocumentProjectionUserKeyResolver,\n createDocumentsWorkflowRuntime,\n createRemoteDocument,\n DOCUMENT_SYNC_TRACE_FRAGMENT,\n DOCUMENT_SYNC_TRACE_PATTERN,\n DOCUMENTS_APP_KIND,\n DocumentRawHistoryUnavailableError,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n isDatabaseUnavailableError,\n isDocumentSyncUpdateIsolationError,\n persistedDocumentCreateStateFromResponse,\n readPullContinuation,\n syncRemoteDocument,\n unwrapContainerKekPath,\n unwrapDocumentContentKeyTarget,\n validateDocumentSyncUpdateImports,\n} from \"./workflows/documents\";\n// Nominal identity constructors are available only through the testing subpath\n// for low-level runtime tests.\nexport type {\n AcknowledgedPrincipalCurrentInput,\n AcknowledgedPrincipalCurrentRetirement,\n AcknowledgedPrincipalPredecessor,\n AuthoredPrincipalMutation,\n OrganizationGroupPolicyHistoryEntry,\n OrganizationNativePurchaseEligibility,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalMemberChangeType,\n OrganizationPrincipalPolicyHistory,\n OrganizationPrincipalPolicyHistoryEntry,\n PrincipalMutationJournalContext,\n PrincipalMutationJournalScope,\n PrincipalMutationResponse,\n ReconcileOrganizationDataUsageInput,\n} from \"./workflows/organizations\";\nexport {\n abandonJournaledPrincipalMutation,\n addOrganizationGroupUser,\n buildInitialGroupPolicyRequest,\n buildInitialMemberGroupPolicyRequest,\n buildOrganizationGroupPolicyHistory,\n buildOrganizationProfileDocumentPatch,\n buildRosterProfileDocumentPatch,\n captureAcknowledgedPrincipalPredecessor,\n checkNativePurchaseEligibility,\n createInitializedRosterProfileDocument,\n createOrganizationGroup,\n DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME,\n deriveOrganizationMetadataContainerSystemSlot,\n deriveOrganizationRosterProfileContainerSystemSlot,\n discardUnreadableJournaledPrincipalMutation,\n GroupMembershipNameMismatchError,\n getOrganizationProfileDocumentLocalId,\n getRosterProfileDocumentLocalId,\n importOrganizationUser,\n loadLocalOrganizationDataUsage,\n loadLocalOrganizationDirectoryAndGroups,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n PendingPrincipalMutationError,\n PrincipalMutationOutcomeUnknownError,\n ROSTER_PROFILE_DOCUMENT_KIND,\n readJournaledPrincipalMutation,\n readOrganizationProfileName,\n reconcileOrganizationDataUsage,\n reconcileOrganizationDirectoryAndGroups,\n recoverJournaledPrincipalMutation,\n removeOrganizationGroupUser,\n resolveOrganizationBillingView,\n retainAcknowledgedPrincipalCurrents,\n revokeOrganizationContainerGrant,\n startOrganizationTrial,\n submitJournaledPrincipalMutation,\n subscribeOrganizationReadModelInvalidation,\n UnreadablePrincipalMutationError,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n} from \"./workflows/organizations\";\nexport type {\n CacheReferencedPrincipalPoliciesOptions,\n PrincipalHistoryProtectionLease,\n ProjectionPolicyHistoryRecoveryOptions,\n RecoveredPrincipalPolicyHistory,\n RecoveredScopedPrincipalPolicyHistory,\n RecoverPrincipalPolicyHistoryOptions,\n RecoverScopedPrincipalPolicyHistoryOptions,\n} from \"./workflows/principals\";\nexport {\n cacheReferencedPrincipalPolicies,\n PrincipalPolicyHistoryReadError,\n recoverPrincipalPolicyHistory,\n recoverProjectionPolicyHistory,\n recoverScopedPrincipalPolicyHistory,\n} from \"./workflows/principals\";\nexport type {\n InitialRootMetadataBootstrap,\n ProvisionedSystemContainerSpec,\n RegisterIdentityInput,\n RegistrationApi,\n} from \"./workflows/registration\";\nexport {\n bootstrapRootContainer,\n buildInitialOrganizationPolicyRequest,\n createInitialRootMetadataBootstrap,\n persistRegistrationBootstrap,\n registerIdentity,\n} from \"./workflows/registration\";\nexport type {\n RootIdentitiesApi,\n RootIdentitiesPage,\n RootIdentitiesQueryInput,\n RootIdentity,\n RootIdentityDetail,\n RootIdentityOrganization,\n RootIdentitySession,\n RootRequestOutcome,\n} from \"./workflows/root\";\nexport {\n listRootDataUsageReport,\n listRootIdentities,\n listRootIdentityOrganizations,\n listRootOrganizationIdentities,\n listRootOrganizations,\n loadRootIdentity,\n loadRootOrganization,\n loadRootOrganizationDataUsage,\n type RootDataUsageApi,\n type RootDataUsageReportPage,\n type RootOrganization,\n type RootOrganizationDetail,\n type RootOrganizationIdentitiesPage,\n type RootOrganizationIdentity,\n type RootOrganizationPageQueryInput,\n type RootOrganizationsApi,\n type RootOrganizationsPage,\n type RootOrganizationsQueryInput,\n} from \"./workflows/root\";\nexport type {\n ClearRemoteSyncStateResult,\n DomainSyncCoordinator,\n DomainSyncSnapshot,\n RemoteResetInput,\n RemoteResetReplacement,\n SyncIdleOptions,\n SyncLane,\n SyncLaneConfig,\n SyncLaneLastAction,\n SyncLanePhase,\n SyncLaneSnapshot,\n SyncLaneStatus,\n} from \"./workflows/sync\";\nexport {\n clearRemoteSyncState,\n getDomainSyncCoordinatorSnapshot,\n getOrCreateDomainSyncCoordinator,\n hasDomainSyncCoordinatorPendingWork,\n requestAllDomainSyncLanes,\n subscribeToDomainSyncCoordinator,\n waitForDomainSyncCoordinatorToSettle,\n} from \"./workflows/sync\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["// SDK: verified identity links, read-only pins and device-first handles.\n// Authority loaders take exact heads, including cached citations. Obsolete\n// adapters are excluded; authored policy journals survive restart. See workflows/README.md.\nexport {\n type ApiRequestCounts,\n type ApiRequestEndpointCounts,\n ApiRequestMetrics,\n type ApiRequestMetricsSnapshot,\n} from \"@tearleads/api-client\";\nexport type {\n AbandonOrganizationPolicyMutationInput,\n AddOrganizationGroupUserInput,\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n BlobInfoSortDirection,\n BlobInfoSortKey,\n BrowserLocalKeyringOptions,\n ClientDatabaseOptions,\n ContainerContents,\n ContainerContentsContextValue,\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerDocumentLinkInput,\n ContainerDocumentLinks,\n ContainerDocumentObjectSyncState,\n ContainerDocumentObjectSyncStatus,\n ContainerDocumentQueries,\n ContainerDocumentSidebarRow,\n ContainerInfo,\n ContainerInfoInput,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n ContainerNode,\n ContainerShareAccessLevel,\n CreateOrganizationOptions,\n DatabaseListener,\n DatabaseOptions,\n DatabaseSnapshot,\n DatabaseStatus,\n DeviceFirst,\n DeviceFirstContainerContents,\n DiscardUnreadableOrganizationPolicyMutationInput,\n DocumentAttachmentStatus,\n DocumentAttachmentUpload,\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n DocumentContextValue,\n DocumentInfo,\n DocumentInfoInput,\n DocumentList,\n DocumentSort,\n DocumentSortDirection,\n DocumentSortKey,\n DocumentStore,\n DocumentSubscriptionOptions,\n Documents,\n DocumentsRuntime,\n DomainScope,\n FileSaver,\n Identity,\n IdentityGenerationResult,\n IdentityKeyPackage,\n IdentityListener,\n IdentityOptions,\n IdentitySnapshot,\n ImportedOrganizationUser,\n IndexedDbLocalKeyringManifestStoreOptions,\n IndexedDbWrappingKeyKeystoreOptions,\n LinkDocumentToContainerInput,\n ListDocumentsInput,\n LocalKeyPurpose,\n LocalKeyring,\n LocalKeyringManifest,\n LocalKeyringManifestFormat,\n LocalKeyringManifestStorage,\n LocalKeyringManifestStore,\n LocalKeyringOptions,\n LocalKeyringPinCode,\n LocalKeyringScope,\n LocalKeyringSession,\n LocalOrganizationSummary,\n LocalProjectionReconciledDelta,\n LocalProjectionSnapshot,\n LocalProjectionView,\n LocalSecretContext,\n LocalStorageLocalKeyringManifestStoreOptions,\n Logger,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n NetworkListener,\n NetworkMode,\n NetworkStatusSource,\n NormalizedLocalKeyringScope,\n OpenContainerDocumentInput,\n OpenDocumentInput,\n OpenDocumentOptions,\n OrganizationBilling,\n OrganizationBillingHistory,\n OrganizationBillingHistoryEntry,\n OrganizationBillingManagementUrl,\n OrganizationBillingView,\n OrganizationContainerGrant,\n OrganizationContainerGrants,\n OrganizationDataUsage,\n OrganizationDirectory,\n OrganizationDirectoryAndGroups,\n OrganizationDirectoryUser,\n OrganizationGrantRef,\n OrganizationGroupContainer,\n OrganizationGroupContainers,\n OrganizationGroupDetails,\n OrganizationGroupMember,\n OrganizationGroupMembers,\n OrganizationGroupMutationReceipt,\n OrganizationGroupPolicyHistory,\n OrganizationGroupSummary,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n /** Verified organization display page with an optional older-page cursor. */\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationProfile,\n Organizations,\n OrganizationUserDetail,\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n // Persistence notifications distinguish placement changes from content saves.\n PersistedDocumentListener,\n PinCodeBrowserLocalKeyringOptions,\n PinCodeWrappingKeyKeystoreOptions,\n PurgeDocumentInput,\n PurgeDocumentResult,\n ReconciliationService,\n RemoveOrganizationGroupUserInput,\n ResolvedUserIdentity,\n SaveFileRequest,\n SecurityIncident,\n SecurityIncidentListener,\n SecurityIncidentObjectKind,\n SecurityIncidents,\n Session,\n SessionContext,\n SessionCreateOrganizationResult,\n SessionListener,\n SessionRecoverOrganizationResult,\n SessionRegistrationRefusal,\n SessionRegistrationResult,\n SessionSnapshot,\n SetActiveDocumentContainerInput,\n SetLinkedContainerIdsForDocument,\n UnlinkDocumentFromContainerInput,\n UnwrapLocalSecretInput,\n UserIdentities,\n UserSession,\n WrapLocalSecretInput,\n WrappedLocalSecretEnvelope,\n WrappedLocalSecretFormat,\n WrappingKeyHandle,\n WrappingKeyKeystore,\n WrappingKeyMaterialStorage,\n} from \"./client\";\nexport {\n type BlobStoreFactory,\n Blobs,\n type ClientOptions,\n createBrowserLocalKeyring,\n createBrowserLocalKeyringManifestStore,\n createBrowserNetworkStatusSource,\n createContainerDocumentObjectSyncState,\n createDomainScope,\n createIndexedDbLocalKeyringManifestStore,\n createIndexedDbWrappingKeyKeystore,\n createLocalKeyring,\n createLocalStorageLocalKeyringManifestStore,\n createMemoryLocalKeyringManifestStore,\n createMemoryWrappingKeyKeystore,\n createPinCodeBrowserLocalKeyring,\n createPinCodeWrappingKeyKeystore,\n createRevenueCatPurchases,\n createUnavailableDirectCheckout,\n createUnavailablePurchases,\n createWebViewLocalKeyring,\n Database,\n DEFAULT_DOCUMENT_ID,\n type DirectCheckoutAppearance,\n type DirectCheckoutCapability,\n type DirectCheckoutConfirmation,\n type DirectCheckoutSession,\n DirectCheckoutUnavailableError,\n decodeLocalKeyringSqliteKey,\n Events,\n type EventsListener,\n type EventsSnapshot,\n encodeLocalKeyringSqliteKey,\n enqueueReconciliationForEvents,\n IDENTITY_KEY_PACKAGE_FORMAT,\n isPinCodeWrappedLocalSecretEnvelope,\n LOCAL_KEYRING_MANIFEST_FORMAT,\n localKeyringScopeKey,\n Network,\n normalizeLocalKeyringScope,\n type PrincipalHistoryKeyProvider,\n type PrincipalHistoryKeyScope,\n PurchaseAbortedError,\n PurchaseAlreadyOwnedError,\n PurchaseCancelledError,\n PurchaseIdentityPendingError,\n PurchaseProviderStalledError,\n type PurchasesCapability,\n PurchasesUnavailableError,\n PurgedOrganizationRecoveryBillingRequiredError,\n parseLocalKeyringManifest,\n type RevenueCatBackend,\n type RevenueCatCustomerInfo,\n type RevenueCatPackage,\n type RevenueCatPurchasesConfig,\n SyncBillingGate,\n type SyncBillingGateListener,\n type SyncPurchaseResult,\n type SyncSubscriptionOption,\n serializeLocalKeyringManifest,\n Tearleads,\n WRAPPED_LOCAL_SECRET_FORMAT,\n} from \"./client\";\nexport type {\n BlobByteSource,\n BlobByteSourceInput,\n BlobBytes,\n BlobStore,\n DiscoveredDocumentInput,\n DocumentAttachment,\n DocumentClientProjectionDefinition,\n DocumentClientProjectionDeleteInput,\n DocumentClientProjectionSaveInput,\n DocumentFieldValidationIssue,\n DocumentProjection,\n DocumentProjectorDefinition,\n DocumentProjectorInput,\n DocumentProjectorRegistry,\n DocumentProjectorRegistryInput,\n DocumentRow,\n DocumentRowSummary,\n DocumentSummary,\n StoredDocumentKind,\n StoredDocumentState,\n StructuredDocumentMap,\n StructuredDocumentShape,\n StructuredDocumentText,\n ValidatedDocumentFields,\n} from \"./documents\";\nexport {\n addDocumentAttachments,\n blobByteSourceInputLength,\n createBlobByteSource,\n createDocumentProjectorRegistry,\n createDocumentSignerDeviceId,\n DEFAULT_DOCUMENT_ACCESS_EPOCH,\n DEFAULT_DOCUMENT_KIND,\n defaultDocumentProjectorRegistry,\n deriveStoredDocumentTitle,\n ensureDocumentAttachmentStructure,\n getDocumentAttachments,\n getDocumentClientProjectionTables,\n getStoredDocumentTypeLabel,\n getUntitledDocumentTitle,\n initializeStoredDocumentKind,\n projectStoredDocumentState,\n readBlobByteSource,\n readStoredDocumentState,\n readStringDocumentField,\n resolveOpIdAttribution,\n sameDocumentAttachments,\n summarizeDocumentContributors,\n writerByPeerId,\n writeStoredDocumentFields,\n} from \"./documents\";\nexport type {\n ContainerContentsSnapshot,\n ContainerContentsStoreRuntime,\n ContainerContentsStoreState,\n ContainerContentsStoreSyncAgent,\n ContainerContentsStoreSyncState,\n ContainerState,\n PurgeOptions,\n PurgeProgress,\n} from \"./stores/container-contents\";\nexport {\n createContainerContentsStore,\n createContainerContentsStoreState,\n createContainerContentsStoreSyncAgent,\n getOrCreateContainerContentsStore,\n isSystemContainerNode,\n requestContainerContentsDocumentPriming,\n subscribeToContainerContentsStore,\n updateContainerContentsSnapshot,\n updateContainerContentsStoreRuntime,\n} from \"./stores/container-contents\";\nexport type {\n DocumentSnapshot,\n DocumentStoreFacade,\n DocumentStoreOpenOptions,\n DocumentStoreRelinkInput,\n DocumentStructuredFieldPatch,\n} from \"./stores/documents\";\nexport {\n createDocumentStore,\n discardRegisteredDocumentLocalState,\n getOrCreateDocumentStore,\n openDocumentStore,\n requestDomainDocumentSync,\n subscribeToPersistedDocuments,\n} from \"./stores/documents\";\nexport type {\n EncryptedBlobStoreCipher,\n EncryptedBlobStoreKey,\n EncryptedBlobStoreOptions,\n WrapEncryptedBlobStoreOptions,\n} from \"./workflows/blobs\";\nexport {\n createBlobStore,\n createEncryptedBlobStore,\n createLazyEncryptedBlobStore,\n createMemoryBlobStore,\n decryptDocumentAttachmentBlob,\n hydrateDocumentAttachmentBlobs,\n purgeOpfsBlobStore,\n uploadDocumentAttachment,\n wrapEncryptedBlobStore,\n} from \"./workflows/blobs\";\nexport type {\n ContainerContentsRootAdopter,\n ContainerContentsRootAdoptionInput,\n ContainerContentsStoreWorkflowRuntime,\n ContainerContentsWorkflowRuntime,\n // Distinct from the canonical `ContainerDocumentLinkInput` (./client); the\n // documentQueries variant has a different shape, so it keeps a disambiguating\n // alias on the public surface.\n ContainerDocumentLinkInput as ContainerDocumentQueriesLinkInput,\n ContainerSystemSlotDefinition,\n PendingDownloadQueueItem,\n RecoveryFolder,\n} from \"./workflows/container-contents\";\nexport {\n createContainerContentsDocumentsRuntime,\n createContainerContentsProjectionUserKeyResolver,\n createContainerContentsStoreWorkflowRuntime,\n createContainerContentsSyncLane,\n createContainerContentsWorkflowRuntime,\n createContainerParentSyncLane,\n createInitializedContainerMetadataDocument,\n defaultContainerContentsPersistence,\n deriveContainerSystemSlot,\n initializeDocumentLinksSchema,\n listBlobInfo,\n listDocumentLinkedContainerIds,\n loadContainerInfo,\n loadContainerSyncWatermark,\n loadDocumentAttributionRanges,\n loadDocumentInfo,\n replaceDocumentLinks,\n saveContainerSyncWatermark,\n syncedContainerDocumentObjectSyncState,\n} from \"./workflows/container-contents\";\nexport type {\n AggregatedContainerKekLog,\n ContainerMutationAuthor,\n ContainerReciteApi,\n ContainerWriteRefusal,\n KeyringRebuildResult,\n MaterializedContainerRekeyPlan,\n} from \"./workflows/containers\";\nexport {\n buildMaterializedContainerRekeyPlan,\n buildRootContainerCreatePlan,\n ContainerAuthorAccessError,\n ContainerKekRepairInaccessibleError,\n ContainerKekRepairRequiredError,\n ContainerKeyringOverrideStaleError,\n ContainerPathTooDeepError,\n classifyContainerWriteRefusal,\n containerWriterProjectionFromRekeyPlan,\n createRemoteContainer,\n fetchContainerKekLog,\n GroupShareNameMismatchError,\n HistoricalWrapUnavailableError,\n type HistoricalWrapUnavailableReason,\n isProjectionVerificationCancelledError,\n moveRemoteContainer,\n rebuildKeyringEntriesFromLog,\n recoverKeyringEntryFromWraps,\n rekeyRemoteContainer,\n revokeRemoteContainer,\n rootContainerWriterProjectionFromCreatePlan,\n shareRemoteContainer,\n shareRemoteContainerWithGroup,\n} from \"./workflows/containers\";\nexport type {\n DocumentRecord,\n DocumentSyncContainerRekeyBuilder,\n DocumentSyncPullContinuation,\n DocumentSyncUpdateIsolationError,\n DocumentsPersistence,\n DocumentsWorkflowRuntime,\n DocumentsWorkflowRuntimeInput,\n IncomingDocumentSyncUpdateValidator,\n LocalAttachmentRecord,\n PendingAttachmentRecord,\n PendingUpdateInsert,\n PendingUpdateRecord,\n SyncRemoteDocumentInput,\n} from \"./workflows/documents\";\nexport {\n buildMaterializedDocumentCreatePlan,\n createDocumentProjectionUserKeyResolver,\n createDocumentsWorkflowRuntime,\n createRemoteDocument,\n DOCUMENT_SYNC_TRACE_FRAGMENT,\n DOCUMENT_SYNC_TRACE_PATTERN,\n DOCUMENTS_APP_KIND,\n DocumentRawHistoryUnavailableError,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n isDatabaseUnavailableError,\n isDocumentSyncUpdateIsolationError,\n persistedDocumentCreateStateFromResponse,\n readPullContinuation,\n syncRemoteDocument,\n unwrapContainerKekPath,\n unwrapDocumentContentKeyTarget,\n validateDocumentSyncUpdateImports,\n} from \"./workflows/documents\";\n// Nominal identity constructors are available only through the testing subpath\n// for low-level runtime tests.\nexport type {\n AcknowledgedPrincipalCurrentInput,\n AcknowledgedPrincipalCurrentRetirement,\n AcknowledgedPrincipalPredecessor,\n AuthoredPrincipalMutation,\n OrganizationGroupPolicyHistoryEntry,\n OrganizationNativePurchaseEligibility,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalMemberChangeType,\n OrganizationPrincipalPolicyHistory,\n OrganizationPrincipalPolicyHistoryEntry,\n PrincipalMutationJournalContext,\n PrincipalMutationJournalScope,\n PrincipalMutationResponse,\n ReconcileOrganizationDataUsageInput,\n} from \"./workflows/organizations\";\nexport {\n abandonJournaledPrincipalMutation,\n addOrganizationGroupUser,\n buildInitialGroupPolicyRequest,\n buildInitialMemberGroupPolicyRequest,\n buildOrganizationGroupPolicyHistory,\n buildOrganizationProfileDocumentPatch,\n buildRosterProfileDocumentPatch,\n captureAcknowledgedPrincipalPredecessor,\n checkNativePurchaseEligibility,\n createInitializedRosterProfileDocument,\n createOrganizationGroup,\n DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME,\n deriveOrganizationMetadataContainerSystemSlot,\n deriveOrganizationRosterProfileContainerSystemSlot,\n discardUnreadableJournaledPrincipalMutation,\n GroupMembershipNameMismatchError,\n getOrganizationProfileDocumentLocalId,\n getRosterProfileDocumentLocalId,\n importOrganizationUser,\n loadLocalOrganizationDataUsage,\n loadLocalOrganizationDirectoryAndGroups,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n PendingPrincipalMutationError,\n PrincipalMutationOutcomeUnknownError,\n ROSTER_PROFILE_DOCUMENT_KIND,\n readJournaledPrincipalMutation,\n readOrganizationProfileName,\n reconcileOrganizationDataUsage,\n reconcileOrganizationDirectoryAndGroups,\n recoverJournaledPrincipalMutation,\n removeOrganizationGroupUser,\n resolveOrganizationBillingView,\n retainAcknowledgedPrincipalCurrents,\n revokeOrganizationContainerGrant,\n startOrganizationTrial,\n submitJournaledPrincipalMutation,\n subscribeOrganizationReadModelInvalidation,\n UnreadablePrincipalMutationError,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n} from \"./workflows/organizations\";\nexport type {\n CacheReferencedPrincipalPoliciesOptions,\n PrincipalHistoryProtectionLease,\n ProjectionPolicyHistoryRecoveryOptions,\n RecoveredPrincipalPolicyHistory,\n RecoveredScopedPrincipalPolicyHistory,\n RecoverPrincipalPolicyHistoryOptions,\n RecoverScopedPrincipalPolicyHistoryOptions,\n} from \"./workflows/principals\";\nexport {\n cacheReferencedPrincipalPolicies,\n PrincipalPolicyHistoryReadError,\n recoverPrincipalPolicyHistory,\n recoverProjectionPolicyHistory,\n recoverScopedPrincipalPolicyHistory,\n} from \"./workflows/principals\";\nexport type {\n InitialRootMetadataBootstrap,\n ProvisionedSystemContainerSpec,\n RegisterIdentityInput,\n RegistrationApi,\n} from \"./workflows/registration\";\nexport {\n bootstrapRootContainer,\n buildInitialOrganizationPolicyRequest,\n createInitialRootMetadataBootstrap,\n persistRegistrationBootstrap,\n registerIdentity,\n} from \"./workflows/registration\";\nexport type {\n RootIdentitiesApi,\n RootIdentitiesPage,\n RootIdentitiesQueryInput,\n RootIdentity,\n RootIdentityDetail,\n RootIdentityOrganization,\n RootIdentitySession,\n RootRequestOutcome,\n} from \"./workflows/root\";\nexport {\n listRootDataUsageReport,\n listRootIdentities,\n listRootIdentityOrganizations,\n listRootOrganizationIdentities,\n listRootOrganizations,\n loadRootIdentity,\n loadRootOrganization,\n loadRootOrganizationDataUsage,\n type RootDataUsageApi,\n type RootDataUsageReportPage,\n type RootOrganization,\n type RootOrganizationDetail,\n type RootOrganizationIdentitiesPage,\n type RootOrganizationIdentity,\n type RootOrganizationPageQueryInput,\n type RootOrganizationsApi,\n type RootOrganizationsPage,\n type RootOrganizationsQueryInput,\n} from \"./workflows/root\";\nexport type {\n ClearRemoteSyncStateResult,\n DomainSyncCoordinator,\n DomainSyncSnapshot,\n RemoteResetInput,\n RemoteResetReplacement,\n SyncIdleOptions,\n SyncLane,\n SyncLaneConfig,\n SyncLaneLastAction,\n SyncLanePhase,\n SyncLaneSnapshot,\n SyncLaneStatus,\n} from \"./workflows/sync\";\nexport {\n clearRemoteSyncState,\n getDomainSyncCoordinatorSnapshot,\n getOrCreateDomainSyncCoordinator,\n hasDomainSyncCoordinatorPendingWork,\n requestAllDomainSyncLanes,\n subscribeToDomainSyncCoordinator,\n waitForDomainSyncCoordinatorToSettle,\n} from \"./workflows/sync\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tearleads/client-sdk",
3
- "version": "0.1.44",
3
+ "version": "0.1.46",
4
4
  "description": "React-free Tearleads client runtime: local SQLite persistence, keys, sync, encrypted blobs, and domain workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1,4 +1,4 @@
1
- import { documentContainerProjectionTables, documentMoveIntentTables, documentProjectionTables, documentTables, } from "../../data/sqlite/schema.js";
1
+ import { documentContainerProjectionTables, documentPlacementIntentTables, documentProjectionTables, documentTables, LOCAL_INTENT_LANES, } from "../../data/sqlite/schema.js";
2
2
  import { ensureSqlTables } from "../../data/sqlite/sqlSchema.js";
3
3
  import { requestDocumentRuntimeTargetSync } from "./documentRuntimeTargetSync.js";
4
4
  import { listDocumentRuntimeTargetsForContainerSubtreeFromRuntime } from "./documentSubtreeQueries.js";
@@ -30,12 +30,7 @@ const PENDING_PRIME_LOCAL_ID_SQL = `
30
30
  AND pending.local_id = stored.local_id
31
31
  AND pending.update_id IS NOT NULL
32
32
  )
33
- OR EXISTS (
34
- SELECT 1
35
- FROM document_sync_failures failure
36
- WHERE failure.app_kind = 'documents'
37
- AND failure.local_id = stored.local_id
38
- )
33
+ OR stored.sync_failure_message IS NOT NULL
39
34
  OR EXISTS (
40
35
  SELECT 1
41
36
  FROM document_pending_attachments attachment
@@ -55,14 +50,15 @@ const STARTUP_DOCUMENT_SYNC_WORK_SQL = `
55
50
  WHERE EXISTS (${PENDING_PRIME_LOCAL_ID_SQL})
56
51
  OR EXISTS (
57
52
  SELECT 1
58
- FROM document_move_intents intent
53
+ FROM local_intents intent
59
54
  -- Blocked and parked denied moves count: blocked intents replay on
60
55
  -- every scan (the blocking condition can heal after hydration), and
61
56
  -- the once-per-launch replay makes denied moves retriable — so a
62
57
  -- relaunch whose only durable work is either kind must still schedule
63
58
  -- the structural pass that re-attempts it (row 7). Unavailable moves
64
59
  -- are excluded: no pass ever replays them (#2278 #4).
65
- WHERE intent.sync_status IN ('pending', 'blocked', 'denied')
60
+ WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'
61
+ AND intent.sync_status IN ('pending', 'blocked', 'denied')
66
62
  )
67
63
  LIMIT 1
68
64
  `;
@@ -73,7 +69,7 @@ export async function hasStartupDocumentSyncWork(runtimeOrExecSql) {
73
69
  await ensureSqlTables(execSql, [
74
70
  ...documentTables,
75
71
  ...documentProjectionTables,
76
- ...documentMoveIntentTables,
72
+ ...documentPlacementIntentTables,
77
73
  ]);
78
74
  const rows = await execSql(STARTUP_DOCUMENT_SYNC_WORK_SQL);
79
75
  return rows.length > 0;
@@ -1 +1 @@
1
- {"version":3,"file":"documentPriming.js","sourceRoot":"","sources":["documentPriming.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n documentContainerProjectionTables,\n documentMoveIntentTables,\n documentProjectionTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerDocumentPrimeHost,\n ContainerDocumentQueriesRuntime,\n} from \"./documentQueries/types\";\nimport { requestDocumentRuntimeTargetSync } from \"./documentRuntimeTargetSync\";\nimport { listDocumentRuntimeTargetsForContainerSubtreeFromRuntime } from \"./documentSubtreeQueries\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\n\ninterface PrimeRequiredDocumentCandidate {\n readonly localId: string;\n}\n\ninterface LoadedRootDocumentPrimeResult {\n readonly candidateCount: number;\n readonly orphanPrimedCount: number;\n readonly primedCount: number;\n readonly rootCount: number;\n readonly unroutableCount: number;\n}\n\n// Documents that still NEED a store opened at prime time: local-only creates,\n// queued outbound updates/attachments, an outgoing-delta marker behind the\n// stored content frontier (a deferred tail; encoding inequality\n// over-approximates, which only re-primes a store the old behavior always\n// primed), a never-hydrated document (a freshly discovered share whose\n// content pull the primed lane performs), or a document with a recorded sync\n// failure (a refused revalidation leaves no queued work, so the failure row\n// is the only ticket that re-drives the store — the retry that clears on the\n// next clean pass). Fully-synced hydrated documents are\n// deliberately absent: priming exists to re-drive durable work, and opening a\n// store per settled document is what made a 1000-document boot a storm.\nconst PENDING_PRIME_LOCAL_ID_SQL = `\n SELECT stored.local_id AS local_id\n FROM documents stored\n WHERE stored.app_kind = 'documents'\n AND (\n stored.document_id IS NULL\n OR stored.snapshot_end_version = ''\n OR stored.pull_continuation IS NOT NULL\n OR COALESCE(stored.pending_base_version, '') <> stored.snapshot_end_version\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = 'documents'\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1\n FROM document_sync_failures failure\n WHERE failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n )\n OR EXISTS (\n SELECT 1\n FROM document_pending_attachments attachment\n WHERE attachment.local_id = stored.local_id\n )\n )\n`;\n\nconst PENDING_PRIME_DOCUMENT_CANDIDATE_SQL = `\n SELECT pending.local_id AS local_id\n FROM (${PENDING_PRIME_LOCAL_ID_SQL}) pending\n ORDER BY pending.local_id ASC\n`;\n\n// The structural startup probe and the priming worker share the same durable\n// predicate so they cannot disagree about what counts as document work.\nconst STARTUP_DOCUMENT_SYNC_WORK_SQL = `\n SELECT 1 AS present\n WHERE EXISTS (${PENDING_PRIME_LOCAL_ID_SQL})\n OR EXISTS (\n SELECT 1\n FROM document_move_intents intent\n -- Blocked and parked denied moves count: blocked intents replay on\n -- every scan (the blocking condition can heal after hydration), and\n -- the once-per-launch replay makes denied moves retriable — so a\n -- relaunch whose only durable work is either kind must still schedule\n -- the structural pass that re-attempts it (row 7). Unavailable moves\n -- are excluded: no pass ever replays them (#2278 #4).\n WHERE intent.sync_status IN ('pending', 'blocked', 'denied')\n )\n LIMIT 1\n`;\n\nexport async function hasStartupDocumentSyncWork(\n runtimeOrExecSql:\n | ContainerDocumentQueriesRuntime\n | ContainerDocumentQueriesRuntime[\"infra\"][\"execSql\"],\n): Promise<boolean> {\n const execSql =\n typeof runtimeOrExecSql === \"function\"\n ? runtimeOrExecSql\n : runtimeOrExecSql.infra.execSql;\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(STARTUP_DOCUMENT_SYNC_WORK_SQL);\n return rows.length > 0;\n}\n\nasync function listPrimeRequiredDocumentCandidatesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<PrimeRequiredDocumentCandidate[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n PENDING_PRIME_DOCUMENT_CANDIDATE_SQL,\n );\n\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n return [{ localId }];\n });\n}\n\n// A row with content but a NULL outgoing-delta marker is deliberately treated\n// as unsettled: the store persist path always sets the marker, so over-priming\n// is the safe direction.\nasync function listPrimeRequiredLocalIdsFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<ReadonlySet<string>> {\n const candidates =\n await listPrimeRequiredDocumentCandidatesFromRuntime(runtime);\n return new Set(candidates.map((candidate) => candidate.localId));\n}\n\n/**\n * Last-link orphans (docs/sync-edge-cases.md row 3): the container cascade\n * nulled their projection container and dropped their link rows, so no\n * subtree listing can route them. Placements held for unsigned tombstones\n * also qualify when every link is hidden; their link rows remain intact.\n * These documents are primed with a null container\n * scope instead — the documents runtime accepts one, and the document's own\n * sync pass then resolves its fate against the server: 403 parks it (row 8),\n * a coded 404 destroys it (row 1), and a local-only orphan's create attempt\n * records a terminal failure row. Hidden document kinds stay excluded, and\n * dangling non-null projections (a container row merely missing locally)\n * stay with stale-root recovery, exactly as before.\n *\n * Organization neutrality: the null scope changes only the runtime's\n * containerId — auth, crypto, and organization plumbing are identical to\n * every container-scoped runtime this store already primes with, the sync\n * pass derives billing and keying organizations from the document's own\n * plan and manifest, and a cross-organization author fails closed at the\n * sync layer's identity guard before anything is signed.\n */\nconst ORPHANED_PRIME_TARGET_SQL = `\n SELECT stored.local_id AS local_id, stored.document_id AS document_id\n FROM documents stored\n INNER JOIN document_projection projection\n ON projection.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"stored.document_id\",\n projectionAlias: \"projection\",\n })}\n ORDER BY stored.local_id ASC\n`;\n\n/**\n * Unattributed rows (empty/NULL organization) are always included: they are\n * device-first documents created before authentication, which belong to this\n * device's sole user and adopt the active organization when they create.\n */\nasync function listOrphanedDocumentPrimeTargets(\n runtime: ContainerDocumentQueriesRuntime,\n organizationId: string,\n): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentContainerProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n ORPHANED_PRIME_TARGET_SQL,\n getOrphanedDocumentQueryBind(organizationId),\n );\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n const documentId = Reflect.get(row, \"document_id\");\n return [\n {\n documentId: typeof documentId === \"string\" ? documentId : null,\n localId,\n runtimeContainerId: null,\n },\n ];\n });\n}\n\nexport async function primeDocumentsForContainerSubtree<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n primeRequiredLocalIds?: ReadonlySet<string>;\n rootContainerId: string;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<number> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) return 0;\n const [targets, primeRequiredLocalIds] = await Promise.all([\n listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId: input.rootContainerId,\n runtime: input.runtime,\n }),\n input.primeRequiredLocalIds ??\n listPrimeRequiredLocalIdsFromRuntime(input.runtime),\n ]);\n if (!isCurrent()) return 0;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter((target) =>\n primeRequiredLocalIds.has(target.localId),\n ),\n });\n return primed.size;\n}\n\nexport async function primeDocumentsForLoadedRoots<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n /**\n * The store scope's organization. Orphan priming is bounded to it: each\n * organization-scoped store resolves only its own orphans, matching the\n * per-organization invariant subtree routing provides implicitly (a pass\n * signed under another organization would fail the sync identity guard\n * instead of resolving). Absent — unauthenticated or scope-less callers —\n * orphan priming is skipped entirely.\n */\n organizationId?: string | null;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<LoadedRootDocumentPrimeResult> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) {\n return {\n candidateCount: 0,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: 0,\n };\n }\n const candidates = await listPrimeRequiredDocumentCandidatesFromRuntime(\n input.runtime,\n );\n if (!isCurrent()) {\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: candidates.length,\n };\n }\n const rootContainerIds = Array.from(input.containersById.values()).flatMap(\n (containerState) =>\n containerState.container.parentId === null\n ? [containerState.container.id]\n : [],\n );\n const requiredLocalIds = new Set(\n candidates.map((candidate) => candidate.localId),\n );\n const primedLocalIds = new Set<string>();\n\n for (const rootContainerId of rootContainerIds) {\n if (!isCurrent()) break;\n const targets =\n await listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId,\n runtime: input.runtime,\n });\n if (!isCurrent()) break;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n ),\n });\n for (const localId of primed) {\n primedLocalIds.add(localId);\n }\n }\n\n const orphanTargets = (\n isCurrent() && input.organizationId\n ? await listOrphanedDocumentPrimeTargets(\n input.runtime,\n input.organizationId,\n )\n : []\n ).filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n );\n const orphanPrimed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: isCurrent() ? orphanTargets : [],\n });\n for (const localId of orphanPrimed) {\n primedLocalIds.add(localId);\n }\n\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: orphanPrimed.size,\n primedCount: primedLocalIds.size,\n rootCount: rootContainerIds.length,\n unroutableCount: candidates.filter(\n (candidate) => !primedLocalIds.has(candidate.localId),\n ).length,\n };\n}\n"]}
1
+ {"version":3,"file":"documentPriming.js","sourceRoot":"","sources":["documentPriming.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n documentContainerProjectionTables,\n documentPlacementIntentTables,\n documentProjectionTables,\n documentTables,\n LOCAL_INTENT_LANES,\n} from \"../../data/sqlite/schema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerDocumentPrimeHost,\n ContainerDocumentQueriesRuntime,\n} from \"./documentQueries/types\";\nimport { requestDocumentRuntimeTargetSync } from \"./documentRuntimeTargetSync\";\nimport { listDocumentRuntimeTargetsForContainerSubtreeFromRuntime } from \"./documentSubtreeQueries\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\n\ninterface PrimeRequiredDocumentCandidate {\n readonly localId: string;\n}\n\ninterface LoadedRootDocumentPrimeResult {\n readonly candidateCount: number;\n readonly orphanPrimedCount: number;\n readonly primedCount: number;\n readonly rootCount: number;\n readonly unroutableCount: number;\n}\n\n// Documents that still NEED a store opened at prime time: local-only creates,\n// queued outbound updates/attachments, an outgoing-delta marker behind the\n// stored content frontier (a deferred tail; encoding inequality\n// over-approximates, which only re-primes a store the old behavior always\n// primed), a never-hydrated document (a freshly discovered share whose\n// content pull the primed lane performs), or a document with a recorded sync\n// failure (a refused revalidation leaves no queued work, so the failure row\n// is the only ticket that re-drives the store — the retry that clears on the\n// next clean pass). Fully-synced hydrated documents are\n// deliberately absent: priming exists to re-drive durable work, and opening a\n// store per settled document is what made a 1000-document boot a storm.\nconst PENDING_PRIME_LOCAL_ID_SQL = `\n SELECT stored.local_id AS local_id\n FROM documents stored\n WHERE stored.app_kind = 'documents'\n AND (\n stored.document_id IS NULL\n OR stored.snapshot_end_version = ''\n OR stored.pull_continuation IS NOT NULL\n OR COALESCE(stored.pending_base_version, '') <> stored.snapshot_end_version\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = 'documents'\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n OR stored.sync_failure_message IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_pending_attachments attachment\n WHERE attachment.local_id = stored.local_id\n )\n )\n`;\n\nconst PENDING_PRIME_DOCUMENT_CANDIDATE_SQL = `\n SELECT pending.local_id AS local_id\n FROM (${PENDING_PRIME_LOCAL_ID_SQL}) pending\n ORDER BY pending.local_id ASC\n`;\n\n// The structural startup probe and the priming worker share the same durable\n// predicate so they cannot disagree about what counts as document work.\nconst STARTUP_DOCUMENT_SYNC_WORK_SQL = `\n SELECT 1 AS present\n WHERE EXISTS (${PENDING_PRIME_LOCAL_ID_SQL})\n OR EXISTS (\n SELECT 1\n FROM local_intents intent\n -- Blocked and parked denied moves count: blocked intents replay on\n -- every scan (the blocking condition can heal after hydration), and\n -- the once-per-launch replay makes denied moves retriable — so a\n -- relaunch whose only durable work is either kind must still schedule\n -- the structural pass that re-attempts it (row 7). Unavailable moves\n -- are excluded: no pass ever replays them (#2278 #4).\n WHERE intent.lane = '${LOCAL_INTENT_LANES.documentPlacement}'\n AND intent.sync_status IN ('pending', 'blocked', 'denied')\n )\n LIMIT 1\n`;\n\nexport async function hasStartupDocumentSyncWork(\n runtimeOrExecSql:\n | ContainerDocumentQueriesRuntime\n | ContainerDocumentQueriesRuntime[\"infra\"][\"execSql\"],\n): Promise<boolean> {\n const execSql =\n typeof runtimeOrExecSql === \"function\"\n ? runtimeOrExecSql\n : runtimeOrExecSql.infra.execSql;\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentPlacementIntentTables,\n ]);\n const rows = await execSql(STARTUP_DOCUMENT_SYNC_WORK_SQL);\n return rows.length > 0;\n}\n\nasync function listPrimeRequiredDocumentCandidatesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<PrimeRequiredDocumentCandidate[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n PENDING_PRIME_DOCUMENT_CANDIDATE_SQL,\n );\n\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n return [{ localId }];\n });\n}\n\n// A row with content but a NULL outgoing-delta marker is deliberately treated\n// as unsettled: the store persist path always sets the marker, so over-priming\n// is the safe direction.\nasync function listPrimeRequiredLocalIdsFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): Promise<ReadonlySet<string>> {\n const candidates =\n await listPrimeRequiredDocumentCandidatesFromRuntime(runtime);\n return new Set(candidates.map((candidate) => candidate.localId));\n}\n\n/**\n * Last-link orphans (docs/sync-edge-cases.md row 3): the container cascade\n * nulled their projection container and dropped their link rows, so no\n * subtree listing can route them. Placements held for unsigned tombstones\n * also qualify when every link is hidden; their link rows remain intact.\n * These documents are primed with a null container\n * scope instead — the documents runtime accepts one, and the document's own\n * sync pass then resolves its fate against the server: 403 parks it (row 8),\n * a coded 404 destroys it (row 1), and a local-only orphan's create attempt\n * records a terminal failure row. Hidden document kinds stay excluded, and\n * dangling non-null projections (a container row merely missing locally)\n * stay with stale-root recovery, exactly as before.\n *\n * Organization neutrality: the null scope changes only the runtime's\n * containerId — auth, crypto, and organization plumbing are identical to\n * every container-scoped runtime this store already primes with, the sync\n * pass derives billing and keying organizations from the document's own\n * plan and manifest, and a cross-organization author fails closed at the\n * sync layer's identity guard before anything is signed.\n */\nconst ORPHANED_PRIME_TARGET_SQL = `\n SELECT stored.local_id AS local_id, stored.document_id AS document_id\n FROM documents stored\n INNER JOIN document_projection projection\n ON projection.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"stored.document_id\",\n projectionAlias: \"projection\",\n })}\n ORDER BY stored.local_id ASC\n`;\n\n/**\n * Unattributed rows (empty/NULL organization) are always included: they are\n * device-first documents created before authentication, which belong to this\n * device's sole user and adopt the active organization when they create.\n */\nasync function listOrphanedDocumentPrimeTargets(\n runtime: ContainerDocumentQueriesRuntime,\n organizationId: string,\n): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n await ensureSqlTables(runtime.infra.execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentContainerProjectionTables,\n ]);\n const rows = await runtime.infra.execSql(\n ORPHANED_PRIME_TARGET_SQL,\n getOrphanedDocumentQueryBind(organizationId),\n );\n return rows.flatMap((row) => {\n const localId = Reflect.get(row, \"local_id\");\n if (typeof localId !== \"string\") {\n return [];\n }\n const documentId = Reflect.get(row, \"document_id\");\n return [\n {\n documentId: typeof documentId === \"string\" ? documentId : null,\n localId,\n runtimeContainerId: null,\n },\n ];\n });\n}\n\nexport async function primeDocumentsForContainerSubtree<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n primeRequiredLocalIds?: ReadonlySet<string>;\n rootContainerId: string;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<number> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) return 0;\n const [targets, primeRequiredLocalIds] = await Promise.all([\n listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId: input.rootContainerId,\n runtime: input.runtime,\n }),\n input.primeRequiredLocalIds ??\n listPrimeRequiredLocalIdsFromRuntime(input.runtime),\n ]);\n if (!isCurrent()) return 0;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter((target) =>\n primeRequiredLocalIds.has(target.localId),\n ),\n });\n return primed.size;\n}\n\nexport async function primeDocumentsForLoadedRoots<TRuntime>(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n host: ContainerDocumentPrimeHost<TRuntime>;\n isCurrent?: (() => boolean) | undefined;\n /**\n * The store scope's organization. Orphan priming is bounded to it: each\n * organization-scoped store resolves only its own orphans, matching the\n * per-organization invariant subtree routing provides implicitly (a pass\n * signed under another organization would fail the sync identity guard\n * instead of resolving). Absent — unauthenticated or scope-less callers —\n * orphan priming is skipped entirely.\n */\n organizationId?: string | null;\n runtime: ContainerDocumentQueriesRuntime;\n}): Promise<LoadedRootDocumentPrimeResult> {\n const isCurrent = input.isCurrent ?? (() => true);\n if (!isCurrent()) {\n return {\n candidateCount: 0,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: 0,\n };\n }\n const candidates = await listPrimeRequiredDocumentCandidatesFromRuntime(\n input.runtime,\n );\n if (!isCurrent()) {\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: 0,\n primedCount: 0,\n rootCount: 0,\n unroutableCount: candidates.length,\n };\n }\n const rootContainerIds = Array.from(input.containersById.values()).flatMap(\n (containerState) =>\n containerState.container.parentId === null\n ? [containerState.container.id]\n : [],\n );\n const requiredLocalIds = new Set(\n candidates.map((candidate) => candidate.localId),\n );\n const primedLocalIds = new Set<string>();\n\n for (const rootContainerId of rootContainerIds) {\n if (!isCurrent()) break;\n const targets =\n await listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n containersById: input.containersById,\n rootContainerId,\n runtime: input.runtime,\n });\n if (!isCurrent()) break;\n const primed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: targets.filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n ),\n });\n for (const localId of primed) {\n primedLocalIds.add(localId);\n }\n }\n\n const orphanTargets = (\n isCurrent() && input.organizationId\n ? await listOrphanedDocumentPrimeTargets(\n input.runtime,\n input.organizationId,\n )\n : []\n ).filter(\n (target) =>\n requiredLocalIds.has(target.localId) &&\n !primedLocalIds.has(target.localId),\n );\n const orphanPrimed = await requestDocumentRuntimeTargetSync({\n host: input.host,\n isCurrent,\n targets: isCurrent() ? orphanTargets : [],\n });\n for (const localId of orphanPrimed) {\n primedLocalIds.add(localId);\n }\n\n return {\n candidateCount: candidates.length,\n orphanPrimedCount: orphanPrimed.size,\n primedCount: primedLocalIds.size,\n rootCount: rootContainerIds.length,\n unroutableCount: candidates.filter(\n (candidate) => !primedLocalIds.has(candidate.localId),\n ).length,\n };\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { LOCAL_INTENT_LANES } from "../../../data/sqlite/schema.js";
1
2
  import { getOrphanedDocumentWhereSql } from "../orphanedDocumentSql.js";
2
3
  import { hydratedProjectionSql } from "./hydrationSql.js";
3
4
  // Keep each IN clause below SQLite's historical 999 bind-parameter limit.
@@ -56,8 +57,8 @@ export function getContainerContentsDocumentPendingStateCtes() {
56
57
  )
57
58
  `;
58
59
  }
59
- export function getContainerDisplayNameSql(aliases) {
60
- return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;
60
+ export function getContainerDisplayNameSql(containerAlias) {
61
+ return `COALESCE(${containerAlias}.display_name, CASE WHEN ${containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;
61
62
  }
62
63
  /**
63
64
  * Display attribution for an object reached through a container: the
@@ -74,7 +75,7 @@ function getContainerContentsContainerSystemSlotFilter(counts) {
74
75
  }
75
76
  if (counts.visibleForeignSystemContainerNameCount > 0) {
76
77
  const visibleSystemNameBindMarkers = Array.from({ length: counts.visibleForeignSystemContainerNameCount }, () => "?").join(", ");
77
- clauses.push(`(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: "c", projectionAlias: "cp" })} IN (${visibleSystemNameBindMarkers}))`);
78
+ clauses.push(`(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql("c")} IN (${visibleSystemNameBindMarkers}))`);
78
79
  }
79
80
  return `(${clauses.join(" OR ")})`;
80
81
  }
@@ -107,12 +108,13 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
107
108
  ),
108
109
  pending_container_create_intents AS (
109
110
  SELECT
110
- container_id,
111
+ subject_id AS container_id,
111
112
  MAX(last_error) AS last_error
112
- FROM container_create_intents
113
- WHERE intent_type = 'container.create'
113
+ FROM local_intents
114
+ WHERE lane = '${LOCAL_INTENT_LANES.containerCreate}'
115
+ AND intent_type = 'container.create'
114
116
  AND sync_status = 'pending'
115
- GROUP BY container_id
117
+ GROUP BY subject_id
116
118
  ),
117
119
  container_items AS (
118
120
  SELECT
@@ -125,17 +127,16 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
125
127
  c.local_updated_at AS local_updated_at,
126
128
  c.server_created_at AS server_created_at,
127
129
  c.server_updated_at AS server_updated_at,
128
- cp.icon AS icon,
130
+ c.icon AS icon,
129
131
  COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,
130
132
  0 AS pending_attachment_count,
131
133
  0 AS pending_attachment_bytes,
132
134
  create_intent.last_error AS sync_last_error,
133
- ${getContainerDisplayNameSql({ containerAlias: "c", projectionAlias: "cp" })} AS name,
135
+ ${getContainerDisplayNameSql("c")} AS name,
134
136
  'folder' AS type_sort,
135
137
  COALESCE(c.server_created_at, c.local_created_at) AS created_at,
136
138
  COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at
137
139
  FROM containers c
138
- LEFT JOIN container_projection cp ON cp.container_id = c.id
139
140
  LEFT JOIN container_metadata_pending_update_counts container_updates
140
141
  ON container_updates.local_id = c.id
141
142
  LEFT JOIN pending_container_create_intents create_intent