@cloudhal/core-contracts 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/schemas/.bundled/analytics-beacon.schema.json +0 -132
- package/schemas/.bundled/analytics-event.schema.json +0 -411
- package/schemas/.bundled/asset.schema.json +0 -519
- package/schemas/.bundled/automation.schema.json +0 -334
- package/schemas/.bundled/comment-submission.schema.json +0 -172
- package/schemas/.bundled/comment.schema.json +0 -425
- package/schemas/.bundled/content-entry.schema.json +0 -514
- package/schemas/.bundled/glossary.schema.json +0 -139
- package/schemas/.bundled/menu.schema.json +0 -371
- package/schemas/.bundled/page.schema.json +0 -738
- package/schemas/.bundled/project.schema.json +0 -97
- package/schemas/.bundled/redirect.schema.json +0 -152
- package/schemas/.bundled/release.schema.json +0 -639
- package/schemas/.bundled/schedule-run.schema.json +0 -310
- package/schemas/.bundled/section.schema.json +0 -434
- package/schemas/.bundled/site.schema.json +0 -1050
- package/schemas/.bundled/skill-manifest.schema.json +0 -51
- package/schemas/.bundled/snapshot.schema.json +0 -192
- package/schemas/.bundled/taxonomy.schema.json +0 -200
- package/schemas/.bundled/term.schema.json +0 -315
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://cloudhal.dev/schemas/v1/automation.schema.json",
|
|
4
|
-
"title": "Automation",
|
|
5
|
-
"description": "A recurring job on a site (RFC-0008), created by a person in Studio: either a built-in deterministic job that Cloudhal runs itself (reports, findings and notifications; it never publishes), or a scheduled agent task that an external agent picks up over MCP with the automation's own key, inside a run window, under a mode cap and budgets. No language model runs inside Cloudhal. Scheduling never grants rights: every call of a task runs with the key's scopes narrowed to its owner's current role. Automations live in D1 next to the graph; they are not graph nodes and are not part of site bundles.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"required": [
|
|
9
|
-
"schemaVersion",
|
|
10
|
-
"id",
|
|
11
|
-
"siteId",
|
|
12
|
-
"name",
|
|
13
|
-
"job",
|
|
14
|
-
"recurrence",
|
|
15
|
-
"state",
|
|
16
|
-
"consecutiveFailures",
|
|
17
|
-
"owner",
|
|
18
|
-
"createdAt",
|
|
19
|
-
"updatedAt",
|
|
20
|
-
"rev"
|
|
21
|
-
],
|
|
22
|
-
"properties": {
|
|
23
|
-
"schemaVersion": {
|
|
24
|
-
"$ref": "#/$defs/SchemaVersion"
|
|
25
|
-
},
|
|
26
|
-
"id": {
|
|
27
|
-
"$ref": "#/$defs/AutomationId"
|
|
28
|
-
},
|
|
29
|
-
"siteId": {
|
|
30
|
-
"$ref": "#/$defs/Id"
|
|
31
|
-
},
|
|
32
|
-
"name": {
|
|
33
|
-
"type": "string",
|
|
34
|
-
"minLength": 1,
|
|
35
|
-
"maxLength": 120,
|
|
36
|
-
"pattern": "^[^\\x00-\\x1F\\x7F\\u202A-\\u202E\\u2066-\\u2069]+$"
|
|
37
|
-
},
|
|
38
|
-
"job": {
|
|
39
|
-
"$ref": "#/$defs/AutomationJob"
|
|
40
|
-
},
|
|
41
|
-
"recurrence": {
|
|
42
|
-
"$ref": "#/$defs/AutomationRecurrence"
|
|
43
|
-
},
|
|
44
|
-
"state": {
|
|
45
|
-
"$ref": "#/$defs/AutomationState"
|
|
46
|
-
},
|
|
47
|
-
"pausedReason": {
|
|
48
|
-
"type": "string",
|
|
49
|
-
"description": "Why the automation is not `active`: a person paused it; its agent paused it; three consecutive failures; a run exceeded its budget; the site's kill switch; its key was revoked; its owner left or no longer holds the scopes it needs.",
|
|
50
|
-
"enum": [
|
|
51
|
-
"person",
|
|
52
|
-
"agent",
|
|
53
|
-
"failures",
|
|
54
|
-
"budget",
|
|
55
|
-
"kill-switch",
|
|
56
|
-
"key-revoked",
|
|
57
|
-
"owner-removed",
|
|
58
|
-
"role-changed"
|
|
59
|
-
]
|
|
60
|
-
},
|
|
61
|
-
"consecutiveFailures": {
|
|
62
|
-
"type": "integer",
|
|
63
|
-
"minimum": 0
|
|
64
|
-
},
|
|
65
|
-
"owner": {
|
|
66
|
-
"$ref": "#/$defs/AutomationOwner"
|
|
67
|
-
},
|
|
68
|
-
"nextRunAt": {
|
|
69
|
-
"$ref": "#/$defs/Timestamp"
|
|
70
|
-
},
|
|
71
|
-
"createdAt": {
|
|
72
|
-
"$ref": "#/$defs/Timestamp"
|
|
73
|
-
},
|
|
74
|
-
"updatedAt": {
|
|
75
|
-
"$ref": "#/$defs/Timestamp"
|
|
76
|
-
},
|
|
77
|
-
"rev": {
|
|
78
|
-
"$ref": "#/$defs/Revision"
|
|
79
|
-
},
|
|
80
|
-
"metadata": {
|
|
81
|
-
"$ref": "#/$defs/Metadata"
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
"$defs": {
|
|
85
|
-
"AutomationBudget": {
|
|
86
|
-
"type": "object",
|
|
87
|
-
"description": "Per-run limits Cloudhal counts and enforces for an agent task: tool calls, mutations, approval requests filed and minutes since the run began. Exceeding one ends the run (`budget-exceeded`) and pauses the automation.",
|
|
88
|
-
"additionalProperties": false,
|
|
89
|
-
"required": [
|
|
90
|
-
"maxToolCalls",
|
|
91
|
-
"maxWrites",
|
|
92
|
-
"maxApprovalRequests",
|
|
93
|
-
"maxMinutes"
|
|
94
|
-
],
|
|
95
|
-
"properties": {
|
|
96
|
-
"maxToolCalls": {
|
|
97
|
-
"type": "integer",
|
|
98
|
-
"minimum": 1,
|
|
99
|
-
"maximum": 500
|
|
100
|
-
},
|
|
101
|
-
"maxWrites": {
|
|
102
|
-
"type": "integer",
|
|
103
|
-
"minimum": 0,
|
|
104
|
-
"maximum": 200
|
|
105
|
-
},
|
|
106
|
-
"maxApprovalRequests": {
|
|
107
|
-
"type": "integer",
|
|
108
|
-
"minimum": 0,
|
|
109
|
-
"maximum": 20
|
|
110
|
-
},
|
|
111
|
-
"maxMinutes": {
|
|
112
|
-
"type": "integer",
|
|
113
|
-
"minimum": 1,
|
|
114
|
-
"maximum": 240
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
"AutomationId": {
|
|
119
|
-
"type": "string",
|
|
120
|
-
"description": "An automation id: `aut_` and 6 to 32 letters or digits.",
|
|
121
|
-
"pattern": "^aut_[A-Za-z0-9]{6,32}$"
|
|
122
|
-
},
|
|
123
|
-
"AutomationJob": {
|
|
124
|
-
"description": "What runs, discriminated by `kind`.",
|
|
125
|
-
"oneOf": [
|
|
126
|
-
{
|
|
127
|
-
"type": "object",
|
|
128
|
-
"title": "BuiltinAutomationJob",
|
|
129
|
-
"description": "A deterministic job Cloudhal runs itself, in bounded steps. Its outputs are findings, reports and Studio notifications; it never changes or publishes content.",
|
|
130
|
-
"additionalProperties": false,
|
|
131
|
-
"required": [
|
|
132
|
-
"kind",
|
|
133
|
-
"builtin"
|
|
134
|
-
],
|
|
135
|
-
"properties": {
|
|
136
|
-
"kind": {
|
|
137
|
-
"type": "string",
|
|
138
|
-
"enum": [
|
|
139
|
-
"builtin"
|
|
140
|
-
]
|
|
141
|
-
},
|
|
142
|
-
"builtin": {
|
|
143
|
-
"type": "string",
|
|
144
|
-
"enum": [
|
|
145
|
-
"broken-links",
|
|
146
|
-
"stale-content",
|
|
147
|
-
"feed-check",
|
|
148
|
-
"weekly-digest",
|
|
149
|
-
"cleanup"
|
|
150
|
-
]
|
|
151
|
-
},
|
|
152
|
-
"staleAfterDays": {
|
|
153
|
-
"type": "integer",
|
|
154
|
-
"description": "`stale-content` only: entries not updated for this many days are listed for review.",
|
|
155
|
-
"minimum": 30,
|
|
156
|
-
"maximum": 1095
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
"type": "object",
|
|
162
|
-
"title": "AgentTaskAutomationJob",
|
|
163
|
-
"description": "A task an external agent performs over MCP. At each occurrence a run window opens for `windowMinutes`; the automation's key (`keyId`, owned by the automation's owner) is valid only inside an open run, which the agent starts with `begin_run` and ends with `end_run`. The run's mode is the key's effective mode capped by `modeCap`; it never waits for a person: calls that need one leave an approval request and the run ends. `readsUntrustedText` declares that the task reads visitor-supplied text (comments, 404 paths, fetched pages); such an automation's key cannot hold write scopes, and any run that reads such text is limited to reading, labelling and hiding from then on.",
|
|
164
|
-
"additionalProperties": false,
|
|
165
|
-
"required": [
|
|
166
|
-
"kind",
|
|
167
|
-
"keyId",
|
|
168
|
-
"instructions",
|
|
169
|
-
"modeCap",
|
|
170
|
-
"readsUntrustedText",
|
|
171
|
-
"windowMinutes",
|
|
172
|
-
"budget"
|
|
173
|
-
],
|
|
174
|
-
"properties": {
|
|
175
|
-
"kind": {
|
|
176
|
-
"type": "string",
|
|
177
|
-
"enum": [
|
|
178
|
-
"agent-task"
|
|
179
|
-
]
|
|
180
|
-
},
|
|
181
|
-
"keyId": {
|
|
182
|
-
"type": "string",
|
|
183
|
-
"pattern": "^[A-Za-z0-9_-]{6,64}$"
|
|
184
|
-
},
|
|
185
|
-
"instructions": {
|
|
186
|
-
"type": "string",
|
|
187
|
-
"description": "What the owner asks the agent to do, shown to the agent by `begin_run`. Plain text.",
|
|
188
|
-
"minLength": 1,
|
|
189
|
-
"maxLength": 2000,
|
|
190
|
-
"pattern": "^[^\\x00-\\x08\\x0B-\\x1F\\x7F\\u202A-\\u202E\\u2066-\\u2069]+$"
|
|
191
|
-
},
|
|
192
|
-
"skill": {
|
|
193
|
-
"type": "string",
|
|
194
|
-
"description": "A skill the run declares (its scopes and approval list narrow the run further).",
|
|
195
|
-
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
|
|
196
|
-
"maxLength": 64
|
|
197
|
-
},
|
|
198
|
-
"modeCap": {
|
|
199
|
-
"type": "string",
|
|
200
|
-
"description": "The most autonomous mode a run may use; never `bypass`.",
|
|
201
|
-
"enum": [
|
|
202
|
-
"plan",
|
|
203
|
-
"manual",
|
|
204
|
-
"edits",
|
|
205
|
-
"auto"
|
|
206
|
-
]
|
|
207
|
-
},
|
|
208
|
-
"readsUntrustedText": {
|
|
209
|
-
"type": "boolean"
|
|
210
|
-
},
|
|
211
|
-
"windowMinutes": {
|
|
212
|
-
"type": "integer",
|
|
213
|
-
"minimum": 5,
|
|
214
|
-
"maximum": 240
|
|
215
|
-
},
|
|
216
|
-
"budget": {
|
|
217
|
-
"$ref": "#/$defs/AutomationBudget"
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
]
|
|
222
|
-
},
|
|
223
|
-
"AutomationOwner": {
|
|
224
|
-
"type": "object",
|
|
225
|
-
"description": "The person who created the automation and owns its key (`user_…`). Agents never own automations.",
|
|
226
|
-
"additionalProperties": false,
|
|
227
|
-
"required": [
|
|
228
|
-
"id"
|
|
229
|
-
],
|
|
230
|
-
"properties": {
|
|
231
|
-
"id": {
|
|
232
|
-
"type": "string",
|
|
233
|
-
"pattern": "^user_[A-Za-z0-9]{6,32}$"
|
|
234
|
-
},
|
|
235
|
-
"name": {
|
|
236
|
-
"type": "string",
|
|
237
|
-
"maxLength": 200
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
"AutomationRecurrence": {
|
|
242
|
-
"type": "object",
|
|
243
|
-
"description": "When the automation runs: the first occurrence as a wall-clock time in `timeZone`, repeated by `rule` (absent: once). Occurrences are computed in the zone, so \"Mondays 09:07\" stays 09:07 across daylight-saving changes; a time that does not exist on a given day (a spring-forward gap) runs at the next valid minute, and a time that occurs twice runs once, at the first (a documented deviation from RFC 5545 §3.3.10, which drops such occurrences). `preset` records which Studio choice produced the rule.",
|
|
244
|
-
"additionalProperties": false,
|
|
245
|
-
"required": [
|
|
246
|
-
"start",
|
|
247
|
-
"timeZone",
|
|
248
|
-
"preset"
|
|
249
|
-
],
|
|
250
|
-
"properties": {
|
|
251
|
-
"start": {
|
|
252
|
-
"$ref": "#/$defs/LocalDateTime"
|
|
253
|
-
},
|
|
254
|
-
"timeZone": {
|
|
255
|
-
"$ref": "#/$defs/TimeZone"
|
|
256
|
-
},
|
|
257
|
-
"rule": {
|
|
258
|
-
"$ref": "#/$defs/AutomationRule"
|
|
259
|
-
},
|
|
260
|
-
"preset": {
|
|
261
|
-
"type": "string",
|
|
262
|
-
"enum": [
|
|
263
|
-
"once",
|
|
264
|
-
"hourly",
|
|
265
|
-
"daily",
|
|
266
|
-
"weekdays",
|
|
267
|
-
"weekly",
|
|
268
|
-
"monthly",
|
|
269
|
-
"custom"
|
|
270
|
-
]
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
"AutomationRule": {
|
|
275
|
-
"type": "string",
|
|
276
|
-
"description": "The recurrence as an RFC 5545 RRULE value in Cloudhal's subset, without the `RRULE:` prefix: FREQ DAILY, WEEKLY or MONTHLY; INTERVAL; BYDAY (ordinals such as 2TU or -1FR only with MONTHLY); BYMONTHDAY (1–31 or -1); BYHOUR; BYMINUTE; COUNT or UNTIL. The pattern bounds the vocabulary; the parser refuses repeated parts, COUNT with UNTIL, ordinals outside MONTHLY and runs closer than the job's minimum interval.",
|
|
277
|
-
"maxLength": 300,
|
|
278
|
-
"pattern": "^FREQ=(?:DAILY|WEEKLY|MONTHLY)(?:;(?:INTERVAL=[1-9][0-9]{0,2}|BYDAY=(?:[+-]?[1-5])?(?:MO|TU|WE|TH|FR|SA|SU)(?:,(?:[+-]?[1-5])?(?:MO|TU|WE|TH|FR|SA|SU)){0,6}|BYMONTHDAY=(?:-1|[1-9]|[12][0-9]|3[01])(?:,(?:-1|[1-9]|[12][0-9]|3[01])){0,30}|BYHOUR=(?:[01]?[0-9]|2[0-3])(?:,(?:[01]?[0-9]|2[0-3])){0,23}|BYMINUTE=[0-5]?[0-9](?:,[0-5]?[0-9]){0,3}|COUNT=[1-9][0-9]{0,3}|UNTIL=[0-9]{8}T[0-9]{6}Z))*$"
|
|
279
|
-
},
|
|
280
|
-
"AutomationState": {
|
|
281
|
-
"type": "string",
|
|
282
|
-
"description": "`active` runs on its recurrence; `paused` and `auto-paused` (by failures or a budget) wait for a person to resume; `broken` needs a person to repair it (key revoked, owner gone); `ended` reached its COUNT or UNTIL.",
|
|
283
|
-
"enum": [
|
|
284
|
-
"active",
|
|
285
|
-
"paused",
|
|
286
|
-
"auto-paused",
|
|
287
|
-
"broken",
|
|
288
|
-
"ended"
|
|
289
|
-
]
|
|
290
|
-
},
|
|
291
|
-
"Id": {
|
|
292
|
-
"type": "string",
|
|
293
|
-
"description": "Prefixed, URL-safe identifier, e.g. site_01HZX8K3Q9. The prefix names the entity kind; agents and the MCP server pass these as opaque handles.",
|
|
294
|
-
"pattern": "^[a-z]+_[A-Za-z0-9]{6,32}$",
|
|
295
|
-
"minLength": 8,
|
|
296
|
-
"maxLength": 48
|
|
297
|
-
},
|
|
298
|
-
"LocalDateTime": {
|
|
299
|
-
"type": "string",
|
|
300
|
-
"description": "A wall-clock date and time without an offset, to the minute (YYYY-MM-DDTHH:mm), as a person entered it; always paired with a TimeZone (RFC-0008).",
|
|
301
|
-
"pattern": "^[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]$"
|
|
302
|
-
},
|
|
303
|
-
"Metadata": {
|
|
304
|
-
"type": "object",
|
|
305
|
-
"description": "Free-form string-to-string map for extensions. Keys should be namespaced (e.g. cloudhal.source).",
|
|
306
|
-
"additionalProperties": {
|
|
307
|
-
"type": "string"
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
"Revision": {
|
|
311
|
-
"type": "integer",
|
|
312
|
-
"description": "Monotonic per-node revision used for optimistic locking (compare-and-swap on write).",
|
|
313
|
-
"minimum": 0
|
|
314
|
-
},
|
|
315
|
-
"SchemaVersion": {
|
|
316
|
-
"type": "integer",
|
|
317
|
-
"description": "Version of this contract. Readers reject unknown versions; migrations move documents forward one version at a time.",
|
|
318
|
-
"enum": [
|
|
319
|
-
1
|
|
320
|
-
]
|
|
321
|
-
},
|
|
322
|
-
"Timestamp": {
|
|
323
|
-
"type": "string",
|
|
324
|
-
"description": "RFC 3339 / ISO 8601 instant in UTC.",
|
|
325
|
-
"format": "date-time"
|
|
326
|
-
},
|
|
327
|
-
"TimeZone": {
|
|
328
|
-
"type": "string",
|
|
329
|
-
"description": "IANA time zone name from the tz database (RFC-0008), e.g. Europe/Istanbul, America/Argentina/Buenos_Aires, Etc/GMT+3 or UTC. Wall-clock times a person enters are kept with their zone, so the instant is recomputed when governments change the rules. The pattern bounds the shape only; writers also check the name against the runtime's Intl zone list.",
|
|
330
|
-
"pattern": "^(?:UTC|[A-Z][A-Za-z_-]+(?:/[A-Za-z0-9_+-]+){1,2})$",
|
|
331
|
-
"maxLength": 64
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://cloudhal.dev/schemas/v1/comment-submission.schema.json",
|
|
4
|
-
"title": "CommentSubmission",
|
|
5
|
-
"description": "What a browser may send to the site Worker's comment endpoints (RFC-0007): `POST /__cloudhal/comments` (a comment) and `POST /__cloudhal/comments/report` (a report). Forms post application/x-www-form-urlencoded and the comments module posts JSON; the server builds this object from either (the endpoint sets `kind`, the server sets `schemaVersion`) and checks it with the precompiled validator before anything else reads it. Everything in it is untrusted. It is loose where the server normalises (it trims, NFC-normalises and re-checks text against the stored Comment contract) and strict where a browser has no business sending something: there is no field for a status, a site, an author kind, a label, an IP address or anything the server derives itself.",
|
|
6
|
-
"oneOf": [
|
|
7
|
-
{
|
|
8
|
-
"type": "object",
|
|
9
|
-
"title": "CommentPostSubmission",
|
|
10
|
-
"description": "A new comment or a reply.",
|
|
11
|
-
"additionalProperties": false,
|
|
12
|
-
"required": [
|
|
13
|
-
"schemaVersion",
|
|
14
|
-
"kind",
|
|
15
|
-
"nodeId",
|
|
16
|
-
"name",
|
|
17
|
-
"body"
|
|
18
|
-
],
|
|
19
|
-
"properties": {
|
|
20
|
-
"schemaVersion": {
|
|
21
|
-
"$ref": "#/$defs/SchemaVersion"
|
|
22
|
-
},
|
|
23
|
-
"kind": {
|
|
24
|
-
"type": "string",
|
|
25
|
-
"enum": [
|
|
26
|
-
"comment"
|
|
27
|
-
]
|
|
28
|
-
},
|
|
29
|
-
"nodeId": {
|
|
30
|
-
"$ref": "#/$defs/Id",
|
|
31
|
-
"description": "The entry commented on. The server accepts it only for a published entry with an open thread, and works out the page to return to itself."
|
|
32
|
-
},
|
|
33
|
-
"parentId": {
|
|
34
|
-
"$ref": "#/$defs/SubmissionCommentId",
|
|
35
|
-
"description": "The comment replied to; it must be approved and in the same thread. The server decides `parentId`/`inReplyToId` of the stored comment."
|
|
36
|
-
},
|
|
37
|
-
"name": {
|
|
38
|
-
"type": "string",
|
|
39
|
-
"description": "The display name as typed (the form says it is shown publicly).",
|
|
40
|
-
"minLength": 1,
|
|
41
|
-
"maxLength": 200
|
|
42
|
-
},
|
|
43
|
-
"email": {
|
|
44
|
-
"type": "string",
|
|
45
|
-
"description": "Optional and never shown. Kept only for moderation, erasure and export requests (v1.1: reply notifications after double opt-in).",
|
|
46
|
-
"maxLength": 254,
|
|
47
|
-
"pattern": "^[^\\s@\\x00-\\x1F\\x7F]{1,64}@[^\\s@\\x00-\\x1F\\x7F]{1,189}$"
|
|
48
|
-
},
|
|
49
|
-
"body": {
|
|
50
|
-
"type": "string",
|
|
51
|
-
"description": "The comment as typed; the server trims and normalises it, then requires 2 to 5,000 characters.",
|
|
52
|
-
"minLength": 1,
|
|
53
|
-
"maxLength": 20000
|
|
54
|
-
},
|
|
55
|
-
"challenge": {
|
|
56
|
-
"$ref": "#/$defs/SubmissionChallenge"
|
|
57
|
-
},
|
|
58
|
-
"solution": {
|
|
59
|
-
"$ref": "#/$defs/SubmissionSolution"
|
|
60
|
-
},
|
|
61
|
-
"turnstileToken": {
|
|
62
|
-
"$ref": "#/$defs/SubmissionTurnstileToken"
|
|
63
|
-
},
|
|
64
|
-
"website": {
|
|
65
|
-
"$ref": "#/$defs/SubmissionHoneypot"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"type": "object",
|
|
71
|
-
"title": "CommentReportSubmission",
|
|
72
|
-
"description": "A reader's notice that a comment breaks the site's rules or the law (EU DSA Art. 16). A report never hides anything by itself: it puts the comment in front of a person.",
|
|
73
|
-
"additionalProperties": false,
|
|
74
|
-
"required": [
|
|
75
|
-
"schemaVersion",
|
|
76
|
-
"kind",
|
|
77
|
-
"commentId",
|
|
78
|
-
"reason"
|
|
79
|
-
],
|
|
80
|
-
"properties": {
|
|
81
|
-
"schemaVersion": {
|
|
82
|
-
"$ref": "#/$defs/SchemaVersion"
|
|
83
|
-
},
|
|
84
|
-
"kind": {
|
|
85
|
-
"type": "string",
|
|
86
|
-
"enum": [
|
|
87
|
-
"report"
|
|
88
|
-
]
|
|
89
|
-
},
|
|
90
|
-
"commentId": {
|
|
91
|
-
"$ref": "#/$defs/SubmissionCommentId"
|
|
92
|
-
},
|
|
93
|
-
"reason": {
|
|
94
|
-
"type": "string",
|
|
95
|
-
"enum": [
|
|
96
|
-
"spam",
|
|
97
|
-
"abuse",
|
|
98
|
-
"personal-data",
|
|
99
|
-
"illegal-content",
|
|
100
|
-
"other"
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
"details": {
|
|
104
|
-
"type": "string",
|
|
105
|
-
"description": "Why, as typed; at most 1,000 characters after normalising.",
|
|
106
|
-
"maxLength": 4000
|
|
107
|
-
},
|
|
108
|
-
"email": {
|
|
109
|
-
"type": "string",
|
|
110
|
-
"description": "Optional, never shown: where the site may answer the notice.",
|
|
111
|
-
"maxLength": 254,
|
|
112
|
-
"pattern": "^[^\\s@\\x00-\\x1F\\x7F]{1,64}@[^\\s@\\x00-\\x1F\\x7F]{1,189}$"
|
|
113
|
-
},
|
|
114
|
-
"challenge": {
|
|
115
|
-
"$ref": "#/$defs/SubmissionChallenge"
|
|
116
|
-
},
|
|
117
|
-
"solution": {
|
|
118
|
-
"$ref": "#/$defs/SubmissionSolution"
|
|
119
|
-
},
|
|
120
|
-
"turnstileToken": {
|
|
121
|
-
"$ref": "#/$defs/SubmissionTurnstileToken"
|
|
122
|
-
},
|
|
123
|
-
"website": {
|
|
124
|
-
"$ref": "#/$defs/SubmissionHoneypot"
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
],
|
|
129
|
-
"$defs": {
|
|
130
|
-
"Id": {
|
|
131
|
-
"type": "string",
|
|
132
|
-
"description": "Prefixed, URL-safe identifier, e.g. site_01HZX8K3Q9. The prefix names the entity kind; agents and the MCP server pass these as opaque handles.",
|
|
133
|
-
"pattern": "^[a-z]+_[A-Za-z0-9]{6,32}$",
|
|
134
|
-
"minLength": 8,
|
|
135
|
-
"maxLength": 48
|
|
136
|
-
},
|
|
137
|
-
"SchemaVersion": {
|
|
138
|
-
"type": "integer",
|
|
139
|
-
"description": "Version of this contract. Readers reject unknown versions; migrations move documents forward one version at a time.",
|
|
140
|
-
"enum": [
|
|
141
|
-
1
|
|
142
|
-
]
|
|
143
|
-
},
|
|
144
|
-
"SubmissionChallenge": {
|
|
145
|
-
"type": "string",
|
|
146
|
-
"description": "The signed proof-of-work challenge from `GET /__cloudhal/comments/challenge`, as issued (base64url segments joined by dots).",
|
|
147
|
-
"minLength": 16,
|
|
148
|
-
"maxLength": 512,
|
|
149
|
-
"pattern": "^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*$"
|
|
150
|
-
},
|
|
151
|
-
"SubmissionCommentId": {
|
|
152
|
-
"type": "string",
|
|
153
|
-
"pattern": "^cmt_[A-Za-z0-9]{6,32}$"
|
|
154
|
-
},
|
|
155
|
-
"SubmissionHoneypot": {
|
|
156
|
-
"type": "string",
|
|
157
|
-
"description": "A field people never see. The schema accepts any short value so that a filled honeypot gets the same answer as a real submission (\"held for moderation\") and nothing is stored.",
|
|
158
|
-
"maxLength": 2048
|
|
159
|
-
},
|
|
160
|
-
"SubmissionSolution": {
|
|
161
|
-
"type": "string",
|
|
162
|
-
"description": "The counter that solves the challenge, in decimal.",
|
|
163
|
-
"pattern": "^(?:0|[1-9][0-9]{0,15})$"
|
|
164
|
-
},
|
|
165
|
-
"SubmissionTurnstileToken": {
|
|
166
|
-
"type": "string",
|
|
167
|
-
"description": "Cloudflare Turnstile's response token, when the site turned Turnstile on.",
|
|
168
|
-
"minLength": 1,
|
|
169
|
-
"maxLength": 2048
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|