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