@amityco/social-plus-vise 0.4.0 → 0.7.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.
- package/README.md +70 -12
- package/dist/outcomes.js +376 -0
- package/dist/tools/ast.js +297 -0
- package/dist/tools/project.js +1184 -11
- package/package.json +10 -4
- package/rules/auth.yaml +126 -0
- package/rules/chat.yaml +876 -0
- package/rules/comments.yaml +906 -0
- package/rules/feed.yaml +2285 -30
- package/rules/live-data.yaml +60 -0
- package/rules/moderation.yaml +1286 -0
- package/rules/network.yaml +66 -0
- package/rules/push.yaml +467 -16
- package/rules/sdk-lifecycle.yaml +60 -0
- package/rules/security.yaml +60 -0
- package/skills/social-plus-vise/SKILL.md +148 -1
|
@@ -0,0 +1,906 @@
|
|
|
1
|
+
{
|
|
2
|
+
"domain": "comments",
|
|
3
|
+
"schema_version": 1,
|
|
4
|
+
"rules": [
|
|
5
|
+
{
|
|
6
|
+
"id": "typescript.comments.target-resolved",
|
|
7
|
+
"version": 1,
|
|
8
|
+
"title": "TypeScript comment target must not be hardcoded",
|
|
9
|
+
"severity": "warning",
|
|
10
|
+
"rationale": "Comment targets (postId, referenceId) should come from navigation props or parent entity, not be invented by the coding agent.",
|
|
11
|
+
"applies_when": {
|
|
12
|
+
"platforms": [
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"outcomes": [
|
|
16
|
+
"add-comments",
|
|
17
|
+
"validate-setup"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"enforcement": {
|
|
21
|
+
"deterministic": [
|
|
22
|
+
{
|
|
23
|
+
"check": "validator-finding-absent",
|
|
24
|
+
"finding_rule_id": "typescript.comments.target-resolved"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"attestation": {
|
|
28
|
+
"allowed": true,
|
|
29
|
+
"host_agent_min_confidence": "high",
|
|
30
|
+
"human_allowed": true,
|
|
31
|
+
"evidence_required": [
|
|
32
|
+
{
|
|
33
|
+
"field": "target_source",
|
|
34
|
+
"description": "Where the comment target (postId/referenceId) originates from.",
|
|
35
|
+
"upload_policy": "upload-with-consent"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "react-native.comments.target-resolved",
|
|
43
|
+
"version": 1,
|
|
44
|
+
"title": "React Native comment target must not be hardcoded",
|
|
45
|
+
"severity": "warning",
|
|
46
|
+
"rationale": "Comment targets (postId, referenceId) should come from navigation props or parent entity, not be invented by the coding agent.",
|
|
47
|
+
"applies_when": {
|
|
48
|
+
"platforms": [
|
|
49
|
+
"react-native"
|
|
50
|
+
],
|
|
51
|
+
"outcomes": [
|
|
52
|
+
"add-comments",
|
|
53
|
+
"validate-setup"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"enforcement": {
|
|
57
|
+
"deterministic": [
|
|
58
|
+
{
|
|
59
|
+
"check": "validator-finding-absent",
|
|
60
|
+
"finding_rule_id": "react-native.comments.target-resolved"
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"attestation": {
|
|
64
|
+
"allowed": true,
|
|
65
|
+
"host_agent_min_confidence": "high",
|
|
66
|
+
"human_allowed": true,
|
|
67
|
+
"evidence_required": [
|
|
68
|
+
{
|
|
69
|
+
"field": "target_source",
|
|
70
|
+
"description": "Where the comment target (postId/referenceId) originates from.",
|
|
71
|
+
"upload_policy": "upload-with-consent"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "android.comments.target-resolved",
|
|
79
|
+
"version": 1,
|
|
80
|
+
"title": "Android comment target must not be hardcoded",
|
|
81
|
+
"severity": "warning",
|
|
82
|
+
"rationale": "Comment targets (postId, referenceId) should come from navigation props or parent entity, not be invented by the coding agent.",
|
|
83
|
+
"applies_when": {
|
|
84
|
+
"platforms": [
|
|
85
|
+
"android"
|
|
86
|
+
],
|
|
87
|
+
"outcomes": [
|
|
88
|
+
"add-comments",
|
|
89
|
+
"validate-setup"
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
"enforcement": {
|
|
93
|
+
"deterministic": [
|
|
94
|
+
{
|
|
95
|
+
"check": "validator-finding-absent",
|
|
96
|
+
"finding_rule_id": "android.comments.target-resolved"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"attestation": {
|
|
100
|
+
"allowed": true,
|
|
101
|
+
"host_agent_min_confidence": "high",
|
|
102
|
+
"human_allowed": true,
|
|
103
|
+
"evidence_required": [
|
|
104
|
+
{
|
|
105
|
+
"field": "target_source",
|
|
106
|
+
"description": "Where the comment target (postId/referenceId) originates from.",
|
|
107
|
+
"upload_policy": "upload-with-consent"
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "flutter.comments.target-resolved",
|
|
115
|
+
"version": 1,
|
|
116
|
+
"title": "Flutter comment target must not be hardcoded",
|
|
117
|
+
"severity": "warning",
|
|
118
|
+
"rationale": "Comment targets (postId, referenceId) should come from navigation props or parent entity, not be invented by the coding agent.",
|
|
119
|
+
"applies_when": {
|
|
120
|
+
"platforms": [
|
|
121
|
+
"flutter"
|
|
122
|
+
],
|
|
123
|
+
"outcomes": [
|
|
124
|
+
"add-comments",
|
|
125
|
+
"validate-setup"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"enforcement": {
|
|
129
|
+
"deterministic": [
|
|
130
|
+
{
|
|
131
|
+
"check": "validator-finding-absent",
|
|
132
|
+
"finding_rule_id": "flutter.comments.target-resolved"
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"attestation": {
|
|
136
|
+
"allowed": true,
|
|
137
|
+
"host_agent_min_confidence": "high",
|
|
138
|
+
"human_allowed": true,
|
|
139
|
+
"evidence_required": [
|
|
140
|
+
{
|
|
141
|
+
"field": "target_source",
|
|
142
|
+
"description": "Where the comment target (postId/referenceId) originates from.",
|
|
143
|
+
"upload_policy": "upload-with-consent"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "ios.comments.target-resolved",
|
|
151
|
+
"version": 1,
|
|
152
|
+
"title": "iOS comment target must not be hardcoded",
|
|
153
|
+
"severity": "warning",
|
|
154
|
+
"rationale": "Comment targets (postId, referenceId) should come from navigation props or parent entity, not be invented by the coding agent.",
|
|
155
|
+
"applies_when": {
|
|
156
|
+
"platforms": [
|
|
157
|
+
"ios"
|
|
158
|
+
],
|
|
159
|
+
"outcomes": [
|
|
160
|
+
"add-comments",
|
|
161
|
+
"validate-setup"
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
"enforcement": {
|
|
165
|
+
"deterministic": [
|
|
166
|
+
{
|
|
167
|
+
"check": "validator-finding-absent",
|
|
168
|
+
"finding_rule_id": "ios.comments.target-resolved"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"attestation": {
|
|
172
|
+
"allowed": true,
|
|
173
|
+
"host_agent_min_confidence": "high",
|
|
174
|
+
"human_allowed": true,
|
|
175
|
+
"evidence_required": [
|
|
176
|
+
{
|
|
177
|
+
"field": "target_source",
|
|
178
|
+
"description": "Where the comment target (postId/referenceId) originates from.",
|
|
179
|
+
"upload_policy": "upload-with-consent"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "typescript.comments.observer-cleanup",
|
|
187
|
+
"version": 1,
|
|
188
|
+
"title": "TypeScript comment observer must be cleaned up",
|
|
189
|
+
"severity": "warning",
|
|
190
|
+
"rationale": "Live comment subscriptions leak memory and produce stale UI updates if not cleaned up when the component/view is destroyed.",
|
|
191
|
+
"applies_when": {
|
|
192
|
+
"platforms": [
|
|
193
|
+
"typescript"
|
|
194
|
+
],
|
|
195
|
+
"outcomes": [
|
|
196
|
+
"add-comments",
|
|
197
|
+
"validate-setup"
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
"enforcement": {
|
|
201
|
+
"deterministic": [
|
|
202
|
+
{
|
|
203
|
+
"check": "validator-finding-absent",
|
|
204
|
+
"finding_rule_id": "typescript.comments.observer-cleanup"
|
|
205
|
+
}
|
|
206
|
+
],
|
|
207
|
+
"attestation": {
|
|
208
|
+
"allowed": true,
|
|
209
|
+
"host_agent_min_confidence": "high",
|
|
210
|
+
"human_allowed": true,
|
|
211
|
+
"evidence_required": [
|
|
212
|
+
{
|
|
213
|
+
"field": "cleanup_mechanism",
|
|
214
|
+
"description": "How comment observers are cleaned up (unsubscribe, useEffect return, dispose).",
|
|
215
|
+
"upload_policy": "upload-with-consent"
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "react-native.comments.observer-cleanup",
|
|
223
|
+
"version": 1,
|
|
224
|
+
"title": "React Native comment observer must be cleaned up",
|
|
225
|
+
"severity": "warning",
|
|
226
|
+
"rationale": "Live comment subscriptions leak memory and produce stale UI updates if not cleaned up when the component is unmounted.",
|
|
227
|
+
"applies_when": {
|
|
228
|
+
"platforms": [
|
|
229
|
+
"react-native"
|
|
230
|
+
],
|
|
231
|
+
"outcomes": [
|
|
232
|
+
"add-comments",
|
|
233
|
+
"validate-setup"
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
"enforcement": {
|
|
237
|
+
"deterministic": [
|
|
238
|
+
{
|
|
239
|
+
"check": "validator-finding-absent",
|
|
240
|
+
"finding_rule_id": "react-native.comments.observer-cleanup"
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
"attestation": {
|
|
244
|
+
"allowed": true,
|
|
245
|
+
"host_agent_min_confidence": "high",
|
|
246
|
+
"human_allowed": true,
|
|
247
|
+
"evidence_required": [
|
|
248
|
+
{
|
|
249
|
+
"field": "cleanup_mechanism",
|
|
250
|
+
"description": "How comment observers are cleaned up (useEffect return, unsubscribe).",
|
|
251
|
+
"upload_policy": "upload-with-consent"
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"id": "android.comments.observer-cleanup",
|
|
259
|
+
"version": 1,
|
|
260
|
+
"title": "Android comment observer must be cleaned up",
|
|
261
|
+
"severity": "warning",
|
|
262
|
+
"rationale": "Live comment subscriptions leak memory and produce stale UI updates if not disposed when the Activity/Fragment/ViewModel lifecycle ends.",
|
|
263
|
+
"applies_when": {
|
|
264
|
+
"platforms": [
|
|
265
|
+
"android"
|
|
266
|
+
],
|
|
267
|
+
"outcomes": [
|
|
268
|
+
"add-comments",
|
|
269
|
+
"validate-setup"
|
|
270
|
+
]
|
|
271
|
+
},
|
|
272
|
+
"enforcement": {
|
|
273
|
+
"deterministic": [
|
|
274
|
+
{
|
|
275
|
+
"check": "validator-finding-absent",
|
|
276
|
+
"finding_rule_id": "android.comments.observer-cleanup"
|
|
277
|
+
}
|
|
278
|
+
],
|
|
279
|
+
"attestation": {
|
|
280
|
+
"allowed": true,
|
|
281
|
+
"host_agent_min_confidence": "high",
|
|
282
|
+
"human_allowed": true,
|
|
283
|
+
"evidence_required": [
|
|
284
|
+
{
|
|
285
|
+
"field": "cleanup_mechanism",
|
|
286
|
+
"description": "How comment observers are cleaned up (dispose, CompositeDisposable, clear).",
|
|
287
|
+
"upload_policy": "upload-with-consent"
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"id": "flutter.comments.observer-cleanup",
|
|
295
|
+
"version": 1,
|
|
296
|
+
"title": "Flutter comment observer must be cleaned up",
|
|
297
|
+
"severity": "warning",
|
|
298
|
+
"rationale": "Live comment stream subscriptions leak memory if not cancelled when the Widget is disposed.",
|
|
299
|
+
"applies_when": {
|
|
300
|
+
"platforms": [
|
|
301
|
+
"flutter"
|
|
302
|
+
],
|
|
303
|
+
"outcomes": [
|
|
304
|
+
"add-comments",
|
|
305
|
+
"validate-setup"
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
"enforcement": {
|
|
309
|
+
"deterministic": [
|
|
310
|
+
{
|
|
311
|
+
"check": "validator-finding-absent",
|
|
312
|
+
"finding_rule_id": "flutter.comments.observer-cleanup"
|
|
313
|
+
}
|
|
314
|
+
],
|
|
315
|
+
"attestation": {
|
|
316
|
+
"allowed": true,
|
|
317
|
+
"host_agent_min_confidence": "high",
|
|
318
|
+
"human_allowed": true,
|
|
319
|
+
"evidence_required": [
|
|
320
|
+
{
|
|
321
|
+
"field": "cleanup_mechanism",
|
|
322
|
+
"description": "How comment stream subscriptions are cleaned up (cancel, dispose).",
|
|
323
|
+
"upload_policy": "upload-with-consent"
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"id": "ios.comments.observer-cleanup",
|
|
331
|
+
"version": 1,
|
|
332
|
+
"title": "iOS comment observer must be cleaned up",
|
|
333
|
+
"severity": "warning",
|
|
334
|
+
"rationale": "Live comment observation tokens leak memory if not invalidated when the ViewController/View lifecycle ends.",
|
|
335
|
+
"applies_when": {
|
|
336
|
+
"platforms": [
|
|
337
|
+
"ios"
|
|
338
|
+
],
|
|
339
|
+
"outcomes": [
|
|
340
|
+
"add-comments",
|
|
341
|
+
"validate-setup"
|
|
342
|
+
]
|
|
343
|
+
},
|
|
344
|
+
"enforcement": {
|
|
345
|
+
"deterministic": [
|
|
346
|
+
{
|
|
347
|
+
"check": "validator-finding-absent",
|
|
348
|
+
"finding_rule_id": "ios.comments.observer-cleanup"
|
|
349
|
+
}
|
|
350
|
+
],
|
|
351
|
+
"attestation": {
|
|
352
|
+
"allowed": true,
|
|
353
|
+
"host_agent_min_confidence": "high",
|
|
354
|
+
"human_allowed": true,
|
|
355
|
+
"evidence_required": [
|
|
356
|
+
{
|
|
357
|
+
"field": "cleanup_mechanism",
|
|
358
|
+
"description": "How comment observer tokens are cleaned up (invalidate, deinit).",
|
|
359
|
+
"upload_policy": "upload-with-consent"
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"id": "typescript.comments.ui-states-present",
|
|
367
|
+
"version": 1,
|
|
368
|
+
"title": "TypeScript comment UI must handle loading, empty, and error states",
|
|
369
|
+
"severity": "warning",
|
|
370
|
+
"rationale": "Comments load asynchronously. Without state handling, users see blank screens or unhandled errors.",
|
|
371
|
+
"applies_when": {
|
|
372
|
+
"platforms": [
|
|
373
|
+
"typescript"
|
|
374
|
+
],
|
|
375
|
+
"outcomes": [
|
|
376
|
+
"add-comments",
|
|
377
|
+
"validate-setup"
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
"enforcement": {
|
|
381
|
+
"deterministic": [
|
|
382
|
+
{
|
|
383
|
+
"check": "validator-finding-absent",
|
|
384
|
+
"finding_rule_id": "typescript.comments.ui-states-present"
|
|
385
|
+
}
|
|
386
|
+
],
|
|
387
|
+
"attestation": {
|
|
388
|
+
"allowed": true,
|
|
389
|
+
"host_agent_min_confidence": "medium",
|
|
390
|
+
"human_allowed": true,
|
|
391
|
+
"evidence_required": [
|
|
392
|
+
{
|
|
393
|
+
"field": "ui_states",
|
|
394
|
+
"description": "How loading, empty, and error states are rendered in the comment UI.",
|
|
395
|
+
"upload_policy": "upload-with-consent"
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"id": "react-native.comments.ui-states-present",
|
|
403
|
+
"version": 1,
|
|
404
|
+
"title": "React Native comment UI must handle loading, empty, and error states",
|
|
405
|
+
"severity": "warning",
|
|
406
|
+
"rationale": "Comments load asynchronously. Without state handling, users see blank screens or unhandled errors.",
|
|
407
|
+
"applies_when": {
|
|
408
|
+
"platforms": [
|
|
409
|
+
"react-native"
|
|
410
|
+
],
|
|
411
|
+
"outcomes": [
|
|
412
|
+
"add-comments",
|
|
413
|
+
"validate-setup"
|
|
414
|
+
]
|
|
415
|
+
},
|
|
416
|
+
"enforcement": {
|
|
417
|
+
"deterministic": [
|
|
418
|
+
{
|
|
419
|
+
"check": "validator-finding-absent",
|
|
420
|
+
"finding_rule_id": "react-native.comments.ui-states-present"
|
|
421
|
+
}
|
|
422
|
+
],
|
|
423
|
+
"attestation": {
|
|
424
|
+
"allowed": true,
|
|
425
|
+
"host_agent_min_confidence": "medium",
|
|
426
|
+
"human_allowed": true,
|
|
427
|
+
"evidence_required": [
|
|
428
|
+
{
|
|
429
|
+
"field": "ui_states",
|
|
430
|
+
"description": "How loading, empty, and error states are rendered in the comment UI.",
|
|
431
|
+
"upload_policy": "upload-with-consent"
|
|
432
|
+
}
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"id": "android.comments.ui-states-present",
|
|
439
|
+
"version": 1,
|
|
440
|
+
"title": "Android comment UI must handle loading, empty, and error states",
|
|
441
|
+
"severity": "warning",
|
|
442
|
+
"rationale": "Comments load asynchronously. Without state handling, users see blank screens or unhandled errors.",
|
|
443
|
+
"applies_when": {
|
|
444
|
+
"platforms": [
|
|
445
|
+
"android"
|
|
446
|
+
],
|
|
447
|
+
"outcomes": [
|
|
448
|
+
"add-comments",
|
|
449
|
+
"validate-setup"
|
|
450
|
+
]
|
|
451
|
+
},
|
|
452
|
+
"enforcement": {
|
|
453
|
+
"deterministic": [
|
|
454
|
+
{
|
|
455
|
+
"check": "validator-finding-absent",
|
|
456
|
+
"finding_rule_id": "android.comments.ui-states-present"
|
|
457
|
+
}
|
|
458
|
+
],
|
|
459
|
+
"attestation": {
|
|
460
|
+
"allowed": true,
|
|
461
|
+
"host_agent_min_confidence": "medium",
|
|
462
|
+
"human_allowed": true,
|
|
463
|
+
"evidence_required": [
|
|
464
|
+
{
|
|
465
|
+
"field": "ui_states",
|
|
466
|
+
"description": "How loading, empty, and error states are rendered in the comment UI.",
|
|
467
|
+
"upload_policy": "upload-with-consent"
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
"id": "flutter.comments.ui-states-present",
|
|
475
|
+
"version": 1,
|
|
476
|
+
"title": "Flutter comment UI must handle loading, empty, and error states",
|
|
477
|
+
"severity": "warning",
|
|
478
|
+
"rationale": "Comments load asynchronously. Without state handling, users see blank screens or unhandled errors.",
|
|
479
|
+
"applies_when": {
|
|
480
|
+
"platforms": [
|
|
481
|
+
"flutter"
|
|
482
|
+
],
|
|
483
|
+
"outcomes": [
|
|
484
|
+
"add-comments",
|
|
485
|
+
"validate-setup"
|
|
486
|
+
]
|
|
487
|
+
},
|
|
488
|
+
"enforcement": {
|
|
489
|
+
"deterministic": [
|
|
490
|
+
{
|
|
491
|
+
"check": "validator-finding-absent",
|
|
492
|
+
"finding_rule_id": "flutter.comments.ui-states-present"
|
|
493
|
+
}
|
|
494
|
+
],
|
|
495
|
+
"attestation": {
|
|
496
|
+
"allowed": true,
|
|
497
|
+
"host_agent_min_confidence": "medium",
|
|
498
|
+
"human_allowed": true,
|
|
499
|
+
"evidence_required": [
|
|
500
|
+
{
|
|
501
|
+
"field": "ui_states",
|
|
502
|
+
"description": "How loading, empty, and error states are rendered in the comment UI.",
|
|
503
|
+
"upload_policy": "upload-with-consent"
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"id": "ios.comments.ui-states-present",
|
|
511
|
+
"version": 1,
|
|
512
|
+
"title": "iOS comment UI must handle loading, empty, and error states",
|
|
513
|
+
"severity": "warning",
|
|
514
|
+
"rationale": "Comments load asynchronously. Without state handling, users see blank screens or unhandled errors.",
|
|
515
|
+
"applies_when": {
|
|
516
|
+
"platforms": [
|
|
517
|
+
"ios"
|
|
518
|
+
],
|
|
519
|
+
"outcomes": [
|
|
520
|
+
"add-comments",
|
|
521
|
+
"validate-setup"
|
|
522
|
+
]
|
|
523
|
+
},
|
|
524
|
+
"enforcement": {
|
|
525
|
+
"deterministic": [
|
|
526
|
+
{
|
|
527
|
+
"check": "validator-finding-absent",
|
|
528
|
+
"finding_rule_id": "ios.comments.ui-states-present"
|
|
529
|
+
}
|
|
530
|
+
],
|
|
531
|
+
"attestation": {
|
|
532
|
+
"allowed": true,
|
|
533
|
+
"host_agent_min_confidence": "medium",
|
|
534
|
+
"human_allowed": true,
|
|
535
|
+
"evidence_required": [
|
|
536
|
+
{
|
|
537
|
+
"field": "ui_states",
|
|
538
|
+
"description": "How loading, empty, and error states are rendered in the comment UI.",
|
|
539
|
+
"upload_policy": "upload-with-consent"
|
|
540
|
+
}
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"id": "typescript.comments.moderation-affordance-present",
|
|
547
|
+
"version": 1,
|
|
548
|
+
"title": "TypeScript comment UI must include moderation affordance",
|
|
549
|
+
"severity": "warning",
|
|
550
|
+
"rationale": "Comments are user-generated content. Without moderation (report/block/hide), harmful content has no removal path.",
|
|
551
|
+
"applies_when": {
|
|
552
|
+
"platforms": [
|
|
553
|
+
"typescript"
|
|
554
|
+
],
|
|
555
|
+
"outcomes": [
|
|
556
|
+
"add-comments",
|
|
557
|
+
"validate-setup"
|
|
558
|
+
]
|
|
559
|
+
},
|
|
560
|
+
"enforcement": {
|
|
561
|
+
"deterministic": [
|
|
562
|
+
{
|
|
563
|
+
"check": "validator-finding-absent",
|
|
564
|
+
"finding_rule_id": "typescript.comments.moderation-affordance-present"
|
|
565
|
+
}
|
|
566
|
+
],
|
|
567
|
+
"attestation": {
|
|
568
|
+
"allowed": true,
|
|
569
|
+
"host_agent_min_confidence": "high",
|
|
570
|
+
"human_allowed": true,
|
|
571
|
+
"evidence_required": [
|
|
572
|
+
{
|
|
573
|
+
"field": "moderation_mechanism",
|
|
574
|
+
"description": "How users can report/block/hide comments.",
|
|
575
|
+
"upload_policy": "upload-with-consent"
|
|
576
|
+
}
|
|
577
|
+
]
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
"id": "react-native.comments.moderation-affordance-present",
|
|
583
|
+
"version": 1,
|
|
584
|
+
"title": "React Native comment UI must include moderation affordance",
|
|
585
|
+
"severity": "warning",
|
|
586
|
+
"rationale": "Comments are user-generated content. Without moderation (report/block/hide), harmful content has no removal path.",
|
|
587
|
+
"applies_when": {
|
|
588
|
+
"platforms": [
|
|
589
|
+
"react-native"
|
|
590
|
+
],
|
|
591
|
+
"outcomes": [
|
|
592
|
+
"add-comments",
|
|
593
|
+
"validate-setup"
|
|
594
|
+
]
|
|
595
|
+
},
|
|
596
|
+
"enforcement": {
|
|
597
|
+
"deterministic": [
|
|
598
|
+
{
|
|
599
|
+
"check": "validator-finding-absent",
|
|
600
|
+
"finding_rule_id": "react-native.comments.moderation-affordance-present"
|
|
601
|
+
}
|
|
602
|
+
],
|
|
603
|
+
"attestation": {
|
|
604
|
+
"allowed": true,
|
|
605
|
+
"host_agent_min_confidence": "high",
|
|
606
|
+
"human_allowed": true,
|
|
607
|
+
"evidence_required": [
|
|
608
|
+
{
|
|
609
|
+
"field": "moderation_mechanism",
|
|
610
|
+
"description": "How users can report/block/hide comments.",
|
|
611
|
+
"upload_policy": "upload-with-consent"
|
|
612
|
+
}
|
|
613
|
+
]
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
"id": "android.comments.moderation-affordance-present",
|
|
619
|
+
"version": 1,
|
|
620
|
+
"title": "Android comment UI must include moderation affordance",
|
|
621
|
+
"severity": "warning",
|
|
622
|
+
"rationale": "Comments are user-generated content. Without moderation (report/block/hide), harmful content has no removal path.",
|
|
623
|
+
"applies_when": {
|
|
624
|
+
"platforms": [
|
|
625
|
+
"android"
|
|
626
|
+
],
|
|
627
|
+
"outcomes": [
|
|
628
|
+
"add-comments",
|
|
629
|
+
"validate-setup"
|
|
630
|
+
]
|
|
631
|
+
},
|
|
632
|
+
"enforcement": {
|
|
633
|
+
"deterministic": [
|
|
634
|
+
{
|
|
635
|
+
"check": "validator-finding-absent",
|
|
636
|
+
"finding_rule_id": "android.comments.moderation-affordance-present"
|
|
637
|
+
}
|
|
638
|
+
],
|
|
639
|
+
"attestation": {
|
|
640
|
+
"allowed": true,
|
|
641
|
+
"host_agent_min_confidence": "high",
|
|
642
|
+
"human_allowed": true,
|
|
643
|
+
"evidence_required": [
|
|
644
|
+
{
|
|
645
|
+
"field": "moderation_mechanism",
|
|
646
|
+
"description": "How users can report/block/hide comments.",
|
|
647
|
+
"upload_policy": "upload-with-consent"
|
|
648
|
+
}
|
|
649
|
+
]
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
"id": "flutter.comments.moderation-affordance-present",
|
|
655
|
+
"version": 1,
|
|
656
|
+
"title": "Flutter comment UI must include moderation affordance",
|
|
657
|
+
"severity": "warning",
|
|
658
|
+
"rationale": "Comments are user-generated content. Without moderation (report/block/hide), harmful content has no removal path.",
|
|
659
|
+
"applies_when": {
|
|
660
|
+
"platforms": [
|
|
661
|
+
"flutter"
|
|
662
|
+
],
|
|
663
|
+
"outcomes": [
|
|
664
|
+
"add-comments",
|
|
665
|
+
"validate-setup"
|
|
666
|
+
]
|
|
667
|
+
},
|
|
668
|
+
"enforcement": {
|
|
669
|
+
"deterministic": [
|
|
670
|
+
{
|
|
671
|
+
"check": "validator-finding-absent",
|
|
672
|
+
"finding_rule_id": "flutter.comments.moderation-affordance-present"
|
|
673
|
+
}
|
|
674
|
+
],
|
|
675
|
+
"attestation": {
|
|
676
|
+
"allowed": true,
|
|
677
|
+
"host_agent_min_confidence": "high",
|
|
678
|
+
"human_allowed": true,
|
|
679
|
+
"evidence_required": [
|
|
680
|
+
{
|
|
681
|
+
"field": "moderation_mechanism",
|
|
682
|
+
"description": "How users can report/block/hide comments.",
|
|
683
|
+
"upload_policy": "upload-with-consent"
|
|
684
|
+
}
|
|
685
|
+
]
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"id": "ios.comments.moderation-affordance-present",
|
|
691
|
+
"version": 1,
|
|
692
|
+
"title": "iOS comment UI must include moderation affordance",
|
|
693
|
+
"severity": "warning",
|
|
694
|
+
"rationale": "Comments are user-generated content. Without moderation (report/block/hide), harmful content has no removal path.",
|
|
695
|
+
"applies_when": {
|
|
696
|
+
"platforms": [
|
|
697
|
+
"ios"
|
|
698
|
+
],
|
|
699
|
+
"outcomes": [
|
|
700
|
+
"add-comments",
|
|
701
|
+
"validate-setup"
|
|
702
|
+
]
|
|
703
|
+
},
|
|
704
|
+
"enforcement": {
|
|
705
|
+
"deterministic": [
|
|
706
|
+
{
|
|
707
|
+
"check": "validator-finding-absent",
|
|
708
|
+
"finding_rule_id": "ios.comments.moderation-affordance-present"
|
|
709
|
+
}
|
|
710
|
+
],
|
|
711
|
+
"attestation": {
|
|
712
|
+
"allowed": true,
|
|
713
|
+
"host_agent_min_confidence": "high",
|
|
714
|
+
"human_allowed": true,
|
|
715
|
+
"evidence_required": [
|
|
716
|
+
{
|
|
717
|
+
"field": "moderation_mechanism",
|
|
718
|
+
"description": "How users can report/block/hide comments.",
|
|
719
|
+
"upload_policy": "upload-with-consent"
|
|
720
|
+
}
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
"id": "typescript.comment.reference-type-enum",
|
|
727
|
+
"version": 1,
|
|
728
|
+
"title": "TypeScript comment reference type must be enum",
|
|
729
|
+
"severity": "warning",
|
|
730
|
+
"rationale": "Comment reference types (e.g., Post, Article) are typed as enums in most SDKs. Using raw strings bypasses type checking and causes silent failures if the server expects a specific casing.",
|
|
731
|
+
"applies_when": {
|
|
732
|
+
"platforms": [
|
|
733
|
+
"typescript"
|
|
734
|
+
],
|
|
735
|
+
"outcomes": [
|
|
736
|
+
"add-comment",
|
|
737
|
+
"validate-setup"
|
|
738
|
+
]
|
|
739
|
+
},
|
|
740
|
+
"enforcement": {
|
|
741
|
+
"deterministic": [
|
|
742
|
+
{
|
|
743
|
+
"check": "validator-finding-absent",
|
|
744
|
+
"finding_rule_id": "typescript.comment.reference-type-enum"
|
|
745
|
+
}
|
|
746
|
+
],
|
|
747
|
+
"attestation": {
|
|
748
|
+
"allowed": true,
|
|
749
|
+
"host_agent_min_confidence": "high",
|
|
750
|
+
"human_allowed": true,
|
|
751
|
+
"evidence_required": [
|
|
752
|
+
{
|
|
753
|
+
"field": "reference_type_source",
|
|
754
|
+
"description": "How reference types are strongly typed.",
|
|
755
|
+
"upload_policy": "upload-with-consent"
|
|
756
|
+
}
|
|
757
|
+
]
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
"id": "react-native.comment.reference-type-enum",
|
|
763
|
+
"version": 1,
|
|
764
|
+
"title": "React Native comment reference type must be enum",
|
|
765
|
+
"severity": "warning",
|
|
766
|
+
"rationale": "Comment reference types (e.g., Post, Article) are typed as enums in most SDKs. Using raw strings bypasses type checking and causes silent failures if the server expects a specific casing.",
|
|
767
|
+
"applies_when": {
|
|
768
|
+
"platforms": [
|
|
769
|
+
"react-native"
|
|
770
|
+
],
|
|
771
|
+
"outcomes": [
|
|
772
|
+
"add-comment",
|
|
773
|
+
"validate-setup"
|
|
774
|
+
]
|
|
775
|
+
},
|
|
776
|
+
"enforcement": {
|
|
777
|
+
"deterministic": [
|
|
778
|
+
{
|
|
779
|
+
"check": "validator-finding-absent",
|
|
780
|
+
"finding_rule_id": "react-native.comment.reference-type-enum"
|
|
781
|
+
}
|
|
782
|
+
],
|
|
783
|
+
"attestation": {
|
|
784
|
+
"allowed": true,
|
|
785
|
+
"host_agent_min_confidence": "high",
|
|
786
|
+
"human_allowed": true,
|
|
787
|
+
"evidence_required": [
|
|
788
|
+
{
|
|
789
|
+
"field": "reference_type_source",
|
|
790
|
+
"description": "How reference types are strongly typed.",
|
|
791
|
+
"upload_policy": "upload-with-consent"
|
|
792
|
+
}
|
|
793
|
+
]
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
"id": "android.comment.reference-type-enum",
|
|
799
|
+
"version": 1,
|
|
800
|
+
"title": "Android comment reference type must be enum",
|
|
801
|
+
"severity": "warning",
|
|
802
|
+
"rationale": "Comment reference types (e.g., Post, Article) are typed as enums in most SDKs. Using raw strings bypasses type checking and causes silent failures if the server expects a specific casing.",
|
|
803
|
+
"applies_when": {
|
|
804
|
+
"platforms": [
|
|
805
|
+
"android"
|
|
806
|
+
],
|
|
807
|
+
"outcomes": [
|
|
808
|
+
"add-comment",
|
|
809
|
+
"validate-setup"
|
|
810
|
+
]
|
|
811
|
+
},
|
|
812
|
+
"enforcement": {
|
|
813
|
+
"deterministic": [
|
|
814
|
+
{
|
|
815
|
+
"check": "validator-finding-absent",
|
|
816
|
+
"finding_rule_id": "android.comment.reference-type-enum"
|
|
817
|
+
}
|
|
818
|
+
],
|
|
819
|
+
"attestation": {
|
|
820
|
+
"allowed": true,
|
|
821
|
+
"host_agent_min_confidence": "high",
|
|
822
|
+
"human_allowed": true,
|
|
823
|
+
"evidence_required": [
|
|
824
|
+
{
|
|
825
|
+
"field": "reference_type_source",
|
|
826
|
+
"description": "How reference types are strongly typed.",
|
|
827
|
+
"upload_policy": "upload-with-consent"
|
|
828
|
+
}
|
|
829
|
+
]
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
"id": "flutter.comment.reference-type-enum",
|
|
835
|
+
"version": 1,
|
|
836
|
+
"title": "Flutter comment reference type must be enum",
|
|
837
|
+
"severity": "warning",
|
|
838
|
+
"rationale": "Comment reference types (e.g., Post, Article) are typed as enums in most SDKs. Using raw strings bypasses type checking and causes silent failures if the server expects a specific casing.",
|
|
839
|
+
"applies_when": {
|
|
840
|
+
"platforms": [
|
|
841
|
+
"flutter"
|
|
842
|
+
],
|
|
843
|
+
"outcomes": [
|
|
844
|
+
"add-comment",
|
|
845
|
+
"validate-setup"
|
|
846
|
+
]
|
|
847
|
+
},
|
|
848
|
+
"enforcement": {
|
|
849
|
+
"deterministic": [
|
|
850
|
+
{
|
|
851
|
+
"check": "validator-finding-absent",
|
|
852
|
+
"finding_rule_id": "flutter.comment.reference-type-enum"
|
|
853
|
+
}
|
|
854
|
+
],
|
|
855
|
+
"attestation": {
|
|
856
|
+
"allowed": true,
|
|
857
|
+
"host_agent_min_confidence": "high",
|
|
858
|
+
"human_allowed": true,
|
|
859
|
+
"evidence_required": [
|
|
860
|
+
{
|
|
861
|
+
"field": "reference_type_source",
|
|
862
|
+
"description": "How reference types are strongly typed.",
|
|
863
|
+
"upload_policy": "upload-with-consent"
|
|
864
|
+
}
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
"id": "ios.comment.reference-type-enum",
|
|
871
|
+
"version": 1,
|
|
872
|
+
"title": "iOS comment reference type must be enum",
|
|
873
|
+
"severity": "warning",
|
|
874
|
+
"rationale": "Comment reference types (e.g., Post, Article) are typed as enums in most SDKs. Using raw strings bypasses type checking and causes silent failures if the server expects a specific casing.",
|
|
875
|
+
"applies_when": {
|
|
876
|
+
"platforms": [
|
|
877
|
+
"ios"
|
|
878
|
+
],
|
|
879
|
+
"outcomes": [
|
|
880
|
+
"add-comment",
|
|
881
|
+
"validate-setup"
|
|
882
|
+
]
|
|
883
|
+
},
|
|
884
|
+
"enforcement": {
|
|
885
|
+
"deterministic": [
|
|
886
|
+
{
|
|
887
|
+
"check": "validator-finding-absent",
|
|
888
|
+
"finding_rule_id": "ios.comment.reference-type-enum"
|
|
889
|
+
}
|
|
890
|
+
],
|
|
891
|
+
"attestation": {
|
|
892
|
+
"allowed": true,
|
|
893
|
+
"host_agent_min_confidence": "high",
|
|
894
|
+
"human_allowed": true,
|
|
895
|
+
"evidence_required": [
|
|
896
|
+
{
|
|
897
|
+
"field": "reference_type_source",
|
|
898
|
+
"description": "How reference types are strongly typed.",
|
|
899
|
+
"upload_policy": "upload-with-consent"
|
|
900
|
+
}
|
|
901
|
+
]
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
]
|
|
906
|
+
}
|