@tearleads/client-sdk 0.1.46 → 0.1.47

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.
@@ -1816,7 +1816,6 @@ export declare class ApiClient {
1816
1816
  }[];
1817
1817
  } | null>;
1818
1818
  getOrganizationBillingManagementUrl(organizationId: string): Promise<{
1819
- canCancelDirectly: boolean;
1820
1819
  managementUrl: string | null;
1821
1820
  } | null>;
1822
1821
  getOrganizationNativePurchaseEligibility(organizationId: string, store: NativeSubscriptionStore): Promise<{
@@ -497,16 +497,12 @@ export declare const getOrganizationBillingManagementUrlOperation: Omit<{
497
497
  readonly path: "/organizations/{organizationId}/billing/management-url";
498
498
  readonly responses: {
499
499
  readonly 200: z.ZodType<{
500
- canCancelDirectly: boolean;
501
500
  managementUrl: string | null;
502
501
  }, {
503
- canCancelDirectly: boolean;
504
502
  managementUrl: string | null;
505
503
  }, z.core.$ZodTypeInternals<{
506
- canCancelDirectly: boolean;
507
504
  managementUrl: string | null;
508
505
  }, {
509
- canCancelDirectly: boolean;
510
506
  managementUrl: string | null;
511
507
  }>>;
512
508
  };
@@ -12,16 +12,12 @@ import { z } from "zod";
12
12
  * this response.
13
13
  */
14
14
  export declare const OrganizationBillingManagementUrlResponseSchema: z.ZodType<{
15
- canCancelDirectly: boolean;
16
15
  managementUrl: string | null;
17
16
  }, {
18
- canCancelDirectly: boolean;
19
17
  managementUrl: string | null;
20
18
  }, z.core.$ZodTypeInternals<{
21
- canCancelDirectly: boolean;
22
19
  managementUrl: string | null;
23
20
  }, {
24
- canCancelDirectly: boolean;
25
21
  managementUrl: string | null;
26
22
  }>>;
27
23
  export type OrganizationBillingManagementUrlResponse = z.infer<typeof OrganizationBillingManagementUrlResponseSchema>;
@@ -13,8 +13,6 @@ import { loosePlainObject } from "../schema.js";
13
13
  * this response.
14
14
  */
15
15
  export const OrganizationBillingManagementUrlResponseSchema = loosePlainObject({
16
- /** Retained for installed clients; current clients read this from the snapshot. */
17
- canCancelDirectly: z.boolean(),
18
16
  managementUrl: z.string().nullable(),
19
17
  });
20
18
  export function isOrganizationBillingManagementUrlResponse(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"organizationBillingManagementUrl.js","sourceRoot":"","sources":["organizationBillingManagementUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,8CAA8C,GAAG,gBAAgB,CAAC;IAC7E,mFAAmF;IACnF,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE;IAC9B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAMH,MAAM,UAAU,0CAA0C,CACxD,KAAc;IAEd,OAAO,8CAA8C,CAAC,SAAS,CAAC,KAAK,CAAC;SACnE,OAAO,CAAC;AACb,CAAC","sourcesContent":["import { z } from \"zod\";\nimport { loosePlainObject } from \"../schema\";\n\n/**\n * The subscription-management URL for an organization's paid subscription. The\n * server resolves it from the billing provider (RevenueCat) using the org's\n * stored customer id, so any org admin — not just the buyer whose device holds\n * the subscription — can reach the manage/cancel page. Native management\n * remains available for lapsed subscriptions so the buyer can repair a payment\n * issue. `managementUrl` is null when the organization has no native\n * provider-managed subscription, the provider exposes no management link, or\n * the lookup could not be completed. Which purchase system owns the\n * subscription is part of the billing snapshot (`subscriptionSource`), not of\n * this response.\n */\nexport const OrganizationBillingManagementUrlResponseSchema = loosePlainObject({\n /** Retained for installed clients; current clients read this from the snapshot. */\n canCancelDirectly: z.boolean(),\n managementUrl: z.string().nullable(),\n});\n\nexport type OrganizationBillingManagementUrlResponse = z.infer<\n typeof OrganizationBillingManagementUrlResponseSchema\n>;\n\nexport function isOrganizationBillingManagementUrlResponse(\n value: unknown,\n): value is OrganizationBillingManagementUrlResponse {\n return OrganizationBillingManagementUrlResponseSchema.safeParse(value)\n .success;\n}\n"]}
1
+ {"version":3,"file":"organizationBillingManagementUrl.js","sourceRoot":"","sources":["organizationBillingManagementUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,8CAA8C,GAAG,gBAAgB,CAAC;IAC7E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAMH,MAAM,UAAU,0CAA0C,CACxD,KAAc;IAEd,OAAO,8CAA8C,CAAC,SAAS,CAAC,KAAK,CAAC;SACnE,OAAO,CAAC;AACb,CAAC","sourcesContent":["import { z } from \"zod\";\nimport { loosePlainObject } from \"../schema\";\n\n/**\n * The subscription-management URL for an organization's paid subscription. The\n * server resolves it from the billing provider (RevenueCat) using the org's\n * stored customer id, so any org admin — not just the buyer whose device holds\n * the subscription — can reach the manage/cancel page. Native management\n * remains available for lapsed subscriptions so the buyer can repair a payment\n * issue. `managementUrl` is null when the organization has no native\n * provider-managed subscription, the provider exposes no management link, or\n * the lookup could not be completed. Which purchase system owns the\n * subscription is part of the billing snapshot (`subscriptionSource`), not of\n * this response.\n */\nexport const OrganizationBillingManagementUrlResponseSchema = loosePlainObject({\n managementUrl: z.string().nullable(),\n});\n\nexport type OrganizationBillingManagementUrlResponse = z.infer<\n typeof OrganizationBillingManagementUrlResponseSchema\n>;\n\nexport function isOrganizationBillingManagementUrlResponse(\n value: unknown,\n): value is OrganizationBillingManagementUrlResponse {\n return OrganizationBillingManagementUrlResponseSchema.safeParse(value)\n .success;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tearleads/client-sdk",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
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": {
@@ -75,21 +75,30 @@ function buildPrincipalPolicyHistoryEntries(bundle) {
75
75
  });
76
76
  return entries.reverse();
77
77
  }
78
+ // Entries run newest first; the oldest one held is the cursor for older
79
+ // entries unless it is genesis.
80
+ function olderEntriesCursor(entries) {
81
+ const oldestVersion = entries.at(-1)?.version;
82
+ return oldestVersion !== undefined && oldestVersion > 1
83
+ ? oldestVersion
84
+ : null;
85
+ }
78
86
  export function buildOrganizationGroupPolicyHistory(bundle, organizationId) {
87
+ const entries = buildPrincipalPolicyHistoryEntries(bundle);
79
88
  return {
80
- entries: buildPrincipalPolicyHistoryEntries(bundle),
89
+ entries,
81
90
  groupId: bundle.currentState.principalId,
91
+ nextBeforeVersion: olderEntriesCursor(entries),
82
92
  organizationId,
83
93
  principalId: bundle.currentState.principalId,
84
94
  principalType: "group",
85
95
  };
86
96
  }
87
97
  export function buildOrganizationPolicyHistory(bundle) {
98
+ const entries = buildPrincipalPolicyHistoryEntries(bundle);
88
99
  return {
89
- entries: buildPrincipalPolicyHistoryEntries(bundle).map((entry) => ({
90
- ...entry,
91
- groupChanges: null,
92
- })),
100
+ entries: entries.map((entry) => ({ ...entry, groupChanges: null })),
101
+ nextBeforeVersion: olderEntriesCursor(entries),
93
102
  organizationId: bundle.currentState.principalId,
94
103
  principalId: bundle.currentState.principalId,
95
104
  principalType: "organization",
@@ -1 +1 @@
1
- {"version":3,"file":"policyHistoryReadModel.js","sourceRoot":"","sources":["policyHistoryReadModel.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PrincipalPolicyBundleResponse,\n PrincipalProjectionMemberResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type {\n OrganizationGroupPolicyHistory,\n OrganizationPolicyHistory,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalPolicyHistoryEntry,\n} from \"./policyHistoryTypes\";\n\nexport type {\n OrganizationGroupPolicyHistory,\n OrganizationGroupPolicyHistoryEntry,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalMemberChangeType,\n OrganizationPrincipalPolicyHistory,\n OrganizationPrincipalPolicyHistoryEntry,\n} from \"./policyHistoryTypes\";\n\ninterface PrincipalPolicyHistoryState {\n readonly projection: ReadonlyArray<PrincipalProjectionMemberResponse>;\n readonly state: PrincipalStateResponse;\n}\n\nfunction projectionMemberKey(\n member: Pick<PrincipalProjectionMemberResponse, \"userId\">,\n): string {\n return member.userId;\n}\n\nfunction comparePrincipalMemberChanges(\n left: OrganizationPrincipalMemberChange,\n right: OrganizationPrincipalMemberChange,\n): number {\n return (\n left.userId.localeCompare(right.userId) ||\n left.changeType.localeCompare(right.changeType)\n );\n}\n\nexport function diffPrincipalProjectionMembers(input: {\n readonly current: ReadonlyArray<PrincipalProjectionMemberResponse>;\n readonly previous: ReadonlyArray<PrincipalProjectionMemberResponse>;\n}): OrganizationPrincipalMemberChange[] {\n const previousMembersByKey = new Map(\n input.previous.map((member) => [projectionMemberKey(member), member]),\n );\n const currentMembersByKey = new Map(\n input.current.map((member) => [projectionMemberKey(member), member]),\n );\n const changes: OrganizationPrincipalMemberChange[] = [];\n\n for (const currentMember of input.current) {\n const previousMember = previousMembersByKey.get(\n projectionMemberKey(currentMember),\n );\n if (!previousMember) {\n changes.push({\n changeType: \"added\",\n userId: currentMember.userId,\n nextRole: currentMember.role,\n previousRole: null,\n });\n continue;\n }\n\n if (previousMember.role !== currentMember.role) {\n changes.push({\n changeType: \"role_changed\",\n userId: currentMember.userId,\n nextRole: currentMember.role,\n previousRole: previousMember.role,\n });\n }\n }\n\n for (const previousMember of input.previous) {\n if (currentMembersByKey.has(projectionMemberKey(previousMember))) {\n continue;\n }\n\n changes.push({\n changeType: \"removed\",\n userId: previousMember.userId,\n nextRole: null,\n previousRole: previousMember.role,\n });\n }\n\n return changes.sort(comparePrincipalMemberChanges);\n}\n\nfunction principalPolicyHistoryStates(\n bundle: PrincipalPolicyBundleResponse,\n): PrincipalPolicyHistoryState[] {\n return [\n ...bundle.previousStates.map((entry) => ({\n projection: entry.projection,\n state: entry.state,\n })),\n {\n projection: bundle.currentProjection,\n state: bundle.currentState,\n },\n ].sort((left, right) => left.state.version - right.state.version);\n}\n\nfunction buildPrincipalPolicyHistoryEntries(\n bundle: PrincipalPolicyBundleResponse,\n): OrganizationPrincipalPolicyHistoryEntry[] {\n const states = principalPolicyHistoryStates(bundle);\n const entries = states.map((entry, index) => {\n const previousProjection = states[index - 1]?.projection ?? [];\n\n return {\n changes: diffPrincipalProjectionMembers({\n current: entry.projection,\n previous: previousProjection,\n }),\n createdAt: entry.state.createdAt,\n keyEpoch: entry.state.keyEpoch,\n memberCount: entry.state.memberCount,\n signedAt: entry.state.signedAt,\n signerUserId: entry.state.signerUserId,\n signerUserKeyFingerprint: entry.state.signerUserKeyFingerprint,\n stateHash: entry.state.stateHash,\n version: entry.state.version,\n };\n });\n\n return entries.reverse();\n}\n\nexport function buildOrganizationGroupPolicyHistory(\n bundle: PrincipalPolicyBundleResponse,\n organizationId: string,\n): OrganizationGroupPolicyHistory {\n return {\n entries: buildPrincipalPolicyHistoryEntries(bundle),\n groupId: bundle.currentState.principalId,\n organizationId,\n principalId: bundle.currentState.principalId,\n principalType: \"group\",\n };\n}\n\nexport function buildOrganizationPolicyHistory(\n bundle: PrincipalPolicyBundleResponse,\n): OrganizationPolicyHistory {\n return {\n entries: buildPrincipalPolicyHistoryEntries(bundle).map((entry) => ({\n ...entry,\n groupChanges: null,\n })),\n organizationId: bundle.currentState.principalId,\n principalId: bundle.currentState.principalId,\n principalType: \"organization\",\n };\n}\n"]}
1
+ {"version":3,"file":"policyHistoryReadModel.js","sourceRoot":"","sources":["policyHistoryReadModel.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PrincipalPolicyBundleResponse,\n PrincipalProjectionMemberResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type {\n OrganizationGroupPolicyHistory,\n OrganizationPolicyHistory,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalPolicyHistoryEntry,\n} from \"./policyHistoryTypes\";\n\nexport type {\n OrganizationGroupPolicyHistory,\n OrganizationGroupPolicyHistoryEntry,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationPrincipalMemberChange,\n OrganizationPrincipalMemberChangeType,\n OrganizationPrincipalPolicyHistory,\n OrganizationPrincipalPolicyHistoryEntry,\n} from \"./policyHistoryTypes\";\n\ninterface PrincipalPolicyHistoryState {\n readonly projection: ReadonlyArray<PrincipalProjectionMemberResponse>;\n readonly state: PrincipalStateResponse;\n}\n\nfunction projectionMemberKey(\n member: Pick<PrincipalProjectionMemberResponse, \"userId\">,\n): string {\n return member.userId;\n}\n\nfunction comparePrincipalMemberChanges(\n left: OrganizationPrincipalMemberChange,\n right: OrganizationPrincipalMemberChange,\n): number {\n return (\n left.userId.localeCompare(right.userId) ||\n left.changeType.localeCompare(right.changeType)\n );\n}\n\nexport function diffPrincipalProjectionMembers(input: {\n readonly current: ReadonlyArray<PrincipalProjectionMemberResponse>;\n readonly previous: ReadonlyArray<PrincipalProjectionMemberResponse>;\n}): OrganizationPrincipalMemberChange[] {\n const previousMembersByKey = new Map(\n input.previous.map((member) => [projectionMemberKey(member), member]),\n );\n const currentMembersByKey = new Map(\n input.current.map((member) => [projectionMemberKey(member), member]),\n );\n const changes: OrganizationPrincipalMemberChange[] = [];\n\n for (const currentMember of input.current) {\n const previousMember = previousMembersByKey.get(\n projectionMemberKey(currentMember),\n );\n if (!previousMember) {\n changes.push({\n changeType: \"added\",\n userId: currentMember.userId,\n nextRole: currentMember.role,\n previousRole: null,\n });\n continue;\n }\n\n if (previousMember.role !== currentMember.role) {\n changes.push({\n changeType: \"role_changed\",\n userId: currentMember.userId,\n nextRole: currentMember.role,\n previousRole: previousMember.role,\n });\n }\n }\n\n for (const previousMember of input.previous) {\n if (currentMembersByKey.has(projectionMemberKey(previousMember))) {\n continue;\n }\n\n changes.push({\n changeType: \"removed\",\n userId: previousMember.userId,\n nextRole: null,\n previousRole: previousMember.role,\n });\n }\n\n return changes.sort(comparePrincipalMemberChanges);\n}\n\nfunction principalPolicyHistoryStates(\n bundle: PrincipalPolicyBundleResponse,\n): PrincipalPolicyHistoryState[] {\n return [\n ...bundle.previousStates.map((entry) => ({\n projection: entry.projection,\n state: entry.state,\n })),\n {\n projection: bundle.currentProjection,\n state: bundle.currentState,\n },\n ].sort((left, right) => left.state.version - right.state.version);\n}\n\nfunction buildPrincipalPolicyHistoryEntries(\n bundle: PrincipalPolicyBundleResponse,\n): OrganizationPrincipalPolicyHistoryEntry[] {\n const states = principalPolicyHistoryStates(bundle);\n const entries = states.map((entry, index) => {\n const previousProjection = states[index - 1]?.projection ?? [];\n\n return {\n changes: diffPrincipalProjectionMembers({\n current: entry.projection,\n previous: previousProjection,\n }),\n createdAt: entry.state.createdAt,\n keyEpoch: entry.state.keyEpoch,\n memberCount: entry.state.memberCount,\n signedAt: entry.state.signedAt,\n signerUserId: entry.state.signerUserId,\n signerUserKeyFingerprint: entry.state.signerUserKeyFingerprint,\n stateHash: entry.state.stateHash,\n version: entry.state.version,\n };\n });\n\n return entries.reverse();\n}\n\n// Entries run newest first; the oldest one held is the cursor for older\n// entries unless it is genesis.\nfunction olderEntriesCursor(\n entries: ReadonlyArray<OrganizationPrincipalPolicyHistoryEntry>,\n): number | null {\n const oldestVersion = entries.at(-1)?.version;\n return oldestVersion !== undefined && oldestVersion > 1\n ? oldestVersion\n : null;\n}\n\nexport function buildOrganizationGroupPolicyHistory(\n bundle: PrincipalPolicyBundleResponse,\n organizationId: string,\n): OrganizationGroupPolicyHistory {\n const entries = buildPrincipalPolicyHistoryEntries(bundle);\n return {\n entries,\n groupId: bundle.currentState.principalId,\n nextBeforeVersion: olderEntriesCursor(entries),\n organizationId,\n principalId: bundle.currentState.principalId,\n principalType: \"group\",\n };\n}\n\nexport function buildOrganizationPolicyHistory(\n bundle: PrincipalPolicyBundleResponse,\n): OrganizationPolicyHistory {\n const entries = buildPrincipalPolicyHistoryEntries(bundle);\n return {\n entries: entries.map((entry) => ({ ...entry, groupChanges: null })),\n nextBeforeVersion: olderEntriesCursor(entries),\n organizationId: bundle.currentState.principalId,\n principalId: bundle.currentState.principalId,\n principalType: \"organization\",\n };\n}\n"]}
@@ -24,14 +24,15 @@ export interface OrganizationPrincipalPolicyHistory {
24
24
  readonly principalType: PrincipalStateResponse["principalType"];
25
25
  }
26
26
  export interface OrganizationGroupPolicyHistory extends OrganizationPrincipalPolicyHistory {
27
- /** Exclusive cursor for older entries; absent on a legacy complete history. */
28
- readonly nextBeforeVersion?: number | null;
27
+ /** Exclusive cursor for older entries; null once the oldest is loaded. */
28
+ readonly nextBeforeVersion: number | null;
29
29
  readonly groupId: string;
30
30
  readonly organizationId: string;
31
31
  readonly principalType: "group";
32
32
  }
33
33
  export interface OrganizationPolicyHistory extends OrganizationPrincipalPolicyHistory {
34
- readonly nextBeforeVersion?: number | null;
34
+ /** Exclusive cursor for older entries; null once the oldest is loaded. */
35
+ readonly nextBeforeVersion: number | null;
35
36
  readonly entries: OrganizationPolicyHistoryEntry[];
36
37
  readonly organizationId: string;
37
38
  readonly principalType: "organization";
@@ -1 +1 @@
1
- {"version":3,"file":"policyHistoryTypes.js","sourceRoot":"","sources":["policyHistoryTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n PrincipalContainerGrantResponse,\n PrincipalProjectionMemberResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\n\nexport type OrganizationPrincipalMemberChangeType =\n | \"added\"\n | \"removed\"\n | \"role_changed\";\nexport interface OrganizationPrincipalMemberChange {\n readonly changeType: OrganizationPrincipalMemberChangeType;\n readonly userId: string;\n readonly nextRole: PrincipalProjectionMemberResponse[\"role\"] | null;\n readonly previousRole: PrincipalProjectionMemberResponse[\"role\"] | null;\n}\nexport interface OrganizationPrincipalPolicyHistoryEntry {\n readonly changes: OrganizationPrincipalMemberChange[];\n readonly createdAt: string;\n readonly keyEpoch: number;\n readonly memberCount: number;\n readonly signedAt: string;\n readonly signerUserId: string;\n readonly signerUserKeyFingerprint: string;\n readonly stateHash: string;\n readonly version: number;\n}\nexport type OrganizationGroupPolicyHistoryEntry =\n OrganizationPrincipalPolicyHistoryEntry;\nexport interface OrganizationPrincipalPolicyHistory {\n readonly entries: OrganizationPrincipalPolicyHistoryEntry[];\n readonly principalId: string;\n readonly principalType: PrincipalStateResponse[\"principalType\"];\n}\nexport interface OrganizationGroupPolicyHistory\n extends OrganizationPrincipalPolicyHistory {\n /** Exclusive cursor for older entries; absent on a legacy complete history. */\n readonly nextBeforeVersion?: number | null;\n readonly groupId: string;\n readonly organizationId: string;\n readonly principalType: \"group\";\n}\nexport interface OrganizationPolicyHistory\n extends OrganizationPrincipalPolicyHistory {\n readonly nextBeforeVersion?: number | null;\n readonly entries: OrganizationPolicyHistoryEntry[];\n readonly organizationId: string;\n readonly principalType: \"organization\";\n}\n\nexport interface OrganizationPolicyHistoryEntry\n extends OrganizationPrincipalPolicyHistoryEntry {\n /** Null when the additional signed evidence has not been loaded. */\n readonly groupChanges: OrganizationPolicyGroupChange[] | null;\n}\n\nexport interface OrganizationPolicyGrantChange {\n readonly containerId: string;\n readonly previousAccess:\n | PrincipalContainerGrantResponse[\"accessLevel\"]\n | null;\n readonly nextAccess: PrincipalContainerGrantResponse[\"accessLevel\"] | null;\n}\n\nexport interface OrganizationPolicyGroupChange {\n readonly groupId: string;\n readonly changeType: \"created\" | \"updated\" | \"deleted\";\n readonly previousVersion: number | null;\n readonly version: number;\n readonly previousKeyEpoch: number | null;\n readonly keyEpoch: number;\n readonly changes: OrganizationPrincipalMemberChange[];\n readonly grantChanges: OrganizationPolicyGrantChange[];\n}\n"]}
1
+ {"version":3,"file":"policyHistoryTypes.js","sourceRoot":"","sources":["policyHistoryTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n PrincipalContainerGrantResponse,\n PrincipalProjectionMemberResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\n\nexport type OrganizationPrincipalMemberChangeType =\n | \"added\"\n | \"removed\"\n | \"role_changed\";\nexport interface OrganizationPrincipalMemberChange {\n readonly changeType: OrganizationPrincipalMemberChangeType;\n readonly userId: string;\n readonly nextRole: PrincipalProjectionMemberResponse[\"role\"] | null;\n readonly previousRole: PrincipalProjectionMemberResponse[\"role\"] | null;\n}\nexport interface OrganizationPrincipalPolicyHistoryEntry {\n readonly changes: OrganizationPrincipalMemberChange[];\n readonly createdAt: string;\n readonly keyEpoch: number;\n readonly memberCount: number;\n readonly signedAt: string;\n readonly signerUserId: string;\n readonly signerUserKeyFingerprint: string;\n readonly stateHash: string;\n readonly version: number;\n}\nexport type OrganizationGroupPolicyHistoryEntry =\n OrganizationPrincipalPolicyHistoryEntry;\nexport interface OrganizationPrincipalPolicyHistory {\n readonly entries: OrganizationPrincipalPolicyHistoryEntry[];\n readonly principalId: string;\n readonly principalType: PrincipalStateResponse[\"principalType\"];\n}\nexport interface OrganizationGroupPolicyHistory\n extends OrganizationPrincipalPolicyHistory {\n /** Exclusive cursor for older entries; null once the oldest is loaded. */\n readonly nextBeforeVersion: number | null;\n readonly groupId: string;\n readonly organizationId: string;\n readonly principalType: \"group\";\n}\nexport interface OrganizationPolicyHistory\n extends OrganizationPrincipalPolicyHistory {\n /** Exclusive cursor for older entries; null once the oldest is loaded. */\n readonly nextBeforeVersion: number | null;\n readonly entries: OrganizationPolicyHistoryEntry[];\n readonly organizationId: string;\n readonly principalType: \"organization\";\n}\n\nexport interface OrganizationPolicyHistoryEntry\n extends OrganizationPrincipalPolicyHistoryEntry {\n /** Null when the additional signed evidence has not been loaded. */\n readonly groupChanges: OrganizationPolicyGroupChange[] | null;\n}\n\nexport interface OrganizationPolicyGrantChange {\n readonly containerId: string;\n readonly previousAccess:\n | PrincipalContainerGrantResponse[\"accessLevel\"]\n | null;\n readonly nextAccess: PrincipalContainerGrantResponse[\"accessLevel\"] | null;\n}\n\nexport interface OrganizationPolicyGroupChange {\n readonly groupId: string;\n readonly changeType: \"created\" | \"updated\" | \"deleted\";\n readonly previousVersion: number | null;\n readonly version: number;\n readonly previousKeyEpoch: number | null;\n readonly keyEpoch: number;\n readonly changes: OrganizationPrincipalMemberChange[];\n readonly grantChanges: OrganizationPolicyGrantChange[];\n}\n"]}