@apart-tech/intelligence-core 1.20.0 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/index.d.ts +12 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +6 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/vector.d.ts +6 -0
  6. package/dist/lib/vector.d.ts.map +1 -0
  7. package/dist/lib/vector.js +17 -0
  8. package/dist/lib/vector.js.map +1 -0
  9. package/dist/lib/vector.test.d.ts +2 -0
  10. package/dist/lib/vector.test.d.ts.map +1 -0
  11. package/dist/lib/vector.test.js +36 -0
  12. package/dist/lib/vector.test.js.map +1 -0
  13. package/dist/services/__tests__/node-service.test.js +3 -3
  14. package/dist/services/__tests__/node-service.test.js.map +1 -1
  15. package/dist/services/agent-cli-reference.d.ts +1 -1
  16. package/dist/services/agent-cli-reference.d.ts.map +1 -1
  17. package/dist/services/agent-cli-reference.js +2 -2
  18. package/dist/services/chat-capture-service.d.ts.map +1 -1
  19. package/dist/services/chat-capture-service.js +1 -0
  20. package/dist/services/chat-capture-service.js.map +1 -1
  21. package/dist/services/chat-tool-definitions.d.ts +178 -0
  22. package/dist/services/chat-tool-definitions.d.ts.map +1 -0
  23. package/dist/services/chat-tool-definitions.js +120 -0
  24. package/dist/services/chat-tool-definitions.js.map +1 -0
  25. package/dist/services/chat-tool-definitions.test.d.ts +2 -0
  26. package/dist/services/chat-tool-definitions.test.d.ts.map +1 -0
  27. package/dist/services/chat-tool-definitions.test.js +150 -0
  28. package/dist/services/chat-tool-definitions.test.js.map +1 -0
  29. package/dist/services/content-policy-service.d.ts +27 -2
  30. package/dist/services/content-policy-service.d.ts.map +1 -1
  31. package/dist/services/content-policy-service.js +147 -18
  32. package/dist/services/content-policy-service.js.map +1 -1
  33. package/dist/services/content-policy-service.test.d.ts +2 -0
  34. package/dist/services/content-policy-service.test.d.ts.map +1 -0
  35. package/dist/services/content-policy-service.test.js +310 -0
  36. package/dist/services/content-policy-service.test.js.map +1 -0
  37. package/dist/services/document-post-check-service.d.ts +47 -0
  38. package/dist/services/document-post-check-service.d.ts.map +1 -0
  39. package/dist/services/document-post-check-service.js +130 -0
  40. package/dist/services/document-post-check-service.js.map +1 -0
  41. package/dist/services/document-post-check-service.test.d.ts +2 -0
  42. package/dist/services/document-post-check-service.test.d.ts.map +1 -0
  43. package/dist/services/document-post-check-service.test.js +150 -0
  44. package/dist/services/document-post-check-service.test.js.map +1 -0
  45. package/dist/services/document-render-service.d.ts +27 -0
  46. package/dist/services/document-render-service.d.ts.map +1 -0
  47. package/dist/services/document-render-service.js +186 -0
  48. package/dist/services/document-render-service.js.map +1 -0
  49. package/dist/services/document-render-service.test.d.ts +2 -0
  50. package/dist/services/document-render-service.test.d.ts.map +1 -0
  51. package/dist/services/document-render-service.test.js +144 -0
  52. package/dist/services/document-render-service.test.js.map +1 -0
  53. package/dist/services/document-service.d.ts +4 -1
  54. package/dist/services/document-service.d.ts.map +1 -1
  55. package/dist/services/document-service.js +24 -1
  56. package/dist/services/document-service.js.map +1 -1
  57. package/dist/services/document-tool-handler.d.ts +44 -0
  58. package/dist/services/document-tool-handler.d.ts.map +1 -0
  59. package/dist/services/document-tool-handler.js +179 -0
  60. package/dist/services/document-tool-handler.js.map +1 -0
  61. package/dist/services/document-tool-handler.test.d.ts +2 -0
  62. package/dist/services/document-tool-handler.test.d.ts.map +1 -0
  63. package/dist/services/document-tool-handler.test.js +149 -0
  64. package/dist/services/document-tool-handler.test.js.map +1 -0
  65. package/dist/services/node-service.js +2 -2
  66. package/dist/services/node-service.js.map +1 -1
  67. package/dist/services/quota-service.d.ts +2 -0
  68. package/dist/services/quota-service.d.ts.map +1 -1
  69. package/dist/services/quota-service.js +17 -1
  70. package/dist/services/quota-service.js.map +1 -1
  71. package/dist/services/usage-service.d.ts +21 -1
  72. package/dist/services/usage-service.d.ts.map +1 -1
  73. package/dist/services/usage-service.js +37 -1
  74. package/dist/services/usage-service.js.map +1 -1
  75. package/dist/types/index.d.ts +12 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/package.json +11 -1
  78. package/prisma/schema.prisma +39 -29
