@tearleads/client-sdk 0.1.36 → 0.1.38
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.
- package/client/Tearleads.d.ts +4 -3
- package/client/Tearleads.js +4 -3
- package/client/Tearleads.js.map +1 -1
- package/client/organizations/organizationGroupHistory.js +1 -1
- package/client/organizations/organizationGroupHistory.js.map +1 -1
- package/client/organizations/organizationHistory.js +1 -1
- package/client/organizations/organizationHistory.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -2
- package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js +39 -51
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +1 -1
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js +4 -0
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js.map +1 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js +7 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js.map +1 -1
- package/data/principals/principalRecoveryEpoch.js +18 -0
- package/data/principals/principalRecoveryEpoch.js.map +1 -0
- package/internal/api-client/ApiClient.d.ts +3 -0
- package/internal/api-client/ApiClient.js +10 -7
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/webSocketTickets.js +45 -0
- package/internal/api-client/webSocketTickets.js.map +1 -0
- package/internal/validators/operation/auth.d.ts +20 -0
- package/internal/validators/realtime/index.js +2 -2
- package/internal/validators/realtime/index.js.map +1 -1
- package/internal/validators/realtime/wsServerFrames.js +3 -8
- package/internal/validators/realtime/wsServerFrames.js.map +1 -1
- package/internal/validators/realtime/wsShared.js +6 -0
- package/internal/validators/realtime/wsShared.js.map +1 -1
- package/internal/validators/response/auth/verify.d.ts +8 -0
- package/internal/validators/response/auth/verify.js +3 -0
- package/internal/validators/response/auth/verify.js.map +1 -1
- package/package.json +1 -1
- package/stores/documents/documentStore.js +3 -3
- package/stores/documents/documentStore.js.map +1 -1
- package/sync/reconciliation/service.js +22 -12
- package/sync/reconciliation/service.js.map +1 -1
- package/sync/reconciliation/serviceTypes.d.ts +10 -1
- package/sync/reconciliation/serviceTypes.js.map +1 -1
- package/workflows/organizations/currentGroupPolicyMutationContext.js +5 -5
- package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -1
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
- package/workflows/principals/principalRecoveryMemo.d.ts +9 -4
- package/workflows/principals/principalRecoveryMemo.js +94 -34
- package/workflows/principals/principalRecoveryMemo.js.map +1 -1
- package/workflows/principals/principalRecoveryMemoValidity.js +33 -0
- package/workflows/principals/principalRecoveryMemoValidity.js.map +1 -0
- package/workflows/principals/principalRecoveryOutage.js +2 -2
- package/workflows/principals/principalRecoveryOutage.js.map +1 -1
- package/workflows/principals/recoverCurrentOrganizationPolicy.js +8 -3
- package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js +42 -8
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverPublicPrincipalHistory.js +5 -5
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +9 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +8 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +4 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +12 -4
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
- package/workflows/runtimeInput.d.ts +4 -3
- package/workflows/runtimeInput.js.map +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { and, eq } from "drizzle-orm";
|
|
2
|
+
import { invalidatePrincipalRecovery } from "../../principals/principalRecoveryEpoch.js";
|
|
2
3
|
import { organizationDataUsageTables } from "../../sqlite/organizationDataUsageSchema.js";
|
|
3
4
|
import { organizationReadModelRequesters } from "../../sqlite/organizationReadModelSchema.js";
|
|
4
5
|
import { organizationReadModelTables } from "../../sqlite/schema.js";
|
|
@@ -41,5 +42,8 @@ export async function purgeOrganizationAccessProjection(input) {
|
|
|
41
42
|
tx,
|
|
42
43
|
});
|
|
43
44
|
});
|
|
45
|
+
// A denial is a realtime-hinted access change: in-flight operations recover
|
|
46
|
+
// the organization's directory again instead of reusing their memo.
|
|
47
|
+
invalidatePrincipalRecovery(input.execSql, input.organizationId);
|
|
44
48
|
}
|
|
45
49
|
//# sourceMappingURL=organizationAccessRevocationPersistence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationAccessRevocationPersistence.js","sourceRoot":"","sources":["organizationAccessRevocationPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,iCAAiC,EAAE,MAAM,uCAAuC,CAAC;AAE1F,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,iDAAiD,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,EAAE,iDAAiD,EAAE,MAAM,8BAA8B,CAAC;AAEjG,MAAM,kCAAkC,GAAG;IACzC,GAAG,2BAA2B;IAC9B,GAAG,2BAA2B;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAIvD;IACC,MAAM,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;IACzE,MAAM,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,CAChE,KAAK,EAAE,EAAE,EAAE,EAAE;QACX,MAAM,EAAE;aACL,MAAM,CAAC,+BAA+B,CAAC;aACvC,KAAK,CACJ,GAAG,CACD,EAAE,CACA,+BAA+B,CAAC,cAAc,EAC9C,KAAK,CAAC,cAAc,CACrB,EACD,EAAE,CAAC,+BAA+B,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAClE,CACF;aACA,GAAG,EAAE,CAAC;QACT,MAAM,CAAC,kBAAkB,CAAC,GAAG,MAAM,EAAE;aAClC,MAAM,CAAC,EAAE,MAAM,EAAE,+BAA+B,CAAC,MAAM,EAAE,CAAC;aAC1D,IAAI,CAAC,+BAA+B,CAAC;aACrC,KAAK,CACJ,EAAE,CACA,+BAA+B,CAAC,cAAc,EAC9C,KAAK,CAAC,cAAc,CACrB,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,MAAM,iDAAiD,CAAC;gBACtD,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,EAAE;aACH,CAAC,CAAC;QACL,CAAC;QACD,MAAM,iDAAiD,CAAC;YACtD,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,EAAE;SACH,CAAC,CAAC;IACL,CAAC,CACF,CAAC;
|
|
1
|
+
{"version":3,"file":"organizationAccessRevocationPersistence.js","sourceRoot":"","sources":["organizationAccessRevocationPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,iCAAiC,EAAE,MAAM,uCAAuC,CAAC;AAE1F,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,iDAAiD,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,EAAE,iDAAiD,EAAE,MAAM,8BAA8B,CAAC;AAEjG,MAAM,kCAAkC,GAAG;IACzC,GAAG,2BAA2B;IAC9B,GAAG,2BAA2B;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAIvD;IACC,MAAM,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;IACzE,MAAM,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,CAChE,KAAK,EAAE,EAAE,EAAE,EAAE;QACX,MAAM,EAAE;aACL,MAAM,CAAC,+BAA+B,CAAC;aACvC,KAAK,CACJ,GAAG,CACD,EAAE,CACA,+BAA+B,CAAC,cAAc,EAC9C,KAAK,CAAC,cAAc,CACrB,EACD,EAAE,CAAC,+BAA+B,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAClE,CACF;aACA,GAAG,EAAE,CAAC;QACT,MAAM,CAAC,kBAAkB,CAAC,GAAG,MAAM,EAAE;aAClC,MAAM,CAAC,EAAE,MAAM,EAAE,+BAA+B,CAAC,MAAM,EAAE,CAAC;aAC1D,IAAI,CAAC,+BAA+B,CAAC;aACrC,KAAK,CACJ,EAAE,CACA,+BAA+B,CAAC,cAAc,EAC9C,KAAK,CAAC,cAAc,CACrB,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,MAAM,iDAAiD,CAAC;gBACtD,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,EAAE;aACH,CAAC,CAAC;QACL,CAAC;QACD,MAAM,iDAAiD,CAAC;YACtD,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,EAAE;SACH,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IACF,4EAA4E;IAC5E,oEAAoE;IACpE,2BAA2B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { invalidatePrincipalRecovery } from \"../../principals/principalRecoveryEpoch\";\nimport { organizationDataUsageTables } from \"../../sqlite/organizationDataUsageSchema\";\nimport { organizationReadModelRequesters } from \"../../sqlite/organizationReadModelSchema\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../sqlite/sqlTableSchema\";\nimport { purgeOrganizationDataUsageProjectionInTransaction } from \"./organizationDataUsagePersistence\";\nimport { purgeOrganizationReadModelProjectionInTransaction } from \"./organizationReadModelPurge\";\n\nconst organizationAccessProjectionTables = [\n ...organizationReadModelTables,\n ...organizationDataUsageTables,\n];\n\n/**\n * Purge one requester's access to an organization's presentation projections\n * after the server denied that requester. The denial is requester-scoped: the\n * shared read-model rows stay while another local identity in the same\n * database still holds a requester row, and organization-wide rows fall with\n * the last requester.\n */\nexport async function purgeOrganizationAccessProjection(input: {\n readonly execSql: ExecSql;\n readonly organizationId: string;\n readonly requesterUserId: string;\n}): Promise<void> {\n await ensureSqlTables(input.execSql, organizationAccessProjectionTables);\n await getClientSQLitePersistenceRuntime(input.execSql).transaction(\n async (tx) => {\n await tx\n .delete(organizationReadModelRequesters)\n .where(\n and(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n eq(organizationReadModelRequesters.userId, input.requesterUserId),\n ),\n )\n .run();\n const [remainingRequester] = await tx\n .select({ userId: organizationReadModelRequesters.userId })\n .from(organizationReadModelRequesters)\n .where(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n )\n .limit(1);\n if (!remainingRequester) {\n await purgeOrganizationReadModelProjectionInTransaction({\n organizationId: input.organizationId,\n tx,\n });\n }\n await purgeOrganizationDataUsageProjectionInTransaction({\n organizationId: input.organizationId,\n requesterUserId: input.requesterUserId,\n tx,\n });\n },\n );\n // A denial is a realtime-hinted access change: in-flight operations recover\n // the organization's directory again instead of reusing their memo.\n invalidatePrincipalRecovery(input.execSql, input.organizationId);\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { eq } from "drizzle-orm";
|
|
2
|
+
import { invalidatePrincipalRecovery } from "../../principals/principalRecoveryEpoch.js";
|
|
2
3
|
import { organizationDataUsageTables } from "../../sqlite/organizationDataUsageSchema.js";
|
|
3
4
|
import { organizationReadModelDirectoryUsers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/organizationReadModelSchema.js";
|
|
4
5
|
import { organizationReadModelTables } from "../../sqlite/schema.js";
|
|
@@ -231,7 +232,7 @@ export async function applyOrganizationReadModelResponse(input) {
|
|
|
231
232
|
...organizationReadModelTables,
|
|
232
233
|
...organizationDataUsageTables,
|
|
233
234
|
]);
|
|
234
|
-
|
|
235
|
+
const disposition = await getClientSQLitePersistenceRuntime(input.execSql).transaction(async (tx) => {
|
|
235
236
|
const current = await loadCurrentState(tx, input.response.organizationId);
|
|
236
237
|
const disposition = resolveApplyDisposition({
|
|
237
238
|
current,
|
|
@@ -287,6 +288,11 @@ export async function applyOrganizationReadModelResponse(input) {
|
|
|
287
288
|
.run();
|
|
288
289
|
return "applied";
|
|
289
290
|
});
|
|
291
|
+
// An applied change follows an organization hint or mutation; in-flight
|
|
292
|
+
// operations recover the directory again instead of reusing their memo.
|
|
293
|
+
if (disposition === "applied")
|
|
294
|
+
invalidatePrincipalRecovery(input.execSql, input.response.organizationId);
|
|
295
|
+
return disposition;
|
|
290
296
|
}
|
|
291
297
|
export async function purgeOrganizationReadModelProjection(execSql, organizationId, options = {}) {
|
|
292
298
|
await ensureSqlTables(execSql, organizationReadModelTables);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationReadModelPersistence.js","sourceRoot":"","sources":["organizationReadModelPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ListOrganizationGroupsResponse,\n OrganizationReadModelDirectoryResponse,\n OrganizationReadModelResponse,\n} from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport { organizationDataUsageTables } from \"../../sqlite/organizationDataUsageSchema\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { clearOrganizationPresentationDenialInTransaction } from \"./organizationPresentationDenialPersistence\";\nimport { applyOrganizationReadModelGrantsLane } from \"./organizationReadModelGrantPersistence\";\nimport {\n applyGroupMembershipsLane,\n assertStoredGroupMembershipBindings,\n} from \"./organizationReadModelMembershipPersistence\";\nimport {\n applyOrganizationPolicyLane,\n replaceGroupPolicyHeads,\n} from \"./organizationReadModelPolicyHeadPersistence\";\nimport {\n loadOrganizationReadModelProjectionInTransaction,\n type OrganizationReadModelProjection,\n} from \"./organizationReadModelProjection\";\nimport {\n loadWithOrganizationReadModelIntegrityPurge,\n pruneInactiveOrganizationRequestersInTransaction,\n purgeOrganizationReadModelProjectionInTransaction,\n} from \"./organizationReadModelPurge\";\nimport { assertOrganizationReadModelResponse } from \"./organizationReadModelResponseAssertions\";\n\nexport type { OrganizationReadModelProjection } from \"./organizationReadModelProjection\";\n\nconst DIRECTORY_INSERT_BATCH_SIZE = 64;\nconst GROUP_INSERT_BATCH_SIZE = 90;\n\ntype ApplyOrganizationReadModelResponseResult =\n | \"already-applied\"\n | \"applied\"\n | \"stale\";\n\ninterface CurrentOrganizationReadModelState {\n readonly cursor: string;\n readonly memberGroupId: string;\n readonly profileDocumentId: string | null;\n}\n\nasync function replaceDirectoryLane(input: {\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n\n const rows = input.directory.users.map((user, sortOrder) => ({\n organizationId: input.organizationId,\n userId: user.userId,\n sortOrder,\n signingKeyFingerprint: user.signingKeyFingerprint,\n signingPublicKey: user.signingPublicKey,\n encapsulationPublicKey: user.encapsulationPublicKey,\n encapsulationKeyFingerprint: user.encapsulationKeyFingerprint,\n isPersonalOrganizationOwner: user.isPersonalOrganizationOwner,\n createdAt: user.createdAt,\n status: user.status,\n profileDocumentId: user.profileDocumentId,\n joinedAt: user.joinedAt,\n updatedAt: user.updatedAt,\n disabledAt: user.disabledAt,\n disabledByUserId: user.disabledByUserId,\n }));\n for (\n let index = 0;\n index < rows.length;\n index += DIRECTORY_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelDirectoryUsers)\n .values(rows.slice(index, index + DIRECTORY_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function upsertRequester(input: {\n readonly currentUserId: string;\n readonly isOrgAdmin: boolean;\n readonly now: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const requesterRow = {\n organizationId: input.organizationId,\n userId: input.currentUserId,\n isOrgAdmin: input.isOrgAdmin,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelRequesters)\n .values(requesterRow)\n .onConflictDoUpdate({\n target: [\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ],\n set: {\n isOrgAdmin: requesterRow.isOrgAdmin,\n updatedAt: requesterRow.updatedAt,\n },\n })\n .run();\n // Storing an authoritative response proves access: retire the durable\n // denial marker for this scope in the same transaction.\n await clearOrganizationPresentationDenialInTransaction({\n organizationId: input.organizationId,\n projection: \"readModel\",\n requesterUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\n/** The directory lane is the authoritative roster: requester rows for users\n * it no longer lists as active must fall with it. */\nasync function pruneRequestersForDirectoryLane(input: {\n readonly currentUserId: string;\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await pruneInactiveOrganizationRequestersInTransaction({\n activeUserIds: input.directory.users\n .filter((user) => user.status === \"active\")\n .map((user) => user.userId),\n organizationId: input.organizationId,\n retainUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\nasync function replaceGroupsLane(input: {\n readonly groups: ListOrganizationGroupsResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const previousGroups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n name: organizationReadModelGroups.name,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const names = new Map(\n previousGroups.map((group) => [group.groupId, group.name]),\n );\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n await replaceGroupPolicyHeads(input);\n\n const rows = input.groups.groups.map((group, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n sortOrder,\n name: names.get(group.groupId) ?? \"\",\n createdAt: group.createdAt,\n isBuiltin: group.isBuiltin,\n stateHash: group.currentState?.stateHash ?? null,\n stateVersion: group.currentState?.version ?? null,\n keyEpoch: group.currentState?.keyEpoch ?? null,\n memberCount: group.currentState?.memberCount ?? null,\n }));\n for (let index = 0; index < rows.length; index += GROUP_INSERT_BATCH_SIZE) {\n await input.tx\n .insert(organizationReadModelGroups)\n .values(rows.slice(index, index + GROUP_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function loadCurrentState(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<CurrentOrganizationReadModelState | null> {\n const [current] = await tx\n .select({\n cursor: organizationReadModelState.cursor,\n memberGroupId: organizationReadModelState.memberGroupId,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n return current ?? null;\n}\n\nfunction resolveApplyDisposition(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): ApplyOrganizationReadModelResponseResult | null {\n const currentCursor = input.current?.cursor ?? null;\n if (currentCursor !== input.requestedCursor) {\n return currentCursor === input.response.nextCursor\n ? \"already-applied\"\n : \"stale\";\n }\n if (!input.current && input.response.mode !== \"snapshot\") {\n throw new Error(\"Organization read-model delta requires a local snapshot\");\n }\n return null;\n}\n\nasync function replaceResponseLanes(input: {\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const directory = input.response.lanes.directory;\n if (directory) {\n await replaceDirectoryLane({\n directory,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n const groups = input.response.lanes.groups;\n if (groups) {\n await replaceGroupsLane({\n groups,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n const organizationPolicy = input.response.lanes.organizationPolicy;\n if (organizationPolicy) {\n await applyOrganizationPolicyLane({\n organizationId: input.response.organizationId,\n organizationPolicy,\n tx: input.tx,\n });\n }\n const groupMemberships = input.response.lanes.groupMemberships;\n if (groupMemberships) {\n await applyGroupMembershipsLane({\n lane: groupMemberships,\n organizationId: input.response.organizationId,\n replaceAll: input.response.mode === \"snapshot\",\n tx: input.tx,\n });\n }\n const grants = input.response.lanes.grants;\n if (grants) {\n await applyOrganizationReadModelGrantsLane({\n lane: grants,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n}\n\nasync function applyResponseLanes(input: {\n readonly currentUserId: string;\n readonly memberGroupId: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await replaceResponseLanes({ response: input.response, tx: input.tx });\n const directoryLane = input.response.lanes.directory;\n if (directoryLane) {\n await pruneRequestersForDirectoryLane({\n currentUserId: input.currentUserId,\n directory: directoryLane,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n if (input.response.lanes.groups || input.response.lanes.groupMemberships) {\n await assertStoredGroupMembershipBindings({\n memberGroupId: input.memberGroupId,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n}\n\nfunction requireMemberGroupId(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly response: OrganizationReadModelResponse;\n}): string {\n const memberGroupId =\n input.response.lanes.groups?.memberGroupId ?? input.current?.memberGroupId;\n if (!memberGroupId) {\n throw new Error(\"Organization read-model member group is missing\");\n }\n return memberGroupId;\n}\n\nexport async function loadOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelProjection | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: (tx) =>\n loadOrganizationReadModelProjectionInTransaction({\n currentUserId,\n organizationId,\n tx,\n }),\n });\n}\n\nexport async function applyOrganizationReadModelResponse(input: {\n readonly currentUserId: string;\n readonly execSql: ExecSql;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): Promise<ApplyOrganizationReadModelResponseResult> {\n assertOrganizationReadModelResponse({\n currentUserId: input.currentUserId,\n response: input.response,\n });\n // The requester prune below also retires pruned users' usage projections.\n await ensureSqlTables(input.execSql, [\n ...organizationReadModelTables,\n ...organizationDataUsageTables,\n ]);\n\n return getClientSQLitePersistenceRuntime(input.execSql).transaction(\n async (tx) => {\n const current = await loadCurrentState(tx, input.response.organizationId);\n const disposition = resolveApplyDisposition({\n current,\n requestedCursor: input.requestedCursor,\n response: input.response,\n });\n if (disposition === \"stale\") {\n return disposition;\n }\n const now = new Date().toISOString();\n await upsertRequester({\n currentUserId: input.currentUserId,\n isOrgAdmin: input.response.currentUser.isOrgAdmin,\n now,\n organizationId: input.response.organizationId,\n tx,\n });\n if (disposition === \"already-applied\") {\n return disposition;\n }\n const memberGroupId = requireMemberGroupId({\n current,\n response: input.response,\n });\n await applyResponseLanes({\n currentUserId: input.currentUserId,\n memberGroupId,\n response: input.response,\n tx,\n });\n const directoryLane = input.response.lanes.directory;\n const stateRow = {\n organizationId: input.response.organizationId,\n cursor: input.response.nextCursor,\n profileDocumentId:\n directoryLane !== undefined\n ? directoryLane.profileDocumentId\n : (current?.profileDocumentId ?? null),\n memberGroupId,\n updatedAt: now,\n };\n await tx\n .insert(organizationReadModelState)\n .values(stateRow)\n .onConflictDoUpdate({\n target: organizationReadModelState.organizationId,\n set: {\n cursor: stateRow.cursor,\n profileDocumentId: stateRow.profileDocumentId,\n memberGroupId: stateRow.memberGroupId,\n updatedAt: stateRow.updatedAt,\n },\n })\n .run();\n\n return \"applied\";\n },\n );\n}\n\nexport async function purgeOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n options: { readonly onlyRequesterUserId?: string } = {},\n): Promise<void> {\n await ensureSqlTables(execSql, organizationReadModelTables);\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (tx) => {\n await purgeOrganizationReadModelProjectionInTransaction({\n onlyRequesterUserId: options.onlyRequesterUserId,\n organizationId,\n tx,\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organizationReadModelPersistence.js","sourceRoot":"","sources":["organizationReadModelPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ListOrganizationGroupsResponse,\n OrganizationReadModelDirectoryResponse,\n OrganizationReadModelResponse,\n} from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport { invalidatePrincipalRecovery } from \"../../principals/principalRecoveryEpoch\";\nimport { organizationDataUsageTables } from \"../../sqlite/organizationDataUsageSchema\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { clearOrganizationPresentationDenialInTransaction } from \"./organizationPresentationDenialPersistence\";\nimport { applyOrganizationReadModelGrantsLane } from \"./organizationReadModelGrantPersistence\";\nimport {\n applyGroupMembershipsLane,\n assertStoredGroupMembershipBindings,\n} from \"./organizationReadModelMembershipPersistence\";\nimport {\n applyOrganizationPolicyLane,\n replaceGroupPolicyHeads,\n} from \"./organizationReadModelPolicyHeadPersistence\";\nimport {\n loadOrganizationReadModelProjectionInTransaction,\n type OrganizationReadModelProjection,\n} from \"./organizationReadModelProjection\";\nimport {\n loadWithOrganizationReadModelIntegrityPurge,\n pruneInactiveOrganizationRequestersInTransaction,\n purgeOrganizationReadModelProjectionInTransaction,\n} from \"./organizationReadModelPurge\";\nimport { assertOrganizationReadModelResponse } from \"./organizationReadModelResponseAssertions\";\n\nexport type { OrganizationReadModelProjection } from \"./organizationReadModelProjection\";\n\nconst DIRECTORY_INSERT_BATCH_SIZE = 64;\nconst GROUP_INSERT_BATCH_SIZE = 90;\n\ntype ApplyOrganizationReadModelResponseResult =\n | \"already-applied\"\n | \"applied\"\n | \"stale\";\n\ninterface CurrentOrganizationReadModelState {\n readonly cursor: string;\n readonly memberGroupId: string;\n readonly profileDocumentId: string | null;\n}\n\nasync function replaceDirectoryLane(input: {\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n\n const rows = input.directory.users.map((user, sortOrder) => ({\n organizationId: input.organizationId,\n userId: user.userId,\n sortOrder,\n signingKeyFingerprint: user.signingKeyFingerprint,\n signingPublicKey: user.signingPublicKey,\n encapsulationPublicKey: user.encapsulationPublicKey,\n encapsulationKeyFingerprint: user.encapsulationKeyFingerprint,\n isPersonalOrganizationOwner: user.isPersonalOrganizationOwner,\n createdAt: user.createdAt,\n status: user.status,\n profileDocumentId: user.profileDocumentId,\n joinedAt: user.joinedAt,\n updatedAt: user.updatedAt,\n disabledAt: user.disabledAt,\n disabledByUserId: user.disabledByUserId,\n }));\n for (\n let index = 0;\n index < rows.length;\n index += DIRECTORY_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelDirectoryUsers)\n .values(rows.slice(index, index + DIRECTORY_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function upsertRequester(input: {\n readonly currentUserId: string;\n readonly isOrgAdmin: boolean;\n readonly now: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const requesterRow = {\n organizationId: input.organizationId,\n userId: input.currentUserId,\n isOrgAdmin: input.isOrgAdmin,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelRequesters)\n .values(requesterRow)\n .onConflictDoUpdate({\n target: [\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ],\n set: {\n isOrgAdmin: requesterRow.isOrgAdmin,\n updatedAt: requesterRow.updatedAt,\n },\n })\n .run();\n // Storing an authoritative response proves access: retire the durable\n // denial marker for this scope in the same transaction.\n await clearOrganizationPresentationDenialInTransaction({\n organizationId: input.organizationId,\n projection: \"readModel\",\n requesterUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\n/** The directory lane is the authoritative roster: requester rows for users\n * it no longer lists as active must fall with it. */\nasync function pruneRequestersForDirectoryLane(input: {\n readonly currentUserId: string;\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await pruneInactiveOrganizationRequestersInTransaction({\n activeUserIds: input.directory.users\n .filter((user) => user.status === \"active\")\n .map((user) => user.userId),\n organizationId: input.organizationId,\n retainUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\nasync function replaceGroupsLane(input: {\n readonly groups: ListOrganizationGroupsResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const previousGroups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n name: organizationReadModelGroups.name,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const names = new Map(\n previousGroups.map((group) => [group.groupId, group.name]),\n );\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n await replaceGroupPolicyHeads(input);\n\n const rows = input.groups.groups.map((group, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n sortOrder,\n name: names.get(group.groupId) ?? \"\",\n createdAt: group.createdAt,\n isBuiltin: group.isBuiltin,\n stateHash: group.currentState?.stateHash ?? null,\n stateVersion: group.currentState?.version ?? null,\n keyEpoch: group.currentState?.keyEpoch ?? null,\n memberCount: group.currentState?.memberCount ?? null,\n }));\n for (let index = 0; index < rows.length; index += GROUP_INSERT_BATCH_SIZE) {\n await input.tx\n .insert(organizationReadModelGroups)\n .values(rows.slice(index, index + GROUP_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function loadCurrentState(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<CurrentOrganizationReadModelState | null> {\n const [current] = await tx\n .select({\n cursor: organizationReadModelState.cursor,\n memberGroupId: organizationReadModelState.memberGroupId,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n return current ?? null;\n}\n\nfunction resolveApplyDisposition(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): ApplyOrganizationReadModelResponseResult | null {\n const currentCursor = input.current?.cursor ?? null;\n if (currentCursor !== input.requestedCursor) {\n return currentCursor === input.response.nextCursor\n ? \"already-applied\"\n : \"stale\";\n }\n if (!input.current && input.response.mode !== \"snapshot\") {\n throw new Error(\"Organization read-model delta requires a local snapshot\");\n }\n return null;\n}\n\nasync function replaceResponseLanes(input: {\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const directory = input.response.lanes.directory;\n if (directory) {\n await replaceDirectoryLane({\n directory,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n const groups = input.response.lanes.groups;\n if (groups) {\n await replaceGroupsLane({\n groups,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n const organizationPolicy = input.response.lanes.organizationPolicy;\n if (organizationPolicy) {\n await applyOrganizationPolicyLane({\n organizationId: input.response.organizationId,\n organizationPolicy,\n tx: input.tx,\n });\n }\n const groupMemberships = input.response.lanes.groupMemberships;\n if (groupMemberships) {\n await applyGroupMembershipsLane({\n lane: groupMemberships,\n organizationId: input.response.organizationId,\n replaceAll: input.response.mode === \"snapshot\",\n tx: input.tx,\n });\n }\n const grants = input.response.lanes.grants;\n if (grants) {\n await applyOrganizationReadModelGrantsLane({\n lane: grants,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n}\n\nasync function applyResponseLanes(input: {\n readonly currentUserId: string;\n readonly memberGroupId: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await replaceResponseLanes({ response: input.response, tx: input.tx });\n const directoryLane = input.response.lanes.directory;\n if (directoryLane) {\n await pruneRequestersForDirectoryLane({\n currentUserId: input.currentUserId,\n directory: directoryLane,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n if (input.response.lanes.groups || input.response.lanes.groupMemberships) {\n await assertStoredGroupMembershipBindings({\n memberGroupId: input.memberGroupId,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n}\n\nfunction requireMemberGroupId(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly response: OrganizationReadModelResponse;\n}): string {\n const memberGroupId =\n input.response.lanes.groups?.memberGroupId ?? input.current?.memberGroupId;\n if (!memberGroupId) {\n throw new Error(\"Organization read-model member group is missing\");\n }\n return memberGroupId;\n}\n\nexport async function loadOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelProjection | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: (tx) =>\n loadOrganizationReadModelProjectionInTransaction({\n currentUserId,\n organizationId,\n tx,\n }),\n });\n}\n\nexport async function applyOrganizationReadModelResponse(input: {\n readonly currentUserId: string;\n readonly execSql: ExecSql;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): Promise<ApplyOrganizationReadModelResponseResult> {\n assertOrganizationReadModelResponse({\n currentUserId: input.currentUserId,\n response: input.response,\n });\n // The requester prune below also retires pruned users' usage projections.\n await ensureSqlTables(input.execSql, [\n ...organizationReadModelTables,\n ...organizationDataUsageTables,\n ]);\n\n const disposition = await getClientSQLitePersistenceRuntime(\n input.execSql,\n ).transaction(\n async (tx): Promise<ApplyOrganizationReadModelResponseResult> => {\n const current = await loadCurrentState(tx, input.response.organizationId);\n const disposition = resolveApplyDisposition({\n current,\n requestedCursor: input.requestedCursor,\n response: input.response,\n });\n if (disposition === \"stale\") {\n return disposition;\n }\n const now = new Date().toISOString();\n await upsertRequester({\n currentUserId: input.currentUserId,\n isOrgAdmin: input.response.currentUser.isOrgAdmin,\n now,\n organizationId: input.response.organizationId,\n tx,\n });\n if (disposition === \"already-applied\") {\n return disposition;\n }\n const memberGroupId = requireMemberGroupId({\n current,\n response: input.response,\n });\n await applyResponseLanes({\n currentUserId: input.currentUserId,\n memberGroupId,\n response: input.response,\n tx,\n });\n const directoryLane = input.response.lanes.directory;\n const stateRow = {\n organizationId: input.response.organizationId,\n cursor: input.response.nextCursor,\n profileDocumentId:\n directoryLane !== undefined\n ? directoryLane.profileDocumentId\n : (current?.profileDocumentId ?? null),\n memberGroupId,\n updatedAt: now,\n };\n await tx\n .insert(organizationReadModelState)\n .values(stateRow)\n .onConflictDoUpdate({\n target: organizationReadModelState.organizationId,\n set: {\n cursor: stateRow.cursor,\n profileDocumentId: stateRow.profileDocumentId,\n memberGroupId: stateRow.memberGroupId,\n updatedAt: stateRow.updatedAt,\n },\n })\n .run();\n\n return \"applied\";\n },\n );\n // An applied change follows an organization hint or mutation; in-flight\n // operations recover the directory again instead of reusing their memo.\n if (disposition === \"applied\")\n invalidatePrincipalRecovery(input.execSql, input.response.organizationId);\n return disposition;\n}\n\nexport async function purgeOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n options: { readonly onlyRequesterUserId?: string } = {},\n): Promise<void> {\n await ensureSqlTables(execSql, organizationReadModelTables);\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (tx) => {\n await purgeOrganizationReadModelProjectionInTransaction({\n onlyRequesterUserId: options.onlyRequesterUserId,\n organizationId,\n tx,\n });\n });\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Per database and organization, the number of applied organization hints in
|
|
2
|
+
// this process. Operation-scoped principal recovery records the value before
|
|
3
|
+
// producing a result and recovers again once it changes. Hints are lossy, so
|
|
4
|
+
// this only shortens reuse; each operation still discovers the current head.
|
|
5
|
+
const epochs = new WeakMap();
|
|
6
|
+
export function principalRecoveryEpoch(execSql, organizationId) {
|
|
7
|
+
return epochs.get(execSql)?.get(organizationId) ?? 0;
|
|
8
|
+
}
|
|
9
|
+
/** Evict recovered directory and Admins views for this organization. */
|
|
10
|
+
export function invalidatePrincipalRecovery(execSql, organizationId) {
|
|
11
|
+
let scoped = epochs.get(execSql);
|
|
12
|
+
if (!scoped) {
|
|
13
|
+
scoped = new Map();
|
|
14
|
+
epochs.set(execSql, scoped);
|
|
15
|
+
}
|
|
16
|
+
scoped.set(organizationId, (scoped.get(organizationId) ?? 0) + 1);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=principalRecoveryEpoch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalRecoveryEpoch.js","sourceRoot":"","sources":["principalRecoveryEpoch.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,MAAM,MAAM,GAAG,IAAI,OAAO,EAAgC,CAAC;AAE3D,MAAM,UAAU,sBAAsB,CACpC,OAAgB,EAChB,cAAsB;IAEtB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,2BAA2B,CACzC,OAAgB,EAChB,cAAsB;IAEtB,IAAI,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC","sourcesContent":["import type { ExecSql } from \"../sqlite/sqlSchema\";\n\n// Per database and organization, the number of applied organization hints in\n// this process. Operation-scoped principal recovery records the value before\n// producing a result and recovers again once it changes. Hints are lossy, so\n// this only shortens reuse; each operation still discovers the current head.\nconst epochs = new WeakMap<ExecSql, Map<string, number>>();\n\nexport function principalRecoveryEpoch(\n execSql: ExecSql,\n organizationId: string,\n): number {\n return epochs.get(execSql)?.get(organizationId) ?? 0;\n}\n\n/** Evict recovered directory and Admins views for this organization. */\nexport function invalidatePrincipalRecovery(\n execSql: ExecSql,\n organizationId: string,\n): void {\n let scoped = epochs.get(execSql);\n if (!scoped) {\n scoped = new Map();\n epochs.set(execSql, scoped);\n }\n scoped.set(organizationId, (scoped.get(organizationId) ?? 0) + 1);\n}\n"]}
|
|
@@ -27,6 +27,7 @@ export declare class ApiClient {
|
|
|
27
27
|
private readonly principalPolicyRequestsByKey;
|
|
28
28
|
private readonly principalPolicyRequests;
|
|
29
29
|
private readonly transport;
|
|
30
|
+
private readonly webSocketTickets;
|
|
30
31
|
private readonly request;
|
|
31
32
|
private readonly requestResult;
|
|
32
33
|
constructor(baseUrl?: string | null, instrumentation?: ApiRequestInstrumentation);
|
|
@@ -922,6 +923,7 @@ export declare class ApiClient {
|
|
|
922
923
|
rootContainerId: string | null;
|
|
923
924
|
token: string;
|
|
924
925
|
userId: string;
|
|
926
|
+
wsTicket: string;
|
|
925
927
|
error?: undefined;
|
|
926
928
|
} | null>;
|
|
927
929
|
authenticateWithChallenge(fingerprint: string, secretKey: Uint8Array, challengeHex: string): Promise<{
|
|
@@ -931,6 +933,7 @@ export declare class ApiClient {
|
|
|
931
933
|
rootContainerId: string | null;
|
|
932
934
|
token: string;
|
|
933
935
|
userId: string;
|
|
936
|
+
wsTicket: string;
|
|
934
937
|
error?: undefined;
|
|
935
938
|
} | null>;
|
|
936
939
|
getUserIdentity(userId: string): Promise<{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sign } from "../crypto/index.js";
|
|
2
|
-
import { bindBlobAttachmentOperation, cancelStripeSubscriptionOperation, challengeOperation, claimNativeOrganizationSubscriptionOperation, completeMultipartBlobStageOperation, createContainerOperation, createContainerWithMetadataDocumentOperation, createDocumentOperation, createOrganizationOperation, createStripeCheckoutOperation, createStripeCheckoutSessionOperation, createStripePortalOperation, deleteContainerOperation, destroySessionOperation, detachBlobAttachmentOperation, documentSyncOperation, getContainerKekLogOperation, getContainerReplacementAuthorizationsOperation, getContainerWriterProjectionOperation, getDocumentWriterProjectionOperation, getHealthOperation, getMultipartBlobStageOperation, getOrganizationBillingHistoryOperation, getOrganizationBillingManagementUrlOperation, getOrganizationBillingOperation, getOrganizationDataUsageOperation, getOrganizationNativePurchaseEligibilityOperation, getOrganizationReadModelOperation, getRootIdentityOperation, getRootOrganizationDataUsageOperation, getRootOrganizationOperation, getStripeCheckoutOptionsOperation, initiateMultipartBlobStageOperation, linkDocumentOperation, listContainerDocumentsOperation, listContainerParentLanesOperation, listDocumentAttachmentsOperation, listOrganizationGroupMembersOperation, listRootDataUsageReportOperation, listRootIdentitiesOperation, listRootIdentityOrganizationsOperation, listRootOrganizationIdentitiesOperation, listRootOrganizationsOperation, listSessionsOperation, logoutOperation, moveContainerOperation, reciteContainerOperation, registerOperation, rekeyContainerOperation, revokeContainerOperation, shareContainerOperation, startOrganizationTrialOperation, unlinkDocumentOperation, updateOrganizationProfileOperation, updateOrganizationRosterEntryOperation, userIdentityOperation, verifyOperation,
|
|
2
|
+
import { bindBlobAttachmentOperation, cancelStripeSubscriptionOperation, challengeOperation, claimNativeOrganizationSubscriptionOperation, completeMultipartBlobStageOperation, createContainerOperation, createContainerWithMetadataDocumentOperation, createDocumentOperation, createOrganizationOperation, createStripeCheckoutOperation, createStripeCheckoutSessionOperation, createStripePortalOperation, deleteContainerOperation, destroySessionOperation, detachBlobAttachmentOperation, documentSyncOperation, getContainerKekLogOperation, getContainerReplacementAuthorizationsOperation, getContainerWriterProjectionOperation, getDocumentWriterProjectionOperation, getHealthOperation, getMultipartBlobStageOperation, getOrganizationBillingHistoryOperation, getOrganizationBillingManagementUrlOperation, getOrganizationBillingOperation, getOrganizationDataUsageOperation, getOrganizationNativePurchaseEligibilityOperation, getOrganizationReadModelOperation, getRootIdentityOperation, getRootOrganizationDataUsageOperation, getRootOrganizationOperation, getStripeCheckoutOptionsOperation, initiateMultipartBlobStageOperation, linkDocumentOperation, listContainerDocumentsOperation, listContainerParentLanesOperation, listDocumentAttachmentsOperation, listOrganizationGroupMembersOperation, listRootDataUsageReportOperation, listRootIdentitiesOperation, listRootIdentityOrganizationsOperation, listRootOrganizationIdentitiesOperation, listRootOrganizationsOperation, listSessionsOperation, logoutOperation, moveContainerOperation, reciteContainerOperation, registerOperation, rekeyContainerOperation, revokeContainerOperation, shareContainerOperation, startOrganizationTrialOperation, unlinkDocumentOperation, updateOrganizationProfileOperation, updateOrganizationRosterEntryOperation, userIdentityOperation, verifyOperation, } from "../validators/operation/index.js";
|
|
3
3
|
import { BoundedCache } from "./ApiCache.js";
|
|
4
4
|
import { ApiRequestRuntime } from "./apiRequestRuntime.js";
|
|
5
5
|
import { getDocumentPurgeProof as readPurgeProof, purgeDocument as submitDocumentPurge, } from "./documentPurge.js";
|
|
@@ -25,6 +25,7 @@ import { updateOrganizationProfile as profileUpdate } from "./routes/organizatio
|
|
|
25
25
|
import { updateOrganizationRosterEntry as rosterUpdate } from "./routes/organizations/roster.js";
|
|
26
26
|
import { organizationStripeCheckout } from "./routes/organizations/stripeCheckout.js";
|
|
27
27
|
import { containerWriterProjection, documentWriterProjection, } from "./routes/writerProjections.js";
|
|
28
|
+
import { WebSocketTickets } from "./webSocketTickets.js";
|
|
28
29
|
import { CitingProjectionCache, evictWriterProjectionsCiting, } from "./writerProjectionCitations.js";
|
|
29
30
|
import { primeWriterProjectionSlot } from "./writerProjectionPrime.js";
|
|
30
31
|
import { writerProjectionRequests } from "./writerProjectionRequests.js";
|
|
@@ -49,6 +50,7 @@ export class ApiClient {
|
|
|
49
50
|
principalPolicyRequestsByKey = new BoundedCache();
|
|
50
51
|
principalPolicyRequests;
|
|
51
52
|
transport;
|
|
53
|
+
webSocketTickets;
|
|
52
54
|
request;
|
|
53
55
|
requestResult;
|
|
54
56
|
constructor(baseUrl, instrumentation) {
|
|
@@ -60,6 +62,7 @@ export class ApiClient {
|
|
|
60
62
|
this.requestResult = this.projectionHistory.wrapRequestResult(projectionRequests.requestResult);
|
|
61
63
|
this.transport = createOperationTransport(this.requestRuntime.responseRequest);
|
|
62
64
|
this.documentAttributionRequests = new DocumentAttributionRequests(this.transport);
|
|
65
|
+
this.webSocketTickets = new WebSocketTickets(this.transport, () => this.getAuthToken());
|
|
63
66
|
}
|
|
64
67
|
clearAuthScopedCaches() {
|
|
65
68
|
this.projectionHistory.clear();
|
|
@@ -191,11 +194,8 @@ export class ApiClient {
|
|
|
191
194
|
getRequestFailure(input) {
|
|
192
195
|
return this.requestRuntime.getRequestFailure(input);
|
|
193
196
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
params: {},
|
|
197
|
-
});
|
|
198
|
-
return response?.ticket ?? null;
|
|
197
|
+
requestWebSocketTicket() {
|
|
198
|
+
return this.webSocketTickets.next();
|
|
199
199
|
}
|
|
200
200
|
getHealth() {
|
|
201
201
|
return this.transport.request(getHealthOperation, { params: {} });
|
|
@@ -240,7 +240,10 @@ export class ApiClient {
|
|
|
240
240
|
body: { fingerprint, signature: Array.from(signed) },
|
|
241
241
|
params: {},
|
|
242
242
|
}, { retryOnSessionExpired: false });
|
|
243
|
-
|
|
243
|
+
if (!response?.authenticated)
|
|
244
|
+
return null;
|
|
245
|
+
this.webSocketTickets.rememberLogin(response);
|
|
246
|
+
return response;
|
|
244
247
|
}
|
|
245
248
|
getUserIdentity(userId) {
|
|
246
249
|
return cachedRequest(this.userIdentityRequestsByUserId, userId, () => this.request(authUserIdentity.path(userId), authUserIdentity.isResponse, authUserIdentity.method, undefined, undefined, userIdentityOperation));
|