restless-sdk 0.1.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,500 @@
1
+ {
2
+ "$generated": "GENERATED FILE - do not edit by hand. Inputs live in spec/cases.ts; run `npm run spec:vectors` to regenerate.",
3
+ "$contract": "spec/CONTRACT.md",
4
+ "specVersion": "1.0.0",
5
+ "cases": [
6
+ {
7
+ "id": "har/basic",
8
+ "requirement": "HAR-001",
9
+ "op": "harEntry",
10
+ "input": {
11
+ "captured": {
12
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
13
+ "startedAt": "2026-01-01T00:00:00.000Z",
14
+ "duration": 42,
15
+ "request": {
16
+ "method": "POST",
17
+ "url": "http://host/p?q=1",
18
+ "headers": {
19
+ "content-type": "application/json"
20
+ },
21
+ "body": "{\"a\":1}"
22
+ },
23
+ "response": {
24
+ "status": 201,
25
+ "headers": {
26
+ "content-type": "application/json"
27
+ },
28
+ "body": "{\"ok\":true}"
29
+ }
30
+ }
31
+ },
32
+ "expected": {
33
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
34
+ "time": 42,
35
+ "request": {
36
+ "method": "POST",
37
+ "url": "http://host/p?q=1",
38
+ "httpVersion": "HTTP/1.1",
39
+ "headers": [
40
+ {
41
+ "name": "content-type",
42
+ "value": "application/json"
43
+ }
44
+ ],
45
+ "queryString": [
46
+ {
47
+ "name": "q",
48
+ "value": "1"
49
+ }
50
+ ],
51
+ "postData": {
52
+ "mimeType": "application/json",
53
+ "text": "{\"a\":1}"
54
+ },
55
+ "headersSize": -1,
56
+ "bodySize": 7
57
+ },
58
+ "response": {
59
+ "status": 201,
60
+ "statusText": "",
61
+ "httpVersion": "HTTP/1.1",
62
+ "headers": [
63
+ {
64
+ "name": "content-type",
65
+ "value": "application/json"
66
+ }
67
+ ],
68
+ "content": {
69
+ "size": 11,
70
+ "mimeType": "application/json",
71
+ "text": "{\"ok\":true}"
72
+ },
73
+ "headersSize": -1,
74
+ "bodySize": 11
75
+ },
76
+ "timings": {
77
+ "send": 0,
78
+ "wait": 42,
79
+ "receive": 0
80
+ }
81
+ }
82
+ },
83
+ {
84
+ "id": "har/no-bodies",
85
+ "requirement": "HAR-011",
86
+ "op": "harEntry",
87
+ "input": {
88
+ "captured": {
89
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
90
+ "startedAt": "2026-01-01T00:00:00.000Z",
91
+ "duration": 0,
92
+ "request": {
93
+ "method": "GET",
94
+ "url": "http://host/",
95
+ "headers": {}
96
+ },
97
+ "response": {
98
+ "status": 204,
99
+ "headers": {}
100
+ }
101
+ }
102
+ },
103
+ "expected": {
104
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
105
+ "time": 0,
106
+ "request": {
107
+ "method": "GET",
108
+ "url": "http://host/",
109
+ "httpVersion": "HTTP/1.1",
110
+ "headers": [],
111
+ "queryString": [],
112
+ "headersSize": -1,
113
+ "bodySize": -1
114
+ },
115
+ "response": {
116
+ "status": 204,
117
+ "statusText": "",
118
+ "httpVersion": "HTTP/1.1",
119
+ "headers": [],
120
+ "content": {
121
+ "size": 0,
122
+ "mimeType": "application/octet-stream",
123
+ "text": ""
124
+ },
125
+ "headersSize": -1,
126
+ "bodySize": -1
127
+ },
128
+ "timings": {
129
+ "send": 0,
130
+ "wait": 0,
131
+ "receive": 0
132
+ }
133
+ },
134
+ "note": "bodySize is -1 on both sides when nothing was captured; content.size is 0."
135
+ },
136
+ {
137
+ "id": "har/empty-string-body",
138
+ "requirement": "HAR-011",
139
+ "op": "harEntry",
140
+ "input": {
141
+ "captured": {
142
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
143
+ "startedAt": "2026-01-01T00:00:00.000Z",
144
+ "duration": 42,
145
+ "request": {
146
+ "method": "POST",
147
+ "url": "http://host/",
148
+ "headers": {},
149
+ "body": ""
150
+ },
151
+ "response": {
152
+ "status": 200,
153
+ "headers": {},
154
+ "body": ""
155
+ }
156
+ }
157
+ },
158
+ "expected": {
159
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
160
+ "time": 42,
161
+ "request": {
162
+ "method": "POST",
163
+ "url": "http://host/",
164
+ "httpVersion": "HTTP/1.1",
165
+ "headers": [],
166
+ "queryString": [],
167
+ "headersSize": -1,
168
+ "bodySize": 0
169
+ },
170
+ "response": {
171
+ "status": 200,
172
+ "statusText": "",
173
+ "httpVersion": "HTTP/1.1",
174
+ "headers": [],
175
+ "content": {
176
+ "size": 0,
177
+ "mimeType": "application/octet-stream",
178
+ "text": ""
179
+ },
180
+ "headersSize": -1,
181
+ "bodySize": 0
182
+ },
183
+ "timings": {
184
+ "send": 0,
185
+ "wait": 42,
186
+ "receive": 0
187
+ }
188
+ },
189
+ "note": "An empty body is not an absent body: sizes are 0, not -1."
190
+ },
191
+ {
192
+ "id": "har/multibyte-sizes",
193
+ "requirement": "HAR-010",
194
+ "op": "harEntry",
195
+ "input": {
196
+ "captured": {
197
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
198
+ "startedAt": "2026-01-01T00:00:00.000Z",
199
+ "duration": 42,
200
+ "request": {
201
+ "method": "POST",
202
+ "url": "http://host/",
203
+ "headers": {
204
+ "content-type": "application/json"
205
+ },
206
+ "body": "{\"m\":\"日本語🚀\"}"
207
+ },
208
+ "response": {
209
+ "status": 200,
210
+ "headers": {
211
+ "content-type": "application/json"
212
+ },
213
+ "body": "{\"m\":\"café\"}"
214
+ }
215
+ }
216
+ },
217
+ "expected": {
218
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
219
+ "time": 42,
220
+ "request": {
221
+ "method": "POST",
222
+ "url": "http://host/",
223
+ "httpVersion": "HTTP/1.1",
224
+ "headers": [
225
+ {
226
+ "name": "content-type",
227
+ "value": "application/json"
228
+ }
229
+ ],
230
+ "queryString": [],
231
+ "postData": {
232
+ "mimeType": "application/json",
233
+ "text": "{\"m\":\"日本語🚀\"}"
234
+ },
235
+ "headersSize": -1,
236
+ "bodySize": 21
237
+ },
238
+ "response": {
239
+ "status": 200,
240
+ "statusText": "",
241
+ "httpVersion": "HTTP/1.1",
242
+ "headers": [
243
+ {
244
+ "name": "content-type",
245
+ "value": "application/json"
246
+ }
247
+ ],
248
+ "content": {
249
+ "size": 13,
250
+ "mimeType": "application/json",
251
+ "text": "{\"m\":\"café\"}"
252
+ },
253
+ "headersSize": -1,
254
+ "bodySize": 13
255
+ },
256
+ "timings": {
257
+ "send": 0,
258
+ "wait": 42,
259
+ "receive": 0
260
+ }
261
+ },
262
+ "note": "Sizes are UTF-8 BYTES. The request body is 12 characters but 22 bytes."
263
+ },
264
+ {
265
+ "id": "har/no-response-content-type",
266
+ "requirement": "HAR-007",
267
+ "op": "harEntry",
268
+ "input": {
269
+ "captured": {
270
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
271
+ "startedAt": "2026-01-01T00:00:00.000Z",
272
+ "duration": 42,
273
+ "request": {
274
+ "method": "GET",
275
+ "url": "http://host/",
276
+ "headers": {}
277
+ },
278
+ "response": {
279
+ "status": 200,
280
+ "headers": {},
281
+ "body": "raw"
282
+ }
283
+ }
284
+ },
285
+ "expected": {
286
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
287
+ "time": 42,
288
+ "request": {
289
+ "method": "GET",
290
+ "url": "http://host/",
291
+ "httpVersion": "HTTP/1.1",
292
+ "headers": [],
293
+ "queryString": [],
294
+ "headersSize": -1,
295
+ "bodySize": -1
296
+ },
297
+ "response": {
298
+ "status": 200,
299
+ "statusText": "",
300
+ "httpVersion": "HTTP/1.1",
301
+ "headers": [],
302
+ "content": {
303
+ "size": 3,
304
+ "mimeType": "application/octet-stream",
305
+ "text": "raw"
306
+ },
307
+ "headersSize": -1,
308
+ "bodySize": 3
309
+ },
310
+ "timings": {
311
+ "send": 0,
312
+ "wait": 42,
313
+ "receive": 0
314
+ }
315
+ },
316
+ "note": "mimeType falls back to application/octet-stream."
317
+ },
318
+ {
319
+ "id": "har/query-string",
320
+ "requirement": "HAR-005",
321
+ "op": "harEntry",
322
+ "input": {
323
+ "captured": {
324
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
325
+ "startedAt": "2026-01-01T00:00:00.000Z",
326
+ "duration": 42,
327
+ "request": {
328
+ "method": "GET",
329
+ "url": "http://host/p?a=1&b=two&a=3&empty=",
330
+ "headers": {}
331
+ },
332
+ "response": {
333
+ "status": 200,
334
+ "headers": {}
335
+ }
336
+ }
337
+ },
338
+ "expected": {
339
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
340
+ "time": 42,
341
+ "request": {
342
+ "method": "GET",
343
+ "url": "http://host/p?a=1&b=two&a=3&empty=",
344
+ "httpVersion": "HTTP/1.1",
345
+ "headers": [],
346
+ "queryString": [
347
+ {
348
+ "name": "a",
349
+ "value": "1"
350
+ },
351
+ {
352
+ "name": "b",
353
+ "value": "two"
354
+ },
355
+ {
356
+ "name": "a",
357
+ "value": "3"
358
+ },
359
+ {
360
+ "name": "empty",
361
+ "value": ""
362
+ }
363
+ ],
364
+ "headersSize": -1,
365
+ "bodySize": -1
366
+ },
367
+ "response": {
368
+ "status": 200,
369
+ "statusText": "",
370
+ "httpVersion": "HTTP/1.1",
371
+ "headers": [],
372
+ "content": {
373
+ "size": 0,
374
+ "mimeType": "application/octet-stream",
375
+ "text": ""
376
+ },
377
+ "headersSize": -1,
378
+ "bodySize": -1
379
+ },
380
+ "timings": {
381
+ "send": 0,
382
+ "wait": 42,
383
+ "receive": 0
384
+ }
385
+ },
386
+ "note": "Repeated keys are preserved in order; values are percent-decoded."
387
+ },
388
+ {
389
+ "id": "har/relative-url",
390
+ "requirement": "HAR-005",
391
+ "op": "harEntry",
392
+ "input": {
393
+ "captured": {
394
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
395
+ "startedAt": "2026-01-01T00:00:00.000Z",
396
+ "duration": 42,
397
+ "request": {
398
+ "method": "GET",
399
+ "url": "/p?a=1",
400
+ "headers": {}
401
+ },
402
+ "response": {
403
+ "status": 200,
404
+ "headers": {}
405
+ }
406
+ }
407
+ },
408
+ "expected": {
409
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
410
+ "time": 42,
411
+ "request": {
412
+ "method": "GET",
413
+ "url": "/p?a=1",
414
+ "httpVersion": "HTTP/1.1",
415
+ "headers": [],
416
+ "queryString": [
417
+ {
418
+ "name": "a",
419
+ "value": "1"
420
+ }
421
+ ],
422
+ "headersSize": -1,
423
+ "bodySize": -1
424
+ },
425
+ "response": {
426
+ "status": 200,
427
+ "statusText": "",
428
+ "httpVersion": "HTTP/1.1",
429
+ "headers": [],
430
+ "content": {
431
+ "size": 0,
432
+ "mimeType": "application/octet-stream",
433
+ "text": ""
434
+ },
435
+ "headersSize": -1,
436
+ "bodySize": -1
437
+ },
438
+ "timings": {
439
+ "send": 0,
440
+ "wait": 42,
441
+ "receive": 0
442
+ }
443
+ },
444
+ "note": "Query parsing must tolerate a relative URL."
445
+ },
446
+ {
447
+ "id": "har/route-pattern-carried",
448
+ "requirement": "HAR-001",
449
+ "op": "harEntry",
450
+ "input": {
451
+ "captured": {
452
+ "requestId": "9f18a0e2-1c3d-4b5a-8e7f-0a1b2c3d4e5f",
453
+ "startedAt": "2026-01-01T00:00:00.000Z",
454
+ "duration": 42,
455
+ "routePattern": "/car/{id}",
456
+ "request": {
457
+ "method": "GET",
458
+ "url": "http://host/car/7",
459
+ "headers": {}
460
+ },
461
+ "response": {
462
+ "status": 200,
463
+ "headers": {}
464
+ }
465
+ }
466
+ },
467
+ "expected": {
468
+ "startedDateTime": "2026-01-01T00:00:00.000Z",
469
+ "time": 42,
470
+ "request": {
471
+ "method": "GET",
472
+ "url": "http://host/car/7",
473
+ "httpVersion": "HTTP/1.1",
474
+ "headers": [],
475
+ "queryString": [],
476
+ "headersSize": -1,
477
+ "bodySize": -1
478
+ },
479
+ "response": {
480
+ "status": 200,
481
+ "statusText": "",
482
+ "httpVersion": "HTTP/1.1",
483
+ "headers": [],
484
+ "content": {
485
+ "size": 0,
486
+ "mimeType": "application/octet-stream",
487
+ "text": ""
488
+ },
489
+ "headersSize": -1,
490
+ "bodySize": -1
491
+ },
492
+ "timings": {
493
+ "send": 0,
494
+ "wait": 42,
495
+ "receive": 0
496
+ }
497
+ }
498
+ }
499
+ ]
500
+ }
@@ -0,0 +1,175 @@
1
+ {
2
+ "$generated": "GENERATED FILE - do not edit by hand. Inputs live in spec/cases.ts; run `npm run spec:vectors` to regenerate.",
3
+ "$contract": "spec/CONTRACT.md",
4
+ "specVersion": "1.0.0",
5
+ "cases": [
6
+ {
7
+ "id": "mask/ascii",
8
+ "requirement": "MASK-001",
9
+ "op": "mask",
10
+ "input": {
11
+ "apiKey": "rdme_abc123wxyz"
12
+ },
13
+ "expected": "sha512-9EnwUksy3KdeldWsv177Ob0E4K8TsatUMyyhhcaihPd82ZqOT7blNbAH5Cy4iQ4W6DjvGgKE1lSJ4qljG9uviQ==?wxyz"
14
+ },
15
+ {
16
+ "id": "mask/short",
17
+ "requirement": "MASK-006",
18
+ "op": "mask",
19
+ "input": {
20
+ "apiKey": "ab"
21
+ },
22
+ "expected": "sha512-LUCKBxfsGIFYJ4p5bGiQRDYdxv3eKNbwSXO4CJbhgjl1zb8S62P54FkTKO4jXYDptb8apqRPRhf/PK9kAOsXLQ==?ab",
23
+ "note": "Fewer than 4 code points: the tail is the whole key."
24
+ },
25
+ {
26
+ "id": "mask/exactly-four",
27
+ "requirement": "MASK-006",
28
+ "op": "mask",
29
+ "input": {
30
+ "apiKey": "abcd"
31
+ },
32
+ "expected": "sha512-2AIvIGCtbv0perc9zFNVybIUBUsNF3ahNqZp0mp9OxT3OqDQ6/8Z7jMzaPAWS2QZqW2knj5IF1Pn6Wtxa9zLbw==?abcd"
33
+ },
34
+ {
35
+ "id": "mask/utf8-hashing",
36
+ "requirement": "MASK-004",
37
+ "op": "mask",
38
+ "input": {
39
+ "apiKey": "clé-café-secrète"
40
+ },
41
+ "expected": "sha512-zhSdzH1P6XSXWG3BiSVUhMerMf+J5HLarUxl7IxPm+0cLnii9aUdOeuLSIG746lYVUqvnAoEy0OKnaqeMYhhkw==?rète",
42
+ "note": "Pins that the digest is over UTF-8 bytes, not UTF-16 or Latin-1."
43
+ },
44
+ {
45
+ "id": "mask/astral-tail",
46
+ "requirement": "MASK-006",
47
+ "op": "mask",
48
+ "input": {
49
+ "apiKey": "key-with-emoji-🙂🚀"
50
+ },
51
+ "expected": "sha512-G7f+UCyi96tbTnudRvKDmKy2mallqX20KRnHQhzK/xvkaZhzKI2HI8/qO/EiGM3hHsx63E3hy2jFpTAwamxWww==?i-🙂🚀",
52
+ "note": "The single highest-value case in this file. A UTF-16 slice(-4) splits the rocket's surrogate pair and yields a different, ill-formed tail. Code-point slicing gives the last four real characters."
53
+ },
54
+ {
55
+ "id": "mask/combining-marks",
56
+ "requirement": "MASK-006",
57
+ "op": "mask",
58
+ "input": {
59
+ "apiKey": "secret-ȩ́"
60
+ },
61
+ "expected": "sha512-u1F1KyzkFFoPkzxHutl8u1Uw2Gybu3XL5VnUoQ9KwZ9dOEQeVLd5FRz0bp9Dx/t2UFf7yaooTTUJJpYtBTTd4g==?-ȩ́",
62
+ "note": "Combining marks are separate code points and count individually. We do NOT normalize (NFC would change the digest)."
63
+ },
64
+ {
65
+ "id": "mask/cjk",
66
+ "requirement": "MASK-004",
67
+ "op": "mask",
68
+ "input": {
69
+ "apiKey": "鍵-秘密-値-一二三四"
70
+ },
71
+ "expected": "sha512-pdC8U8FfDRw9Le0IfdI0mRJy5+kUpDl7jDbaXp2zOfHCCo4Qm7PTy1/mxUU46K80C96qlVd4XiaC2xwTWJ8owA==?一二三四"
72
+ },
73
+ {
74
+ "id": "mask/base64-padding",
75
+ "requirement": "MASK-003",
76
+ "op": "mask",
77
+ "input": {
78
+ "apiKey": "a"
79
+ },
80
+ "expected": "sha512-H0D8ktokFpR1CXnubPWC8tXX0o4YM13gWrxU0FYOD1MChgxlK/CNVgJSql50IQVG82n7u86MEs/HlXsmUv6adQ==?a",
81
+ "note": "SHA-512 is 64 bytes, so standard base64 always emits exactly 88 chars ending in '=='. Catches a port that used base64url or stripped padding."
82
+ },
83
+ {
84
+ "id": "mask/empty",
85
+ "requirement": "MASK-010",
86
+ "op": "mask",
87
+ "input": {
88
+ "apiKey": ""
89
+ },
90
+ "expected": null
91
+ },
92
+ {
93
+ "id": "mask/null",
94
+ "requirement": "MASK-010",
95
+ "op": "mask",
96
+ "input": {
97
+ "apiKey": null
98
+ },
99
+ "expected": null
100
+ },
101
+ {
102
+ "id": "mask/placeholder-api-key-here",
103
+ "requirement": "MASK-011",
104
+ "op": "mask",
105
+ "input": {
106
+ "apiKey": "API_KEY_HERE"
107
+ },
108
+ "expected": null
109
+ },
110
+ {
111
+ "id": "mask/placeholder-your-api-key",
112
+ "requirement": "MASK-011",
113
+ "op": "mask",
114
+ "input": {
115
+ "apiKey": "YOUR_API_KEY"
116
+ },
117
+ "expected": null
118
+ },
119
+ {
120
+ "id": "mask/placeholder-your-key",
121
+ "requirement": "MASK-011",
122
+ "op": "mask",
123
+ "input": {
124
+ "apiKey": "YOUR_KEY"
125
+ },
126
+ "expected": null
127
+ },
128
+ {
129
+ "id": "mask/placeholder-replace-me",
130
+ "requirement": "MASK-011",
131
+ "op": "mask",
132
+ "input": {
133
+ "apiKey": "REPLACE_ME"
134
+ },
135
+ "expected": null
136
+ },
137
+ {
138
+ "id": "mask/placeholder-case-sensitive",
139
+ "requirement": "MASK-011",
140
+ "op": "mask",
141
+ "input": {
142
+ "apiKey": "api_key_here"
143
+ },
144
+ "expected": "sha512-B+B/ipsQny7yJ+DxnkOroo/6tTYwJxAerKK7+9v74bpnFdPHqcqojnn32/yhOnrdacucCy8kOMcjM2QBDLmmGg==?here",
145
+ "note": "Placeholders match exactly. A lowercase variant is a real key."
146
+ },
147
+ {
148
+ "id": "mask/idempotent",
149
+ "requirement": "MASK-012",
150
+ "op": "mask",
151
+ "input": {
152
+ "apiKey": "sha512-3q2+7w==?wxyz"
153
+ },
154
+ "expected": "sha512-3q2+7w==?wxyz"
155
+ },
156
+ {
157
+ "id": "mask/redacted-passthrough-long",
158
+ "requirement": "MASK-013",
159
+ "op": "mask",
160
+ "input": {
161
+ "apiKey": "<REDACTED:24:u234>"
162
+ },
163
+ "expected": "<REDACTED:24:u234>"
164
+ },
165
+ {
166
+ "id": "mask/redacted-passthrough-short",
167
+ "requirement": "MASK-013",
168
+ "op": "mask",
169
+ "input": {
170
+ "apiKey": "<REDACTED:7>"
171
+ },
172
+ "expected": "<REDACTED:7>"
173
+ }
174
+ ]
175
+ }