@vantageos/backend-doctor 0.1.5 → 0.1.6
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/dist/detectors/source/jobs.js +113 -42
- package/package.json +1 -1
|
@@ -142,57 +142,128 @@ export function scanR20(files) {
|
|
|
142
142
|
//
|
|
143
143
|
// SOURCE READ: convex/credentials.ts issues a Bearer under a rate limit of
|
|
144
144
|
// `maxPerWindow: 5` over `windowMs: 60_000` (lines 513-514), rejecting with a
|
|
145
|
-
// `429` (line 523)
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
145
|
+
// `429` (line 523); mcp-server/server-http.ts declares the DCR `/register`
|
|
146
|
+
// limiter as the `REGISTER_RATE_LIMIT = 5` / `REGISTER_RATE_WINDOW_MS = 60_000`
|
|
147
|
+
// const pair (lines 297-298) — numeric rate + numeric window at ONE site.
|
|
148
|
+
//
|
|
149
|
+
// SITE-scoped, not file-scoped. Two defects the old file-wide scan carried:
|
|
150
|
+
// (1) FALSE POSITIVE — `referencesRate` was true for ANY file containing the
|
|
151
|
+
// substring `rateLimit`, so the schema TABLE NAME `credentialsRateLimits`
|
|
152
|
+
// (convex/schema.ts) dragged schema.ts into the scan, and the file-wide
|
|
153
|
+
// window pattern then matched the unrelated `2000` in
|
|
154
|
+
// `body: v.string(), // truncated to 2000 chars` (schema.ts:540) — a
|
|
155
|
+
// phantom R-23 violation on a v.string() field. A schema table declaration
|
|
156
|
+
// is NOT a rate-limit control, and a numeric elsewhere in the file is not
|
|
157
|
+
// "this control's window".
|
|
158
|
+
// (2) FILE→SITE leak — because window/max/exception were found file-wide, ONE
|
|
159
|
+
// `rate-limit exception:` marker anywhere conformed EVERY control in the
|
|
160
|
+
// file. The window was never bound to its own max/control.
|
|
161
|
+
//
|
|
162
|
+
// PATTERN: locate each CONTROL SITE (a local region declaring/enforcing a
|
|
163
|
+
// limiter — a `maxPerWindow:` key, a `*_RATE_LIMIT =` numeric const, a
|
|
164
|
+
// `per minute/second/hour` check, or a written-exception marker). A schema
|
|
165
|
+
// `defineTable(...)` block or a validator field (`v.number()`) is NEVER a
|
|
166
|
+
// control site. Each site is judged WITHIN its own local line span: a numeric
|
|
167
|
+
// max AND a numeric window there -> conform; else an exception marker bound to
|
|
168
|
+
// THAT site -> conform; else -> violate. A numeric/exception on a DIFFERENT
|
|
169
|
+
// site does not carry.
|
|
150
170
|
// ---------------------------------------------------------------------------
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
const NUMERIC_MAX = /maxperwindow\s*:\s*\d|\b\d+\s*(req|requests|per)\b/i;
|
|
171
|
+
const NUMERIC_WINDOW = /windowms\s*:\s*\d|\brate_?window\w*\s*=\s*\d|(\d[\d_]*)\s*(ms|_?000)\b|per\s+(minute|second|hour)/i;
|
|
172
|
+
const NUMERIC_MAX = /maxperwindow\s*:\s*\d|\brate_?limit\w*\s*=\s*\d|\b\d+\s*(req|requests|per)\b/i;
|
|
154
173
|
const WRITTEN_EXCEPTION = /allow-unbounded|written exception|rate-limit exception/i;
|
|
155
|
-
|
|
156
|
-
|
|
174
|
+
// A limiter DECLARATION/enforcement, not a mere keyword mention:
|
|
175
|
+
// - `maxPerWindow:` — the per-window MAX key (the definitive throttle signal;
|
|
176
|
+
// a lone `windowMs` is only a duration and appears everywhere, so it is
|
|
177
|
+
// never an anchor by itself — only a window CONFIRMATION inside a site).
|
|
178
|
+
// - `*_RATE_LIMIT = <numeric>` — the const-pair form (server-http.ts).
|
|
179
|
+
// A `per minute/second/hour` phrase is NOT an anchor: it appears in
|
|
180
|
+
// human-readable rejection strings (`"...5 registrations per minute per IP."`)
|
|
181
|
+
// that are not control declarations. It survives only as a WINDOW confirmation
|
|
182
|
+
// inside a site already anchored by a real limiter declaration.
|
|
183
|
+
const RATE_CONTROL_DECL = /maxperwindow\s*:|\brate_?limit\w*\s*=\s*\d/i;
|
|
184
|
+
// A schema table declaration or a validator field is never a control SITE —
|
|
185
|
+
// this is what excludes `credentialsRateLimits: defineTable(...)` and
|
|
186
|
+
// `maxPerWindow: v.number()` from anchoring a site.
|
|
187
|
+
const SCHEMA_DECL = /definetable\s*\(|v\.\w+\s*\(/i;
|
|
188
|
+
// Local span geometry: consecutive anchors within MERGE_GAP lines collapse into
|
|
189
|
+
// ONE site (a const group / a single call's arg object); the site's judgement
|
|
190
|
+
// window is that anchor run padded by CONTEXT lines each side — never the file.
|
|
191
|
+
const CONTEXT = 3;
|
|
192
|
+
const MERGE_GAP = 3;
|
|
193
|
+
function isControlAnchor(raw) {
|
|
194
|
+
// An explicit written exception always marks a site, even on an odd line.
|
|
195
|
+
if (WRITTEN_EXCEPTION.test(raw))
|
|
196
|
+
return true;
|
|
197
|
+
// A schema table decl / validator field is never a control site.
|
|
198
|
+
if (SCHEMA_DECL.test(raw))
|
|
199
|
+
return false;
|
|
200
|
+
return RATE_CONTROL_DECL.test(raw);
|
|
157
201
|
}
|
|
158
202
|
export function scanR23(files) {
|
|
159
203
|
const scan = emptyScan();
|
|
160
204
|
for (const f of files) {
|
|
161
|
-
if (!isJudgeable(f)
|
|
205
|
+
if (!isJudgeable(f))
|
|
162
206
|
continue;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
let
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
if (!windowLine && NUMERIC_WINDOW.test(l.raw))
|
|
170
|
-
windowLine = l.n;
|
|
171
|
-
if (!maxLine && NUMERIC_MAX.test(l.raw))
|
|
172
|
-
maxLine = l.n;
|
|
173
|
-
if (!exception && WRITTEN_EXCEPTION.test(l.raw))
|
|
174
|
-
exception = l.n;
|
|
175
|
-
}
|
|
176
|
-
if (windowLine && maxLine) {
|
|
177
|
-
scan.conform.push({
|
|
178
|
-
rel: f.rel,
|
|
179
|
-
n: maxLine,
|
|
180
|
-
note: `rate control declares a numeric max (line ${maxLine}) and window (line ${windowLine})`,
|
|
181
|
-
});
|
|
207
|
+
// 1. Collect the code-line indices that anchor a control site.
|
|
208
|
+
const anchors = [];
|
|
209
|
+
for (let i = 0; i < f.lines.length; i++) {
|
|
210
|
+
const l = f.lines[i];
|
|
211
|
+
if (code(l) && isControlAnchor(l.raw))
|
|
212
|
+
anchors.push(i);
|
|
182
213
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
214
|
+
if (anchors.length === 0)
|
|
215
|
+
continue;
|
|
216
|
+
// 2. Merge adjacent anchors (gap <= MERGE_GAP) into one site.
|
|
217
|
+
const sites = [];
|
|
218
|
+
for (const idx of anchors) {
|
|
219
|
+
const open = sites[sites.length - 1];
|
|
220
|
+
if (open && idx - open.last <= MERGE_GAP) {
|
|
221
|
+
open.last = idx;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
sites.push({ first: idx, last: idx });
|
|
225
|
+
}
|
|
189
226
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
227
|
+
// 3. Judge each site WITHIN its own local span — never file-wide.
|
|
228
|
+
for (const site of sites) {
|
|
229
|
+
const from = Math.max(0, site.first - CONTEXT);
|
|
230
|
+
const to = Math.min(f.lines.length - 1, site.last + CONTEXT);
|
|
231
|
+
let windowLine = 0;
|
|
232
|
+
let maxLine = 0;
|
|
233
|
+
let exception = 0;
|
|
234
|
+
for (let j = from; j <= to; j++) {
|
|
235
|
+
const l = f.lines[j];
|
|
236
|
+
if (!code(l))
|
|
237
|
+
continue;
|
|
238
|
+
if (!windowLine && NUMERIC_WINDOW.test(l.raw))
|
|
239
|
+
windowLine = l.n;
|
|
240
|
+
if (!maxLine && NUMERIC_MAX.test(l.raw))
|
|
241
|
+
maxLine = l.n;
|
|
242
|
+
if (!exception && WRITTEN_EXCEPTION.test(l.raw))
|
|
243
|
+
exception = l.n;
|
|
244
|
+
}
|
|
245
|
+
const repLine = f.lines[site.first].n;
|
|
246
|
+
if (windowLine && maxLine) {
|
|
247
|
+
scan.conform.push({
|
|
248
|
+
rel: f.rel,
|
|
249
|
+
n: maxLine,
|
|
250
|
+
note: `rate control site declares a numeric max (line ${maxLine}) and window (line ${windowLine}) bound to the same site`,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else if (exception) {
|
|
254
|
+
scan.conform.push({
|
|
255
|
+
rel: f.rel,
|
|
256
|
+
n: exception,
|
|
257
|
+
note: `rate bound absent but a written exception is bound to THIS control site (line ${exception})`,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
scan.violate.push({
|
|
262
|
+
rel: f.rel,
|
|
263
|
+
n: windowLine || maxLine || repLine,
|
|
264
|
+
note: "rate-limit control site present but its bound is not numeric (placeholder) and no written exception is bound to this site",
|
|
265
|
+
});
|
|
266
|
+
}
|
|
196
267
|
}
|
|
197
268
|
}
|
|
198
269
|
return scan;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantageos/backend-doctor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A conformance instrument that measures the VantagePeers backend against the pinned backend standard. The THIRD doctor built ON the @vantageos/mcp-doctor engine — never a third engine. It consumes runDoctor/renderTable and adds only detectors.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|