@amityco/social-plus-vise 1.5.0 → 1.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.
@@ -0,0 +1,136 @@
1
+ {
2
+ "domain": "channel-archive",
3
+ "schema_version": 1,
4
+ "rules": [
5
+ {
6
+ "id": "typescript.channel-archive.live-collection",
7
+ "version": 1,
8
+ "symbol_anchored": { "platform": "typescript", "types": ["ChannelRepository"], "members": ["getArchivedChannels"], "basis": "names-only" },
9
+ "title": "TypeScript archived-channels view should use the reactive getArchivedChannels LiveCollection",
10
+ "severity": "warning",
11
+ "rationale": "The archived-channels list is a Live Collection — it updates as channels are archived/unarchived. A one-shot getArchivedChannelIds fetch (or getArchivedChannels with no callback) renders a list that never updates. Pass the live callback: ChannelRepository.getArchivedChannels(params, callback).",
12
+ "applies_when": {
13
+ "platforms": ["typescript"],
14
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
15
+ },
16
+ "enforcement": {
17
+ "deterministic": [
18
+ { "check": "validator-finding-absent", "finding_rule_id": "typescript.channel-archive.live-collection" }
19
+ ],
20
+ "attestation": {
21
+ "allowed": true,
22
+ "host_agent_min_confidence": "high",
23
+ "human_allowed": true,
24
+ "evidence_required": [
25
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating archived-channels list is appropriate here.", "upload_policy": "upload-with-consent" }
26
+ ]
27
+ }
28
+ },
29
+ "symptoms": ["Archived channels list never updates", "Archive/unarchive not reflected"]
30
+ },
31
+ {
32
+ "id": "react-native.channel-archive.live-collection",
33
+ "version": 1,
34
+ "symbol_anchored": { "platform": "react-native", "types": ["ChannelRepository"], "members": ["getArchivedChannels"], "basis": "names-only" },
35
+ "title": "React Native archived-channels view should use the reactive getArchivedChannels LiveCollection",
36
+ "severity": "warning",
37
+ "rationale": "The archived-channels list is a Live Collection — it updates as channels are archived/unarchived. A one-shot getArchivedChannelIds fetch (or getArchivedChannels with no callback) renders a list that never updates. Pass the live callback: ChannelRepository.getArchivedChannels(params, callback).",
38
+ "applies_when": {
39
+ "platforms": ["react-native"],
40
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
41
+ },
42
+ "enforcement": {
43
+ "deterministic": [
44
+ { "check": "validator-finding-absent", "finding_rule_id": "react-native.channel-archive.live-collection" }
45
+ ],
46
+ "attestation": {
47
+ "allowed": true,
48
+ "host_agent_min_confidence": "high",
49
+ "human_allowed": true,
50
+ "evidence_required": [
51
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating archived-channels list is appropriate here.", "upload_policy": "upload-with-consent" }
52
+ ]
53
+ }
54
+ },
55
+ "symptoms": ["Archived channels list never updates", "Archive/unarchive not reflected"]
56
+ },
57
+ {
58
+ "id": "android.channel-archive.live-collection",
59
+ "version": 1,
60
+ "symbol_anchored": { "platform": "android", "types": ["AmityChannelRepository"], "members": ["getArchivedChannels"], "basis": "names-only" },
61
+ "title": "Android archived-channels view should use the reactive getArchivedChannels LiveCollection",
62
+ "severity": "warning",
63
+ "rationale": "The archived-channels list is a Live Collection — it updates as channels are archived/unarchived. A one-shot fetch renders a list that never updates. Observe the PagingData stream: AmityChannelRepository.getArchivedChannels().doOnNext { _: PagingData<AmityChannel> -> }.subscribe().",
64
+ "applies_when": {
65
+ "platforms": ["android"],
66
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
67
+ },
68
+ "enforcement": {
69
+ "deterministic": [
70
+ { "check": "validator-finding-absent", "finding_rule_id": "android.channel-archive.live-collection" }
71
+ ],
72
+ "attestation": {
73
+ "allowed": true,
74
+ "host_agent_min_confidence": "high",
75
+ "human_allowed": true,
76
+ "evidence_required": [
77
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating archived-channels list is appropriate here.", "upload_policy": "upload-with-consent" }
78
+ ]
79
+ }
80
+ },
81
+ "symptoms": ["Archived channels list never updates", "Archive/unarchive not reflected"]
82
+ },
83
+ {
84
+ "id": "ios.channel-archive.live-collection",
85
+ "version": 1,
86
+ "symbol_anchored": { "platform": "ios", "types": ["AmityChannelRepository"], "members": ["getArchivedChannels"], "basis": "names-only" },
87
+ "title": "iOS archived-channels view should use the reactive getArchivedChannels LiveCollection",
88
+ "severity": "warning",
89
+ "rationale": "The archived-channels list is a Live Collection — it updates as channels are archived/unarchived. A one-shot completion handler renders a list that never updates. Observe the collection: amityChannelRepository.getArchivedChannels() then .observe on the returned collection.",
90
+ "applies_when": {
91
+ "platforms": ["ios"],
92
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
93
+ },
94
+ "enforcement": {
95
+ "deterministic": [
96
+ { "check": "validator-finding-absent", "finding_rule_id": "ios.channel-archive.live-collection" }
97
+ ],
98
+ "attestation": {
99
+ "allowed": true,
100
+ "host_agent_min_confidence": "high",
101
+ "human_allowed": true,
102
+ "evidence_required": [
103
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating archived-channels list is appropriate here.", "upload_policy": "upload-with-consent" }
104
+ ]
105
+ }
106
+ },
107
+ "symptoms": ["Archived channels list never updates", "Archive/unarchive not reflected"]
108
+ },
109
+ {
110
+ "id": "flutter.channel-archive.live-collection",
111
+ "version": 1,
112
+ "symbol_anchored": { "platform": "flutter", "types": ["AmityChannelRepository"], "members": ["getArchivedChannels"], "basis": "names-only" },
113
+ "title": "Flutter archived-channels view should use the reactive getArchivedChannels LiveCollection",
114
+ "severity": "warning",
115
+ "rationale": "The archived-channels list is a Live Collection — it updates as channels are archived/unarchived. A one-shot fetch renders a list that never updates. Wire a PagingController over getArchivedChannels: PagingController(pageFuture: (token) => ...getArchivedChannels().getPagingData(token: token, limit: 20)).",
116
+ "applies_when": {
117
+ "platforms": ["flutter"],
118
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
119
+ },
120
+ "enforcement": {
121
+ "deterministic": [
122
+ { "check": "validator-finding-absent", "finding_rule_id": "flutter.channel-archive.live-collection" }
123
+ ],
124
+ "attestation": {
125
+ "allowed": true,
126
+ "host_agent_min_confidence": "high",
127
+ "human_allowed": true,
128
+ "evidence_required": [
129
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating archived-channels list is appropriate here.", "upload_policy": "upload-with-consent" }
130
+ ]
131
+ }
132
+ },
133
+ "symptoms": ["Archived channels list never updates", "Archive/unarchive not reflected"]
134
+ }
135
+ ]
136
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "domain": "for-you-feed",
3
+ "schema_version": 1,
4
+ "rules": [
5
+ {
6
+ "id": "typescript.for-you-feed.live-collection",
7
+ "version": 1,
8
+ "symbol_anchored": { "platform": "typescript", "types": ["FeedRepository"], "members": ["getForYouFeed"], "basis": "names-only" },
9
+ "title": "TypeScript For-You feed should use the reactive getForYouFeed LiveCollection",
10
+ "severity": "warning",
11
+ "rationale": "The personalized For-You feed is a Live Collection — it updates as ranking and freshness change. A one-shot fetch-and-map renders a stale feed. Pass the live callback: FeedRepository.getForYouFeed(params, callback). Gate on getForYouFeedSetting and fall back to the global feed when For-You is disabled (AmityForYouFeedDisabledError).",
12
+ "applies_when": {
13
+ "platforms": ["typescript"],
14
+ "outcomes": ["add-feed", "setup-live-data", "validate-setup"]
15
+ },
16
+ "enforcement": {
17
+ "deterministic": [
18
+ { "check": "validator-finding-absent", "finding_rule_id": "typescript.for-you-feed.live-collection" }
19
+ ],
20
+ "attestation": {
21
+ "allowed": true,
22
+ "host_agent_min_confidence": "high",
23
+ "human_allowed": true,
24
+ "evidence_required": [
25
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating For-You feed is appropriate here.", "upload_policy": "upload-with-consent" }
26
+ ]
27
+ }
28
+ },
29
+ "symptoms": ["For-You feed never updates", "Stale personalized ranking"]
30
+ },
31
+ {
32
+ "id": "react-native.for-you-feed.live-collection",
33
+ "version": 1,
34
+ "symbol_anchored": { "platform": "react-native", "types": ["FeedRepository"], "members": ["getForYouFeed"], "basis": "names-only" },
35
+ "title": "React Native For-You feed should use the reactive getForYouFeed LiveCollection",
36
+ "severity": "warning",
37
+ "rationale": "The personalized For-You feed is a Live Collection — it updates as ranking and freshness change. A one-shot fetch-and-map renders a stale feed. Pass the live callback: FeedRepository.getForYouFeed(params, callback). Gate on getForYouFeedSetting and fall back to the global feed when For-You is disabled (AmityForYouFeedDisabledError).",
38
+ "applies_when": {
39
+ "platforms": ["react-native"],
40
+ "outcomes": ["add-feed", "setup-live-data", "validate-setup"]
41
+ },
42
+ "enforcement": {
43
+ "deterministic": [
44
+ { "check": "validator-finding-absent", "finding_rule_id": "react-native.for-you-feed.live-collection" }
45
+ ],
46
+ "attestation": {
47
+ "allowed": true,
48
+ "host_agent_min_confidence": "high",
49
+ "human_allowed": true,
50
+ "evidence_required": [
51
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating For-You feed is appropriate here.", "upload_policy": "upload-with-consent" }
52
+ ]
53
+ }
54
+ },
55
+ "symptoms": ["For-You feed never updates", "Stale personalized ranking"]
56
+ },
57
+ {
58
+ "id": "android.for-you-feed.live-collection",
59
+ "version": 1,
60
+ "symbol_anchored": { "platform": "android", "types": ["AmityFeedRepository"], "members": ["getForYouFeed"], "basis": "names-only" },
61
+ "title": "Android For-You feed should use the reactive getForYouFeed LiveCollection",
62
+ "severity": "warning",
63
+ "rationale": "The personalized For-You feed is a Live Collection — it updates as ranking and freshness change. A one-shot fetch renders a stale feed. Observe the PagingData stream: AmityFeedRepository.getForYouFeed().doOnNext { _: PagingData<AmityPost> -> }.subscribe(). Gate on getForYouFeedSetting and fall back to the global feed when disabled.",
64
+ "applies_when": {
65
+ "platforms": ["android"],
66
+ "outcomes": ["add-feed", "setup-live-data", "validate-setup"]
67
+ },
68
+ "enforcement": {
69
+ "deterministic": [
70
+ { "check": "validator-finding-absent", "finding_rule_id": "android.for-you-feed.live-collection" }
71
+ ],
72
+ "attestation": {
73
+ "allowed": true,
74
+ "host_agent_min_confidence": "high",
75
+ "human_allowed": true,
76
+ "evidence_required": [
77
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating For-You feed is appropriate here.", "upload_policy": "upload-with-consent" }
78
+ ]
79
+ }
80
+ },
81
+ "symptoms": ["For-You feed never updates", "Stale personalized ranking"]
82
+ },
83
+ {
84
+ "id": "ios.for-you-feed.live-collection",
85
+ "version": 1,
86
+ "symbol_anchored": { "platform": "ios", "types": ["AmityFeedRepository"], "members": ["getForYouFeed"], "basis": "names-only" },
87
+ "title": "iOS For-You feed should use the reactive getForYouFeed LiveCollection",
88
+ "severity": "warning",
89
+ "rationale": "The personalized For-You feed is a Live Collection — it updates as ranking and freshness change. A one-shot completion handler renders a stale feed. Observe the collection: amityFeedRepository.getForYouFeed() then .observe. Gate on getForYouFeedSetting and fall back to the global feed when disabled (forYouFeedDisabled).",
90
+ "applies_when": {
91
+ "platforms": ["ios"],
92
+ "outcomes": ["add-feed", "setup-live-data", "validate-setup"]
93
+ },
94
+ "enforcement": {
95
+ "deterministic": [
96
+ { "check": "validator-finding-absent", "finding_rule_id": "ios.for-you-feed.live-collection" }
97
+ ],
98
+ "attestation": {
99
+ "allowed": true,
100
+ "host_agent_min_confidence": "high",
101
+ "human_allowed": true,
102
+ "evidence_required": [
103
+ { "field": "query_lifetime", "description": "Why a one-shot, non-updating For-You feed is appropriate here.", "upload_policy": "upload-with-consent" }
104
+ ]
105
+ }
106
+ },
107
+ "symptoms": ["For-You feed never updates", "Stale personalized ranking"]
108
+ }
109
+ ]
110
+ }
@@ -0,0 +1,136 @@
1
+ {
2
+ "domain": "message-search",
3
+ "schema_version": 1,
4
+ "rules": [
5
+ {
6
+ "id": "typescript.message-search.live-collection",
7
+ "version": 1,
8
+ "symbol_anchored": { "platform": "typescript", "types": ["MessageRepository"], "members": ["searchMessage"], "basis": "names-only" },
9
+ "title": "TypeScript message search should use the reactive, paginated Search Message LiveCollection",
10
+ "severity": "warning",
11
+ "rationale": "In-chat message search is a paginated Live Collection. A one-shot searchMessage (no callback) renders only the first page and never updates as messages arrive or sync. Pass the live callback: MessageRepository.searchMessage(params, callback).",
12
+ "applies_when": {
13
+ "platforms": ["typescript"],
14
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
15
+ },
16
+ "enforcement": {
17
+ "deterministic": [
18
+ { "check": "validator-finding-absent", "finding_rule_id": "typescript.message-search.live-collection" }
19
+ ],
20
+ "attestation": {
21
+ "allowed": true,
22
+ "host_agent_min_confidence": "high",
23
+ "human_allowed": true,
24
+ "evidence_required": [
25
+ { "field": "query_lifetime", "description": "Why a one-shot, single-page message search is appropriate here.", "upload_policy": "upload-with-consent" }
26
+ ]
27
+ }
28
+ },
29
+ "symptoms": ["Message search shows only first page", "Stale message-search results"]
30
+ },
31
+ {
32
+ "id": "react-native.message-search.live-collection",
33
+ "version": 1,
34
+ "symbol_anchored": { "platform": "react-native", "types": ["MessageRepository"], "members": ["searchMessage"], "basis": "names-only" },
35
+ "title": "React Native message search should use the reactive, paginated Search Message LiveCollection",
36
+ "severity": "warning",
37
+ "rationale": "In-chat message search is a paginated Live Collection. A one-shot searchMessage (no callback) renders only the first page and never updates as messages arrive or sync. Pass the live callback: MessageRepository.searchMessage(params, callback).",
38
+ "applies_when": {
39
+ "platforms": ["react-native"],
40
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
41
+ },
42
+ "enforcement": {
43
+ "deterministic": [
44
+ { "check": "validator-finding-absent", "finding_rule_id": "react-native.message-search.live-collection" }
45
+ ],
46
+ "attestation": {
47
+ "allowed": true,
48
+ "host_agent_min_confidence": "high",
49
+ "human_allowed": true,
50
+ "evidence_required": [
51
+ { "field": "query_lifetime", "description": "Why a one-shot, single-page message search is appropriate here.", "upload_policy": "upload-with-consent" }
52
+ ]
53
+ }
54
+ },
55
+ "symptoms": ["Message search shows only first page", "Stale message-search results"]
56
+ },
57
+ {
58
+ "id": "android.message-search.live-collection",
59
+ "version": 1,
60
+ "symbol_anchored": { "platform": "android", "types": ["AmityMessageRepository"], "members": ["searchMessages"], "basis": "names-only" },
61
+ "title": "Android message search should use the reactive, paginated Search Message LiveCollection",
62
+ "severity": "warning",
63
+ "rationale": "In-chat message search is a paginated Live Collection. A one-shot fetch renders only the first page and never updates. Observe the PagingData stream: AmityMessageRepository.searchMessages(...).doOnNext { _: PagingData<AmityMessage> -> }.subscribe().",
64
+ "applies_when": {
65
+ "platforms": ["android"],
66
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
67
+ },
68
+ "enforcement": {
69
+ "deterministic": [
70
+ { "check": "validator-finding-absent", "finding_rule_id": "android.message-search.live-collection" }
71
+ ],
72
+ "attestation": {
73
+ "allowed": true,
74
+ "host_agent_min_confidence": "high",
75
+ "human_allowed": true,
76
+ "evidence_required": [
77
+ { "field": "query_lifetime", "description": "Why a one-shot, single-page message search is appropriate here.", "upload_policy": "upload-with-consent" }
78
+ ]
79
+ }
80
+ },
81
+ "symptoms": ["Message search shows only first page", "Stale message-search results"]
82
+ },
83
+ {
84
+ "id": "ios.message-search.live-collection",
85
+ "version": 1,
86
+ "symbol_anchored": { "platform": "ios", "types": ["AmityMessageRepository"], "members": ["searchMessages"], "basis": "names-only" },
87
+ "title": "iOS message search should use the reactive, paginated Search Message LiveCollection",
88
+ "severity": "warning",
89
+ "rationale": "In-chat message search is a paginated Live Collection. A one-shot completion handler renders only the first page and never updates. Observe the collection: amityMessageRepository.searchMessages(options:) then .observe on the returned collection.",
90
+ "applies_when": {
91
+ "platforms": ["ios"],
92
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
93
+ },
94
+ "enforcement": {
95
+ "deterministic": [
96
+ { "check": "validator-finding-absent", "finding_rule_id": "ios.message-search.live-collection" }
97
+ ],
98
+ "attestation": {
99
+ "allowed": true,
100
+ "host_agent_min_confidence": "high",
101
+ "human_allowed": true,
102
+ "evidence_required": [
103
+ { "field": "query_lifetime", "description": "Why a one-shot, single-page message search is appropriate here.", "upload_policy": "upload-with-consent" }
104
+ ]
105
+ }
106
+ },
107
+ "symptoms": ["Message search shows only first page", "Stale message-search results"]
108
+ },
109
+ {
110
+ "id": "flutter.message-search.live-collection",
111
+ "version": 1,
112
+ "symbol_anchored": { "platform": "flutter", "types": ["MessageRepository"], "members": ["searchMessage"], "basis": "names-only" },
113
+ "title": "Flutter message search should use the reactive, paginated Search Message LiveCollection",
114
+ "severity": "warning",
115
+ "rationale": "In-chat message search is a paginated Live Collection. A one-shot fetch renders only the first page and never updates. Wire a PagingController over the SearchMessageLiveCollection: PagingController(pageFuture: (token) => messageRepository.searchMessage(...).getPagingData(token: token, limit: 20)).",
116
+ "applies_when": {
117
+ "platforms": ["flutter"],
118
+ "outcomes": ["add-chat", "setup-live-data", "validate-setup"]
119
+ },
120
+ "enforcement": {
121
+ "deterministic": [
122
+ { "check": "validator-finding-absent", "finding_rule_id": "flutter.message-search.live-collection" }
123
+ ],
124
+ "attestation": {
125
+ "allowed": true,
126
+ "host_agent_min_confidence": "high",
127
+ "human_allowed": true,
128
+ "evidence_required": [
129
+ { "field": "query_lifetime", "description": "Why a one-shot, single-page message search is appropriate here.", "upload_policy": "upload-with-consent" }
130
+ ]
131
+ }
132
+ },
133
+ "symptoms": ["Message search shows only first page", "Stale message-search results"]
134
+ }
135
+ ]
136
+ }