@@ -0,0 +1,310 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ContentPolicyService, DEFAULT_THRESHOLDS } from "./content-policy-service.js";
3
+ const ORG_ID = "org-test-123";
4
+ function makeKeywordPolicy(overrides) {
5
+ return {
6
+ id: "policy-kw-1",
7
+ organizationId: ORG_ID,
8
+ name: "Block strategic terms",
9
+ description: "",
10
+ category: "strategic",
11
+ keywords: ["confidential", "board meeting"],
12
+ action: "block",
13
+ enabled: true,
14
+ priority: 10,
15
+ matchMode: "keyword",
16
+ sensitivity: null,
17
+ createdAt: new Date(),
18
+ updatedAt: new Date(),
19
+ ...overrides,
20
+ };
21
+ }
22
+ function makeSemanticPolicy(overrides) {
23
+ return {
24
+ id: "policy-sem-1",
25
+ organization_id: ORG_ID,
26
+ name: "Block strategic planning",
27
+ description: "Strategic planning, competitive analysis, market positioning",
28
+ category: "strategic",
29
+ keywords: "[]",
30
+ action: "block",
31
+ enabled: true,
32
+ priority: 5,
33
+ match_mode: "semantic",
34
+ sensitivity: "moderate",
35
+ reference_embedding: "[0.1,0.2,0.3,0.4,0.5]",
36
+ created_at: new Date(),
37
+ updated_at: new Date(),
38
+ ...overrides,
39
+ };
40
+ }
41
+ function makeMockDb(opts) {
42
+ return {
43
+ orgContentPolicy: {
44
+ findMany: vi.fn(async () => opts?.policies ?? []),
45
+ findUnique: vi.fn(async () => null),
46
+ create: vi.fn(async (args) => ({ id: "new-id", ...args.data })),
47
+ update: vi.fn(async (args) => ({ id: args.where.id, ...args.data })),
48
+ delete: vi.fn(async () => ({})),
49
+ },
50
+ contentPolicyLog: {
51
+ findMany: vi.fn(async () => []),
52
+ create: vi.fn(async () => ({})),
53
+ },
54
+ $queryRaw: vi.fn(async () => opts?.rawPolicies ?? []),
55
+ $executeRaw: vi.fn(async () => 1),
56
+ };
57
+ }
58
+ describe("ContentPolicyService", () => {
59
+ describe("evaluate — keyword mode", () => {
60
+ it("detects keyword violations with word-boundary match", async () => {
61
+ const db = makeMockDb({
62
+ policies: [makeKeywordPolicy()],
63
+ });
64
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
65
+ const result = await svc.evaluate("This is a confidential document");
66
+ expect(result.allowed).toBe(false);
67
+ expect(result.violations).toHaveLength(1);
68
+ expect(result.violations[0].matchedKeyword).toBe("confidential");
69
+ });
70
+ it("allows content without matching keywords", async () => {
71
+ const db = makeMockDb({
72
+ policies: [makeKeywordPolicy()],
73
+ });
74
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
75
+ const result = await svc.evaluate("Let's plan the office party");
76
+ expect(result.allowed).toBe(true);
77
+ expect(result.violations).toHaveLength(0);
78
+ });
79
+ it("handles warn action without blocking", async () => {
80
+ const db = makeMockDb({
81
+ policies: [makeKeywordPolicy({ action: "warn" })],
82
+ });
83
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
84
+ const result = await svc.evaluate("This is confidential");
85
+ expect(result.allowed).toBe(true);
86
+ expect(result.violations).toHaveLength(1);
87
+ expect(result.violations[0].action).toBe("warn");
88
+ });
89
+ it("skips semantic policies when no embedding provided", async () => {
90
+ const db = makeMockDb({
91
+ policies: [
92
+ makeKeywordPolicy(),
93
+ // Semantic policy is present in the findMany results but won't be evaluated
94
+ {
95
+ ...makeKeywordPolicy({ id: "policy-sem-1" }),
96
+ matchMode: "semantic",
97
+ sensitivity: "moderate",
98
+ keywords: [],
99
+ },
100
+ ],
101
+ });
102
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
103
+ const result = await svc.evaluate("let's discuss strategy");
104
+ // Only keyword evaluation runs; "strategy" doesn't match "confidential" or "board meeting"
105
+ expect(result.violations).toHaveLength(0);
106
+ });
107
+ });
108
+ describe("evaluate — semantic mode", () => {
109
+ // Matching embedding (identical to reference [0.1,0.2,0.3,0.4,0.5] → similarity = 1.0)
110
+ const similarEmbedding = [0.1, 0.2, 0.3, 0.4, 0.5];
111
+ // Low but positive similarity to reference
112
+ const lowSimilarityEmbedding = [0.5, 0.1, 0.05, 0.05, 0.01];
113
+ // Orthogonal / negative similarity
114
+ const differentEmbedding = [0.5, -0.3, 0.1, -0.4, 0.2];
115
+ it("blocks content with high similarity at moderate threshold", async () => {
116
+ const db = makeMockDb({
117
+ rawPolicies: [makeSemanticPolicy()],
118
+ });
119
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
120
+ const result = await svc.evaluate("strategic planning", similarEmbedding);
121
+ expect(result.allowed).toBe(false);
122
+ expect(result.violations).toHaveLength(1);
123
+ expect(result.violations[0].matchedKeyword).toMatch(/^semantic:[\d.]+$/);
124
+ });
125
+ it("allows content with low similarity", async () => {
126
+ const db = makeMockDb({
127
+ rawPolicies: [makeSemanticPolicy()],
128
+ });
129
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
130
+ const result = await svc.evaluate("office holiday party", differentEmbedding);
131
+ // Similarity should be below moderate threshold (0.65)
132
+ expect(result.allowed).toBe(true);
133
+ });
134
+ it("respects strict sensitivity (lower threshold)", async () => {
135
+ const db = makeMockDb({
136
+ rawPolicies: [makeSemanticPolicy({ sensitivity: "strict" })],
137
+ });
138
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
139
+ // Use a somewhat similar embedding — would pass moderate but fail strict
140
+ const partialMatch = [0.15, 0.18, 0.25, 0.35, 0.42];
141
+ const result = await svc.evaluate("somewhat related", partialMatch);
142
+ // With strict threshold (0.50), this embedding has high enough cosine sim
143
+ // cosineSimilarity([0.15,0.18,0.25,0.35,0.42], [0.1,0.2,0.3,0.4,0.5]) should be > 0.5
144
+ expect(result.violations.length).toBeGreaterThanOrEqual(0); // depends on actual similarity
145
+ });
146
+ it("uses org threshold overrides when provided", async () => {
147
+ const db = makeMockDb({
148
+ rawPolicies: [makeSemanticPolicy({ sensitivity: "moderate" })],
149
+ });
150
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
151
+ // lowSimilarityEmbedding has positive but low cosine similarity to [0.1,0.2,0.3,0.4,0.5].
152
+ // With default moderate threshold (0.65) it should NOT trigger.
153
+ const resultDefault = await svc.evaluate("anything", lowSimilarityEmbedding);
154
+ expect(resultDefault.violations).toHaveLength(0);
155
+ // With a very low override (0.01), even low similarity should trigger.
156
+ const resultOverride = await svc.evaluate("anything", lowSimilarityEmbedding, {
157
+ moderate: 0.01,
158
+ });
159
+ expect(resultOverride.violations).toHaveLength(1);
160
+ expect(resultOverride.allowed).toBe(false);
161
+ });
162
+ it("skips policy on dimension mismatch", async () => {
163
+ const db = makeMockDb({
164
+ rawPolicies: [makeSemanticPolicy()],
165
+ });
166
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
167
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
168
+ // Content embedding has different dimensions than reference (5 elements)
169
+ const wrongDimEmbedding = [0.1, 0.2, 0.3];
170
+ const result = await svc.evaluate("strategic planning", wrongDimEmbedding);
171
+ expect(result.allowed).toBe(true);
172
+ expect(result.violations).toHaveLength(0);
173
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("Dimension mismatch"));
174
+ warnSpy.mockRestore();
175
+ });
176
+ it("skips semantic policies when reference_embedding is null", async () => {
177
+ const db = makeMockDb({
178
+ rawPolicies: [makeSemanticPolicy({ reference_embedding: null })],
179
+ });
180
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
181
+ const result = await svc.evaluate("strategic planning", similarEmbedding);
182
+ expect(result.allowed).toBe(true);
183
+ expect(result.violations).toHaveLength(0);
184
+ });
185
+ });
186
+ describe("create", () => {
187
+ it("creates a keyword policy with defaults", async () => {
188
+ const db = makeMockDb();
189
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
190
+ await svc.create({
191
+ name: "Test",
192
+ category: "test",
193
+ keywords: ["foo"],
194
+ action: "block",
195
+ });
196
+ expect(db.orgContentPolicy.create).toHaveBeenCalledWith(expect.objectContaining({
197
+ data: expect.objectContaining({
198
+ matchMode: "keyword",
199
+ sensitivity: null,
200
+ }),
201
+ }));
202
+ });
203
+ it("creates a semantic policy and writes embedding via raw SQL", async () => {
204
+ const db = makeMockDb();
205
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
206
+ await svc.create({
207
+ name: "Semantic test",
208
+ description: "Test topic",
209
+ category: "test",
210
+ keywords: [],
211
+ action: "block",
212
+ matchMode: "semantic",
213
+ sensitivity: "moderate",
214
+ referenceEmbedding: [0.1, 0.2, 0.3],
215
+ });
216
+ expect(db.orgContentPolicy.create).toHaveBeenCalledWith(expect.objectContaining({
217
+ data: expect.objectContaining({
218
+ matchMode: "semantic",
219
+ sensitivity: "moderate",
220
+ }),
221
+ }));
222
+ expect(db.$executeRaw).toHaveBeenCalled();
223
+ });
224
+ });
225
+ describe("allowOverride", () => {
226
+ it("includes allowOverride in keyword violations", async () => {
227
+ const db = makeMockDb({
228
+ policies: [makeKeywordPolicy({ allowOverride: true })],
229
+ });
230
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
231
+ const result = await svc.evaluate("confidential stuff");
232
+ expect(result.violations).toHaveLength(1);
233
+ expect(result.violations[0].allowOverride).toBe(true);
234
+ });
235
+ it("defaults allowOverride to true for policies without the field", async () => {
236
+ const db = makeMockDb({
237
+ policies: [makeKeywordPolicy()],
238
+ });
239
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
240
+ const result = await svc.evaluate("confidential info");
241
+ expect(result.violations[0].allowOverride).toBe(true);
242
+ });
243
+ it("returns allowOverride=false when policy disallows overrides", async () => {
244
+ const db = makeMockDb({
245
+ policies: [makeKeywordPolicy({ allowOverride: false })],
246
+ });
247
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
248
+ const result = await svc.evaluate("confidential data");
249
+ expect(result.violations[0].allowOverride).toBe(false);
250
+ });
251
+ it("creates a policy with allowOverride=false", async () => {
252
+ const db = makeMockDb();
253
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
254
+ await svc.create({
255
+ name: "Strict",
256
+ category: "test",
257
+ keywords: ["secret"],
258
+ action: "block",
259
+ allowOverride: false,
260
+ });
261
+ expect(db.orgContentPolicy.create).toHaveBeenCalledWith(expect.objectContaining({
262
+ data: expect.objectContaining({
263
+ allowOverride: false,
264
+ }),
265
+ }));
266
+ });
267
+ });
268
+ describe("logViolation", () => {
269
+ it("logs with userOverride=false by default", async () => {
270
+ const db = makeMockDb();
271
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
272
+ await svc.logViolation({
273
+ policyId: "p1",
274
+ policyName: "Test",
275
+ userId: "u1",
276
+ action: "blocked",
277
+ matchedKeyword: "secret",
278
+ });
279
+ expect(db.contentPolicyLog.create).toHaveBeenCalledWith(expect.objectContaining({
280
+ data: expect.objectContaining({
281
+ userOverride: false,
282
+ }),
283
+ }));
284
+ });
285
+ it("logs with userOverride=true when specified", async () => {
286
+ const db = makeMockDb();
287
+ const svc = new ContentPolicyService(db, { organizationId: ORG_ID });
288
+ await svc.logViolation({
289
+ policyId: "p1",
290
+ policyName: "Test",
291
+ userId: "u1",
292
+ action: "overridden",
293
+ matchedKeyword: "secret",
294
+ userOverride: true,
295
+ });
296
+ expect(db.contentPolicyLog.create).toHaveBeenCalledWith(expect.objectContaining({
297
+ data: expect.objectContaining({
298
+ userOverride: true,
299
+ }),
300
+ }));
301
+ });
302
+ });
303
+ describe("DEFAULT_THRESHOLDS", () => {
304
+ it("has correct ordering: mild > moderate > strict", () => {
305
+ expect(DEFAULT_THRESHOLDS.mild).toBeGreaterThan(DEFAULT_THRESHOLDS.moderate);
306
+ expect(DEFAULT_THRESHOLDS.moderate).toBeGreaterThan(DEFAULT_THRESHOLDS.strict);
307
+ });
308
+ });
309
+ });
310
+ //# sourceMappingURL=content-policy-service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-policy-service.test.js","sourceRoot":"","sources":["../../src/services/content-policy-service.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAc,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAKvF,MAAM,MAAM,GAAG,cAAc,CAAC;AAE9B,SAAS,iBAAiB,CAAC,SAAmC;IAC5D,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,cAAc,EAAE,MAAM;QACtB,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;QAC3C,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,SAAS;QACpB,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAmC;IAC7D,OAAO;QACL,EAAE,EAAE,cAAc;QAClB,eAAe,EAAE,MAAM;QACvB,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,8DAA8D;QAC3E,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,UAAU;QACtB,WAAW,EAAE,UAAU;QACvB,mBAAmB,EAAE,uBAAuB;QAC5C,UAAU,EAAE,IAAI,IAAI,EAAE;QACtB,UAAU,EAAE,IAAI,IAAI,EAAE;QACtB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAGnB;IACC,OAAO;QACL,gBAAgB,EAAE;YAChB,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;YACjD,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC;YACnC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACpE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACzE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChC;QACD,gBAAgB,EAAE;YAChB,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/B,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChC;QACD,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QACrD,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;KACd,CAAC;AACxB,CAAC;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;aAChC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC;YAErE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;aAChC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;aAClD,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE;oBACR,iBAAiB,EAAE;oBACnB,4EAA4E;oBAC5E;wBACE,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC;wBAC5C,SAAS,EAAE,UAAU;wBACrB,WAAW,EAAE,UAAU;wBACvB,QAAQ,EAAE,EAAE;qBACb;iBACF;aACF,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;YAE5D,2FAA2F;YAC3F,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,uFAAuF;QACvF,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,2CAA2C;QAC3C,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5D,mCAAmC;QACnC,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAEvD,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,EAAE,CAAC;aACpC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC;YAE1E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,EAAE,CAAC;aACpC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC;YAE9E,uDAAuD;YACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;aAC7D,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,yEAAyE;YACzE,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;YAEpE,0EAA0E;YAC1E,sFAAsF;YACtF,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,+BAA+B;QAC7F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;aAC/D,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,0FAA0F;YAC1F,gEAAgE;YAChE,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;YAC7E,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAEjD,uEAAuE;YACvE,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,sBAAsB,EAAE;gBAC5E,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YACH,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,EAAE,CAAC;aACpC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAEvE,yEAAyE;YACzE,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC;YAE3E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAClC,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAC9C,CAAC;YAEF,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACxE,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,WAAW,EAAE,CAAC,kBAAkB,CAAC,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;aACjE,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC;YAE1E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,MAAM,GAAG,CAAC,MAAM,CAAC;gBACf,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,CAAC,KAAK,CAAC;gBACjB,MAAM,EAAE,OAAO;aAChB,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACrD,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,SAAS,EAAE,SAAS;oBACpB,WAAW,EAAE,IAAI;iBAClB,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,MAAM,GAAG,CAAC,MAAM,CAAC;gBACf,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,YAAY;gBACzB,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,EAAE;gBACZ,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,UAAU;gBACrB,WAAW,EAAE,UAAU;gBACvB,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;aACpC,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACrD,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,SAAS,EAAE,UAAU;oBACrB,WAAW,EAAE,UAAU;iBACxB,CAAC;aACH,CAAC,CACH,CAAC;YACF,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;aACvD,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YAExD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC7E,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;aAChC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAEvD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,EAAE,GAAG,UAAU,CAAC;gBACpB,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;aACxD,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAEvD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,MAAM,GAAG,CAAC,MAAM,CAAC;gBACf,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,CAAC,QAAQ,CAAC;gBACpB,MAAM,EAAE,OAAO;gBACf,aAAa,EAAE,KAAK;aACrB,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACrD,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,aAAa,EAAE,KAAK;iBACrB,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,MAAM,GAAG,CAAC,YAAY,CAAC;gBACrB,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,MAAM;gBAClB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,SAAS;gBACjB,cAAc,EAAE,QAAQ;aACzB,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACrD,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,YAAY,EAAE,KAAK;iBACpB,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,oBAAoB,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAErE,MAAM,GAAG,CAAC,YAAY,CAAC;gBACrB,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,MAAM;gBAClB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,YAAY;gBACpB,cAAc,EAAE,QAAQ;gBACxB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,oBAAoB,CACrD,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,YAAY,EAAE,IAAI;iBACnB,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC7E,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Post-check service for document editing.
3
+ *
4
+ * Extracts text from rendered document buffers and runs policy/PII checks.
5
+ * Used after sandbox editing completes to verify the output meets org policies.
6
+ */
7
+ import type { ContentPolicyService } from "./content-policy-service.js";
8
+ import type { PiiDetectorService } from "./pii-detector-service.js";
9
+ export interface PostCheckInput {
10
+ buffer: Buffer;
11
+ mimeType: string;
12
+ piiOutputPolicy: "warn" | "block" | "strip";
13
+ contentPolicyService?: ContentPolicyService;
14
+ piiDetector?: PiiDetectorService;
15
+ }
16
+ export interface PostCheckResult {
17
+ allowed: boolean;
18
+ piiDetected: boolean;
19
+ piiWarning: boolean;
20
+ policyViolation?: string;
21
+ extractedTextLength: number;
22
+ }
23
+ export declare class DocumentPostCheckService {
24
+ /**
25
+ * Extract user-visible text from a document buffer.
26
+ * Format-aware: handles XLSX, DOCX, PPTX, and CSV.
27
+ */
28
+ extractText(buffer: Buffer, mimeType: string): Promise<string>;
29
+ /**
30
+ * Run post-check: extract text → policy check → PII check.
31
+ */
32
+ postCheck(input: PostCheckInput): Promise<PostCheckResult>;
33
+ /**
34
+ * Extract text from an XLSX buffer using ExcelJS.
35
+ */
36
+ private extractXlsxText;
37
+ /**
38
+ * Extract text from a DOCX buffer using mammoth.
39
+ */
40
+ private extractDocxText;
41
+ /**
42
+ * Extract text from a PPTX buffer by parsing the OOXML zip.
43
+ * Uses jszip to read slide XML files and extracts text content.
44
+ */
45
+ private extractPptxText;
46
+ }
47
+ //# sourceMappingURL=document-post-check-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.d.ts","sourceRoot":"","sources":["../../src/services/document-post-check-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC5C,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,wBAAwB;IACnC;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAepE;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAuDhE;;OAEG;YACW,eAAe;IAwB7B;;OAEG;YACW,eAAe;IAM7B;;;OAGG;YACW,eAAe;CAuB9B"}
@@ -0,0 +1,130 @@
1
+ export class DocumentPostCheckService {
2
+ /**
3
+ * Extract user-visible text from a document buffer.
4
+ * Format-aware: handles XLSX, DOCX, PPTX, and CSV.
5
+ */
6
+ async extractText(buffer, mimeType) {
7
+ switch (mimeType) {
8
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
9
+ return this.extractXlsxText(buffer);
10
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
11
+ return this.extractDocxText(buffer);
12
+ case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
13
+ return this.extractPptxText(buffer);
14
+ case "text/csv":
15
+ return buffer.toString("utf-8");
16
+ default:
17
+ return buffer.toString("utf-8");
18
+ }
19
+ }
20
+ /**
21
+ * Run post-check: extract text → policy check → PII check.
22
+ */
23
+ async postCheck(input) {
24
+ const text = await this.extractText(input.buffer, input.mimeType);
25
+ // Content policy check
26
+ if (input.contentPolicyService) {
27
+ try {
28
+ const evaluation = await input.contentPolicyService.evaluate(text);
29
+ if (!evaluation.allowed) {
30
+ const block = evaluation.violations.find((v) => v.action === "block");
31
+ return {
32
+ allowed: false,
33
+ piiDetected: false,
34
+ piiWarning: false,
35
+ policyViolation: `Blocked by policy "${block?.policyName ?? "unknown"}"`,
36
+ extractedTextLength: text.length,
37
+ };
38
+ }
39
+ }
40
+ catch (err) {
41
+ console.error("[DocumentPostCheck] Policy evaluation failed, proceeding:", err);
42
+ }
43
+ }
44
+ // PII check
45
+ let piiDetected = false;
46
+ let piiWarning = false;
47
+ if (input.piiDetector) {
48
+ try {
49
+ const piiResult = input.piiDetector.detect(text);
50
+ piiDetected = piiResult.matches.length > 0;
51
+ if (piiDetected) {
52
+ if (input.piiOutputPolicy === "block") {
53
+ return {
54
+ allowed: false,
55
+ piiDetected: true,
56
+ piiWarning: false,
57
+ policyViolation: "Edited document contains PII that is not allowed by organization policy.",
58
+ extractedTextLength: text.length,
59
+ };
60
+ }
61
+ piiWarning = input.piiOutputPolicy === "warn";
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.error("[DocumentPostCheck] PII detection failed, proceeding:", err);
66
+ }
67
+ }
68
+ return {
69
+ allowed: true,
70
+ piiDetected,
71
+ piiWarning,
72
+ extractedTextLength: text.length,
73
+ };
74
+ }
75
+ /**
76
+ * Extract text from an XLSX buffer using ExcelJS.
77
+ */
78
+ async extractXlsxText(buffer) {
79
+ const ExcelJS = await import("exceljs");
80
+ const workbook = new ExcelJS.default.Workbook();
81
+ await workbook.xlsx.load(buffer);
82
+ const parts = [];
83
+ workbook.eachSheet((sheet) => {
84
+ parts.push(`[Sheet: ${sheet.name}]`);
85
+ sheet.eachRow((row) => {
86
+ const values = [];
87
+ row.eachCell((cell) => {
88
+ if (cell.value != null) {
89
+ values.push(String(cell.value));
90
+ }
91
+ });
92
+ if (values.length > 0) {
93
+ parts.push(values.join("\t"));
94
+ }
95
+ });
96
+ });
97
+ return parts.join("\n");
98
+ }
99
+ /**
100
+ * Extract text from a DOCX buffer using mammoth.
101
+ */
102
+ async extractDocxText(buffer) {
103
+ const mammoth = await import("mammoth");
104
+ const result = await mammoth.extractRawText({ buffer });
105
+ return result.value;
106
+ }
107
+ /**
108
+ * Extract text from a PPTX buffer by parsing the OOXML zip.
109
+ * Uses jszip to read slide XML files and extracts text content.
110
+ */
111
+ async extractPptxText(buffer) {
112
+ const JSZip = (await import("jszip")).default;
113
+ const zip = await JSZip.loadAsync(buffer);
114
+ const parts = [];
115
+ const slideFiles = Object.keys(zip.files)
116
+ .filter((name) => /^ppt\/slides\/slide\d+\.xml$/.test(name))
117
+ .sort();
118
+ for (const slidePath of slideFiles) {
119
+ const xml = await zip.files[slidePath].async("text");
120
+ // Extract text content from XML using regex (lightweight, no XML parser needed)
121
+ const textMatches = xml.match(/<a:t[^>]*>([^<]*)<\/a:t>/g);
122
+ if (textMatches) {
123
+ const slideTexts = textMatches.map((m) => m.replace(/<a:t[^>]*>/, "").replace(/<\/a:t>/, ""));
124
+ parts.push(slideTexts.join(" "));
125
+ }
126
+ }
127
+ return parts.join("\n");
128
+ }
129
+ }
130
+ //# sourceMappingURL=document-post-check-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.js","sourceRoot":"","sources":["../../src/services/document-post-check-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=document-post-check-service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-post-check-service.test.d.ts","sourceRoot":"","sources":["../../src/services/document-post-check-service.test.ts"],"names":[],"mappings":""}