@firedrill-tools/slack 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +369 -0
  3. package/firedrill/agent.target.json +17 -0
  4. package/firedrill/baseline.scenario.json +5 -0
  5. package/firedrill/bounds.scenario.json +112 -0
  6. package/firedrill/conformance.suite.json +21 -0
  7. package/firedrill/history-unavailable.scenario.json +11 -0
  8. package/firedrill/open-long-handles.scenario.json +263 -0
  9. package/firedrill/open-member-bound.scenario.json +24 -0
  10. package/firedrill/post-rate-limited.scenario.json +11 -0
  11. package/firedrill/response-budget.scenario.json +24 -0
  12. package/firedrill/slack-bounds.drill.json +428 -0
  13. package/firedrill/slack-denied.drill.json +74 -0
  14. package/firedrill/slack-fresh-install.drill.json +132 -0
  15. package/firedrill/slack-history-unavailable.drill.json +83 -0
  16. package/firedrill/slack-invalid-auth.drill.json +408 -0
  17. package/firedrill/slack-mcp-aliases.drill.json +219 -0
  18. package/firedrill/slack-open-long-handles.drill.json +82 -0
  19. package/firedrill/slack-open-member-bound.drill.json +135 -0
  20. package/firedrill/slack-post-rate-limited.drill.json +96 -0
  21. package/firedrill/slack-response-budget.drill.json +118 -0
  22. package/firedrill/slack-thread-many-repliers.drill.json +100 -0
  23. package/firedrill/slack-ts-sequence-full.drill.json +165 -0
  24. package/firedrill/slack-visibility.drill.json +110 -0
  25. package/firedrill/slack-web-api-flow.drill.json +896 -0
  26. package/firedrill/thread-many-repliers.scenario.json +79 -0
  27. package/firedrill/tools/slack/app/assets/ATTRIBUTION.md +40 -0
  28. package/firedrill/tools/slack/app/assets/fonts/OFL.txt +93 -0
  29. package/firedrill/tools/slack/app/assets/fonts/lato-latin-400.woff2 +0 -0
  30. package/firedrill/tools/slack/app/assets/fonts/lato-latin-700.woff2 +0 -0
  31. package/firedrill/tools/slack/app/assets/fonts/lato-latin-900.woff2 +0 -0
  32. package/firedrill/tools/slack/app/assets/slack-wordmark.svg +1 -0
  33. package/firedrill/tools/slack/app/assets/slack.svg +1 -0
  34. package/firedrill/tools/slack/app/site/app.js +2202 -0
  35. package/firedrill/tools/slack/app/site/assets/fonts/lato-latin-400.woff2 +0 -0
  36. package/firedrill/tools/slack/app/site/assets/fonts/lato-latin-700.woff2 +0 -0
  37. package/firedrill/tools/slack/app/site/assets/fonts/lato-latin-900.woff2 +0 -0
  38. package/firedrill/tools/slack/app/site/assets/slack-wordmark.svg +1 -0
  39. package/firedrill/tools/slack/app/site/assets/slack.svg +1 -0
  40. package/firedrill/tools/slack/app/site/chrome.css +73 -0
  41. package/firedrill/tools/slack/app/site/chrome.js +96 -0
  42. package/firedrill/tools/slack/app/site/icons.js +96 -0
  43. package/firedrill/tools/slack/app/site/index.html +253 -0
  44. package/firedrill/tools/slack/app/site/styles.css +2719 -0
  45. package/firedrill/tools/slack/app/site/ui.js +491 -0
  46. package/firedrill/tools/slack/behavior.mjs +1171 -0
  47. package/firedrill/tools/slack/lib/access.mjs +138 -0
  48. package/firedrill/tools/slack/lib/budget.mjs +67 -0
  49. package/firedrill/tools/slack/lib/ids.mjs +146 -0
  50. package/firedrill/tools/slack/lib/search.mjs +172 -0
  51. package/firedrill/tools/slack/lib/wire.mjs +144 -0
  52. package/firedrill/tools/slack/slack.tool.json +6114 -0
  53. package/firedrill/ts-sequence-full.scenario.json +38 -0
  54. package/firedrill/world.json +2008 -0
  55. package/firedrill.json +5 -0
  56. package/package.json +62 -0
  57. package/starter.json +1562 -0
  58. package/test/conformance.mjs +1166 -0
