@oxyhq/crowdsource-contracts 0.1.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.
Files changed (57) hide show
  1. package/README.md +129 -0
  2. package/dist/case-envelope.d.ts +1130 -0
  3. package/dist/case-envelope.d.ts.map +1 -0
  4. package/dist/case-envelope.js +383 -0
  5. package/dist/case-envelope.js.map +1 -0
  6. package/dist/decisions.d.ts +353 -0
  7. package/dist/decisions.d.ts.map +1 -0
  8. package/dist/decisions.js +198 -0
  9. package/dist/decisions.js.map +1 -0
  10. package/dist/index.d.ts +45 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +61 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/json-schema.d.ts +43 -0
  15. package/dist/json-schema.d.ts.map +1 -0
  16. package/dist/json-schema.js +83 -0
  17. package/dist/json-schema.js.map +1 -0
  18. package/dist/policies.d.ts +286 -0
  19. package/dist/policies.d.ts.map +1 -0
  20. package/dist/policies.js +178 -0
  21. package/dist/policies.js.map +1 -0
  22. package/dist/primitives.d.ts +185 -0
  23. package/dist/primitives.d.ts.map +1 -0
  24. package/dist/primitives.js +231 -0
  25. package/dist/primitives.js.map +1 -0
  26. package/dist/reputation-events.d.ts +349 -0
  27. package/dist/reputation-events.d.ts.map +1 -0
  28. package/dist/reputation-events.js +128 -0
  29. package/dist/reputation-events.js.map +1 -0
  30. package/dist/resources.d.ts +484 -0
  31. package/dist/resources.d.ts.map +1 -0
  32. package/dist/resources.js +436 -0
  33. package/dist/resources.js.map +1 -0
  34. package/dist/reviews.d.ts +276 -0
  35. package/dist/reviews.d.ts.map +1 -0
  36. package/dist/reviews.js +144 -0
  37. package/dist/reviews.js.map +1 -0
  38. package/dist/taxonomy.d.ts +266 -0
  39. package/dist/taxonomy.d.ts.map +1 -0
  40. package/dist/taxonomy.js +282 -0
  41. package/dist/taxonomy.js.map +1 -0
  42. package/dist/webhooks.d.ts +604 -0
  43. package/dist/webhooks.d.ts.map +1 -0
  44. package/dist/webhooks.js +192 -0
  45. package/dist/webhooks.js.map +1 -0
  46. package/package.json +56 -0
  47. package/src/case-envelope.ts +433 -0
  48. package/src/decisions.ts +216 -0
  49. package/src/index.ts +45 -0
  50. package/src/json-schema.ts +89 -0
  51. package/src/policies.ts +203 -0
  52. package/src/primitives.ts +283 -0
  53. package/src/reputation-events.ts +144 -0
  54. package/src/resources.ts +489 -0
  55. package/src/reviews.ts +159 -0
  56. package/src/taxonomy.ts +313 -0
  57. package/src/webhooks.ts +215 -0
