@voltro/plugin-deactivation 0.86.0 → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/guard.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Effect as e, Schema as t } from "effect";
2
- //#region src/guard.ts
2
+ // src/guard.ts
3
3
  var n = class extends t.TaggedError()("AccountDeactivated", {
4
4
  userId: t.String,
5
5
  deactivatedAt: t.String
@@ -49,5 +49,4 @@ var n = class extends t.TaggedError()("AccountDeactivated", {
49
49
  };
50
50
  };
51
51
  };
52
- //#endregion
53
52
  export { r as ACCOUNT_DEACTIVATED_CODE, n as AccountDeactivated, o as deactivationGuard, s as deactivationSubjectGuard };
package/dist/mixin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineMixin as e, reference as t, requireActors as n, timestamp as r } from "@voltro/database";
2
2
  import { audit as i } from "@voltro/plugin-audit/mixin";
3
- //#region src/mixin.ts
3
+ // src/mixin.ts
4
4
  var a = () => e({
5
5
  id: "voltro/deactivation",
6
6
  requires: [i()],
@@ -9,5 +9,4 @@ var a = () => e({
9
9
  deactivatedBy: t(n()).nullable()
10
10
  }
11
11
  });
12
- //#endregion
13
12
  export { a as deactivation };
@@ -0,0 +1,32 @@
1
+ import { Effect } from 'effect'
2
+ import { defineSchedule } from '@voltro/runtime'
3
+ import { PrivacyService } from '@voltro/plugin-deactivation/privacy'
4
+ import { PrivacyCoordinatorFailure } from '@voltro/plugin-deactivation/privacy/contract'
5
+ import type { PrivacyDispatchCursor } from '@voltro/plugin-deactivation/privacy'
6
+
7
+ export default defineSchedule({
8
+ name: 'privacy.dispatch',
9
+ cron: '* * * * *',
10
+ timezone: 'UTC',
11
+ handler: ctx => Effect.gen(function* () {
12
+ const service = yield* PrivacyService
13
+ const workflows = ctx.app.workflows
14
+ const refused = () => new PrivacyCoordinatorFailure({ code: 'request_unavailable', completed: [], missing: [] })
15
+ if (workflows === undefined) return yield* Effect.fail(refused())
16
+ let after: PrivacyDispatchCursor | undefined
17
+ let failed = false
18
+ for (let page = 0; page < 100; page++) {
19
+ const batch = yield* service.dispatch({ limit: 100, ...(after === undefined ? {} : { after }) },
20
+ payload => workflows.start('privacy.erase', payload))
21
+ failed ||= batch.failed.length > 0
22
+ if (batch.next === null) {
23
+ if (failed) return yield* Effect.fail(refused())
24
+ return
25
+ }
26
+ after = batch.next
27
+ }
28
+ // A firing that cannot exhaust its bounded scan reports failure. SQL rows
29
+ // remain eligible for the next firing; no local cursor or second queue.
30
+ return yield* Effect.fail(refused())
31
+ }),
32
+ })
@@ -0,0 +1,16 @@
1
+ import { Effect } from 'effect'
2
+ import { step } from '@voltro/workflow'
3
+ import { PrivacyService } from '@voltro/plugin-deactivation/privacy'
4
+ import { PrivacyCoordinatorFailure, PrivacyRequestReceiptSchema } from '@voltro/plugin-deactivation/privacy/contract'
5
+
6
+ export default () => (payload: { readonly requestId: string }) => Effect.gen(function* () {
7
+ const service = yield* PrivacyService
8
+ // SQL claims and every external hook stay inside one recoverable activity;
9
+ // only its safe receipt is journaled. A replay after terminal SQL is a read.
10
+ return yield* step({
11
+ name: 'complete-subject-erasure',
12
+ success: PrivacyRequestReceiptSchema,
13
+ error: PrivacyCoordinatorFailure,
14
+ execute: service.execute(payload.requestId),
15
+ })
16
+ })
@@ -0,0 +1 @@
1
+ export { PrivacyErasure } from '@voltro/plugin-deactivation/privacy/workflow'
@@ -0,0 +1,37 @@
1
+ import { Schema } from 'effect';
2
+ import { YieldableError } from 'effect/Cause';
3
+
4
+ /** Default export packaging slot; hooks have already validated and detached JSON. */
5
+ export declare const jsonPrivacyExport: (input: PrivacyExportPackage) => PrivacyExportPackage;
6
+
7
+ export declare class PrivacyCoordinatorFailure extends PrivacyCoordinatorFailure_base {
8
+ }
9
+
10
+ declare const PrivacyCoordinatorFailure_base: Schema.Class<PrivacyCoordinatorFailure, Schema.TaggedStruct<"PrivacyCoordinatorFailure", {
11
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_request", "request_unavailable", "active_request_exists", "invalid_transition", "coverage_missing", "hook_failed"]>;
12
+ readonly completed: Schema.$Array<Schema.String>;
13
+ readonly missing: Schema.$Array<Schema.String>;
14
+ }>, YieldableError>;
15
+
16
+ export declare type PrivacyExportPackage = typeof PrivacyExportPackageSchema.Type;
17
+
18
+ export declare const PrivacyExportPackageSchema: Schema.Struct<{
19
+ readonly requestId: Schema.String;
20
+ readonly plugins: Schema.$Array<Schema.Struct<{
21
+ readonly name: Schema.String;
22
+ readonly data: Schema.Unknown;
23
+ }>>;
24
+ }>;
25
+
26
+ export declare const PrivacyRequestReceiptSchema: Schema.Struct<{
27
+ readonly requestId: Schema.String;
28
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
29
+ readonly requestedAt: Schema.Number;
30
+ readonly dueAt: Schema.Number;
31
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
32
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
33
+ readonly completedAt: Schema.NullOr<Schema.Number>;
34
+ readonly completedPlugins: Schema.$Array<Schema.String>;
35
+ }>;
36
+
37
+ export { }
@@ -0,0 +1,42 @@
1
+ import { Schema as e } from "effect";
2
+ // src/privacyContract.ts
3
+ var t = class extends e.TaggedError()("PrivacyCoordinatorFailure", {
4
+ code: e.Literals([
5
+ "identity_required",
6
+ "invalid_request",
7
+ "request_unavailable",
8
+ "active_request_exists",
9
+ "invalid_transition",
10
+ "coverage_missing",
11
+ "hook_failed"
12
+ ]),
13
+ completed: e.Array(e.String),
14
+ missing: e.Array(e.String)
15
+ }) {}, n = e.Struct({
16
+ requestId: e.String,
17
+ status: e.Literals([
18
+ "pending",
19
+ "erasing",
20
+ "withdrawn",
21
+ "completed"
22
+ ]),
23
+ requestedAt: e.Number,
24
+ dueAt: e.Number,
25
+ claimedAt: e.NullOr(e.Number),
26
+ withdrawnAt: e.NullOr(e.Number),
27
+ completedAt: e.NullOr(e.Number),
28
+ completedPlugins: e.Array(e.String)
29
+ }), r = e.Struct({
30
+ requestId: e.String,
31
+ plugins: e.Array(e.Struct({
32
+ name: e.String,
33
+ data: e.Unknown
34
+ }))
35
+ }), i = (e) => ({
36
+ requestId: e.requestId,
37
+ plugins: e.plugins.map((e) => ({
38
+ name: e.name,
39
+ data: e.data
40
+ }))
41
+ });
42
+ export { t as PrivacyCoordinatorFailure, r as PrivacyExportPackageSchema, n as PrivacyRequestReceiptSchema, i as jsonPrivacyExport };
@@ -0,0 +1,91 @@
1
+ import { PrivacyCoordinatorFailure as e } from "./privacyContract.js";
2
+ import { PrivacyRequestRefused as t, dataStorePrivacyRequests as n } from "./privacyRequests.js";
3
+ import { Effect as r, Result as i } from "effect";
4
+ import { randomUUID as a } from "node:crypto";
5
+ // src/privacyCoordinator.ts
6
+ var o = (t) => new e({
7
+ code: t,
8
+ completed: [],
9
+ missing: []
10
+ }), s = (e) => r.tryPromise({
11
+ try: e,
12
+ catch: (e) => o(e instanceof t ? e.code : "request_unavailable")
13
+ }), c = (e) => r.suspend(() => e.type !== "user" || !e.id.trim() || !e.tenantId.trim() ? r.fail(o("identity_required")) : r.succeed(Object.freeze({
14
+ subjectId: e.id,
15
+ tenantId: e.tenantId,
16
+ kind: e.kind === "guest" ? "guest" : "user"
17
+ }))), l = (t, l, u = {}) => {
18
+ let d = n(t, {
19
+ withdrawalMs: u.withdrawalMs ?? 2592e6,
20
+ ...u.now === void 0 ? {} : { now: u.now }
21
+ }), f = (t) => r.suspend(() => {
22
+ let n = l.coverage(t);
23
+ return n.missing.length !== 0 || n.participants.length === 0 ? r.fail(new e({
24
+ code: "coverage_missing",
25
+ completed: [],
26
+ missing: [...n.missing]
27
+ })) : r.void;
28
+ }), p = (t) => new e({
29
+ code: t.code === "coverage_missing" ? "coverage_missing" : t.code === "invalid_request" ? "invalid_request" : t.code === "unavailable" ? "request_unavailable" : "hook_failed",
30
+ completed: [...t.completed],
31
+ missing: [...t.missing]
32
+ });
33
+ return {
34
+ requestErasure: (e, t = a()) => r.gen(function* () {
35
+ let n = yield* c(e);
36
+ return yield* f(n.kind), yield* s(() => d.request(t, n));
37
+ }),
38
+ readSelf: (e, t) => r.gen(function* () {
39
+ let n = yield* c(e);
40
+ return yield* s(() => d.readOwned(t, n));
41
+ }),
42
+ withdraw: (e, t) => r.gen(function* () {
43
+ let n = yield* c(e);
44
+ return yield* s(() => d.withdraw(t, n));
45
+ }),
46
+ exportSelf: (e, t = a()) => r.gen(function* () {
47
+ let n = yield* c(e), i = yield* l.exportSubject({
48
+ requestId: t,
49
+ target: n
50
+ }).pipe(r.mapError(p));
51
+ return {
52
+ requestId: i.requestId,
53
+ plugins: i.plugins
54
+ };
55
+ }),
56
+ execute: (e) => r.gen(function* () {
57
+ let t = yield* s(() => d.readWorker(e));
58
+ if (t === null) return yield* r.fail(o("request_unavailable"));
59
+ if (t.receipt.status === "completed" || t.receipt.status === "withdrawn") return t.receipt;
60
+ yield* f(t.kind);
61
+ let n = yield* s(() => d.claim(e));
62
+ if (n.target === null) return n.receipt;
63
+ let i = n.target, a = yield* l.eraseSubject({
64
+ requestId: e,
65
+ target: i
66
+ }).pipe(r.mapError(p));
67
+ (yield* s(() => d.readWorker(e)))?.receipt.status !== "completed" && (yield* s(() => d.finish(e, i, a.completed)));
68
+ let c = yield* s(() => d.readWorker(e));
69
+ return c?.receipt.status === "completed" ? c.receipt : yield* r.fail(o("request_unavailable"));
70
+ }),
71
+ dispatch: (e, t) => r.gen(function* () {
72
+ let n = yield* s(() => d.dispatchBatch(e)), a = [], o = [];
73
+ for (let e of n.requestIds) {
74
+ let n = yield* r.tryPromise({
75
+ try: () => t({ requestId: e }),
76
+ catch: () => e
77
+ }).pipe(r.result);
78
+ i.isFailure(n) ? o.push(e) : a.push({
79
+ requestId: e,
80
+ status: n.success.status
81
+ });
82
+ }
83
+ return {
84
+ submitted: a,
85
+ failed: o,
86
+ next: n.next
87
+ };
88
+ })
89
+ };
90
+ };
91
+ export { l as dataStorePrivacyCoordinator, c as privacyTargetFromSubject };
@@ -0,0 +1,139 @@
1
+ import { ColumnBuilder } from '@voltro/database';
2
+ import { Context } from 'effect';
3
+ import { Effect } from 'effect';
4
+ import { FieldDefinitions } from '@voltro/database';
5
+ import { Schema } from 'effect';
6
+ import { Subject } from '@voltro/protocol';
7
+ import { Table } from '@voltro/database';
8
+ import { VoltroPlugin } from '@voltro/protocol';
9
+ import { WorkflowRunHandle } from '@voltro/protocol';
10
+ import { YieldableError } from 'effect/Cause';
11
+
12
+ /** Default export packaging slot; hooks have already validated and detached JSON. */
13
+ export declare const jsonPrivacyExport: (input: PrivacyExportPackage) => PrivacyExportPackage;
14
+
15
+ export declare class PrivacyCoordinatorFailure extends PrivacyCoordinatorFailure_base {
16
+ }
17
+
18
+ declare const PrivacyCoordinatorFailure_base: Schema.Class<PrivacyCoordinatorFailure, Schema.TaggedStruct<"PrivacyCoordinatorFailure", {
19
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_request", "request_unavailable", "active_request_exists", "invalid_transition", "coverage_missing", "hook_failed"]>;
20
+ readonly completed: Schema.$Array<Schema.String>;
21
+ readonly missing: Schema.$Array<Schema.String>;
22
+ }>, YieldableError>;
23
+
24
+ /** Internal scan position, not caller identity or authorization. */
25
+ export declare interface PrivacyDispatchCursor {
26
+ readonly dueAt: number;
27
+ readonly requestId: string;
28
+ }
29
+
30
+ export declare interface PrivacyDispatchResult {
31
+ readonly submitted: ReadonlyArray<{
32
+ readonly requestId: string;
33
+ readonly status: WorkflowRunHandle['status'];
34
+ }>;
35
+ readonly failed: ReadonlyArray<string>;
36
+ readonly next: PrivacyDispatchCursor | null;
37
+ }
38
+
39
+ export declare type PrivacyExportPackage = typeof PrivacyExportPackageSchema.Type;
40
+
41
+ export declare const PrivacyExportPackageSchema: Schema.Struct<{
42
+ readonly requestId: Schema.String;
43
+ readonly plugins: Schema.$Array<Schema.Struct<{
44
+ readonly name: Schema.String;
45
+ readonly data: Schema.Unknown;
46
+ }>>;
47
+ }>;
48
+
49
+ export declare interface PrivacyOperations {
50
+ readonly requestErasure: (subject: Subject, requestId?: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
51
+ readonly readSelf: (subject: Subject, requestId: string) => Effect.Effect<PrivacyRequestReceipt | null, PrivacyCoordinatorFailure>;
52
+ readonly withdraw: (subject: Subject, requestId: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
53
+ readonly exportSelf: (subject: Subject, requestId?: string) => Effect.Effect<PrivacyExportPackage, PrivacyCoordinatorFailure>;
54
+ /** Trusted worker only; wire procedures never expose this method. */
55
+ readonly execute: (requestId: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
56
+ /** Trusted schedule only; this port owns no timer or queue. */
57
+ readonly dispatch: (input: {
58
+ readonly limit: number;
59
+ readonly after?: PrivacyDispatchCursor;
60
+ }, start: (payload: {
61
+ readonly requestId: string;
62
+ }) => Promise<WorkflowRunHandle>) => Effect.Effect<PrivacyDispatchResult, PrivacyCoordinatorFailure>;
63
+ }
64
+
65
+ /** Install self-service actions and app-shaped durable workflow/schedule sources.
66
+ * Subject and tenant always come from server authentication, never action input. */
67
+ export declare const privacyPlugin: (options?: PrivacyPluginOptions) => VoltroPlugin;
68
+
69
+ export declare interface PrivacyPluginOptions {
70
+ /** Original request deadline; retry never extends it. Defaults to 30 days. */
71
+ readonly withdrawalMs?: number;
72
+ /** Replace export packaging after the registry completes every export hook. */
73
+ readonly exportPackage?: (input: PrivacyExportPackage) => PrivacyExportPackage;
74
+ /** Replace the app's operations port; the request-table owner remains installed. */
75
+ readonly operations?: PrivacyOperations;
76
+ /** Test clock, shared by the coordinator and its SQL completion owner. */
77
+ readonly now?: () => number;
78
+ }
79
+
80
+ export declare interface PrivacyRequestReceipt {
81
+ readonly requestId: string;
82
+ readonly status: 'pending' | 'erasing' | 'withdrawn' | 'completed';
83
+ readonly requestedAt: number;
84
+ readonly dueAt: number;
85
+ readonly claimedAt: number | null;
86
+ readonly withdrawnAt: number | null;
87
+ readonly completedAt: number | null;
88
+ readonly completedPlugins: ReadonlyArray<string>;
89
+ }
90
+
91
+ export declare const PrivacyRequestReceiptSchema: Schema.Struct<{
92
+ readonly requestId: Schema.String;
93
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
94
+ readonly requestedAt: Schema.Number;
95
+ readonly dueAt: Schema.Number;
96
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
97
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
98
+ readonly completedAt: Schema.NullOr<Schema.Number>;
99
+ readonly completedPlugins: Schema.$Array<Schema.String>;
100
+ }>;
101
+
102
+ export declare const privacyRequestsTable: Table<"_voltro_privacy_requests", FieldDefinitions<{
103
+ readonly id: ColumnBuilder<string, "id", boolean>;
104
+ readonly subjectId: ColumnBuilder<string | null, "text", boolean>;
105
+ readonly tenantId: ColumnBuilder<string | null, "text", boolean>;
106
+ readonly kind: ColumnBuilder<"user" | "guest", "text", boolean>;
107
+ readonly activeKey: ColumnBuilder<string, "text", boolean>;
108
+ readonly status: ColumnBuilder<"completed" | "pending" | "withdrawn" | "erasing", "text", boolean>;
109
+ readonly requestedAt: ColumnBuilder<Date, "timestamp", boolean>;
110
+ readonly dueAt: ColumnBuilder<Date, "timestamp", boolean>;
111
+ readonly claimedAt: ColumnBuilder<Date | null, "timestamp", boolean>;
112
+ readonly withdrawnAt: ColumnBuilder<Date | null, "timestamp", boolean>;
113
+ readonly completedAt: ColumnBuilder<Date | null, "timestamp", boolean>;
114
+ readonly completedPlugins: ColumnBuilder<unknown, "json", boolean>;
115
+ }>, false, never>;
116
+
117
+ export declare class PrivacyService extends PrivacyService_base {
118
+ }
119
+
120
+ declare const PrivacyService_base: Context.ServiceClass<PrivacyService, "voltro/PrivacyService", PrivacyOperations>;
121
+
122
+ export declare const privacySystemContract: {
123
+ readonly slots: {
124
+ readonly exportPackage: {
125
+ readonly defaultExport: "jsonPrivacyExport";
126
+ readonly fixtureExport: "privacyExportFixture";
127
+ };
128
+ };
129
+ readonly ports: {
130
+ readonly operations: {
131
+ readonly tagExport: "PrivacyService";
132
+ readonly fakeLayerExport: "privacyFakeLayer";
133
+ readonly fixtureExport: "privacyPortFixture";
134
+ };
135
+ };
136
+ readonly events: readonly [];
137
+ };
138
+
139
+ export { }
@@ -0,0 +1,138 @@
1
+ import { PrivacyCoordinatorFailure as e, PrivacyExportPackageSchema as t, PrivacyRequestReceiptSchema as n, jsonPrivacyExport as r } from "./privacyContract.js";
2
+ import { PrivacyRequestRefused as i, dataStorePrivacyRequests as a, privacyRequestsTable as o } from "./privacyRequests.js";
3
+ import { dataStorePrivacyCoordinator as s, privacyTargetFromSubject as c } from "./privacyCoordinator.js";
4
+ import { PrivacyService as l } from "./privacyService.js";
5
+ import { exportSelfDescriptor as u, privacyRpcClientImports as d, requestErasureDescriptor as f, requestStatusDescriptor as p, withdrawErasureDescriptor as m } from "./privacyRpc.js";
6
+ import { Effect as h, Layer as g, Schema as _ } from "effect";
7
+ import { fileURLToPath as v } from "node:url";
8
+ import { definePlugin as y } from "@voltro/protocol";
9
+ // src/privacyPlugin.ts
10
+ var b = {
11
+ slots: { exportPackage: {
12
+ defaultExport: "jsonPrivacyExport",
13
+ fixtureExport: "privacyExportFixture"
14
+ } },
15
+ ports: { operations: {
16
+ tagExport: "PrivacyService",
17
+ fakeLayerExport: "privacyFakeLayer",
18
+ fixtureExport: "privacyPortFixture"
19
+ } },
20
+ events: []
21
+ }, x = () => new e({
22
+ code: "request_unavailable",
23
+ completed: [],
24
+ missing: []
25
+ }), S = (e) => e.requestId, C = (n = {}) => {
26
+ let b = n.withdrawalMs ?? 2592e6;
27
+ if (!Number.isSafeInteger(b) || b < 0) throw Error("Privacy withdrawal window must be a non-negative safe integer");
28
+ let C = n.exportPackage ?? r, w, T, E, D, O = (e) => h.suspend(() => w === void 0 ? h.fail(x()) : e(w)), k = {
29
+ requestErasure: (e, t) => c(e).pipe(h.flatMap(() => O((n) => n.requestErasure(e, t)))),
30
+ readSelf: (e, t) => c(e).pipe(h.flatMap(() => O((n) => n.readSelf(e, t)))),
31
+ withdraw: (e, t) => c(e).pipe(h.flatMap(() => O((n) => n.withdraw(e, t)))),
32
+ exportSelf: (e, n) => c(e).pipe(h.flatMap(() => O((t) => t.exportSelf(e, n))), h.flatMap((e) => h.try({
33
+ try: () => _.decodeUnknownSync(t)(C(e)),
34
+ catch: x
35
+ }))),
36
+ execute: (e) => O((t) => t.execute(e)),
37
+ dispatch: (e, t) => O((n) => n.dispatch(e, t))
38
+ }, A = [
39
+ {
40
+ ...f,
41
+ execute: (e, t) => k.requestErasure(t.request.subject, S(e))
42
+ },
43
+ {
44
+ ...p,
45
+ execute: (e, t) => k.readSelf(t.request.subject, e.requestId)
46
+ },
47
+ {
48
+ ...m,
49
+ execute: (e, t) => k.withdraw(t.request.subject, e.requestId)
50
+ },
51
+ {
52
+ ...u,
53
+ execute: (e, t) => k.exportSelf(t.request.subject, S(e))
54
+ }
55
+ ];
56
+ return y({
57
+ name: "@voltro/plugin-deactivation",
58
+ description: "Durable subject privacy requests, withdrawal and JSON export.",
59
+ permissions: ["store:write", "inspect:read"],
60
+ services: g.succeed(l, k),
61
+ routes: A,
62
+ rpcClientDescriptors: d,
63
+ sources: v(new URL("./privacy-app", "" + import.meta.url)),
64
+ extendSchema: { tables: [o] },
65
+ inspectEndpoints: [{
66
+ method: "GET",
67
+ path: "/status",
68
+ scope: "shared-store",
69
+ description: "Bounded recent privacy receipts and declared subject hook coverage; no subject or tenant identifiers.",
70
+ handler: () => h.tryPromise({
71
+ try: async () => T === void 0 || D === void 0 ? {
72
+ kind: "json",
73
+ status: 503,
74
+ data: { error: "privacy_unavailable" }
75
+ } : {
76
+ kind: "json",
77
+ data: {
78
+ ...await T.inspectRecent(),
79
+ withdrawalMs: b,
80
+ limit: 100,
81
+ coverage: {
82
+ user: D.coverage("user"),
83
+ guest: D.coverage("guest")
84
+ }
85
+ }
86
+ },
87
+ catch: x
88
+ })
89
+ }],
90
+ subjectPrivacy: {
91
+ tables: [o.tableName],
92
+ kinds: ["user", "guest"],
93
+ erasePhase: "finalize"
94
+ },
95
+ onExport: (e, t) => h.tryPromise({
96
+ try: async () => {
97
+ if (T === void 0) throw x();
98
+ return T.exportOwned({
99
+ subjectId: e,
100
+ tenantId: t.tenantId,
101
+ kind: t.kind
102
+ });
103
+ },
104
+ catch: x
105
+ }),
106
+ onErase: (t, n) => h.tryPromise({
107
+ try: async () => {
108
+ if (T === void 0 || n.completed === void 0) throw x();
109
+ (await T.readWorker(n.requestId))?.receipt.status !== "completed" && await T.finish(n.requestId, {
110
+ subjectId: t,
111
+ tenantId: n.tenantId,
112
+ kind: n.kind
113
+ }, [...n.completed, "@voltro/plugin-deactivation"]);
114
+ },
115
+ catch: (t) => new e({
116
+ code: t instanceof i ? t.code : "request_unavailable",
117
+ completed: [],
118
+ missing: []
119
+ })
120
+ }),
121
+ bindDataStore: (e, t) => {
122
+ if (t?.privacyRegistry === void 0) throw Error("Privacy orchestration requires the installing app privacy registry");
123
+ if (E !== void 0 && E !== e) throw Error("Privacy plugin instance cannot be shared between app stores");
124
+ if (D !== void 0 && D !== t.privacyRegistry) throw Error("Privacy plugin instance cannot be shared between app registries");
125
+ E = e, D = t.privacyRegistry, T = a(e, {
126
+ withdrawalMs: b,
127
+ ...n.now === void 0 ? {} : { now: n.now }
128
+ }), w = n.operations ?? s(e, t.privacyRegistry, {
129
+ withdrawalMs: b,
130
+ ...n.now === void 0 ? {} : { now: n.now }
131
+ });
132
+ },
133
+ onDeactivate: () => h.sync(() => {
134
+ w = void 0, T = void 0, E = void 0, D = void 0;
135
+ })
136
+ });
137
+ };
138
+ export { e as PrivacyCoordinatorFailure, t as PrivacyExportPackageSchema, n as PrivacyRequestReceiptSchema, l as PrivacyService, r as jsonPrivacyExport, C as privacyPlugin, o as privacyRequestsTable, b as privacySystemContract };