coderifts 1.8.1 → 1.8.3
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/README.md +30 -0
- package/bin/coderifts.js +18 -0
- package/corpus/vectors-mcp-fpfn.json +435 -0
- package/corpus/vectors-openapi-fpfn.json +475 -0
- package/dist/cli.js +1882 -25
- package/package.json +6 -5
- package/scripts/copy-corpus.js +26 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "openapi-fp-001",
|
|
4
|
+
"description": "FP: Add optional query parameter. Classic additive change, safe for existing clients/agents.",
|
|
5
|
+
"category": "false-positive",
|
|
6
|
+
"protocol": "openapi",
|
|
7
|
+
"vector_type": "optional_param_add",
|
|
8
|
+
"old": {
|
|
9
|
+
"parameters": [
|
|
10
|
+
{
|
|
11
|
+
"name": "q",
|
|
12
|
+
"in": "query",
|
|
13
|
+
"schema": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"required": true
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"new": {
|
|
21
|
+
"parameters": [
|
|
22
|
+
{
|
|
23
|
+
"name": "q",
|
|
24
|
+
"in": "query",
|
|
25
|
+
"schema": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"required": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "filter",
|
|
32
|
+
"in": "query",
|
|
33
|
+
"schema": {
|
|
34
|
+
"type": "string"
|
|
35
|
+
},
|
|
36
|
+
"required": false
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"expected": {
|
|
41
|
+
"has_breaking": false,
|
|
42
|
+
"risk_max": 10,
|
|
43
|
+
"notes": "Optional query param addition never breaks existing calls that omit it. Must not flag."
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "openapi-fp-002",
|
|
48
|
+
"description": "FP: Add non-required field to 200 response schema. Agents can ignore extra fields.",
|
|
49
|
+
"category": "false-positive",
|
|
50
|
+
"protocol": "openapi",
|
|
51
|
+
"vector_type": "response_field_add",
|
|
52
|
+
"old": {
|
|
53
|
+
"responses": {
|
|
54
|
+
"200": {
|
|
55
|
+
"description": "OK",
|
|
56
|
+
"content": {
|
|
57
|
+
"application/json": {
|
|
58
|
+
"schema": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"id": {
|
|
62
|
+
"type": "string"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"new": {
|
|
72
|
+
"responses": {
|
|
73
|
+
"200": {
|
|
74
|
+
"description": "OK",
|
|
75
|
+
"content": {
|
|
76
|
+
"application/json": {
|
|
77
|
+
"schema": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"id": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
},
|
|
83
|
+
"meta": {
|
|
84
|
+
"type": "object"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"expected": {
|
|
94
|
+
"has_breaking": false,
|
|
95
|
+
"risk_max": 8,
|
|
96
|
+
"notes": "Extra response fields are ignored by most clients unless they use strict additionalProperties:false. Non-breaking."
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "openapi-fp-003",
|
|
101
|
+
"description": "FP: Expand enum in response (more possible values returned). Old clients that handle a subset continue to work.",
|
|
102
|
+
"category": "false-positive",
|
|
103
|
+
"protocol": "openapi",
|
|
104
|
+
"vector_type": "response_enum_expand",
|
|
105
|
+
"old": {
|
|
106
|
+
"responses": {
|
|
107
|
+
"200": {
|
|
108
|
+
"content": {
|
|
109
|
+
"application/json": {
|
|
110
|
+
"schema": {
|
|
111
|
+
"type": "object",
|
|
112
|
+
"properties": {
|
|
113
|
+
"state": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"enum": [
|
|
116
|
+
"open",
|
|
117
|
+
"closed"
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"new": {
|
|
128
|
+
"responses": {
|
|
129
|
+
"200": {
|
|
130
|
+
"content": {
|
|
131
|
+
"application/json": {
|
|
132
|
+
"schema": {
|
|
133
|
+
"type": "object",
|
|
134
|
+
"properties": {
|
|
135
|
+
"state": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"enum": [
|
|
138
|
+
"open",
|
|
139
|
+
"closed",
|
|
140
|
+
"archived"
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"expected": {
|
|
151
|
+
"has_breaking": false,
|
|
152
|
+
"risk_max": 12,
|
|
153
|
+
"notes": "Response enum expansion gives clients more cases to handle optionally. Existing handling of open/closed remains valid."
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "openapi-fn-001",
|
|
158
|
+
"description": "FN: Make existing query param required. Looks like 'just added required flag'. Breaks all callers that omitted it.",
|
|
159
|
+
"category": "false-negative",
|
|
160
|
+
"protocol": "openapi",
|
|
161
|
+
"vector_type": "make_param_required",
|
|
162
|
+
"old": {
|
|
163
|
+
"parameters": [
|
|
164
|
+
{
|
|
165
|
+
"name": "org",
|
|
166
|
+
"in": "query",
|
|
167
|
+
"schema": {
|
|
168
|
+
"type": "string"
|
|
169
|
+
},
|
|
170
|
+
"required": false
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
"new": {
|
|
175
|
+
"parameters": [
|
|
176
|
+
{
|
|
177
|
+
"name": "org",
|
|
178
|
+
"in": "query",
|
|
179
|
+
"schema": {
|
|
180
|
+
"type": "string"
|
|
181
|
+
},
|
|
182
|
+
"required": true
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
"expected": {
|
|
187
|
+
"has_breaking": true,
|
|
188
|
+
"risk_min": 70,
|
|
189
|
+
"notes": "All prior requests without 'org' now invalid. Direct breaking change for agents and SDK clients. Must be caught."
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"id": "openapi-fn-002",
|
|
194
|
+
"description": "FP: Add a new required field to a 200 response schema. Response-tightening is non-breaking for callers under mainstream consumer semantics (and oasdiff's default).",
|
|
195
|
+
"category": "false-positive",
|
|
196
|
+
"protocol": "openapi",
|
|
197
|
+
"vector_type": "response_required_add",
|
|
198
|
+
"old": {
|
|
199
|
+
"responses": {
|
|
200
|
+
"200": {
|
|
201
|
+
"content": {
|
|
202
|
+
"application/json": {
|
|
203
|
+
"schema": {
|
|
204
|
+
"type": "object",
|
|
205
|
+
"properties": {
|
|
206
|
+
"data": {
|
|
207
|
+
"type": "object"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"new": {
|
|
217
|
+
"responses": {
|
|
218
|
+
"200": {
|
|
219
|
+
"content": {
|
|
220
|
+
"application/json": {
|
|
221
|
+
"schema": {
|
|
222
|
+
"type": "object",
|
|
223
|
+
"properties": {
|
|
224
|
+
"data": {
|
|
225
|
+
"type": "object"
|
|
226
|
+
},
|
|
227
|
+
"traceId": {
|
|
228
|
+
"type": "string"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"required": [
|
|
232
|
+
"data",
|
|
233
|
+
"traceId"
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"expected": {
|
|
242
|
+
"has_breaking": false,
|
|
243
|
+
"note": "response-tightening treated as non-breaking (oasdiff default / mainstream consumer compat)",
|
|
244
|
+
"notes": "Reclassified from FN to safe: adding a required field to a response does not break existing callers (they receive more, not less). oasdiff default and mainstream consumer semantics treat this as non-breaking."
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"id": "openapi-fn-003",
|
|
249
|
+
"description": "FN: Rename property inside requestBody schema (remove old, introduce new required name). Classic silent contract break.",
|
|
250
|
+
"category": "false-negative",
|
|
251
|
+
"protocol": "openapi",
|
|
252
|
+
"vector_type": "request_body_rename",
|
|
253
|
+
"old": {
|
|
254
|
+
"requestBody": {
|
|
255
|
+
"content": {
|
|
256
|
+
"application/json": {
|
|
257
|
+
"schema": {
|
|
258
|
+
"type": "object",
|
|
259
|
+
"properties": {
|
|
260
|
+
"userId": {
|
|
261
|
+
"type": "string"
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
"required": [
|
|
265
|
+
"userId"
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
"new": {
|
|
273
|
+
"requestBody": {
|
|
274
|
+
"content": {
|
|
275
|
+
"application/json": {
|
|
276
|
+
"schema": {
|
|
277
|
+
"type": "object",
|
|
278
|
+
"properties": {
|
|
279
|
+
"accountId": {
|
|
280
|
+
"type": "string"
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
"required": [
|
|
284
|
+
"accountId"
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
"expected": {
|
|
292
|
+
"has_breaking": true,
|
|
293
|
+
"risk_min": 75,
|
|
294
|
+
"notes": "Request payload shape changed for a required identifier. Old 'userId' submissions rejected. Must detect rename as breaking."
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"id": "openapi-fn-004",
|
|
299
|
+
"description": "FP: Remove a value from a response enum + make another response field required. Response-tightening is non-breaking for callers under mainstream consumer semantics (and oasdiff's default).",
|
|
300
|
+
"category": "false-positive",
|
|
301
|
+
"protocol": "openapi",
|
|
302
|
+
"vector_type": "response_enum_shrink_required_add",
|
|
303
|
+
"old": {
|
|
304
|
+
"responses": {
|
|
305
|
+
"200": {
|
|
306
|
+
"content": {
|
|
307
|
+
"application/json": {
|
|
308
|
+
"schema": {
|
|
309
|
+
"type": "object",
|
|
310
|
+
"properties": {
|
|
311
|
+
"result": {
|
|
312
|
+
"type": "string",
|
|
313
|
+
"enum": [
|
|
314
|
+
"ok",
|
|
315
|
+
"partial",
|
|
316
|
+
"error"
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
"detail": {
|
|
320
|
+
"type": "string"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
"new": {
|
|
330
|
+
"responses": {
|
|
331
|
+
"200": {
|
|
332
|
+
"content": {
|
|
333
|
+
"application/json": {
|
|
334
|
+
"schema": {
|
|
335
|
+
"type": "object",
|
|
336
|
+
"properties": {
|
|
337
|
+
"result": {
|
|
338
|
+
"type": "string",
|
|
339
|
+
"enum": [
|
|
340
|
+
"ok",
|
|
341
|
+
"partial"
|
|
342
|
+
]
|
|
343
|
+
},
|
|
344
|
+
"detail": {
|
|
345
|
+
"type": "string"
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"required": [
|
|
349
|
+
"result",
|
|
350
|
+
"detail"
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
"expected": {
|
|
359
|
+
"has_breaking": false,
|
|
360
|
+
"note": "response-tightening treated as non-breaking (oasdiff default / mainstream consumer compat)",
|
|
361
|
+
"deep_signals": [
|
|
362
|
+
"enum_value_removed",
|
|
363
|
+
"required_added"
|
|
364
|
+
],
|
|
365
|
+
"notes": "Reclassified from FN to safe: response enum shrink + response required-add are response-side tightening, which oasdiff and mainstream consumer semantics treat as non-breaking. Signals are still surfaced for visibility."
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
"id": "openapi-fn-005",
|
|
370
|
+
"description": "FN: Tighten request body constraints (add format+email, flip nullable true->false).",
|
|
371
|
+
"category": "false-negative",
|
|
372
|
+
"protocol": "openapi",
|
|
373
|
+
"vector_type": "request_body_constraint_tightening",
|
|
374
|
+
"old": {
|
|
375
|
+
"requestBody": {
|
|
376
|
+
"content": {
|
|
377
|
+
"application/json": {
|
|
378
|
+
"schema": {
|
|
379
|
+
"type": "object",
|
|
380
|
+
"properties": {
|
|
381
|
+
"email": {
|
|
382
|
+
"type": "string"
|
|
383
|
+
},
|
|
384
|
+
"nickname": {
|
|
385
|
+
"type": "string",
|
|
386
|
+
"nullable": true
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
"new": {
|
|
395
|
+
"requestBody": {
|
|
396
|
+
"content": {
|
|
397
|
+
"application/json": {
|
|
398
|
+
"schema": {
|
|
399
|
+
"type": "object",
|
|
400
|
+
"properties": {
|
|
401
|
+
"email": {
|
|
402
|
+
"type": "string",
|
|
403
|
+
"format": "email"
|
|
404
|
+
},
|
|
405
|
+
"nickname": {
|
|
406
|
+
"type": "string",
|
|
407
|
+
"nullable": false
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
"expected": {
|
|
416
|
+
"has_breaking": true,
|
|
417
|
+
"risk_min": 50,
|
|
418
|
+
"notes": "Request-side tightening rejects previously-valid payloads. Must be caught."
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"id": "openapi-fp-004",
|
|
423
|
+
"description": "FP: Loosen a request property to nullable (nullable false->true only; format identical both sides).",
|
|
424
|
+
"category": "false-positive",
|
|
425
|
+
"protocol": "openapi",
|
|
426
|
+
"vector_type": "request_property_became_nullable",
|
|
427
|
+
"old": {
|
|
428
|
+
"requestBody": {
|
|
429
|
+
"content": {
|
|
430
|
+
"application/json": {
|
|
431
|
+
"schema": {
|
|
432
|
+
"type": "object",
|
|
433
|
+
"properties": {
|
|
434
|
+
"email": {
|
|
435
|
+
"type": "string",
|
|
436
|
+
"format": "email"
|
|
437
|
+
},
|
|
438
|
+
"nickname": {
|
|
439
|
+
"type": "string",
|
|
440
|
+
"nullable": false
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
"new": {
|
|
449
|
+
"requestBody": {
|
|
450
|
+
"content": {
|
|
451
|
+
"application/json": {
|
|
452
|
+
"schema": {
|
|
453
|
+
"type": "object",
|
|
454
|
+
"properties": {
|
|
455
|
+
"email": {
|
|
456
|
+
"type": "string",
|
|
457
|
+
"format": "email"
|
|
458
|
+
},
|
|
459
|
+
"nickname": {
|
|
460
|
+
"type": "string",
|
|
461
|
+
"nullable": true
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
"expected": {
|
|
470
|
+
"has_breaking": false,
|
|
471
|
+
"risk_max": 10,
|
|
472
|
+
"notes": "Request-side loosening (nullable false->true, format unchanged): all previously-valid payloads stay valid. Must NOT be flagged breaking."
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
]
|