@@ -0,0 +1,604 @@
1
+ /**
2
+ * Outbound webhooks (§10.6–§10.9) and the signature contract (§10.8).
3
+ *
4
+ * §10.11 asks for two behaviours that pull in opposite directions: unknown
5
+ * EVENTS must be ignored safely, and unknown FIELDS must not break clients.
6
+ * This module gives each its own schema rather than compromising on one.
7
+ *
8
+ * * `WebhookEventEnvelopeSchema` validates only what every event has —
9
+ * identity, type, timing, tenant — and leaves `data` opaque. A receiver
10
+ * verifies the signature, records the event id for idempotency, and ignores
11
+ * what it does not recognise, without a schema update ever being the reason
12
+ * a delivery fails.
13
+ * * `KnownWebhookEventSchema` is the discriminated union of the eight events
14
+ * §10.6 defines, for the branch that actually handles one.
15
+ *
16
+ * Everything here is `.loose()`. These payloads travel from CrowdSource to a
17
+ * tenant, so an unknown field is a newer server, not an attack; stripping it
18
+ * would silently discard data from a receiver that persists `event.data` for
19
+ * later processing — which is precisely what §10.8's "respond 2xx quickly and
20
+ * queue the processing" tells receivers to do.
21
+ */
22
+ import { z } from 'zod';
23
+ /** §10.6. */
24
+ export declare const WEBHOOK_EVENT_TYPES: readonly ["report.received", "case.created", "case.escalated", "case.decided", "decision.corrected", "appeal.created", "appeal.decided", "case.closed"];
25
+ export declare const WebhookEventTypeSchema: z.ZodEnum<{
26
+ "report.received": "report.received";
27
+ "case.created": "case.created";
28
+ "case.escalated": "case.escalated";
29
+ "case.decided": "case.decided";
30
+ "decision.corrected": "decision.corrected";
31
+ "appeal.created": "appeal.created";
32
+ "appeal.decided": "appeal.decided";
33
+ "case.closed": "case.closed";
34
+ }>;
35
+ export type WebhookEventType = z.infer<typeof WebhookEventTypeSchema>;
36
+ /**
37
+ * Any event type, including ones this version of the contract does not know.
38
+ *
39
+ * Shape-checked but not enumerated, so that "unknown events must be ignored
40
+ * safely" is something a receiver can DO rather than something it is told about
41
+ * after its parse has already thrown.
42
+ */
43
+ export declare const AnyWebhookEventTypeSchema: z.ZodString;
44
+ /**
45
+ * The envelope every delivery shares (§10.7), with `data` left opaque.
46
+ *
47
+ * Parse with this first. `id` is the idempotency key §10.8 requires receivers
48
+ * to store; `type` decides whether there is anything to do.
49
+ */
50
+ export declare const WebhookEventEnvelopeSchema: z.ZodObject<{
51
+ type: z.ZodString;
52
+ data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
53
+ id: z.ZodString;
54
+ createdAt: z.ZodISODateTime;
55
+ organizationId: z.ZodString;
56
+ applicationId: z.ZodString;
57
+ }, z.core.$loose>;
58
+ export type WebhookEventEnvelope = z.infer<typeof WebhookEventEnvelopeSchema>;
59
+ /**
60
+ * The eight events of §10.6, discriminated on `type`.
61
+ *
62
+ * Only `case.decided` has its payload specified in the plan (§10.7). The other
63
+ * seven carry the case they are about and whatever identifies the object that
64
+ * moved; they are loose, so filling them in later is additive and needs no
65
+ * version bump (§10.11).
66
+ */
67
+ export declare const KnownWebhookEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
68
+ type: z.ZodLiteral<"report.received">;
69
+ data: z.ZodObject<{
70
+ reportId: z.ZodString;
71
+ caseId: z.ZodString;
72
+ status: z.ZodEnum<{
73
+ received: "received";
74
+ merged: "merged";
75
+ invalid: "invalid";
76
+ withdrawn: "withdrawn";
77
+ closed: "closed";
78
+ }>;
79
+ merged: z.ZodBoolean;
80
+ }, z.core.$loose>;
81
+ id: z.ZodString;
82
+ createdAt: z.ZodISODateTime;
83
+ organizationId: z.ZodString;
84
+ applicationId: z.ZodString;
85
+ }, z.core.$loose>, z.ZodObject<{
86
+ type: z.ZodLiteral<"case.created">;
87
+ data: z.ZodObject<{
88
+ caseId: z.ZodString;
89
+ }, z.core.$loose>;
90
+ id: z.ZodString;
91
+ createdAt: z.ZodISODateTime;
92
+ organizationId: z.ZodString;
93
+ applicationId: z.ZodString;
94
+ }, z.core.$loose>, z.ZodObject<{
95
+ type: z.ZodLiteral<"case.escalated">;
96
+ data: z.ZodObject<{
97
+ caseId: z.ZodString;
98
+ }, z.core.$loose>;
99
+ id: z.ZodString;
100
+ createdAt: z.ZodISODateTime;
101
+ organizationId: z.ZodString;
102
+ applicationId: z.ZodString;
103
+ }, z.core.$loose>, z.ZodObject<{
104
+ type: z.ZodLiteral<"case.decided">;
105
+ data: z.ZodObject<{
106
+ caseId: z.ZodString;
107
+ decision: z.ZodObject<{
108
+ id: z.ZodString;
109
+ caseId: z.ZodString;
110
+ revision: z.ZodNumber;
111
+ status: z.ZodEnum<{
112
+ provisional: "provisional";
113
+ final: "final";
114
+ superseded: "superseded";
115
+ corrected: "corrected";
116
+ }>;
117
+ outcome: z.ZodEnum<{
118
+ violation: "violation";
119
+ no_violation: "no_violation";
120
+ insufficient_context: "insufficient_context";
121
+ content_unavailable: "content_unavailable";
122
+ inconclusive: "inconclusive";
123
+ duplicate: "duplicate";
124
+ escalated: "escalated";
125
+ }>;
126
+ contextSufficiency: z.ZodEnum<{
127
+ sufficient: "sufficient";
128
+ insufficient: "insufficient";
129
+ }>;
130
+ confidence: z.ZodNumber;
131
+ findings: z.ZodArray<z.ZodObject<{
132
+ code: z.ZodEnum<{
133
+ "integrity.spam": "integrity.spam";
134
+ "integrity.scam": "integrity.scam";
135
+ "integrity.fraud": "integrity.fraud";
136
+ "integrity.impersonation": "integrity.impersonation";
137
+ "integrity.coordinated_manipulation": "integrity.coordinated_manipulation";
138
+ "harassment.insult": "harassment.insult";
139
+ "harassment.targeted_abuse": "harassment.targeted_abuse";
140
+ "harassment.sexual_harassment": "harassment.sexual_harassment";
141
+ "harassment.doxxing": "harassment.doxxing";
142
+ "harassment.credible_threat": "harassment.credible_threat";
143
+ "hate.dehumanization": "hate.dehumanization";
144
+ "hate.slur": "hate.slur";
145
+ "hate.incitement": "hate.incitement";
146
+ "hate.protected_targeting": "hate.protected_targeting";
147
+ "violence.graphic": "violence.graphic";
148
+ "violence.threat": "violence.threat";
149
+ "violence.instruction": "violence.instruction";
150
+ "violence.celebration": "violence.celebration";
151
+ "sexual_content.nudity": "sexual_content.nudity";
152
+ "sexual_content.explicit_activity": "sexual_content.explicit_activity";
153
+ "sexual_content.non_consensual": "sexual_content.non_consensual";
154
+ "sexual_content.exploitation": "sexual_content.exploitation";
155
+ "child_safety.sexualization": "child_safety.sexualization";
156
+ "child_safety.grooming": "child_safety.grooming";
157
+ "child_safety.exploitation": "child_safety.exploitation";
158
+ "self_harm.promotion": "self_harm.promotion";
159
+ "self_harm.instruction": "self_harm.instruction";
160
+ "self_harm.imminent_risk": "self_harm.imminent_risk";
161
+ "privacy.personal_information": "privacy.personal_information";
162
+ "privacy.intimate_media": "privacy.intimate_media";
163
+ "privacy.location_exposure": "privacy.location_exposure";
164
+ "commerce.prohibited_item": "commerce.prohibited_item";
165
+ "commerce.counterfeit": "commerce.counterfeit";
166
+ "commerce.misleading_listing": "commerce.misleading_listing";
167
+ "commerce.unsafe_product": "commerce.unsafe_product";
168
+ "platform_abuse.ban_evasion": "platform_abuse.ban_evasion";
169
+ "platform_abuse.report_abuse": "platform_abuse.report_abuse";
170
+ "platform_abuse.automation_abuse": "platform_abuse.automation_abuse";
171
+ "other.policy_specific": "other.policy_specific";
172
+ "other.unclassifiable": "other.unclassifiable";
173
+ }>;
174
+ resourceIds: z.ZodArray<z.ZodString>;
175
+ severity: z.ZodEnum<{
176
+ low: "low";
177
+ medium: "medium";
178
+ high: "high";
179
+ critical: "critical";
180
+ }>;
181
+ context: z.ZodOptional<z.ZodEnum<{
182
+ artistic: "artistic";
183
+ educational: "educational";
184
+ documentary: "documentary";
185
+ newsworthy: "newsworthy";
186
+ satire: "satire";
187
+ counter_speech: "counter_speech";
188
+ medical: "medical";
189
+ consensual: "consensual";
190
+ fictional: "fictional";
191
+ }>>;
192
+ scope: z.ZodEnum<{
193
+ application_local: "application_local";
194
+ oxy_network: "oxy_network";
195
+ identity_integrity: "identity_integrity";
196
+ }>;
197
+ attribution: z.ZodOptional<z.ZodEnum<{
198
+ author: "author";
199
+ reporter: "reporter";
200
+ reviewer: "reviewer";
201
+ }>>;
202
+ policyRuleIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
203
+ }, z.core.$loose>>;
204
+ recommendedActions: z.ZodArray<z.ZodObject<{
205
+ action: z.ZodEnum<{
206
+ remove_or_restrict: "remove_or_restrict";
207
+ allow_with_label: "allow_with_label";
208
+ remove: "remove";
209
+ hide: "hide";
210
+ label: "label";
211
+ age_gate: "age_gate";
212
+ reduce_distribution: "reduce_distribution";
213
+ freeze_transaction: "freeze_transaction";
214
+ suspend_user: "suspend_user";
215
+ request_changes: "request_changes";
216
+ allow: "allow";
217
+ restore: "restore";
218
+ no_action: "no_action";
219
+ request_more_context: "request_more_context";
220
+ hold: "hold";
221
+ local_manual_review: "local_manual_review";
222
+ keep_restricted_temporarily: "keep_restricted_temporarily";
223
+ escalate: "escalate";
224
+ no_global_effect: "no_global_effect";
225
+ specialist_queue: "specialist_queue";
226
+ legal_queue: "legal_queue";
227
+ safety_queue: "safety_queue";
228
+ }>;
229
+ targetResourceIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
230
+ }, z.core.$loose>>;
231
+ jury: z.ZodObject<{
232
+ size: z.ZodNumber;
233
+ decisiveVotes: z.ZodNumber;
234
+ winningVotes: z.ZodNumber;
235
+ agreement: z.ZodNumber;
236
+ specialistPresent: z.ZodBoolean;
237
+ }, z.core.$loose>;
238
+ policyVersions: z.ZodObject<{
239
+ taxonomy: z.ZodString;
240
+ application: z.ZodString;
241
+ oxyConduct: z.ZodString;
242
+ }, z.core.$loose>;
243
+ supersedesDecisionId: z.ZodOptional<z.ZodString>;
244
+ publishedAt: z.ZodISODateTime;
245
+ }, z.core.$loose>;
246
+ }, z.core.$loose>;
247
+ id: z.ZodString;
248
+ createdAt: z.ZodISODateTime;
249
+ organizationId: z.ZodString;
250
+ applicationId: z.ZodString;
251
+ }, z.core.$loose>, z.ZodObject<{
252
+ type: z.ZodLiteral<"decision.corrected">;
253
+ data: z.ZodObject<{
254
+ caseId: z.ZodString;
255
+ decision: z.ZodObject<{
256
+ id: z.ZodString;
257
+ caseId: z.ZodString;
258
+ revision: z.ZodNumber;
259
+ status: z.ZodEnum<{
260
+ provisional: "provisional";
261
+ final: "final";
262
+ superseded: "superseded";
263
+ corrected: "corrected";
264
+ }>;
265
+ outcome: z.ZodEnum<{
266
+ violation: "violation";
267
+ no_violation: "no_violation";
268
+ insufficient_context: "insufficient_context";
269
+ content_unavailable: "content_unavailable";
270
+ inconclusive: "inconclusive";
271
+ duplicate: "duplicate";
272
+ escalated: "escalated";
273
+ }>;
274
+ contextSufficiency: z.ZodEnum<{
275
+ sufficient: "sufficient";
276
+ insufficient: "insufficient";
277
+ }>;
278
+ confidence: z.ZodNumber;
279
+ findings: z.ZodArray<z.ZodObject<{
280
+ code: z.ZodEnum<{
281
+ "integrity.spam": "integrity.spam";
282
+ "integrity.scam": "integrity.scam";
283
+ "integrity.fraud": "integrity.fraud";
284
+ "integrity.impersonation": "integrity.impersonation";
285
+ "integrity.coordinated_manipulation": "integrity.coordinated_manipulation";
286
+ "harassment.insult": "harassment.insult";
287
+ "harassment.targeted_abuse": "harassment.targeted_abuse";
288
+ "harassment.sexual_harassment": "harassment.sexual_harassment";
289
+ "harassment.doxxing": "harassment.doxxing";
290
+ "harassment.credible_threat": "harassment.credible_threat";
291
+ "hate.dehumanization": "hate.dehumanization";
292
+ "hate.slur": "hate.slur";
293
+ "hate.incitement": "hate.incitement";
294
+ "hate.protected_targeting": "hate.protected_targeting";
295
+ "violence.graphic": "violence.graphic";
296
+ "violence.threat": "violence.threat";
297
+ "violence.instruction": "violence.instruction";
298
+ "violence.celebration": "violence.celebration";
299
+ "sexual_content.nudity": "sexual_content.nudity";
300
+ "sexual_content.explicit_activity": "sexual_content.explicit_activity";
301
+ "sexual_content.non_consensual": "sexual_content.non_consensual";
302
+ "sexual_content.exploitation": "sexual_content.exploitation";
303
+ "child_safety.sexualization": "child_safety.sexualization";
304
+ "child_safety.grooming": "child_safety.grooming";
305
+ "child_safety.exploitation": "child_safety.exploitation";
306
+ "self_harm.promotion": "self_harm.promotion";
307
+ "self_harm.instruction": "self_harm.instruction";
308
+ "self_harm.imminent_risk": "self_harm.imminent_risk";
309
+ "privacy.personal_information": "privacy.personal_information";
310
+ "privacy.intimate_media": "privacy.intimate_media";
311
+ "privacy.location_exposure": "privacy.location_exposure";
312
+ "commerce.prohibited_item": "commerce.prohibited_item";
313
+ "commerce.counterfeit": "commerce.counterfeit";
314
+ "commerce.misleading_listing": "commerce.misleading_listing";
315
+ "commerce.unsafe_product": "commerce.unsafe_product";
316
+ "platform_abuse.ban_evasion": "platform_abuse.ban_evasion";
317
+ "platform_abuse.report_abuse": "platform_abuse.report_abuse";
318
+ "platform_abuse.automation_abuse": "platform_abuse.automation_abuse";
319
+ "other.policy_specific": "other.policy_specific";
320
+ "other.unclassifiable": "other.unclassifiable";
321
+ }>;
322
+ resourceIds: z.ZodArray<z.ZodString>;
323
+ severity: z.ZodEnum<{
324
+ low: "low";
325
+ medium: "medium";
326
+ high: "high";
327
+ critical: "critical";
328
+ }>;
329
+ context: z.ZodOptional<z.ZodEnum<{
330
+ artistic: "artistic";
331
+ educational: "educational";
332
+ documentary: "documentary";
333
+ newsworthy: "newsworthy";
334
+ satire: "satire";
335
+ counter_speech: "counter_speech";
336
+ medical: "medical";
337
+ consensual: "consensual";
338
+ fictional: "fictional";
339
+ }>>;
340
+ scope: z.ZodEnum<{
341
+ application_local: "application_local";
342
+ oxy_network: "oxy_network";
343
+ identity_integrity: "identity_integrity";
344
+ }>;
345
+ attribution: z.ZodOptional<z.ZodEnum<{
346
+ author: "author";
347
+ reporter: "reporter";
348
+ reviewer: "reviewer";
349
+ }>>;
350
+ policyRuleIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
351
+ }, z.core.$loose>>;
352
+ recommendedActions: z.ZodArray<z.ZodObject<{
353
+ action: z.ZodEnum<{
354
+ remove_or_restrict: "remove_or_restrict";
355
+ allow_with_label: "allow_with_label";
356
+ remove: "remove";
357
+ hide: "hide";
358
+ label: "label";
359
+ age_gate: "age_gate";
360
+ reduce_distribution: "reduce_distribution";
361
+ freeze_transaction: "freeze_transaction";
362
+ suspend_user: "suspend_user";
363
+ request_changes: "request_changes";
364
+ allow: "allow";
365
+ restore: "restore";
366
+ no_action: "no_action";
367
+ request_more_context: "request_more_context";
368
+ hold: "hold";
369
+ local_manual_review: "local_manual_review";
370
+ keep_restricted_temporarily: "keep_restricted_temporarily";
371
+ escalate: "escalate";
372
+ no_global_effect: "no_global_effect";
373
+ specialist_queue: "specialist_queue";
374
+ legal_queue: "legal_queue";
375
+ safety_queue: "safety_queue";
376
+ }>;
377
+ targetResourceIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
378
+ }, z.core.$loose>>;
379
+ jury: z.ZodObject<{
380
+ size: z.ZodNumber;
381
+ decisiveVotes: z.ZodNumber;
382
+ winningVotes: z.ZodNumber;
383
+ agreement: z.ZodNumber;
384
+ specialistPresent: z.ZodBoolean;
385
+ }, z.core.$loose>;
386
+ policyVersions: z.ZodObject<{
387
+ taxonomy: z.ZodString;
388
+ application: z.ZodString;
389
+ oxyConduct: z.ZodString;
390
+ }, z.core.$loose>;
391
+ supersedesDecisionId: z.ZodOptional<z.ZodString>;
392
+ publishedAt: z.ZodISODateTime;
393
+ }, z.core.$loose>;
394
+ }, z.core.$loose>;
395
+ id: z.ZodString;
396
+ createdAt: z.ZodISODateTime;
397
+ organizationId: z.ZodString;
398
+ applicationId: z.ZodString;
399
+ }, z.core.$loose>, z.ZodObject<{
400
+ type: z.ZodLiteral<"appeal.created">;
401
+ data: z.ZodObject<{
402
+ caseId: z.ZodString;
403
+ appealId: z.ZodString;
404
+ }, z.core.$loose>;
405
+ id: z.ZodString;
406
+ createdAt: z.ZodISODateTime;
407
+ organizationId: z.ZodString;
408
+ applicationId: z.ZodString;
409
+ }, z.core.$loose>, z.ZodObject<{
410
+ type: z.ZodLiteral<"appeal.decided">;
411
+ data: z.ZodObject<{
412
+ caseId: z.ZodString;
413
+ appealId: z.ZodString;
414
+ decision: z.ZodObject<{
415
+ id: z.ZodString;
416
+ caseId: z.ZodString;
417
+ revision: z.ZodNumber;
418
+ status: z.ZodEnum<{
419
+ provisional: "provisional";
420
+ final: "final";
421
+ superseded: "superseded";
422
+ corrected: "corrected";
423
+ }>;
424
+ outcome: z.ZodEnum<{
425
+ violation: "violation";
426
+ no_violation: "no_violation";
427
+ insufficient_context: "insufficient_context";
428
+ content_unavailable: "content_unavailable";
429
+ inconclusive: "inconclusive";
430
+ duplicate: "duplicate";
431
+ escalated: "escalated";
432
+ }>;
433
+ contextSufficiency: z.ZodEnum<{
434
+ sufficient: "sufficient";
435
+ insufficient: "insufficient";
436
+ }>;
437
+ confidence: z.ZodNumber;
438
+ findings: z.ZodArray<z.ZodObject<{
439
+ code: z.ZodEnum<{
440
+ "integrity.spam": "integrity.spam";
441
+ "integrity.scam": "integrity.scam";
442
+ "integrity.fraud": "integrity.fraud";
443
+ "integrity.impersonation": "integrity.impersonation";
444
+ "integrity.coordinated_manipulation": "integrity.coordinated_manipulation";
445
+ "harassment.insult": "harassment.insult";
446
+ "harassment.targeted_abuse": "harassment.targeted_abuse";
447
+ "harassment.sexual_harassment": "harassment.sexual_harassment";
448
+ "harassment.doxxing": "harassment.doxxing";
449
+ "harassment.credible_threat": "harassment.credible_threat";
450
+ "hate.dehumanization": "hate.dehumanization";
451
+ "hate.slur": "hate.slur";
452
+ "hate.incitement": "hate.incitement";
453
+ "hate.protected_targeting": "hate.protected_targeting";
454
+ "violence.graphic": "violence.graphic";
455
+ "violence.threat": "violence.threat";
456
+ "violence.instruction": "violence.instruction";
457
+ "violence.celebration": "violence.celebration";
458
+ "sexual_content.nudity": "sexual_content.nudity";
459
+ "sexual_content.explicit_activity": "sexual_content.explicit_activity";
460
+ "sexual_content.non_consensual": "sexual_content.non_consensual";
461
+ "sexual_content.exploitation": "sexual_content.exploitation";
462
+ "child_safety.sexualization": "child_safety.sexualization";
463
+ "child_safety.grooming": "child_safety.grooming";
464
+ "child_safety.exploitation": "child_safety.exploitation";
465
+ "self_harm.promotion": "self_harm.promotion";
466
+ "self_harm.instruction": "self_harm.instruction";
467
+ "self_harm.imminent_risk": "self_harm.imminent_risk";
468
+ "privacy.personal_information": "privacy.personal_information";
469
+ "privacy.intimate_media": "privacy.intimate_media";
470
+ "privacy.location_exposure": "privacy.location_exposure";
471
+ "commerce.prohibited_item": "commerce.prohibited_item";
472
+ "commerce.counterfeit": "commerce.counterfeit";
473
+ "commerce.misleading_listing": "commerce.misleading_listing";
474
+ "commerce.unsafe_product": "commerce.unsafe_product";
475
+ "platform_abuse.ban_evasion": "platform_abuse.ban_evasion";
476
+ "platform_abuse.report_abuse": "platform_abuse.report_abuse";
477
+ "platform_abuse.automation_abuse": "platform_abuse.automation_abuse";
478
+ "other.policy_specific": "other.policy_specific";
479
+ "other.unclassifiable": "other.unclassifiable";
480
+ }>;
481
+ resourceIds: z.ZodArray<z.ZodString>;
482
+ severity: z.ZodEnum<{
483
+ low: "low";
484
+ medium: "medium";
485
+ high: "high";
486
+ critical: "critical";
487
+ }>;
488
+ context: z.ZodOptional<z.ZodEnum<{
489
+ artistic: "artistic";
490
+ educational: "educational";
491
+ documentary: "documentary";
492
+ newsworthy: "newsworthy";
493
+ satire: "satire";
494
+ counter_speech: "counter_speech";
495
+ medical: "medical";
496
+ consensual: "consensual";
497
+ fictional: "fictional";
498
+ }>>;
499
+ scope: z.ZodEnum<{
500
+ application_local: "application_local";
501
+ oxy_network: "oxy_network";
502
+ identity_integrity: "identity_integrity";
503
+ }>;
504
+ attribution: z.ZodOptional<z.ZodEnum<{
505
+ author: "author";
506
+ reporter: "reporter";
507
+ reviewer: "reviewer";
508
+ }>>;
509
+ policyRuleIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
510
+ }, z.core.$loose>>;
511
+ recommendedActions: z.ZodArray<z.ZodObject<{
512
+ action: z.ZodEnum<{
513
+ remove_or_restrict: "remove_or_restrict";
514
+ allow_with_label: "allow_with_label";
515
+ remove: "remove";
516
+ hide: "hide";
517
+ label: "label";
518
+ age_gate: "age_gate";
519
+ reduce_distribution: "reduce_distribution";
520
+ freeze_transaction: "freeze_transaction";
521
+ suspend_user: "suspend_user";
522
+ request_changes: "request_changes";
523
+ allow: "allow";
524
+ restore: "restore";
525
+ no_action: "no_action";
526
+ request_more_context: "request_more_context";
527
+ hold: "hold";
528
+ local_manual_review: "local_manual_review";
529
+ keep_restricted_temporarily: "keep_restricted_temporarily";
530
+ escalate: "escalate";
531
+ no_global_effect: "no_global_effect";
532
+ specialist_queue: "specialist_queue";
533
+ legal_queue: "legal_queue";
534
+ safety_queue: "safety_queue";
535
+ }>;
536
+ targetResourceIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
537
+ }, z.core.$loose>>;
538
+ jury: z.ZodObject<{
539
+ size: z.ZodNumber;
540
+ decisiveVotes: z.ZodNumber;
541
+ winningVotes: z.ZodNumber;
542
+ agreement: z.ZodNumber;
543
+ specialistPresent: z.ZodBoolean;
544
+ }, z.core.$loose>;
545
+ policyVersions: z.ZodObject<{
546
+ taxonomy: z.ZodString;
547
+ application: z.ZodString;
548
+ oxyConduct: z.ZodString;
549
+ }, z.core.$loose>;
550
+ supersedesDecisionId: z.ZodOptional<z.ZodString>;
551
+ publishedAt: z.ZodISODateTime;
552
+ }, z.core.$loose>;
553
+ }, z.core.$loose>;
554
+ id: z.ZodString;
555
+ createdAt: z.ZodISODateTime;
556
+ organizationId: z.ZodString;
557
+ applicationId: z.ZodString;
558
+ }, z.core.$loose>, z.ZodObject<{
559
+ type: z.ZodLiteral<"case.closed">;
560
+ data: z.ZodObject<{
561
+ caseId: z.ZodString;
562
+ }, z.core.$loose>;
563
+ id: z.ZodString;
564
+ createdAt: z.ZodISODateTime;
565
+ organizationId: z.ZodString;
566
+ applicationId: z.ZodString;
567
+ }, z.core.$loose>], "type">;
568
+ export type KnownWebhookEvent = z.infer<typeof KnownWebhookEventSchema>;
569
+ /** §10.8 headers, in their canonical casing. HTTP header names are case-insensitive; look them up accordingly. */
570
+ export declare const WEBHOOK_EVENT_ID_HEADER = "X-CrowdSource-Event-Id";
571
+ export declare const WEBHOOK_TIMESTAMP_HEADER = "X-CrowdSource-Timestamp";
572
+ export declare const WEBHOOK_SIGNATURE_HEADER = "X-CrowdSource-Signature";
573
+ /** The signature scheme prefix, as in `v1=<hex>`. */
574
+ export declare const WEBHOOK_SIGNATURE_VERSION = "v1";
575
+ /** §10.8: reject timestamps more than five minutes away from now. */
576
+ export declare const WEBHOOK_TIMESTAMP_TOLERANCE_SECONDS = 300;
577
+ /** Unix seconds, as the header carries them. */
578
+ export declare const WebhookTimestampHeaderSchema: z.ZodString;
579
+ /** `v1=<64 lowercase hex>` — HMAC-SHA256 of the signed payload. */
580
+ export declare const WebhookSignatureHeaderSchema: z.ZodString;
581
+ /**
582
+ * The exact bytes both sides sign: `timestamp + "." + rawBody` (§10.8).
583
+ *
584
+ * This lives in the contract, not in the signer or the verifier, because a
585
+ * disagreement between those two about what gets signed is invisible until
586
+ * every delivery starts failing — or, far worse, until a signature validates
587
+ * over bytes that are not the ones the receiver goes on to parse. There is no
588
+ * cryptography here and no transport; the HMAC belongs to the backend's signer
589
+ * and the SDK's middleware.
590
+ *
591
+ * `timestamp` is the header value VERBATIM. Re-deriving it from a parsed number
592
+ * is the mistake this signature exists to catch, and the receiver must verify
593
+ * over exactly what arrived.
594
+ */
595
+ export declare function buildWebhookSignedPayload(timestamp: string, rawBody: string): string;
596
+ /**
597
+ * §10.9's backoff, in seconds after the initial attempt.
598
+ *
599
+ * Published behaviour a tenant plans around, so it belongs to the contract
600
+ * rather than to the delivery worker. After the last one the delivery is
601
+ * `dead_letter`, the tenant is alerted, and replay is manual.
602
+ */
603
+ export declare const WEBHOOK_RETRY_SCHEDULE_SECONDS: readonly number[];
604
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,aAAa;AACb,eAAO,MAAM,mBAAmB,yJAStB,CAAC;AACX,eAAO,MAAM,sBAAsB;;;;;;;;;EAA8B,CAAC;AAClE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,aAI+C,CAAC;AAStF;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B;;;;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAoE9E;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,kHAAkH;AAClH,eAAO,MAAM,uBAAuB,2BAA2B,CAAC;AAChE,eAAO,MAAM,wBAAwB,4BAA4B,CAAC;AAClE,eAAO,MAAM,wBAAwB,4BAA4B,CAAC;AAElE,qDAAqD;AACrD,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,qEAAqE;AACrE,eAAO,MAAM,mCAAmC,MAAM,CAAC;AAEvD,gDAAgD;AAChD,eAAO,MAAM,4BAA4B,aAEQ,CAAC;AAElD,mEAAmE;AACnE,eAAO,MAAM,4BAA4B,aAE6C,CAAC;AAEvF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAO1D,CAAC"}