@voltro/plugin-deactivation 0.86.0 → 0.87.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.
@@ -0,0 +1,221 @@
1
+ import { and as e, eq as t, gt as n, id as r, json as i, lte as a, or as o, queryFor as s, table as c, text as l, timestamp as u } from "@voltro/database";
2
+ import { createHash as d } from "node:crypto";
3
+ //#region src/privacyRequests.ts
4
+ var f = c("_voltro_privacy_requests", {
5
+ id: r({ prefix: "pvreq" }),
6
+ subjectId: l().nullable(),
7
+ tenantId: l().nullable(),
8
+ kind: l().oneOf(["user", "guest"]),
9
+ activeKey: l().unique(),
10
+ status: l().oneOf([
11
+ "pending",
12
+ "erasing",
13
+ "withdrawn",
14
+ "completed"
15
+ ]),
16
+ requestedAt: u(),
17
+ dueAt: u(),
18
+ claimedAt: u().nullable(),
19
+ withdrawnAt: u().nullable(),
20
+ completedAt: u().nullable(),
21
+ completedPlugins: i()
22
+ }).index(["status", "dueAt"]).index(["subjectId", "tenantId"]).nonReactive(), p = f.tableName, m = (e) => s(f).where(t("id", e)).descriptor, h = (n) => e(t("subjectId", n.subjectId), t("tenantId", n.tenantId), t("kind", n.kind)), g = class extends Error {
23
+ code;
24
+ constructor(e) {
25
+ super(`privacy request: ${e}`), this.code = e, this.name = "PrivacyRequestRefused";
26
+ }
27
+ }, _ = (e) => {
28
+ let t = e instanceof Date ? e.getTime() : new Date(String(e)).getTime();
29
+ if (!Number.isSafeInteger(t)) throw new g("request_unavailable");
30
+ return t;
31
+ }, v = (e) => e === null ? null : _(e), y = (e) => {
32
+ if (typeof e.id != "string" || ![
33
+ "pending",
34
+ "erasing",
35
+ "withdrawn",
36
+ "completed"
37
+ ].includes(String(e.status)) || !Array.isArray(e.completedPlugins) || !e.completedPlugins.every((e) => typeof e == "string")) throw new g("request_unavailable");
38
+ return {
39
+ requestId: e.id,
40
+ status: e.status,
41
+ requestedAt: _(e.requestedAt),
42
+ dueAt: _(e.dueAt),
43
+ claimedAt: v(e.claimedAt),
44
+ withdrawnAt: v(e.withdrawnAt),
45
+ completedAt: v(e.completedAt),
46
+ completedPlugins: [...e.completedPlugins]
47
+ };
48
+ }, b = (e) => {
49
+ if (typeof e != "string" || e.trim().length === 0 || e.length > 128) throw new g("invalid_request");
50
+ }, x = (e) => {
51
+ if (b(e.subjectId), e.kind !== "user" && e.kind !== "guest" || e.tenantId !== null && (typeof e.tenantId != "string" || !e.tenantId.trim())) throw new g("invalid_request");
52
+ }, S = (e) => "active:" + d("sha256").update(JSON.stringify([
53
+ e.tenantId,
54
+ e.kind,
55
+ e.subjectId
56
+ ])).digest("hex"), C = (e, t) => e.subjectId === t.subjectId && e.tenantId === t.tenantId && e.kind === t.kind, w = async (e) => {
57
+ try {
58
+ return await e();
59
+ } catch (e) {
60
+ throw e instanceof g ? e : new g("request_unavailable");
61
+ }
62
+ }, T = (r, i) => {
63
+ if (!Number.isSafeInteger(i.withdrawalMs) || i.withdrawalMs < 0) throw new g("invalid_request");
64
+ let c = i.now ?? Date.now, l = () => {
65
+ let e = c();
66
+ if (!Number.isSafeInteger(e) || !Number.isFinite(new Date(e).getTime())) throw new g("invalid_request");
67
+ return e;
68
+ }, u = async (e, t) => (await e.query(m(t)))[0];
69
+ return {
70
+ inspectRecent: async () => w(async () => {
71
+ let e = l(), t = await r.query(s(f).orderBy("requestedAt", "desc").orderBy("id", "desc").limit(101).descriptor);
72
+ return {
73
+ observedAt: e,
74
+ hasMore: t.length > 100,
75
+ requests: t.slice(0, 100).map(y)
76
+ };
77
+ }),
78
+ exportOwned: async (t) => w(async () => {
79
+ x(t);
80
+ let i = [], a;
81
+ for (let o = 0; o < 100; o++) {
82
+ let o = a === void 0 ? h(t) : e(h(t), n("id", a)), c = await r.query(s(f).where(o).orderBy("id", "asc").limit(1e3).descriptor);
83
+ for (let e of c) C(e, t) && i.push(y(e));
84
+ if (c.length < 1e3) return i;
85
+ let l = c.at(-1);
86
+ if (typeof l?.id != "string" || l.id === a) throw new g("request_unavailable");
87
+ a = l.id;
88
+ }
89
+ throw new g("request_unavailable");
90
+ }),
91
+ dispatchBatch: async (i) => w(async () => {
92
+ if (!Number.isSafeInteger(i.limit) || i.limit < 1 || i.limit > 1e3) throw new g("invalid_request");
93
+ let c = l(), u = o(t("status", "erasing"), e(t("status", "pending"), a("dueAt", new Date(c)))), d = i.after;
94
+ if (d !== void 0 && (b(d.requestId), !Number.isSafeInteger(d.dueAt) || !Number.isFinite(new Date(d.dueAt).getTime()))) throw new g("invalid_request");
95
+ let p = d === void 0 ? u : e(u, o(n("dueAt", new Date(d.dueAt)), e(t("dueAt", new Date(d.dueAt)), n("id", d.requestId)))), m = await r.query(s(f).where(p).orderBy("dueAt", "asc").orderBy("id", "asc").select("id", "dueAt").limit(i.limit + 1).descriptor), h = m.slice(0, i.limit).map((e) => {
96
+ if (typeof e.id != "string") throw new g("request_unavailable");
97
+ return b(e.id), {
98
+ requestId: e.id,
99
+ dueAt: _(e.dueAt)
100
+ };
101
+ });
102
+ return {
103
+ requestIds: h.map((e) => e.requestId),
104
+ next: m.length > i.limit ? h.at(-1) ?? null : null
105
+ };
106
+ }),
107
+ readWorker: async (e) => w(async () => {
108
+ b(e);
109
+ let t = await u(r, e);
110
+ if (!t) return null;
111
+ if (t.kind !== "user" && t.kind !== "guest") throw new g("request_unavailable");
112
+ return {
113
+ receipt: y(t),
114
+ kind: t.kind
115
+ };
116
+ }),
117
+ request: async (e, n) => w(async () => {
118
+ b(e), x(n);
119
+ let a = l(), o = a + i.withdrawalMs;
120
+ if (!Number.isSafeInteger(o) || !Number.isFinite(new Date(o).getTime())) throw new g("invalid_request");
121
+ try {
122
+ let t = await r.insertIgnoreWithOutcome(p, {
123
+ id: e,
124
+ subjectId: n.subjectId,
125
+ tenantId: n.tenantId,
126
+ kind: n.kind,
127
+ activeKey: S(n),
128
+ status: "pending",
129
+ requestedAt: new Date(a),
130
+ dueAt: new Date(o),
131
+ claimedAt: null,
132
+ withdrawnAt: null,
133
+ completedAt: null,
134
+ completedPlugins: []
135
+ }, { conflictColumns: ["id"] });
136
+ if (!C(t.row, n)) throw new g("request_unavailable");
137
+ return y(t.row);
138
+ } catch (i) {
139
+ let a = await u(r, e);
140
+ if (a) {
141
+ if (!C(a, n)) throw new g("request_unavailable");
142
+ return y(a);
143
+ }
144
+ throw (await r.query(s(f).where(t("activeKey", S(n))).descriptor)).length === 0 ? i : new g("active_request_exists");
145
+ }
146
+ }),
147
+ readOwned: async (e, t) => w(async () => {
148
+ b(e), x(t);
149
+ let n = await u(r, e);
150
+ return n && C(n, t) ? y(n) : null;
151
+ }),
152
+ withdraw: async (i, a) => w(async () => {
153
+ b(i), x(a);
154
+ let o = l();
155
+ return r.transactional(async (r) => {
156
+ await r.updateMany(p, {
157
+ status: "withdrawn",
158
+ withdrawnAt: new Date(o),
159
+ activeKey: `terminal:${i}`
160
+ }, { where: e(t("id", i), h(a), t("status", "pending"), n("dueAt", new Date(o))) });
161
+ let s = await u(r, i);
162
+ if (!s || !C(s, a)) throw new g("request_unavailable");
163
+ if (s.status !== "withdrawn") throw new g("invalid_transition");
164
+ return y(s);
165
+ });
166
+ }),
167
+ claim: async (n) => w(async () => {
168
+ b(n);
169
+ let i = l();
170
+ return r.transactional(async (r) => {
171
+ await r.updateMany(p, {
172
+ status: "erasing",
173
+ claimedAt: new Date(i)
174
+ }, { where: e(t("id", n), t("status", "pending"), a("dueAt", new Date(i))) });
175
+ let o = await u(r, n);
176
+ if (!o) throw new g("request_unavailable");
177
+ let s = y(o);
178
+ if (s.status === "pending") throw new g("invalid_transition");
179
+ if (s.status !== "erasing") return {
180
+ receipt: s,
181
+ target: null
182
+ };
183
+ if (typeof o.subjectId != "string" || o.tenantId !== null && typeof o.tenantId != "string" || o.kind !== "user" && o.kind !== "guest") throw new g("request_unavailable");
184
+ return {
185
+ receipt: s,
186
+ target: {
187
+ subjectId: o.subjectId,
188
+ tenantId: o.tenantId,
189
+ kind: o.kind
190
+ }
191
+ };
192
+ });
193
+ }),
194
+ finish: async (n, i, a) => w(async () => {
195
+ if (b(n), x(i), a.some((e) => typeof e != "string" || !e.trim()) || new Set(a).size !== a.length) throw new g("invalid_request");
196
+ let o = l();
197
+ await r.transactional(async (r) => {
198
+ let c = await r.updateMany(p, { status: "erasing" }, { where: e(t("id", n), h(i), t("status", "erasing")) }), l = await u(r, n);
199
+ if (c !== 1 || !l || !C(l, i) || typeof l.id != "string") throw new g("invalid_transition");
200
+ await r.update(p, l.id, {
201
+ status: "completed",
202
+ completedAt: new Date(o),
203
+ completedPlugins: [...a],
204
+ subjectId: null,
205
+ tenantId: null,
206
+ activeKey: `terminal:${l.id}`
207
+ });
208
+ for (let e of await r.query(s(f).where(h(i)).descriptor)) if (C(e, i)) {
209
+ if (e.status !== "withdrawn" || typeof e.id != "string") throw new g("invalid_transition");
210
+ await r.update(p, e.id, {
211
+ subjectId: null,
212
+ tenantId: null,
213
+ activeKey: `terminal:${e.id}`
214
+ });
215
+ }
216
+ });
217
+ })
218
+ };
219
+ };
220
+ //#endregion
221
+ export { g as PrivacyRequestRefused, T as dataStorePrivacyRequests, f as privacyRequestsTable };
@@ -0,0 +1,66 @@
1
+ import { ActionProcedureDescriptor } from '@voltro/protocol';
2
+ import { PluginRpcClientDescriptor } from '@voltro/protocol';
3
+ import { Schema } from 'effect';
4
+ import { YieldableError } from 'effect/Cause';
5
+
6
+ export declare const exportSelfDescriptor: ActionProcedureDescriptor<"privacy.exportSelf", Schema.Struct<{
7
+ readonly requestId: Schema.optional<Schema.String>;
8
+ }>, Schema.Struct<{
9
+ readonly requestId: Schema.String;
10
+ readonly plugins: Schema.$Array<Schema.Struct<{
11
+ readonly name: Schema.String;
12
+ readonly data: Schema.Unknown;
13
+ }>>;
14
+ }>, typeof PrivacyCoordinatorFailure>;
15
+
16
+ declare class PrivacyCoordinatorFailure extends PrivacyCoordinatorFailure_base {
17
+ }
18
+
19
+ declare const PrivacyCoordinatorFailure_base: Schema.Class<PrivacyCoordinatorFailure, Schema.TaggedStruct<"PrivacyCoordinatorFailure", {
20
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_request", "request_unavailable", "active_request_exists", "invalid_transition", "coverage_missing", "hook_failed"]>;
21
+ readonly completed: Schema.$Array<Schema.String>;
22
+ readonly missing: Schema.$Array<Schema.String>;
23
+ }>, YieldableError>;
24
+
25
+ export declare const privacyRpcClientImports: ReadonlyArray<PluginRpcClientDescriptor>;
26
+
27
+ export declare const requestErasureDescriptor: ActionProcedureDescriptor<"privacy.requestErasure", Schema.Struct<{
28
+ readonly requestId: Schema.optional<Schema.String>;
29
+ }>, Schema.Struct<{
30
+ readonly requestId: Schema.String;
31
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
32
+ readonly requestedAt: Schema.Number;
33
+ readonly dueAt: Schema.Number;
34
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
35
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
36
+ readonly completedAt: Schema.NullOr<Schema.Number>;
37
+ readonly completedPlugins: Schema.$Array<Schema.String>;
38
+ }>, typeof PrivacyCoordinatorFailure>;
39
+
40
+ export declare const requestStatusDescriptor: ActionProcedureDescriptor<"privacy.requestStatus", Schema.Struct<{
41
+ readonly requestId: Schema.String;
42
+ }>, Schema.NullOr<Schema.Struct<{
43
+ readonly requestId: Schema.String;
44
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
45
+ readonly requestedAt: Schema.Number;
46
+ readonly dueAt: Schema.Number;
47
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
48
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
49
+ readonly completedAt: Schema.NullOr<Schema.Number>;
50
+ readonly completedPlugins: Schema.$Array<Schema.String>;
51
+ }>>, typeof PrivacyCoordinatorFailure>;
52
+
53
+ export declare const withdrawErasureDescriptor: ActionProcedureDescriptor<"privacy.withdrawErasure", Schema.Struct<{
54
+ readonly requestId: Schema.String;
55
+ }>, Schema.Struct<{
56
+ readonly requestId: Schema.String;
57
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
58
+ readonly requestedAt: Schema.Number;
59
+ readonly dueAt: Schema.Number;
60
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
61
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
62
+ readonly completedAt: Schema.NullOr<Schema.Number>;
63
+ readonly completedPlugins: Schema.$Array<Schema.String>;
64
+ }>, typeof PrivacyCoordinatorFailure>;
65
+
66
+ export { }
@@ -0,0 +1,64 @@
1
+ import { PrivacyCoordinatorFailure as e, PrivacyExportPackageSchema as t, PrivacyRequestReceiptSchema as n } from "./privacyContract.js";
2
+ import { Schema as r } from "effect";
3
+ import { defineAction as i } from "@voltro/protocol";
4
+ //#region src/privacyRpc.ts
5
+ var a = r.Struct({ requestId: r.optional(r.String) }), o = r.Struct({ requestId: r.String }), s = i({
6
+ name: "privacy.requestErasure",
7
+ input: a,
8
+ output: n,
9
+ error: e,
10
+ guards: [{ authenticated: !0 }]
11
+ }), c = i({
12
+ name: "privacy.requestStatus",
13
+ input: o,
14
+ output: r.NullOr(n),
15
+ error: e,
16
+ guards: [{ authenticated: !0 }]
17
+ }), l = i({
18
+ name: "privacy.withdrawErasure",
19
+ input: o,
20
+ output: n,
21
+ error: e,
22
+ guards: [{ authenticated: !0 }]
23
+ }), u = i({
24
+ name: "privacy.exportSelf",
25
+ input: a,
26
+ output: t,
27
+ error: e,
28
+ guards: [{ authenticated: !0 }]
29
+ }), d = [
30
+ {
31
+ tag: "privacy.requestErasure",
32
+ kind: "action",
33
+ import: {
34
+ module: "@voltro/plugin-deactivation/privacy/rpc",
35
+ name: "requestErasureDescriptor"
36
+ }
37
+ },
38
+ {
39
+ tag: "privacy.requestStatus",
40
+ kind: "action",
41
+ import: {
42
+ module: "@voltro/plugin-deactivation/privacy/rpc",
43
+ name: "requestStatusDescriptor"
44
+ }
45
+ },
46
+ {
47
+ tag: "privacy.withdrawErasure",
48
+ kind: "action",
49
+ import: {
50
+ module: "@voltro/plugin-deactivation/privacy/rpc",
51
+ name: "withdrawErasureDescriptor"
52
+ }
53
+ },
54
+ {
55
+ tag: "privacy.exportSelf",
56
+ kind: "action",
57
+ import: {
58
+ module: "@voltro/plugin-deactivation/privacy/rpc",
59
+ name: "exportSelfDescriptor"
60
+ }
61
+ }
62
+ ];
63
+ //#endregion
64
+ export { u as exportSelfDescriptor, d as privacyRpcClientImports, s as requestErasureDescriptor, c as requestStatusDescriptor, l as withdrawErasureDescriptor };
@@ -0,0 +1,5 @@
1
+ import { Context as e } from "effect";
2
+ //#region src/privacyService.ts
3
+ var t = class extends e.Service()("voltro/PrivacyService") {};
4
+ //#endregion
5
+ export { t as PrivacyService };
@@ -0,0 +1,85 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { Layer } from 'effect';
4
+ import { Schema } from 'effect';
5
+ import { Subject } from '@voltro/protocol';
6
+ import { SystemPortFixture } from '@voltro/testing/system';
7
+ import { SystemSlotFixture } from '@voltro/testing/system';
8
+ import { WorkflowRunHandle } from '@voltro/protocol';
9
+ import { YieldableError } from 'effect/Cause';
10
+
11
+ export declare const fakePrivacyOperations: (overrides?: Partial<PrivacyOperations>) => PrivacyOperations;
12
+
13
+ declare class PrivacyCoordinatorFailure extends PrivacyCoordinatorFailure_base {
14
+ }
15
+
16
+ declare const PrivacyCoordinatorFailure_base: Schema.Class<PrivacyCoordinatorFailure, Schema.TaggedStruct<"PrivacyCoordinatorFailure", {
17
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_request", "request_unavailable", "active_request_exists", "invalid_transition", "coverage_missing", "hook_failed"]>;
18
+ readonly completed: Schema.$Array<Schema.String>;
19
+ readonly missing: Schema.$Array<Schema.String>;
20
+ }>, YieldableError>;
21
+
22
+ /** Internal scan position, not caller identity or authorization. */
23
+ declare interface PrivacyDispatchCursor {
24
+ readonly dueAt: number;
25
+ readonly requestId: string;
26
+ }
27
+
28
+ declare interface PrivacyDispatchResult {
29
+ readonly submitted: ReadonlyArray<{
30
+ readonly requestId: string;
31
+ readonly status: WorkflowRunHandle['status'];
32
+ }>;
33
+ readonly failed: ReadonlyArray<string>;
34
+ readonly next: PrivacyDispatchCursor | null;
35
+ }
36
+
37
+ export declare const privacyExportFixture: SystemSlotFixture;
38
+
39
+ declare type PrivacyExportPackage = typeof PrivacyExportPackageSchema.Type;
40
+
41
+ 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 const privacyFakeLayer: Layer.Layer<PrivacyService, never, never>;
50
+
51
+ declare interface PrivacyOperations {
52
+ readonly requestErasure: (subject: Subject, requestId?: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
53
+ readonly readSelf: (subject: Subject, requestId: string) => Effect.Effect<PrivacyRequestReceipt | null, PrivacyCoordinatorFailure>;
54
+ readonly withdraw: (subject: Subject, requestId: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
55
+ readonly exportSelf: (subject: Subject, requestId?: string) => Effect.Effect<PrivacyExportPackage, PrivacyCoordinatorFailure>;
56
+ /** Trusted worker only; wire procedures never expose this method. */
57
+ readonly execute: (requestId: string) => Effect.Effect<PrivacyRequestReceipt, PrivacyCoordinatorFailure>;
58
+ /** Trusted schedule only; this port owns no timer or queue. */
59
+ readonly dispatch: (input: {
60
+ readonly limit: number;
61
+ readonly after?: PrivacyDispatchCursor;
62
+ }, start: (payload: {
63
+ readonly requestId: string;
64
+ }) => Promise<WorkflowRunHandle>) => Effect.Effect<PrivacyDispatchResult, PrivacyCoordinatorFailure>;
65
+ }
66
+
67
+ export declare const privacyPortFixture: SystemPortFixture;
68
+
69
+ declare interface PrivacyRequestReceipt {
70
+ readonly requestId: string;
71
+ readonly status: 'pending' | 'erasing' | 'withdrawn' | 'completed';
72
+ readonly requestedAt: number;
73
+ readonly dueAt: number;
74
+ readonly claimedAt: number | null;
75
+ readonly withdrawnAt: number | null;
76
+ readonly completedAt: number | null;
77
+ readonly completedPlugins: ReadonlyArray<string>;
78
+ }
79
+
80
+ declare class PrivacyService extends PrivacyService_base {
81
+ }
82
+
83
+ declare const PrivacyService_base: Context.ServiceClass<PrivacyService, "voltro/PrivacyService", PrivacyOperations>;
84
+
85
+ export { }
@@ -0,0 +1,55 @@
1
+ import { PrivacyCoordinatorFailure as e, jsonPrivacyExport as t } from "./privacyContract.js";
2
+ import { PrivacyService as n } from "./privacyService.js";
3
+ import { Effect as r, Layer as i } from "effect";
4
+ import { systemPortFixture as a } from "@voltro/testing/system";
5
+ //#region src/privacyTesting.ts
6
+ var o = () => r.fail(new e({
7
+ code: "request_unavailable",
8
+ completed: [],
9
+ missing: []
10
+ })), s = (e = {}) => ({
11
+ requestErasure: o,
12
+ readSelf: () => r.succeed(null),
13
+ withdraw: o,
14
+ exportSelf: o,
15
+ execute: o,
16
+ dispatch: o,
17
+ ...e
18
+ }), c = i.succeed(n, s()), l = a({
19
+ tag: n,
20
+ fakeLayer: c,
21
+ read: r.flatMap(n, (e) => e.readSelf({
22
+ type: "user",
23
+ id: "fixture",
24
+ tenantId: "fixture"
25
+ }, "fixture")),
26
+ expected: null
27
+ }), u = {
28
+ kind: "slot",
29
+ defaultImplementation: t,
30
+ defaultProbe: {
31
+ run: () => r.sync(() => t({
32
+ requestId: "export",
33
+ plugins: []
34
+ })),
35
+ expected: {
36
+ requestId: "export",
37
+ plugins: []
38
+ }
39
+ },
40
+ overrideProbe: {
41
+ run: () => r.sync(() => ({
42
+ ...t({
43
+ requestId: "export",
44
+ plugins: []
45
+ }),
46
+ requestId: "packaged-export"
47
+ })),
48
+ expected: {
49
+ requestId: "packaged-export",
50
+ plugins: []
51
+ }
52
+ }
53
+ };
54
+ //#endregion
55
+ export { s as fakePrivacyOperations, u as privacyExportFixture, c as privacyFakeLayer, l as privacyPortFixture };
@@ -0,0 +1,34 @@
1
+ import { Schema } from 'effect';
2
+ import { Workflow } from 'effect/workflow/Workflow';
3
+ import { WorkflowMessagesCarrier } from '@voltro/workflow';
4
+ import { YieldableError } from 'effect/Cause';
5
+
6
+ declare class PrivacyCoordinatorFailure extends PrivacyCoordinatorFailure_base {
7
+ }
8
+
9
+ declare const PrivacyCoordinatorFailure_base: Schema.Class<PrivacyCoordinatorFailure, Schema.TaggedStruct<"PrivacyCoordinatorFailure", {
10
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_request", "request_unavailable", "active_request_exists", "invalid_transition", "coverage_missing", "hook_failed"]>;
11
+ readonly completed: Schema.$Array<Schema.String>;
12
+ readonly missing: Schema.$Array<Schema.String>;
13
+ }>, YieldableError>;
14
+
15
+ /** Payload/journal carry an opaque request identity and safe receipt only. */
16
+ export declare const PrivacyErasure: Workflow<"privacy.erase", Schema.Struct<{
17
+ requestId: Schema.NonEmptyString;
18
+ }>, Schema.Struct<{
19
+ readonly requestId: Schema.String;
20
+ readonly status: Schema.Literals<readonly ["pending", "erasing", "withdrawn", "completed"]>;
21
+ readonly requestedAt: Schema.Number;
22
+ readonly dueAt: Schema.Number;
23
+ readonly claimedAt: Schema.NullOr<Schema.Number>;
24
+ readonly withdrawnAt: Schema.NullOr<Schema.Number>;
25
+ readonly completedAt: Schema.NullOr<Schema.Number>;
26
+ readonly completedPlugins: Schema.$Array<Schema.String>;
27
+ }>, typeof PrivacyCoordinatorFailure> & {
28
+ readonly name: "privacy.erase";
29
+ } & WorkflowMessagesCarrier<{
30
+ readonly signals: {};
31
+ readonly updates: {};
32
+ }>;
33
+
34
+ export { }
@@ -0,0 +1,16 @@
1
+ import { PrivacyCoordinatorFailure as e, PrivacyRequestReceiptSchema as t } from "./privacyContract.js";
2
+ import { Schema as n } from "effect";
3
+ import { workflow as r } from "@voltro/workflow/define";
4
+ //#region src/privacyWorkflow.ts
5
+ var i = r({
6
+ name: "privacy.erase",
7
+ payload: { requestId: n.NonEmptyString },
8
+ success: t,
9
+ error: e,
10
+ idempotencyKey: ({ requestId: e }) => `privacy:${e}`,
11
+ concurrency: { limit: 4 },
12
+ suspendOnFailure: !0,
13
+ internal: !0
14
+ });
15
+ //#endregion
16
+ export { i as PrivacyErasure };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-deactivation",
3
- "version": "0.86.0",
3
+ "version": "0.87.0",
4
4
  "description": "Deactivation plugin — ships the `deactivation()` schema mixin (deactivatedAt + deactivatedBy → Actor). A deactivated subject can't log in but its data stays VISIBLE (distinct from soft-delete, which hides + anonymises). Pure schema mixin, like audit().",
5
5
  "keywords": [
6
6
  "voltro",
@@ -33,7 +33,32 @@
33
33
  "import": "./dist/guard.js",
34
34
  "default": "./dist/guard.js"
35
35
  },
36
- "./package.json": "./package.json"
36
+ "./package.json": "./package.json",
37
+ "./privacy": {
38
+ "types": "./dist/privacyPlugin.d.ts",
39
+ "import": "./dist/privacyPlugin.js",
40
+ "default": "./dist/privacyPlugin.js"
41
+ },
42
+ "./privacy/rpc": {
43
+ "types": "./dist/privacyRpc.d.ts",
44
+ "import": "./dist/privacyRpc.js",
45
+ "default": "./dist/privacyRpc.js"
46
+ },
47
+ "./privacy/contract": {
48
+ "types": "./dist/privacyContract.d.ts",
49
+ "import": "./dist/privacyContract.js",
50
+ "default": "./dist/privacyContract.js"
51
+ },
52
+ "./privacy/workflow": {
53
+ "types": "./dist/privacyWorkflow.d.ts",
54
+ "import": "./dist/privacyWorkflow.js",
55
+ "default": "./dist/privacyWorkflow.js"
56
+ },
57
+ "./privacy/testing": {
58
+ "types": "./dist/privacyTesting.d.ts",
59
+ "import": "./dist/privacyTesting.js",
60
+ "default": "./dist/privacyTesting.js"
61
+ }
37
62
  },
38
63
  "main": "./dist/index.js",
39
64
  "module": "./dist/index.js",
@@ -43,17 +68,23 @@
43
68
  "node": ">=24.0.0"
44
69
  },
45
70
  "dependencies": {
46
- "@voltro/database": "0.86.0",
47
- "@voltro/plugin-audit": "0.86.0",
48
- "@voltro/protocol": "0.86.0"
71
+ "@voltro/database": "0.87.0",
72
+ "@voltro/plugin-audit": "0.87.0",
73
+ "@voltro/protocol": "0.87.0",
74
+ "@voltro/workflow": "0.87.0",
75
+ "@voltro/runtime": "0.87.0"
49
76
  },
50
77
  "peerDependencies": {
51
- "@voltro/plugin-auth": "0.86.0",
52
- "effect": "4.0.1"
78
+ "@voltro/plugin-auth": "0.87.0",
79
+ "effect": "4.0.1",
80
+ "@voltro/testing": "0.87.0"
53
81
  },
54
82
  "peerDependenciesMeta": {
55
83
  "@voltro/plugin-auth": {
56
84
  "optional": true
85
+ },
86
+ "@voltro/testing": {
87
+ "optional": true
57
88
  }
58
89
  },
59
90
  "publishConfig": {