@@ -0,0 +1,135 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "slack-open-member-bound",
4
+ "title": "conversations.open over the member bound answers 400 too_many_rows naming no conversation id and stores nothing; the ids it would have used go to the next IM and channel",
5
+ "targetId": "conformance-agent",
6
+ "scenarioId": "open-member-bound",
7
+ "actorId": "member",
8
+ "task": {
9
+ "instruction": "Run the open-member-bound conformance flow against the synthetic Slack Tool and fail loudly on any unexpected status or body."
10
+ },
11
+ "assertions": [
12
+ {
13
+ "id": "open-refused",
14
+ "kind": "operation.count",
15
+ "operation": {
16
+ "packageId": "slack",
17
+ "operationId": "conversations.open"
18
+ },
19
+ "outcomes": [
20
+ "tool_error"
21
+ ],
22
+ "comparison": {
23
+ "operator": "equals",
24
+ "value": 2
25
+ }
26
+ },
27
+ {
28
+ "id": "open-ok",
29
+ "kind": "operation.count",
30
+ "operation": {
31
+ "packageId": "slack",
32
+ "operationId": "conversations.open"
33
+ },
34
+ "outcomes": [
35
+ "ok"
36
+ ],
37
+ "comparison": {
38
+ "operator": "equals",
39
+ "value": 1
40
+ }
41
+ },
42
+ {
43
+ "id": "info-of-unallocated-id-not-found",
44
+ "kind": "operation.count",
45
+ "operation": {
46
+ "packageId": "slack",
47
+ "operationId": "conversations.info"
48
+ },
49
+ "outcomes": [
50
+ "tool_error"
51
+ ],
52
+ "comparison": {
53
+ "operator": "equals",
54
+ "value": 1
55
+ }
56
+ },
57
+ {
58
+ "id": "create-ok",
59
+ "kind": "operation.count",
60
+ "operation": {
61
+ "packageId": "slack",
62
+ "operationId": "conversations.create"
63
+ },
64
+ "outcomes": [
65
+ "ok"
66
+ ],
67
+ "comparison": {
68
+ "operator": "equals",
69
+ "value": 1
70
+ }
71
+ },
72
+ {
73
+ "id": "conversations-only-im-and-channel-added",
74
+ "kind": "state.count",
75
+ "packageId": "slack",
76
+ "namespace": "conversations",
77
+ "comparison": {
78
+ "operator": "equals",
79
+ "value": 12
80
+ }
81
+ },
82
+ {
83
+ "id": "memberships-only-im-and-channel-added",
84
+ "kind": "state.count",
85
+ "packageId": "slack",
86
+ "namespace": "memberships",
87
+ "comparison": {
88
+ "operator": "equals",
89
+ "value": 33
90
+ }
91
+ },
92
+ {
93
+ "id": "id-sequence-advanced-twice",
94
+ "kind": "state.value",
95
+ "packageId": "slack",
96
+ "namespace": "workspace",
97
+ "rowId": "team",
98
+ "path": [
99
+ "id_sequence"
100
+ ],
101
+ "comparison": {
102
+ "operator": "equals",
103
+ "value": 52
104
+ }
105
+ },
106
+ {
107
+ "id": "im-took-first-free-id",
108
+ "kind": "state.value",
109
+ "packageId": "slack",
110
+ "namespace": "conversations",
111
+ "rowId": "D000000001F",
112
+ "path": [
113
+ "user"
114
+ ],
115
+ "comparison": {
116
+ "operator": "equals",
117
+ "value": "U01PRIYA003"
118
+ }
119
+ },
120
+ {
121
+ "id": "channel-took-next-id",
122
+ "kind": "state.value",
123
+ "packageId": "slack",
124
+ "namespace": "conversations",
125
+ "rowId": "C000000001G",
126
+ "path": [
127
+ "name"
128
+ ],
129
+ "comparison": {
130
+ "operator": "equals",
131
+ "value": "after-refused-open"
132
+ }
133
+ }
134
+ ]
135
+ }
@@ -0,0 +1,96 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "slack-post-rate-limited",
4
+ "title": "Posting is rate limited (429 + Retry-After) without changing state",
5
+ "targetId": "conformance-agent",
6
+ "scenarioId": "post-rate-limited",
7
+ "actorId": "member",
8
+ "task": {
9
+ "instruction": "Run the post-rate-limited conformance flow against the synthetic Slack Tool and fail loudly on any unexpected status or body."
10
+ },
11
+ "assertions": [
12
+ {
13
+ "id": "post-limited",
14
+ "kind": "operation.count",
15
+ "operation": {
16
+ "packageId": "slack",
17
+ "operationId": "chat.post-message"
18
+ },
19
+ "outcomes": [
20
+ "tool_error"
21
+ ],
22
+ "comparison": {
23
+ "operator": "equals",
24
+ "value": 1
25
+ }
26
+ },
27
+ {
28
+ "id": "reply-limited",
29
+ "kind": "operation.count",
30
+ "operation": {
31
+ "packageId": "slack",
32
+ "operationId": "chat.reply"
33
+ },
34
+ "outcomes": [
35
+ "tool_error"
36
+ ],
37
+ "comparison": {
38
+ "operator": "equals",
39
+ "value": 1
40
+ }
41
+ },
42
+ {
43
+ "id": "update-limited",
44
+ "kind": "operation.count",
45
+ "operation": {
46
+ "packageId": "slack",
47
+ "operationId": "chat.update"
48
+ },
49
+ "outcomes": [
50
+ "tool_error"
51
+ ],
52
+ "comparison": {
53
+ "operator": "equals",
54
+ "value": 1
55
+ }
56
+ },
57
+ {
58
+ "id": "reaction-ok",
59
+ "kind": "operation.count",
60
+ "operation": {
61
+ "packageId": "slack",
62
+ "operationId": "reactions.add"
63
+ },
64
+ "outcomes": [
65
+ "ok"
66
+ ],
67
+ "comparison": {
68
+ "operator": "equals",
69
+ "value": 1
70
+ }
71
+ },
72
+ {
73
+ "id": "nothing-posted",
74
+ "kind": "event.count",
75
+ "event": {
76
+ "packageId": "slack",
77
+ "eventId": "message.posted"
78
+ },
79
+ "phase": "emitted",
80
+ "comparison": {
81
+ "operator": "equals",
82
+ "value": 0
83
+ }
84
+ },
85
+ {
86
+ "id": "messages-untouched",
87
+ "kind": "state.count",
88
+ "packageId": "slack",
89
+ "namespace": "messages",
90
+ "comparison": {
91
+ "operator": "equals",
92
+ "value": 38
93
+ }
94
+ }
95
+ ]
96
+ }
@@ -0,0 +1,118 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "slack-response-budget",
4
+ "title": "Lists and reads page by UTF-8 encoded bytes under workspace.limits.response_bytes, every row appears exactly once, and a single message over the budget answers 400 response_too_large",
5
+ "targetId": "conformance-agent",
6
+ "scenarioId": "response-budget",
7
+ "actorId": "member",
8
+ "task": {
9
+ "instruction": "Run the response-budget conformance flow against the synthetic Slack Tool and fail loudly on any unexpected status or body."
10
+ },
11
+ "assertions": [
12
+ {
13
+ "id": "users-listed",
14
+ "kind": "operation.count",
15
+ "operation": {
16
+ "packageId": "slack",
17
+ "operationId": "users.list"
18
+ },
19
+ "outcomes": [
20
+ "ok"
21
+ ],
22
+ "comparison": {
23
+ "operator": "greater_than_or_equal",
24
+ "value": 1
25
+ }
26
+ },
27
+ {
28
+ "id": "history-paged",
29
+ "kind": "operation.count",
30
+ "operation": {
31
+ "packageId": "slack",
32
+ "operationId": "conversations.history"
33
+ },
34
+ "outcomes": [
35
+ "ok"
36
+ ],
37
+ "comparison": {
38
+ "operator": "greater_than_or_equal",
39
+ "value": 3
40
+ }
41
+ },
42
+ {
43
+ "id": "replies-paged",
44
+ "kind": "operation.count",
45
+ "operation": {
46
+ "packageId": "slack",
47
+ "operationId": "conversations.replies"
48
+ },
49
+ "outcomes": [
50
+ "ok"
51
+ ],
52
+ "comparison": {
53
+ "operator": "greater_than_or_equal",
54
+ "value": 2
55
+ }
56
+ },
57
+ {
58
+ "id": "history-too-large",
59
+ "kind": "operation.count",
60
+ "operation": {
61
+ "packageId": "slack",
62
+ "operationId": "conversations.history"
63
+ },
64
+ "outcomes": [
65
+ "tool_error"
66
+ ],
67
+ "comparison": {
68
+ "operator": "greater_than_or_equal",
69
+ "value": 1
70
+ }
71
+ },
72
+ {
73
+ "id": "replies-too-large",
74
+ "kind": "operation.count",
75
+ "operation": {
76
+ "packageId": "slack",
77
+ "operationId": "conversations.replies"
78
+ },
79
+ "outcomes": [
80
+ "tool_error"
81
+ ],
82
+ "comparison": {
83
+ "operator": "greater_than_or_equal",
84
+ "value": 1
85
+ }
86
+ },
87
+ {
88
+ "id": "search-too-large",
89
+ "kind": "operation.count",
90
+ "operation": {
91
+ "packageId": "slack",
92
+ "operationId": "search.messages"
93
+ },
94
+ "outcomes": [
95
+ "tool_error"
96
+ ],
97
+ "comparison": {
98
+ "operator": "greater_than_or_equal",
99
+ "value": 1
100
+ }
101
+ },
102
+ {
103
+ "id": "pins-too-large",
104
+ "kind": "operation.count",
105
+ "operation": {
106
+ "packageId": "slack",
107
+ "operationId": "pins.list"
108
+ },
109
+ "outcomes": [
110
+ "tool_error"
111
+ ],
112
+ "comparison": {
113
+ "operator": "equals",
114
+ "value": 1
115
+ }
116
+ }
117
+ ]
118
+ }
@@ -0,0 +1,100 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "slack-thread-many-repliers",
4
+ "title": "Replies from a 51st distinct participant are posted: reply_users stays at the first 50, reply_users_count and reply_count keep counting, and nothing fails",
5
+ "targetId": "conformance-agent",
6
+ "scenarioId": "thread-many-repliers",
7
+ "actorId": "member",
8
+ "task": {
9
+ "instruction": "Run the thread-many-repliers conformance flow against the synthetic Slack Tool and fail loudly on any unexpected status or body."
10
+ },
11
+ "assertions": [
12
+ {
13
+ "id": "replies-posted",
14
+ "kind": "operation.count",
15
+ "operation": {
16
+ "packageId": "slack",
17
+ "operationId": "chat.post-message"
18
+ },
19
+ "outcomes": [
20
+ "ok"
21
+ ],
22
+ "comparison": {
23
+ "operator": "equals",
24
+ "value": 2
25
+ }
26
+ },
27
+ {
28
+ "id": "no-reply-refused",
29
+ "kind": "operation.count",
30
+ "operation": {
31
+ "packageId": "slack",
32
+ "operationId": "chat.post-message"
33
+ },
34
+ "outcomes": [
35
+ "tool_error"
36
+ ],
37
+ "comparison": {
38
+ "operator": "equals",
39
+ "value": 0
40
+ }
41
+ },
42
+ {
43
+ "id": "reply-count-counts-every-reply",
44
+ "kind": "state.value",
45
+ "packageId": "slack",
46
+ "namespace": "messages",
47
+ "rowId": "C01GENERAL1:1789290000.000199",
48
+ "path": [
49
+ "reply_count"
50
+ ],
51
+ "comparison": {
52
+ "operator": "equals",
53
+ "value": 52
54
+ }
55
+ },
56
+ {
57
+ "id": "distinct-repliers-counted-once",
58
+ "kind": "state.value",
59
+ "packageId": "slack",
60
+ "namespace": "messages",
61
+ "rowId": "C01GENERAL1:1789290000.000199",
62
+ "path": [
63
+ "reply_users_count"
64
+ ],
65
+ "comparison": {
66
+ "operator": "equals",
67
+ "value": 51
68
+ }
69
+ },
70
+ {
71
+ "id": "reply-users-keeps-first-fifty",
72
+ "kind": "state.value",
73
+ "packageId": "slack",
74
+ "namespace": "messages",
75
+ "rowId": "C01GENERAL1:1789290000.000199",
76
+ "path": [
77
+ "reply_users",
78
+ 49
79
+ ],
80
+ "comparison": {
81
+ "operator": "equals",
82
+ "value": "U0REPLY0050"
83
+ }
84
+ },
85
+ {
86
+ "id": "latest-reply-is-second-reply",
87
+ "kind": "state.value",
88
+ "packageId": "slack",
89
+ "namespace": "messages",
90
+ "rowId": "C01GENERAL1:1789290000.000199",
91
+ "path": [
92
+ "latest_reply"
93
+ ],
94
+ "comparison": {
95
+ "operator": "equals",
96
+ "value": "1789376400.000002"
97
+ }
98
+ }
99
+ ]
100
+ }
@@ -0,0 +1,165 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "slack-ts-sequence-full",
4
+ "title": "A virtual second holds at most 999,999 message timestamps: the last one is allocated, then posting, replying, joining and inviting refuse with too_many_rows and write nothing",
5
+ "targetId": "conformance-agent",
6
+ "scenarioId": "ts-sequence-full",
7
+ "actorId": "member",
8
+ "task": {
9
+ "instruction": "Run the ts-sequence-full conformance flow against the synthetic Slack Tool and fail loudly on any unexpected status or body."
10
+ },
11
+ "assertions": [
12
+ {
13
+ "id": "chat-post-message-ok",
14
+ "kind": "operation.count",
15
+ "operation": {
16
+ "packageId": "slack",
17
+ "operationId": "chat.post-message"
18
+ },
19
+ "outcomes": [
20
+ "ok"
21
+ ],
22
+ "comparison": {
23
+ "operator": "equals",
24
+ "value": 1
25
+ }
26
+ },
27
+ {
28
+ "id": "chat-post-message-tool-error",
29
+ "kind": "operation.count",
30
+ "operation": {
31
+ "packageId": "slack",
32
+ "operationId": "chat.post-message"
33
+ },
34
+ "outcomes": [
35
+ "tool_error"
36
+ ],
37
+ "comparison": {
38
+ "operator": "equals",
39
+ "value": 2
40
+ }
41
+ },
42
+ {
43
+ "id": "chat-reply-tool-error",
44
+ "kind": "operation.count",
45
+ "operation": {
46
+ "packageId": "slack",
47
+ "operationId": "chat.reply"
48
+ },
49
+ "outcomes": [
50
+ "tool_error"
51
+ ],
52
+ "comparison": {
53
+ "operator": "equals",
54
+ "value": 1
55
+ }
56
+ },
57
+ {
58
+ "id": "conversations-join-tool-error",
59
+ "kind": "operation.count",
60
+ "operation": {
61
+ "packageId": "slack",
62
+ "operationId": "conversations.join"
63
+ },
64
+ "outcomes": [
65
+ "tool_error"
66
+ ],
67
+ "comparison": {
68
+ "operator": "equals",
69
+ "value": 1
70
+ }
71
+ },
72
+ {
73
+ "id": "conversations-invite-tool-error",
74
+ "kind": "operation.count",
75
+ "operation": {
76
+ "packageId": "slack",
77
+ "operationId": "conversations.invite"
78
+ },
79
+ "outcomes": [
80
+ "tool_error"
81
+ ],
82
+ "comparison": {
83
+ "operator": "equals",
84
+ "value": 1
85
+ }
86
+ },
87
+ {
88
+ "id": "chat-update-ok",
89
+ "kind": "operation.count",
90
+ "operation": {
91
+ "packageId": "slack",
92
+ "operationId": "chat.update"
93
+ },
94
+ "outcomes": [
95
+ "ok"
96
+ ],
97
+ "comparison": {
98
+ "operator": "equals",
99
+ "value": 1
100
+ }
101
+ },
102
+ {
103
+ "id": "reactions-add-ok",
104
+ "kind": "operation.count",
105
+ "operation": {
106
+ "packageId": "slack",
107
+ "operationId": "reactions.add"
108
+ },
109
+ "outcomes": [
110
+ "ok"
111
+ ],
112
+ "comparison": {
113
+ "operator": "equals",
114
+ "value": 1
115
+ }
116
+ },
117
+ {
118
+ "id": "one-message-posted",
119
+ "kind": "event.count",
120
+ "event": {
121
+ "packageId": "slack",
122
+ "eventId": "message.posted"
123
+ },
124
+ "phase": "emitted",
125
+ "comparison": {
126
+ "operator": "equals",
127
+ "value": 1
128
+ }
129
+ },
130
+ {
131
+ "id": "last-ts-of-the-second",
132
+ "kind": "state.value",
133
+ "packageId": "slack",
134
+ "namespace": "messages",
135
+ "rowId": "C01INCIDENT:1789376400.999999",
136
+ "path": [
137
+ "text"
138
+ ],
139
+ "comparison": {
140
+ "operator": "equals",
141
+ "value": "edited"
142
+ }
143
+ },
144
+ {
145
+ "id": "one-row-more",
146
+ "kind": "state.count",
147
+ "packageId": "slack",
148
+ "namespace": "messages",
149
+ "comparison": {
150
+ "operator": "equals",
151
+ "value": 40
152
+ }
153
+ },
154
+ {
155
+ "id": "memberships-untouched",
156
+ "kind": "state.count",
157
+ "packageId": "slack",
158
+ "namespace": "memberships",
159
+ "comparison": {
160
+ "operator": "equals",
161
+ "value": 30
162
+ }
163
+ }
164
+ ]
165
+ }