digital-workers 2.1.1 → 2.3.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/CHANGELOG.md +23 -0
- package/README.md +136 -180
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +34 -21
- package/dist/actions.js.map +1 -1
- package/dist/agent-comms.d.ts +438 -0
- package/dist/agent-comms.d.ts.map +1 -0
- package/dist/agent-comms.js +677 -0
- package/dist/agent-comms.js.map +1 -0
- package/dist/approve.d.ts +40 -8
- package/dist/approve.d.ts.map +1 -1
- package/dist/approve.js +86 -20
- package/dist/approve.js.map +1 -1
- package/dist/ask.d.ts +38 -7
- package/dist/ask.d.ts.map +1 -1
- package/dist/ask.js +85 -25
- package/dist/ask.js.map +1 -1
- package/dist/browse.d.ts +223 -0
- package/dist/browse.d.ts.map +1 -0
- package/dist/browse.js +392 -0
- package/dist/browse.js.map +1 -0
- package/dist/capability-tiers.d.ts +230 -0
- package/dist/capability-tiers.d.ts.map +1 -0
- package/dist/capability-tiers.js +388 -0
- package/dist/capability-tiers.js.map +1 -0
- package/dist/cascade-context.d.ts +523 -0
- package/dist/cascade-context.d.ts.map +1 -0
- package/dist/cascade-context.js +494 -0
- package/dist/cascade-context.js.map +1 -0
- package/dist/client.d.ts +162 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +64 -0
- package/dist/client.js.map +1 -0
- package/dist/decide.d.ts +42 -6
- package/dist/decide.d.ts.map +1 -1
- package/dist/decide.js +54 -11
- package/dist/decide.js.map +1 -1
- package/dist/do.d.ts +36 -7
- package/dist/do.d.ts.map +1 -1
- package/dist/do.js +82 -39
- package/dist/do.js.map +1 -1
- package/dist/error-escalation.d.ts +416 -0
- package/dist/error-escalation.d.ts.map +1 -0
- package/dist/error-escalation.js +656 -0
- package/dist/error-escalation.js.map +1 -0
- package/dist/generate.d.ts +48 -7
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +49 -8
- package/dist/generate.js.map +1 -1
- package/dist/goals.d.ts +10 -9
- package/dist/goals.d.ts.map +1 -1
- package/dist/goals.js +30 -24
- package/dist/goals.js.map +1 -1
- package/dist/image.d.ts +189 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +528 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +59 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +92 -2
- package/dist/index.js.map +1 -1
- package/dist/is.d.ts +45 -10
- package/dist/is.d.ts.map +1 -1
- package/dist/is.js +56 -21
- package/dist/is.js.map +1 -1
- package/dist/kpis.d.ts +24 -15
- package/dist/kpis.d.ts.map +1 -1
- package/dist/kpis.js +16 -14
- package/dist/kpis.js.map +1 -1
- package/dist/load-balancing.d.ts +395 -0
- package/dist/load-balancing.d.ts.map +1 -0
- package/dist/load-balancing.js +991 -0
- package/dist/load-balancing.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +39 -0
- package/dist/logger.js.map +1 -0
- package/dist/notify.d.ts +38 -9
- package/dist/notify.d.ts.map +1 -1
- package/dist/notify.js +72 -17
- package/dist/notify.js.map +1 -1
- package/dist/role.d.ts +5 -4
- package/dist/role.d.ts.map +1 -1
- package/dist/role.js +13 -10
- package/dist/role.js.map +1 -1
- package/dist/runtime.d.ts +310 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +510 -0
- package/dist/runtime.js.map +1 -0
- package/dist/team.d.ts +11 -6
- package/dist/team.d.ts.map +1 -1
- package/dist/team.js +22 -15
- package/dist/team.js.map +1 -1
- package/dist/transports/email.d.ts +318 -0
- package/dist/transports/email.d.ts.map +1 -0
- package/dist/transports/email.js +779 -0
- package/dist/transports/email.js.map +1 -0
- package/dist/transports/slack.d.ts +515 -0
- package/dist/transports/slack.d.ts.map +1 -0
- package/dist/transports/slack.js +844 -0
- package/dist/transports/slack.js.map +1 -0
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +44 -25
- package/dist/transports.js.map +1 -1
- package/dist/types.d.ts +149 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/id.d.ts +19 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +21 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/video.d.ts +203 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +528 -0
- package/dist/video.js.map +1 -0
- package/dist/worker.d.ts +343 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +698 -0
- package/dist/worker.js.map +1 -0
- package/package.json +24 -5
- package/src/actions.ts +48 -38
- package/src/agent-comms.ts +1200 -0
- package/src/approve.ts +91 -20
- package/src/ask.ts +99 -25
- package/src/browse.ts +627 -0
- package/src/capability-tiers.ts +545 -0
- package/src/cascade-context.ts +648 -0
- package/src/client.ts +221 -0
- package/src/decide.ts +81 -35
- package/src/do.ts +98 -52
- package/src/error-escalation.ts +1123 -0
- package/src/generate.ts +52 -18
- package/src/goals.ts +36 -27
- package/src/image.ts +816 -0
- package/src/index.ts +410 -2
- package/src/is.ts +59 -25
- package/src/kpis.ts +41 -36
- package/src/load-balancing.ts +1467 -0
- package/src/logger.ts +93 -0
- package/src/notify.ts +78 -17
- package/src/role.ts +30 -20
- package/src/runtime.ts +796 -0
- package/src/team.ts +24 -19
- package/src/transports/email.ts +1160 -0
- package/src/transports/slack.ts +1320 -0
- package/src/transports.ts +58 -43
- package/src/types.ts +182 -46
- package/src/utils/id.ts +21 -0
- package/src/video.ts +906 -0
- package/src/worker.ts +1007 -0
- package/test/agent-comms.test.ts +1397 -0
- package/test/approve.test.ts +305 -0
- package/test/ask.test.ts +274 -0
- package/test/browse.test.ts +361 -0
- package/test/capability-tiers.test.ts +631 -0
- package/test/cascade-context.test.ts +692 -0
- package/test/decide.test.ts +252 -0
- package/test/do.test.ts +144 -0
- package/test/error-escalation.test.ts +1205 -0
- package/test/error-logging.test.ts +357 -0
- package/test/generate.test.ts +319 -0
- package/test/image.test.ts +398 -0
- package/test/is.test.ts +287 -0
- package/test/load-balancing-safety.test.ts +404 -0
- package/test/load-balancing-thread-safety.test.ts +464 -0
- package/test/load-balancing.test.ts +1145 -0
- package/test/notify.test.ts +434 -0
- package/test/primitives.test.ts +320 -0
- package/test/runtime-integration.test.ts +892 -0
- package/test/transports/crypto.test.ts +230 -0
- package/test/transports/email.test.ts +866 -0
- package/test/transports/id-generation.test.ts +91 -0
- package/test/transports/slack.test.ts +760 -0
- package/test/type-safety.test.ts +834 -0
- package/test/types.test.ts +95 -2
- package/test/video.test.ts +530 -0
- package/test/worker.test.ts +1433 -0
- package/tsconfig.json +4 -1
- package/vitest.config.ts +42 -0
- package/wrangler.jsonc +36 -0
- package/.turbo/turbo-build.log +0 -5
- package/src/actions.js +0 -436
- package/src/approve.js +0 -234
- package/src/ask.js +0 -226
- package/src/decide.js +0 -244
- package/src/do.js +0 -227
- package/src/generate.js +0 -298
- package/src/goals.js +0 -205
- package/src/index.js +0 -68
- package/src/is.js +0 -317
- package/src/kpis.js +0 -270
- package/src/notify.js +0 -219
- package/src/role.js +0 -110
- package/src/team.js +0 -130
- package/src/transports.js +0 -357
- package/src/types.js +0 -71
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Slack Signature Verification Crypto Functions
|
|
3
|
+
*
|
|
4
|
+
* This module tests the HMAC-SHA256 signature verification used by Slack webhooks.
|
|
5
|
+
* The implementation should work in both Node.js and Cloudflare Workers environments
|
|
6
|
+
* using the Web Crypto API.
|
|
7
|
+
*
|
|
8
|
+
* Bead issue: aip-621l
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect } from 'vitest'
|
|
12
|
+
import { verifySlackSignature, computeHmacSha256Hex } from '../../src/transports/slack.js'
|
|
13
|
+
|
|
14
|
+
// Test constants matching Slack's signing secret format
|
|
15
|
+
const TEST_SIGNING_SECRET = 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6'
|
|
16
|
+
const TEST_TIMESTAMP = '1531420618'
|
|
17
|
+
const TEST_BODY = 'token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow'
|
|
18
|
+
|
|
19
|
+
// Pre-computed signature for the test data above
|
|
20
|
+
// This is the expected signature when signing "v0:1531420618:token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow"
|
|
21
|
+
// with the signing secret "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
|
22
|
+
// Note: We'll compute the actual expected value when implementing
|
|
23
|
+
|
|
24
|
+
describe('Slack Signature Verification', () => {
|
|
25
|
+
describe('computeHmacSha256Hex', () => {
|
|
26
|
+
it('should compute HMAC-SHA256 and return hex string', async () => {
|
|
27
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
28
|
+
const result = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
29
|
+
|
|
30
|
+
// Result should be a 64-character hex string (256 bits = 32 bytes = 64 hex chars)
|
|
31
|
+
expect(result).toMatch(/^[a-f0-9]{64}$/)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should produce consistent results for same input', async () => {
|
|
35
|
+
const data = 'test data'
|
|
36
|
+
const secret = 'test secret'
|
|
37
|
+
|
|
38
|
+
const result1 = await computeHmacSha256Hex(data, secret)
|
|
39
|
+
const result2 = await computeHmacSha256Hex(data, secret)
|
|
40
|
+
|
|
41
|
+
expect(result1).toBe(result2)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should produce different results for different data', async () => {
|
|
45
|
+
const secret = 'test secret'
|
|
46
|
+
|
|
47
|
+
const result1 = await computeHmacSha256Hex('data1', secret)
|
|
48
|
+
const result2 = await computeHmacSha256Hex('data2', secret)
|
|
49
|
+
|
|
50
|
+
expect(result1).not.toBe(result2)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('should produce different results for different secrets', async () => {
|
|
54
|
+
const data = 'test data'
|
|
55
|
+
|
|
56
|
+
const result1 = await computeHmacSha256Hex(data, 'secret1')
|
|
57
|
+
const result2 = await computeHmacSha256Hex(data, 'secret2')
|
|
58
|
+
|
|
59
|
+
expect(result1).not.toBe(result2)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should handle empty data', async () => {
|
|
63
|
+
const result = await computeHmacSha256Hex('', 'secret')
|
|
64
|
+
|
|
65
|
+
expect(result).toMatch(/^[a-f0-9]{64}$/)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should handle unicode data', async () => {
|
|
69
|
+
const result = await computeHmacSha256Hex('Hello, World! Emoji test: *smile*', 'secret')
|
|
70
|
+
|
|
71
|
+
expect(result).toMatch(/^[a-f0-9]{64}$/)
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('verifySlackSignature', () => {
|
|
76
|
+
it('should verify a valid signature', async () => {
|
|
77
|
+
// First compute what the signature should be
|
|
78
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
79
|
+
const hmac = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
80
|
+
const validSignature = `v0=${hmac}`
|
|
81
|
+
|
|
82
|
+
const isValid = await verifySlackSignature(
|
|
83
|
+
validSignature,
|
|
84
|
+
TEST_TIMESTAMP,
|
|
85
|
+
TEST_BODY,
|
|
86
|
+
TEST_SIGNING_SECRET
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
expect(isValid).toBe(true)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should reject an invalid signature', async () => {
|
|
93
|
+
const invalidSignature = 'v0=0000000000000000000000000000000000000000000000000000000000000000'
|
|
94
|
+
|
|
95
|
+
const isValid = await verifySlackSignature(
|
|
96
|
+
invalidSignature,
|
|
97
|
+
TEST_TIMESTAMP,
|
|
98
|
+
TEST_BODY,
|
|
99
|
+
TEST_SIGNING_SECRET
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
expect(isValid).toBe(false)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('should reject a malformed signature (missing v0= prefix)', async () => {
|
|
106
|
+
const malformedSignature = 'abc123def456'
|
|
107
|
+
|
|
108
|
+
const isValid = await verifySlackSignature(
|
|
109
|
+
malformedSignature,
|
|
110
|
+
TEST_TIMESTAMP,
|
|
111
|
+
TEST_BODY,
|
|
112
|
+
TEST_SIGNING_SECRET
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
expect(isValid).toBe(false)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('should reject signature with wrong secret', async () => {
|
|
119
|
+
// Compute signature with correct secret
|
|
120
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
121
|
+
const hmac = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
122
|
+
const signature = `v0=${hmac}`
|
|
123
|
+
|
|
124
|
+
// Verify with wrong secret
|
|
125
|
+
const isValid = await verifySlackSignature(
|
|
126
|
+
signature,
|
|
127
|
+
TEST_TIMESTAMP,
|
|
128
|
+
TEST_BODY,
|
|
129
|
+
'wrong-secret-key'
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
expect(isValid).toBe(false)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('should reject signature with tampered body', async () => {
|
|
136
|
+
// Compute signature with original body
|
|
137
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
138
|
+
const hmac = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
139
|
+
const signature = `v0=${hmac}`
|
|
140
|
+
|
|
141
|
+
// Verify with tampered body
|
|
142
|
+
const isValid = await verifySlackSignature(
|
|
143
|
+
signature,
|
|
144
|
+
TEST_TIMESTAMP,
|
|
145
|
+
TEST_BODY + 'tampered',
|
|
146
|
+
TEST_SIGNING_SECRET
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
expect(isValid).toBe(false)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('should reject signature with wrong timestamp', async () => {
|
|
153
|
+
// Compute signature with original timestamp
|
|
154
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
155
|
+
const hmac = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
156
|
+
const signature = `v0=${hmac}`
|
|
157
|
+
|
|
158
|
+
// Verify with different timestamp
|
|
159
|
+
const isValid = await verifySlackSignature(
|
|
160
|
+
signature,
|
|
161
|
+
'1234567890',
|
|
162
|
+
TEST_BODY,
|
|
163
|
+
TEST_SIGNING_SECRET
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
expect(isValid).toBe(false)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('should use constant-time comparison to prevent timing attacks', async () => {
|
|
170
|
+
// This test verifies the function handles different-length signatures safely
|
|
171
|
+
const baseString = `v0:${TEST_TIMESTAMP}:${TEST_BODY}`
|
|
172
|
+
const hmac = await computeHmacSha256Hex(baseString, TEST_SIGNING_SECRET)
|
|
173
|
+
const validSignature = `v0=${hmac}`
|
|
174
|
+
|
|
175
|
+
// Short signature
|
|
176
|
+
const isValidShort = await verifySlackSignature(
|
|
177
|
+
'v0=abc',
|
|
178
|
+
TEST_TIMESTAMP,
|
|
179
|
+
TEST_BODY,
|
|
180
|
+
TEST_SIGNING_SECRET
|
|
181
|
+
)
|
|
182
|
+
expect(isValidShort).toBe(false)
|
|
183
|
+
|
|
184
|
+
// Long signature
|
|
185
|
+
const isValidLong = await verifySlackSignature(
|
|
186
|
+
validSignature + 'extra',
|
|
187
|
+
TEST_TIMESTAMP,
|
|
188
|
+
TEST_BODY,
|
|
189
|
+
TEST_SIGNING_SECRET
|
|
190
|
+
)
|
|
191
|
+
expect(isValidLong).toBe(false)
|
|
192
|
+
|
|
193
|
+
// Correct length but wrong content
|
|
194
|
+
const wrongSig = 'v0=' + '0'.repeat(64)
|
|
195
|
+
const isValidWrong = await verifySlackSignature(
|
|
196
|
+
wrongSig,
|
|
197
|
+
TEST_TIMESTAMP,
|
|
198
|
+
TEST_BODY,
|
|
199
|
+
TEST_SIGNING_SECRET
|
|
200
|
+
)
|
|
201
|
+
expect(isValidWrong).toBe(false)
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
describe('Web Crypto API compatibility', () => {
|
|
206
|
+
it('should work in environments with crypto.subtle', async () => {
|
|
207
|
+
// This test verifies that the global crypto.subtle is being used
|
|
208
|
+
expect(globalThis.crypto).toBeDefined()
|
|
209
|
+
expect(globalThis.crypto.subtle).toBeDefined()
|
|
210
|
+
|
|
211
|
+
// The actual crypto operations should work
|
|
212
|
+
const result = await computeHmacSha256Hex('test', 'secret')
|
|
213
|
+
expect(result).toMatch(/^[a-f0-9]{64}$/)
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('should produce results compatible with known HMAC-SHA256 test vectors', async () => {
|
|
217
|
+
// RFC 4231 test vector (truncated to check format)
|
|
218
|
+
// Key: "key"
|
|
219
|
+
// Data: "The quick brown fox jumps over the lazy dog"
|
|
220
|
+
// Expected HMAC-SHA256: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
|
|
221
|
+
const testKey = 'key'
|
|
222
|
+
const testData = 'The quick brown fox jumps over the lazy dog'
|
|
223
|
+
const expectedHmac = 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8'
|
|
224
|
+
|
|
225
|
+
const result = await computeHmacSha256Hex(testData, testKey)
|
|
226
|
+
|
|
227
|
+
expect(result).toBe(expectedHmac)
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
})
|