@oxyhq/crowdsource-contracts 0.3.0 → 0.4.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 (81) hide show
  1. package/dist/appeals.d.ts +323 -0
  2. package/dist/appeals.d.ts.map +1 -0
  3. package/dist/appeals.js +203 -0
  4. package/dist/appeals.js.map +1 -0
  5. package/dist/case-envelope.d.ts +3 -3
  6. package/dist/case-envelope.d.ts.map +1 -1
  7. package/dist/case-envelope.js +32 -32
  8. package/dist/case-envelope.js.map +1 -1
  9. package/dist/decisions.d.ts +1 -1
  10. package/dist/decisions.d.ts.map +1 -1
  11. package/dist/decisions.js +28 -28
  12. package/dist/decisions.js.map +1 -1
  13. package/dist/esm/appeals.js +200 -0
  14. package/dist/esm/appeals.js.map +1 -0
  15. package/dist/esm/case-envelope.js +380 -0
  16. package/dist/esm/case-envelope.js.map +1 -0
  17. package/dist/esm/closed.js +32 -0
  18. package/dist/esm/closed.js.map +1 -0
  19. package/dist/esm/decisions.js +195 -0
  20. package/dist/esm/decisions.js.map +1 -0
  21. package/dist/esm/index.js +48 -0
  22. package/dist/esm/index.js.map +1 -0
  23. package/dist/esm/json-schema.js +84 -0
  24. package/dist/esm/json-schema.js.map +1 -0
  25. package/dist/esm/package.json +1 -0
  26. package/dist/esm/policies.js +175 -0
  27. package/dist/esm/policies.js.map +1 -0
  28. package/dist/esm/primitives.js +249 -0
  29. package/dist/esm/primitives.js.map +1 -0
  30. package/dist/esm/reputation-events.js +125 -0
  31. package/dist/esm/reputation-events.js.map +1 -0
  32. package/dist/esm/resources.js +455 -0
  33. package/dist/esm/resources.js.map +1 -0
  34. package/dist/esm/reviewer-surface.js +612 -0
  35. package/dist/esm/reviewer-surface.js.map +1 -0
  36. package/dist/esm/reviews.js +141 -0
  37. package/dist/esm/reviews.js.map +1 -0
  38. package/dist/esm/taxonomy.js +278 -0
  39. package/dist/esm/taxonomy.js.map +1 -0
  40. package/dist/esm/webhooks.js +188 -0
  41. package/dist/esm/webhooks.js.map +1 -0
  42. package/dist/index.d.ts +13 -11
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +13 -11
  45. package/dist/index.js.map +1 -1
  46. package/dist/json-schema.d.ts +1 -1
  47. package/dist/json-schema.d.ts.map +1 -1
  48. package/dist/json-schema.js +25 -20
  49. package/dist/json-schema.js.map +1 -1
  50. package/dist/policies.d.ts +1 -1
  51. package/dist/policies.d.ts.map +1 -1
  52. package/dist/policies.js +14 -14
  53. package/dist/policies.js.map +1 -1
  54. package/dist/reputation-events.js +19 -19
  55. package/dist/reputation-events.js.map +1 -1
  56. package/dist/resources.d.ts +60 -2
  57. package/dist/resources.d.ts.map +1 -1
  58. package/dist/resources.js +116 -103
  59. package/dist/resources.js.map +1 -1
  60. package/dist/reviewer-surface.d.ts +1956 -0
  61. package/dist/reviewer-surface.d.ts.map +1 -0
  62. package/dist/reviewer-surface.js +615 -0
  63. package/dist/reviewer-surface.js.map +1 -0
  64. package/dist/reviews.js +15 -15
  65. package/dist/reviews.js.map +1 -1
  66. package/dist/webhooks.d.ts +1 -1
  67. package/dist/webhooks.d.ts.map +1 -1
  68. package/dist/webhooks.js +18 -18
  69. package/dist/webhooks.js.map +1 -1
  70. package/package.json +4 -4
  71. package/src/appeals.ts +229 -0
  72. package/src/case-envelope.ts +5 -5
  73. package/src/decisions.ts +6 -6
  74. package/src/index.ts +13 -11
  75. package/src/json-schema.ts +12 -7
  76. package/src/policies.ts +3 -3
  77. package/src/reputation-events.ts +4 -4
  78. package/src/resources.ts +99 -73
  79. package/src/reviewer-surface.ts +715 -0
  80. package/src/reviews.ts +4 -4
  81. package/src/webhooks.ts +4 -4
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Public entry point for `@oxyhq/crowdsource-contracts`.
3
+ *
4
+ * The contracts every CrowdSource surface agrees on: the backend, the reviewer
5
+ * and console clients, the published SDKs, and third-party integrators. One
6
+ * entry point because the package publishes one `exports` path — this is the
7
+ * package boundary, not a convenience barrel over an internal tree.
8
+ *
9
+ * Two version numbers live here and mean different things. `/v1` is the route
10
+ * prefix and is not this package's business. `CASE_ENVELOPE_SCHEMA_VERSION`
11
+ * travels inside the payload and is validated separately (§10.11). Additive
12
+ * changes bump neither.
13
+ *
14
+ * Where strictness lands, and why, since it is the one thing a reader will want
15
+ * to look up:
16
+ *
17
+ * * **Inbound from a tenant or a reviewer — strict.** The Case Envelope tree,
18
+ * the review submission, the recusal, the policy set, the resource schema
19
+ * registration. A dropped field here is context a jury never sees or an
20
+ * input nobody reviewed, and §10.11 makes the exception explicitly for
21
+ * fields "the schema forbids for safety".
22
+ * * **Outbound to a tenant — loose.** Decisions, webhook envelopes and event
23
+ * payloads pass unknown fields through, so a newer CrowdSource never breaks
24
+ * an older client and a receiver that persists `event.data` keeps all of it.
25
+ * * **Internal, to Oxy Trust — strict.** The reputation event carries no
26
+ * resource ids and no free text on purpose; an unrecognised field is how
27
+ * content reaches a reputation ledger. The `.v1` in the event type is what
28
+ * handles evolution there.
29
+ *
30
+ * Open bags (`metadata`, custom payloads, registered JSON Schemas) are the
31
+ * deliberate exception in both directions: open by definition, but flat or
32
+ * depth-bounded, scalar-typed, key-restricted and free of prototype-bearing
33
+ * names.
34
+ */
35
+ export * from './closed.js';
36
+ export * from './primitives.js';
37
+ export * from './taxonomy.js';
38
+ export * from './policies.js';
39
+ export * from './resources.js';
40
+ export * from './case-envelope.js';
41
+ export * from './reviews.js';
42
+ export * from './reviewer-surface.js';
43
+ export * from './decisions.js';
44
+ export * from './appeals.js';
45
+ export * from './webhooks.js';
46
+ export * from './reputation-events.js';
47
+ export * from './json-schema.js';
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The same contracts as JSON Schema, for integrators who are not on TypeScript.
3
+ *
4
+ * §15.2 asks for "Zod and exportable JSON Schema". Conversion is deliberately
5
+ * lazy — a function, not a frozen constant — so importing the package to
6
+ * validate one report does not pay for thirteen schema conversions.
7
+ *
8
+ * **What JSON Schema does NOT carry.** Zod refinements have no JSON Schema
9
+ * equivalent and are dropped silently by the conversion. Everything structural
10
+ * survives — types, enums, patterns, bounds, required keys, `additionalProperties`
11
+ * — and every cross-field and cross-reference rule does not:
12
+ *
13
+ * * §5.5 reference resolution (relations, `primaryResourceId`, allegation
14
+ * resource ids, author and seller refs, conversation members, avatars)
15
+ * * the `oxy_user` binding-proof requirement
16
+ * * a required `fileId` on every asset, media type agreement, coarse coordinates,
17
+ * price-with-currency
18
+ * * `agreement = winningVotes / decisiveVotes` and the vote count nesting
19
+ * * revision 1 supersedes nothing / later revisions must
20
+ * * `externalReportId` matching between request and envelope
21
+ *
22
+ * So a payload that passes the JSON Schema is well-FORMED, not accepted. The
23
+ * server validates with Zod, and that is the authority. This is stated here
24
+ * because an integrator who assumes otherwise will build against a contract
25
+ * that is looser than the one they will meet in production, and will discover
26
+ * the difference as a 422.
27
+ */
28
+ import { z } from 'zod';
29
+ import { AppealSchema, AppealSubmissionSchema } from './appeals.js';
30
+ import { CaseEnvelopeSchema, CreateReportRequestSchema, CreateReportResponseSchema } from './case-envelope.js';
31
+ import { DecisionSchema } from './decisions.js';
32
+ import { PolicySetVersionSchema } from './policies.js';
33
+ import { ReputationEventSchema } from './reputation-events.js';
34
+ import { RelationSchema, ResourceSchema, ResourceSchemaRegistrationSchema } from './resources.js';
35
+ import { RecusalSubmissionSchema, ReviewSubmissionSchema } from './reviews.js';
36
+ import { KnownWebhookEventSchema, WebhookEventEnvelopeSchema } from './webhooks.js';
37
+ export const CONTRACT_JSON_SCHEMA_NAMES = [
38
+ 'case-envelope',
39
+ 'create-report-request',
40
+ 'create-report-response',
41
+ 'resource',
42
+ 'relation',
43
+ 'resource-schema-registration',
44
+ 'policy-set-version',
45
+ 'review-submission',
46
+ 'recusal-submission',
47
+ 'decision',
48
+ 'appeal-submission',
49
+ 'appeal',
50
+ 'webhook-event-envelope',
51
+ 'known-webhook-event',
52
+ 'reputation-event',
53
+ ];
54
+ /**
55
+ * The Zod schema behind each published name.
56
+ *
57
+ * Typed as an exhaustive `Record` so adding a name without a schema — or a
58
+ * schema without a name — is a compile error rather than a runtime hole in the
59
+ * exported contract set.
60
+ */
61
+ export const CONTRACT_SCHEMAS = {
62
+ 'case-envelope': CaseEnvelopeSchema,
63
+ 'create-report-request': CreateReportRequestSchema,
64
+ 'create-report-response': CreateReportResponseSchema,
65
+ resource: ResourceSchema,
66
+ relation: RelationSchema,
67
+ 'resource-schema-registration': ResourceSchemaRegistrationSchema,
68
+ 'policy-set-version': PolicySetVersionSchema,
69
+ 'review-submission': ReviewSubmissionSchema,
70
+ 'recusal-submission': RecusalSubmissionSchema,
71
+ decision: DecisionSchema,
72
+ 'appeal-submission': AppealSubmissionSchema,
73
+ appeal: AppealSchema,
74
+ 'webhook-event-envelope': WebhookEventEnvelopeSchema,
75
+ 'known-webhook-event': KnownWebhookEventSchema,
76
+ 'reputation-event': ReputationEventSchema,
77
+ };
78
+ /** JSON Schema draft 2020-12, so `$defs` and `unevaluatedProperties` mean what integrators expect. */
79
+ const JSON_SCHEMA_TARGET = 'draft-2020-12';
80
+ /** The JSON Schema for one published contract. */
81
+ export function crowdSourceJsonSchema(name) {
82
+ return z.toJSONSchema(CONTRACT_SCHEMAS[name], { target: JSON_SCHEMA_TARGET });
83
+ }
84
+ //# sourceMappingURL=json-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../src/json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAClG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAKpF,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,eAAe;IACf,uBAAuB;IACvB,wBAAwB;IACxB,UAAU;IACV,UAAU;IACV,8BAA8B;IAC9B,oBAAoB;IACpB,mBAAmB;IACnB,oBAAoB;IACpB,UAAU;IACV,mBAAmB;IACnB,QAAQ;IACR,wBAAwB;IACxB,qBAAqB;IACrB,kBAAkB;CACV,CAAC;AAIX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA8C;IACzE,eAAe,EAAE,kBAAkB;IACnC,uBAAuB,EAAE,yBAAyB;IAClD,wBAAwB,EAAE,0BAA0B;IACpD,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,cAAc;IACxB,8BAA8B,EAAE,gCAAgC;IAChE,oBAAoB,EAAE,sBAAsB;IAC5C,mBAAmB,EAAE,sBAAsB;IAC3C,oBAAoB,EAAE,uBAAuB;IAC7C,QAAQ,EAAE,cAAc;IACxB,mBAAmB,EAAE,sBAAsB;IAC3C,MAAM,EAAE,YAAY;IACpB,wBAAwB,EAAE,0BAA0B;IACpD,qBAAqB,EAAE,uBAAuB;IAC9C,kBAAkB,EAAE,qBAAqB;CAC1C,CAAC;AAEF,sGAAsG;AACtG,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAE3C,kDAAkD;AAClD,MAAM,UAAU,qBAAqB,CAAC,IAA4B;IAChE,OAAO,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * The application-policy layer (§6.1 layer 2) and policy versioning (§6.4).
3
+ *
4
+ * The taxonomy says what the material contains; a policy set says whether that
5
+ * violates THIS application's rules. The two are versioned independently and
6
+ * every decision records both (plus the Oxy conduct policy version), because
7
+ * §6.4 forbids a policy update from silently changing what a past decision
8
+ * meant.
9
+ *
10
+ * The security boundary of this module is §6.4's last line: "rules must be
11
+ * expressed as data, not as arbitrary code supplied by the tenant". A rule here
12
+ * therefore has an id, a title, the taxonomy codes it responds to, a default
13
+ * severity and recommended actions — and no expression, predicate, script,
14
+ * template or callback field of any kind. That absence is the control. It is
15
+ * enforced by `.strict()`: a policy set carrying an unrecognised key is
16
+ * rejected outright rather than accepted with the key quietly dropped, because
17
+ * "dropped" and "never evaluated" look identical right up until something
18
+ * decides to evaluate it.
19
+ */
20
+ import { z } from 'zod';
21
+ import { CONTRACT_LIMITS, LanguageTagSchema, TimestampSchema } from './primitives.js';
22
+ import { RecommendedActionSchema, SeveritySchema, TaxonomyCodeSchema } from './taxonomy.js';
23
+ /** A namespaced policy set id, e.g. `mention.community`. */
24
+ export const PolicySetIdSchema = z
25
+ .string()
26
+ .min(3)
27
+ .max(CONTRACT_LIMITS.IDENTIFIER_MAX_LENGTH)
28
+ .regex(/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$/, 'must be a dotted lowercase namespace, e.g. "mention.community"');
29
+ /** A rule id within a policy set, e.g. `mention.harassment.2`. */
30
+ export const PolicyRuleIdSchema = z
31
+ .string()
32
+ .min(3)
33
+ .max(CONTRACT_LIMITS.IDENTIFIER_MAX_LENGTH)
34
+ .regex(/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$/, 'must be a dotted lowercase namespace, e.g. "mention.harassment.2"');
35
+ /**
36
+ * An immutable policy version token, e.g. `2026.07`, `mention.2026.07`,
37
+ * `oxy.2026.1`.
38
+ *
39
+ * Deliberately not semver: the plan's own tokens are calendar-shaped and
40
+ * tenant-prefixed, and a policy version is an opaque label pointing at a frozen
41
+ * document — nothing compares two of them for ordering.
42
+ */
43
+ export const PolicyVersionSchema = z
44
+ .string()
45
+ .min(1)
46
+ .max(64)
47
+ .regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, 'must start with a letter or digit and contain only letters, digits, ".", "_" or "-"');
48
+ /**
49
+ * The version of the Oxy Conduct Policy every decision is stamped with (§6.4).
50
+ *
51
+ * §6.1 assigns the third layer — "should this conduct affect global Oxy trust?"
52
+ * — to the Oxy Conduct Policy, evaluated by the Reputation Bridge. That bridge
53
+ * does not exist yet, and this constant is deliberately NOT a promise that it
54
+ * does. What it is: the label a decision published today records, so that when
55
+ * the bridge arrives it can tell which conduct policy a historical decision was
56
+ * decided under and refuse to re-interpret it under a newer one. §6.4's "a
57
+ * policy update never silently rewrites historical decisions" is unenforceable
58
+ * without a version on every decision from the first one.
59
+ *
60
+ * The value is Appendix B's. It is pinned here, in the package both the
61
+ * decision DTO and the reputation event import, so the two cannot drift into
62
+ * describing the same decision under two different conduct policies.
63
+ */
64
+ export const OXY_CONDUCT_POLICY_VERSION = 'oxy.2026.1';
65
+ /**
66
+ * The policy an envelope asks to be evaluated under (§5.1 `policy`).
67
+ *
68
+ * `locale` selects the language the policy text is shown to the reviewer in
69
+ * (Appendix A), and is not the language of the reported material — that is
70
+ * `resource.language`.
71
+ */
72
+ export const CasePolicyRefSchema = z.strictObject({
73
+ policySetId: PolicySetIdSchema,
74
+ version: PolicyVersionSchema,
75
+ locale: LanguageTagSchema.optional(),
76
+ });
77
+ /**
78
+ * The three policy versions a decision is decided under (§6.4).
79
+ *
80
+ * Field names follow Appendix B (`taxonomy`), which is the reference Decision.
81
+ * §6.4's prose calls the same field `universalTaxonomyVersion` and §11.6's
82
+ * internal event calls it `universal`; see `ReputationPolicyVersionsSchema` for
83
+ * why both spellings survive.
84
+ */
85
+ export const DecisionPolicyVersionsSchema = z.looseObject({
86
+ taxonomy: PolicyVersionSchema,
87
+ application: PolicyVersionSchema,
88
+ oxyConduct: PolicyVersionSchema,
89
+ });
90
+ /**
91
+ * The same three versions as carried by the internal reputation event (§11.6).
92
+ *
93
+ * §11.6 spells the first key `universal` where Appendix B spells it `taxonomy`.
94
+ * Both are reference payloads in the approved plan and both are load-bearing
95
+ * for a different consumer, so each surface keeps the spelling its own
96
+ * reference document uses rather than one of the two documents being quietly
97
+ * rewritten here. Unifying them is a one-line change and worth doing when the
98
+ * event contract is agreed with OxyHQServices — it is called out in the package
99
+ * README as the single naming inconsistency the contract preserves on purpose.
100
+ */
101
+ export const ReputationPolicyVersionsSchema = z.strictObject({
102
+ universal: PolicyVersionSchema,
103
+ application: PolicyVersionSchema,
104
+ oxyConduct: PolicyVersionSchema,
105
+ });
106
+ /** §6.4: a draft may be edited, a published version may not. */
107
+ export const POLICY_SET_STATUSES = ['draft', 'published'];
108
+ export const PolicySetStatusSchema = z.enum(POLICY_SET_STATUSES);
109
+ /**
110
+ * One rule inside a policy version — data, never code.
111
+ *
112
+ * `taxonomyCodes` is what binds layer 2 back to layer 1: the rule declares
113
+ * which universal findings it responds to, so a jury classifies once (§9.2 step
114
+ * one) and any number of applications evaluate that same classification against
115
+ * their own rules (§6.2).
116
+ */
117
+ export const PolicyRuleSchema = z.strictObject({
118
+ id: PolicyRuleIdSchema,
119
+ title: z.string().min(1).max(CONTRACT_LIMITS.SHORT_TEXT_MAX_LENGTH),
120
+ description: z.string().max(CONTRACT_LIMITS.LONG_TEXT_MAX_LENGTH).optional(),
121
+ taxonomyCodes: z.array(TaxonomyCodeSchema).min(1).max(CONTRACT_LIMITS.FINDINGS_MAX),
122
+ defaultSeverity: SeveritySchema.optional(),
123
+ recommendedActions: z
124
+ .array(RecommendedActionSchema)
125
+ .max(CONTRACT_LIMITS.RECOMMENDED_ACTIONS_MAX)
126
+ .optional(),
127
+ });
128
+ const POLICY_RULES_MAX = 500;
129
+ /**
130
+ * A policy set at one version (§6.4).
131
+ *
132
+ * The `status`/`publishedAt` pairing is the immutability rule expressed where a
133
+ * schema can express it: a published version must record when it was published,
134
+ * and a draft must not claim to have been. Actual immutability — never
135
+ * rewriting a published version's rules — is a storage rule the registry
136
+ * enforces; no parse can see a second write.
137
+ */
138
+ export const PolicySetVersionSchema = z
139
+ .strictObject({
140
+ policySetId: PolicySetIdSchema,
141
+ version: PolicyVersionSchema,
142
+ status: PolicySetStatusSchema,
143
+ title: z.string().min(1).max(CONTRACT_LIMITS.SHORT_TEXT_MAX_LENGTH),
144
+ locale: LanguageTagSchema.optional(),
145
+ publishedAt: TimestampSchema.optional(),
146
+ rules: z.array(PolicyRuleSchema).min(1).max(POLICY_RULES_MAX),
147
+ })
148
+ .superRefine((policySet, ctx) => {
149
+ if (policySet.status === 'published' && policySet.publishedAt === undefined) {
150
+ ctx.addIssue({
151
+ code: 'custom',
152
+ path: ['publishedAt'],
153
+ message: 'a published policy version must record publishedAt',
154
+ });
155
+ }
156
+ if (policySet.status === 'draft' && policySet.publishedAt !== undefined) {
157
+ ctx.addIssue({
158
+ code: 'custom',
159
+ path: ['publishedAt'],
160
+ message: 'a draft policy version must not record publishedAt',
161
+ });
162
+ }
163
+ const seen = new Set();
164
+ policySet.rules.forEach((rule, index) => {
165
+ if (seen.has(rule.id)) {
166
+ ctx.addIssue({
167
+ code: 'custom',
168
+ path: ['rules', index, 'id'],
169
+ message: `duplicate rule id "${rule.id}"`,
170
+ });
171
+ }
172
+ seen.add(rule.id);
173
+ });
174
+ });
175
+ //# sourceMappingURL=policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.js","sourceRoot":"","sources":["../../src/policies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Scalar contracts shared by every CrowdSource surface.
3
+ *
4
+ * Nothing here belongs to a single contract module; everything here is depended
5
+ * on by several of them. Two properties drive most of the choices below:
6
+ *
7
+ * 1. **The envelope is content-addressed.** §7.3 derives `caseDedupKey` from
8
+ * `applicationId`, `subject.externalId`, the canonical envelope hash and
9
+ * the policy version. Two byte-different representations of the SAME value
10
+ * produce two different keys, therefore two cases, therefore two penalties
11
+ * for one incident — the exact opposite of the "one penalty per incident"
12
+ * invariant. So every scalar that can travel in more than one shape is
13
+ * pinned to ONE canonical shape here: digests are always `sha256:<hex>`,
14
+ * timestamps are always millisecond-precision UTC.
15
+ *
16
+ * 2. **`:` is a structural separator.** §7.3 joins the dedup key components
17
+ * with `:`. An identifier that may itself contain `:` makes that join
18
+ * ambiguous — two distinct tuples can flatten to the same string and merge
19
+ * two unrelated cases. Every identifier schema below therefore excludes
20
+ * `:`. (The same character is independently forbidden in BullMQ queue and
21
+ * job ids, so this also keeps identifiers usable as dispatch keys.)
22
+ */
23
+ import { z } from 'zod';
24
+ /**
25
+ * Bounds applied across the contracts.
26
+ *
27
+ * §7.2.3 requires ingress to check "size limits, number of resources and MIME
28
+ * types" but the plan never states the numbers. These are the contract's own
29
+ * declared limits: generous enough not to reject real moderation material,
30
+ * finite so that no array or string in the contract is unbounded. A tenant may
31
+ * be held to something tighter by quota; nothing may exceed these.
32
+ */
33
+ export const CONTRACT_LIMITS = Object.freeze({
34
+ /** Envelope-local ids (`res_post`), policy ids, principal refs. */
35
+ IDENTIFIER_MAX_LENGTH: 128,
36
+ /** Ids minted by the application (`mention_report_123`, `post_987`). */
37
+ EXTERNAL_ID_MAX_LENGTH: 200,
38
+ RESOURCES_PER_ENVELOPE_MAX: 50,
39
+ RELATIONS_PER_ENVELOPE_MAX: 200,
40
+ ALLEGATIONS_PER_ENVELOPE_MAX: 20,
41
+ PRINCIPAL_BINDINGS_PER_ENVELOPE_MAX: 50,
42
+ /** A reported text resource. Long enough for an article, not a corpus. */
43
+ TEXT_RESOURCE_MAX_LENGTH: 100000,
44
+ /** Titles, labels, display names, place names. */
45
+ SHORT_TEXT_MAX_LENGTH: 500,
46
+ /** Descriptions, bios, reporter details, reviewer notes. */
47
+ LONG_TEXT_MAX_LENGTH: 5000,
48
+ /** Audio transcript, document extracted text, link snapshot. */
49
+ EXTRACTED_TEXT_MAX_LENGTH: 200000,
50
+ METADATA_KEYS_MAX: 50,
51
+ METADATA_KEY_MAX_LENGTH: 64,
52
+ METADATA_STRING_VALUE_MAX_LENGTH: 1000,
53
+ /** §5.7 custom payloads: data, bounded, never a document tree. */
54
+ CUSTOM_PAYLOAD_MAX_DEPTH: 5,
55
+ CUSTOM_PAYLOAD_ARRAY_MAX_LENGTH: 100,
56
+ CUSTOM_PAYLOAD_STRING_MAX_LENGTH: 10000,
57
+ CONVERSATION_MESSAGES_MAX: 50,
58
+ LISTING_MEDIA_REFS_MAX: 20,
59
+ PROFILE_CLAIMS_MAX: 20,
60
+ FINDINGS_MAX: 20,
61
+ RESOURCE_REFS_PER_FINDING_MAX: 50,
62
+ POLICY_RULE_IDS_MAX: 20,
63
+ RECOMMENDED_ACTIONS_MAX: 10,
64
+ /** §13.6 defaults to 30 days "configurable by policy"; this is the ceiling. */
65
+ RETENTION_DAYS_MAX: 3650,
66
+ /** A jury is 3, 5 or 7 today (§9.4). The bound only stops absurd values. */
67
+ JURY_SIZE_MAX: 99,
68
+ });
69
+ /**
70
+ * Keys that must never appear in a caller-supplied object, at any depth.
71
+ *
72
+ * A payload is data. These three names are how a data payload stops being data
73
+ * the moment anything merges, clones or `Object.assign`s it into a prototype
74
+ * chain. Rejecting them at the contract boundary is cheap and total; sanitising
75
+ * them later depends on every consumer remembering to.
76
+ *
77
+ * One of the three behaves differently and it is worth knowing which, because
78
+ * the list reads as though it were doing all the work: Zod removes an own
79
+ * `__proto__` property from any input before a key schema or a strict-key check
80
+ * ever sees it, so `__proto__` is DROPPED rather than rejected, and this list
81
+ * never fires for it. The safety outcome is the same — nothing is polluted, and
82
+ * the key cannot survive into parsed output — but a test asserting that
83
+ * `__proto__` is *rejected* would fail, and a reader assuming this constant is
84
+ * what prevents pollution would be assuming the wrong thing. `constructor` and
85
+ * `prototype` are ordinary keys to Zod and are rejected here.
86
+ */
87
+ export const FORBIDDEN_OBJECT_KEYS = Object.freeze([
88
+ '__proto__',
89
+ 'constructor',
90
+ 'prototype',
91
+ ]);
92
+ const IDENTIFIER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
93
+ /**
94
+ * An id that is local to one envelope, policy set or contract payload.
95
+ *
96
+ * Deliberately opaque: the plan writes both slugs (`app_mention`,
97
+ * `mention.community`) and ULID-prefixed ids (`case_01...`) in the same fields,
98
+ * so pinning the format would reject the plan's own reference documents. What
99
+ * IS pinned is the character set — see the `:` note in the module comment.
100
+ */
101
+ export const IdentifierSchema = z
102
+ .string()
103
+ .min(1)
104
+ .max(CONTRACT_LIMITS.IDENTIFIER_MAX_LENGTH)
105
+ .regex(IDENTIFIER_PATTERN, 'must start with a letter or digit and contain only letters, digits, ".", "_" or "-"');
106
+ /** An id minted by the reporting application, echoed back but never trusted. */
107
+ export const ExternalIdSchema = z
108
+ .string()
109
+ .min(1)
110
+ .max(CONTRACT_LIMITS.EXTERNAL_ID_MAX_LENGTH)
111
+ .regex(IDENTIFIER_PATTERN, 'must start with a letter or digit and contain only letters, digits, ".", "_" or "-"');
112
+ /**
113
+ * `sha256:<64 lowercase hex>` — the ONLY accepted digest form.
114
+ *
115
+ * Appendix A writes `"sha256:..."`; §5.8 writes `"..."`. Accepting both would
116
+ * let the same bytes be described two ways, and the canonical envelope hash
117
+ * would differ between them (see property 1 in the module comment). Appendix A
118
+ * is the reference document, so the prefixed form wins and the bare form is
119
+ * rejected rather than silently normalised — normalising would mean the digest
120
+ * CrowdSource stores is not the digest the application sent.
121
+ */
122
+ export const Sha256DigestSchema = z
123
+ .string()
124
+ .regex(/^sha256:[0-9a-f]{64}$/, 'must be "sha256:" followed by 64 lowercase hex characters');
125
+ /**
126
+ * Millisecond-precision UTC, e.g. `2026-07-28T18:00:00.000Z`.
127
+ *
128
+ * Every timestamp in the plan is written this way, and it is what
129
+ * `Date.prototype.toISOString()` produces, so the canonical form costs a
130
+ * JavaScript integrator nothing. Offsets are rejected: `18:00+02:00` and
131
+ * `16:00Z` are the same instant and would hash differently.
132
+ */
133
+ export const TimestampSchema = z.iso.datetime({ offset: false, precision: 3 });
134
+ /**
135
+ * BCP 47, restricted to `language[-Script][-Region][-variant…]`.
136
+ *
137
+ * A syntactic subset, not the full grammar (no extensions, no private use, no
138
+ * grandfathered tags). Covers `es` and `es-ES` from the plan and everything a
139
+ * real application sends; a tag outside the subset is a signal worth rejecting
140
+ * at ingress rather than carrying into reviewer language eligibility.
141
+ */
142
+ export const LanguageTagSchema = z
143
+ .string()
144
+ .regex(/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?(-([0-9][A-Za-z0-9]{3}|[A-Za-z0-9]{5,8}))*$/, 'must be a BCP 47 tag of the form language[-Script][-Region][-variant]');
145
+ /**
146
+ * An absolute `http`/`https` URL.
147
+ *
148
+ * §7.2.7 rejects "dangerous schemes and executable resources". Scheme is a
149
+ * purely syntactic property, so the contract enforces it. Host reachability is
150
+ * NOT enforced here: deciding whether a host is internal needs DNS resolution
151
+ * and belongs to `safeFetch` at ingestion time. A scheme check that pretended
152
+ * to be an SSRF control would be the more dangerous of the two.
153
+ */
154
+ export const HttpUrlSchema = z.url({ protocol: /^https?$/ }).max(2048);
155
+ /**
156
+ * A bare Oxy file id — the one way bytes enter a case.
157
+ *
158
+ * Evidence goes through the Oxy media chokepoint (`getFileDownloadUrl`) rather
159
+ * than a presigned bucket, which is the §12.3 divergence recorded in
160
+ * `AGENTS.md`. A file id is what that chokepoint takes, so it is what an asset
161
+ * carries: never a URL, never a host, never a variant. The reviewer client
162
+ * resolves it once through Bloom's `ImageResolver`, so nothing downstream needs
163
+ * to know where `cloud.oxy.so` is.
164
+ *
165
+ * Deliberately opaque, for the same reason `IdentifierSchema` is: the format
166
+ * belongs to Oxy, not to CrowdSource, and pinning it here would make an Oxy
167
+ * change look like a CrowdSource contract violation. What is pinned is that it
168
+ * is a bounded, non-empty token with no separators that could smuggle a path or
169
+ * a scheme into a resolver — `..`, `/` and `:` are all excluded by the pattern.
170
+ */
171
+ export const OxyFileIdSchema = z
172
+ .string()
173
+ .min(1)
174
+ .max(CONTRACT_LIMITS.IDENTIFIER_MAX_LENGTH)
175
+ .regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/, 'must be a bare Oxy file id: letters, digits, "_" or "-", starting with a letter or digit');
176
+ /** A `type/subtype` media type, without parameters. */
177
+ export const MimeTypeSchema = z
178
+ .string()
179
+ .max(255)
180
+ .regex(/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/, 'must be a lowercase "type/subtype" media type without parameters');
181
+ const METADATA_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9._-]*$/;
182
+ /** A key in any caller-supplied open bag. */
183
+ export const ObjectKeySchema = z
184
+ .string()
185
+ .min(1)
186
+ .max(CONTRACT_LIMITS.METADATA_KEY_MAX_LENGTH)
187
+ .regex(METADATA_KEY_PATTERN, 'must start with a letter and contain only letters, digits, ".", "_" or "-"')
188
+ .refine((key) => !FORBIDDEN_OBJECT_KEYS.includes(key), {
189
+ message: 'must not be a prototype-bearing key',
190
+ });
191
+ /** A single metadata value: scalar only, never a nested structure. */
192
+ export const MetadataValueSchema = z.union([
193
+ z.string().max(CONTRACT_LIMITS.METADATA_STRING_VALUE_MAX_LENGTH),
194
+ z.number().finite(),
195
+ z.boolean(),
196
+ z.null(),
197
+ ]);
198
+ /**
199
+ * An open key/value bag (§5.1 `metadata`, §5.3 the `metadata` resource type).
200
+ *
201
+ * Open by definition — the plan calls it "typed key value fields" and every
202
+ * tenant's keys differ — but flat and bounded. Allowing nesting here would make
203
+ * this the one field in the envelope through which an application could ship an
204
+ * arbitrary document tree past every other constraint in the contract.
205
+ */
206
+ export const MetadataBagSchema = z
207
+ .record(ObjectKeySchema, MetadataValueSchema)
208
+ .refine((bag) => Object.keys(bag).length <= CONTRACT_LIMITS.METADATA_KEYS_MAX, {
209
+ message: `must not have more than ${CONTRACT_LIMITS.METADATA_KEYS_MAX} keys`,
210
+ });
211
+ const customPayloadScalarSchema = z.union([
212
+ z.string().max(CONTRACT_LIMITS.CUSTOM_PAYLOAD_STRING_MAX_LENGTH),
213
+ z.number().finite(),
214
+ z.boolean(),
215
+ z.null(),
216
+ ]);
217
+ const buildCustomPayloadValueSchema = () => {
218
+ let value = customPayloadScalarSchema;
219
+ for (let depth = 1; depth < CONTRACT_LIMITS.CUSTOM_PAYLOAD_MAX_DEPTH; depth += 1) {
220
+ value = z.union([
221
+ customPayloadScalarSchema,
222
+ z.array(value).max(CONTRACT_LIMITS.CUSTOM_PAYLOAD_ARRAY_MAX_LENGTH),
223
+ z.record(ObjectKeySchema, value),
224
+ ]);
225
+ }
226
+ return value;
227
+ };
228
+ /**
229
+ * The value grammar for a §5.7 custom payload.
230
+ *
231
+ * Nesting is unrolled to a fixed depth rather than made recursive so the bound
232
+ * is part of the type, enforced by the same parse as everything else, and
233
+ * visible in the exported JSON Schema. Depth is what stops a payload being a
234
+ * document; `ObjectKeySchema` is what stops it being a prototype.
235
+ *
236
+ * Note what is deliberately absent: no lexical filter on string values. A
237
+ * moderation payload legitimately carries the exact hostile text under review —
238
+ * markup, script fragments, `javascript:` URLs quoted inside a harassment
239
+ * report. Rejecting those strings would reject the material the system exists
240
+ * to review. §5.7's boundary is structural, not lexical: the contract has no
241
+ * field anywhere that carries markup, a template, a component or a remote URL
242
+ * to be rendered, so there is nothing for such a string to be interpreted as.
243
+ */
244
+ export const CustomPayloadValueSchema = buildCustomPayloadValueSchema();
245
+ /** The top level of a §5.7 custom payload: always an object, never an array. */
246
+ export const CustomPayloadSchema = z.record(ObjectKeySchema, CustomPayloadValueSchema);
247
+ /** A number in the closed interval [0, 1] — §9.5 clamps confidence to it. */
248
+ export const UnitIntervalSchema = z.number().min(0).max(1);
249
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/primitives.ts"],"names":[],"mappings":"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"}