@cybedefend/vibedefend 1.4.7 → 1.6.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/README.md +77 -2
- package/dist/api/gateway-request.js +49 -0
- package/dist/api/gateway-request.js.map +1 -0
- package/dist/api/projects.js +67 -0
- package/dist/api/projects.js.map +1 -1
- package/dist/api/repository-link.js +157 -0
- package/dist/api/repository-link.js.map +1 -0
- package/dist/auth/auth-store.js +107 -25
- package/dist/auth/auth-store.js.map +1 -1
- package/dist/auth/auth.js +21 -0
- package/dist/auth/auth.js.map +1 -1
- package/dist/clients/cursor.js +5 -1
- package/dist/clients/cursor.js.map +1 -1
- package/dist/clients/vscode.js +38 -29
- package/dist/clients/vscode.js.map +1 -1
- package/dist/commands/mcp/allow.js +219 -0
- package/dist/commands/mcp/allow.js.map +1 -0
- package/dist/commands/mcp/connect.js +337 -0
- package/dist/commands/mcp/connect.js.map +1 -0
- package/dist/commands/mcp/index.js +170 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/mcp/proxy.js +264 -0
- package/dist/commands/mcp/proxy.js.map +1 -0
- package/dist/commands/mcp/scan.js +349 -0
- package/dist/commands/mcp/scan.js.map +1 -0
- package/dist/commands/mcp/sync.js +215 -0
- package/dist/commands/mcp/sync.js.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +78 -12
- package/dist/diagnostics.js.map +1 -1
- package/dist/doctor.js +19 -0
- package/dist/doctor.js.map +1 -1
- package/dist/guards-evaluator/analysis-types.js +27 -0
- package/dist/guards-evaluator/analysis-types.js.map +1 -0
- package/dist/guards-evaluator/command-analysis.js +572 -0
- package/dist/guards-evaluator/command-analysis.js.map +1 -0
- package/dist/guards-evaluator/command-view.js +586 -0
- package/dist/guards-evaluator/command-view.js.map +1 -0
- package/dist/guards-evaluator/env.js +11 -0
- package/dist/guards-evaluator/env.js.map +1 -0
- package/dist/guards-evaluator/evaluate.js +91 -41
- package/dist/guards-evaluator/evaluate.js.map +1 -1
- package/dist/guards-evaluator/index.js +2 -1
- package/dist/guards-evaluator/index.js.map +1 -1
- package/dist/guards-evaluator/inline-code.js +259 -0
- package/dist/guards-evaluator/inline-code.js.map +1 -0
- package/dist/guards-evaluator/normalize.js +716 -0
- package/dist/guards-evaluator/normalize.js.map +1 -0
- package/dist/guards-evaluator/preprocess.js +13 -5
- package/dist/guards-evaluator/preprocess.js.map +1 -1
- package/dist/guards-evaluator/redact.js +19 -0
- package/dist/guards-evaluator/redact.js.map +1 -1
- package/dist/guards-evaluator/regex.js +25 -3
- package/dist/guards-evaluator/regex.js.map +1 -1
- package/dist/guards-evaluator/safe-commands.js +155 -0
- package/dist/guards-evaluator/safe-commands.js.map +1 -0
- package/dist/guards-evaluator/triage.js +315 -0
- package/dist/guards-evaluator/triage.js.map +1 -0
- package/dist/hook-runner.js +24873 -5068
- package/dist/hooks/install.js +38 -0
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/config.js +38 -0
- package/dist/hooks/runtime/config.js.map +1 -1
- package/dist/hooks/runtime/emit.js +126 -53
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +27 -7
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/gateway-http-error.js +34 -0
- package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
- package/dist/hooks/runtime/guard-rules-cache.js +139 -17
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
- package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
- package/dist/hooks/runtime/judge-cache.js +6 -0
- package/dist/hooks/runtime/judge-cache.js.map +1 -1
- package/dist/hooks/runtime/judge-triage.js +193 -0
- package/dist/hooks/runtime/judge-triage.js.map +1 -0
- package/dist/hooks/runtime/judge.js +7 -1
- package/dist/hooks/runtime/judge.js.map +1 -1
- package/dist/hooks/runtime/pre-compact.js +21 -6
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +108 -17
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/retry-policy.js +57 -0
- package/dist/hooks/runtime/retry-policy.js.map +1 -0
- package/dist/hooks/runtime/review-sessions.js +74 -0
- package/dist/hooks/runtime/review-sessions.js.map +1 -0
- package/dist/hooks/runtime/script-resolve.js +695 -0
- package/dist/hooks/runtime/script-resolve.js.map +1 -0
- package/dist/hooks/runtime/session-activation.js +226 -0
- package/dist/hooks/runtime/session-activation.js.map +1 -0
- package/dist/hooks/runtime/session-review.js +174 -46
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +35 -4
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/session-writes.js +232 -0
- package/dist/hooks/runtime/session-writes.js.map +1 -0
- package/dist/hooks/runtime/sniff.js +26 -7
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/target-resolve.js +336 -0
- package/dist/hooks/runtime/target-resolve.js.map +1 -0
- package/dist/hooks/runtime/unmapped-tools.js +93 -0
- package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
- package/dist/hooks/runtime/usage-block.js +4 -0
- package/dist/hooks/runtime/usage-block.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +8 -2
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/hooks/runtime/wire-text.js +41 -0
- package/dist/hooks/runtime/wire-text.js.map +1 -0
- package/dist/hooks/runtime/work-dir.js +84 -0
- package/dist/hooks/runtime/work-dir.js.map +1 -0
- package/dist/index.js +45 -12
- package/dist/index.js.map +1 -1
- package/dist/install.js +174 -11
- package/dist/install.js.map +1 -1
- package/dist/link.js +74 -48
- package/dist/link.js.map +1 -1
- package/dist/login.js +99 -14
- package/dist/login.js.map +1 -1
- package/dist/mcp/auth/agent-sign-ins.js +174 -0
- package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
- package/dist/mcp/auth/callback.js +200 -0
- package/dist/mcp/auth/callback.js.map +1 -0
- package/dist/mcp/auth/connect.js +392 -0
- package/dist/mcp/auth/connect.js.map +1 -0
- package/dist/mcp/auth/discovery.js +399 -0
- package/dist/mcp/auth/discovery.js.map +1 -0
- package/dist/mcp/auth/oauth.js +326 -0
- package/dist/mcp/auth/oauth.js.map +1 -0
- package/dist/mcp/auth/probe.js +128 -0
- package/dist/mcp/auth/probe.js.map +1 -0
- package/dist/mcp/auth/secrets.js +446 -0
- package/dist/mcp/auth/secrets.js.map +1 -0
- package/dist/mcp/auth/store.js +260 -0
- package/dist/mcp/auth/store.js.map +1 -0
- package/dist/mcp/auth/tokenSource.js +55 -0
- package/dist/mcp/auth/tokenSource.js.map +1 -0
- package/dist/mcp/config/atomicWrite.js +98 -0
- package/dist/mcp/config/atomicWrite.js.map +1 -0
- package/dist/mcp/config/clients.js +171 -0
- package/dist/mcp/config/clients.js.map +1 -0
- package/dist/mcp/config/cybedefend-servers.js +48 -0
- package/dist/mcp/config/cybedefend-servers.js.map +1 -0
- package/dist/mcp/config/discover.js +114 -0
- package/dist/mcp/config/discover.js.map +1 -0
- package/dist/mcp/config/hook.js +123 -0
- package/dist/mcp/config/hook.js.map +1 -0
- package/dist/mcp/config/index.js +11 -0
- package/dist/mcp/config/index.js.map +1 -0
- package/dist/mcp/config/install.js +132 -0
- package/dist/mcp/config/install.js.map +1 -0
- package/dist/mcp/config/installed.js +37 -0
- package/dist/mcp/config/installed.js.map +1 -0
- package/dist/mcp/config/jsonEdit.js +119 -0
- package/dist/mcp/config/jsonEdit.js.map +1 -0
- package/dist/mcp/config/lock.js +102 -0
- package/dist/mcp/config/lock.js.map +1 -0
- package/dist/mcp/config/proxyBinary.js +211 -0
- package/dist/mcp/config/proxyBinary.js.map +1 -0
- package/dist/mcp/config/rewrite.js +388 -0
- package/dist/mcp/config/rewrite.js.map +1 -0
- package/dist/mcp/config/types.js +34 -0
- package/dist/mcp/config/types.js.map +1 -0
- package/dist/mcp/proxy/audit.js +83 -0
- package/dist/mcp/proxy/audit.js.map +1 -0
- package/dist/mcp/proxy/authInterceptor.js +119 -0
- package/dist/mcp/proxy/authInterceptor.js.map +1 -0
- package/dist/mcp/proxy/expand.js +93 -0
- package/dist/mcp/proxy/expand.js.map +1 -0
- package/dist/mcp/proxy/inject.js +397 -0
- package/dist/mcp/proxy/inject.js.map +1 -0
- package/dist/mcp/proxy/intercept.js +37 -0
- package/dist/mcp/proxy/intercept.js.map +1 -0
- package/dist/mcp/proxy/jsonrpc.js +153 -0
- package/dist/mcp/proxy/jsonrpc.js.map +1 -0
- package/dist/mcp/proxy/log.js +109 -0
- package/dist/mcp/proxy/log.js.map +1 -0
- package/dist/mcp/proxy/paths.js +53 -0
- package/dist/mcp/proxy/paths.js.map +1 -0
- package/dist/mcp/proxy/proxy.js +510 -0
- package/dist/mcp/proxy/proxy.js.map +1 -0
- package/dist/mcp/proxy/spec.js +203 -0
- package/dist/mcp/proxy/spec.js.map +1 -0
- package/dist/mcp/proxy/sse.js +77 -0
- package/dist/mcp/proxy/sse.js.map +1 -0
- package/dist/mcp/proxy/upstream.js +2 -0
- package/dist/mcp/proxy/upstream.js.map +1 -0
- package/dist/mcp/proxy/upstreamHttp.js +499 -0
- package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
- package/dist/mcp/proxy/upstreamStdio.js +188 -0
- package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
- package/dist/mcp/proxy/upstreams.js +143 -0
- package/dist/mcp/proxy/upstreams.js.map +1 -0
- package/dist/mcp/proxy/verifyInterceptor.js +559 -0
- package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
- package/dist/mcp/proxy/windowsCommand.js +99 -0
- package/dist/mcp/proxy/windowsCommand.js.map +1 -0
- package/dist/mcp/scan/args.js +228 -0
- package/dist/mcp/scan/args.js.map +1 -0
- package/dist/mcp/scan/results.js +253 -0
- package/dist/mcp/scan/results.js.map +1 -0
- package/dist/mcp/scan/types.js +40 -0
- package/dist/mcp/scan/types.js.map +1 -0
- package/dist/mcp/verify/api.js +475 -0
- package/dist/mcp/verify/api.js.map +1 -0
- package/dist/mcp/verify/backend.js +143 -0
- package/dist/mcp/verify/backend.js.map +1 -0
- package/dist/mcp/verify/cache.js +182 -0
- package/dist/mcp/verify/cache.js.map +1 -0
- package/dist/mcp/verify/contract-errors.js +198 -0
- package/dist/mcp/verify/contract-errors.js.map +1 -0
- package/dist/mcp/verify/digest.js +91 -0
- package/dist/mcp/verify/digest.js.map +1 -0
- package/dist/mcp/verify/factory.js +56 -0
- package/dist/mcp/verify/factory.js.map +1 -0
- package/dist/mcp/verify/identity.js +173 -0
- package/dist/mcp/verify/identity.js.map +1 -0
- package/dist/mcp/verify/policy-store.js +63 -0
- package/dist/mcp/verify/policy-store.js.map +1 -0
- package/dist/mcp/verify/policy.js +158 -0
- package/dist/mcp/verify/policy.js.map +1 -0
- package/dist/mcp/verify/pool.js +27 -0
- package/dist/mcp/verify/pool.js.map +1 -0
- package/dist/mcp/verify/token-refresh.js +44 -0
- package/dist/mcp/verify/token-refresh.js.map +1 -0
- package/dist/mcp/verify/token.js +67 -0
- package/dist/mcp/verify/token.js.map +1 -0
- package/dist/mcp/verify/verifier.js +1009 -0
- package/dist/mcp/verify/verifier.js.map +1 -0
- package/dist/org-gate.js +1 -1
- package/dist/org-gate.js.map +1 -1
- package/dist/org.js +146 -0
- package/dist/org.js.map +1 -0
- package/dist/project-create.js +129 -0
- package/dist/project-create.js.map +1 -0
- package/dist/prompts.js +21 -0
- package/dist/prompts.js.map +1 -1
- package/dist/re2.wasm +0 -0
- package/dist/status.js +61 -0
- package/dist/status.js.map +1 -1
- package/dist/uninstall.js +49 -4
- package/dist/uninstall.js.map +1 -1
- package/dist/utils.js +62 -6
- package/dist/utils.js.map +1 -1
- package/package.json +10 -3
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Violations (deny/warn outcomes) are appended as JSON lines to a local
|
|
5
5
|
* buffer file (`~/.cybedefend/guards-violations-buffer.jsonl`) and flushed
|
|
6
|
-
* to the gateway
|
|
6
|
+
* to the gateway by a detached `flush-violations` process that the hook
|
|
7
|
+
* starts when there is something to post (BACK-240 L2: the hook used to
|
|
8
|
+
* await the POST before returning, on every tool call).
|
|
7
9
|
*
|
|
8
10
|
* Why JSONL + append semantics?
|
|
9
11
|
* - Append to a file is atomic at the OS level for small writes.
|
|
@@ -23,16 +25,54 @@
|
|
|
23
25
|
* for another) only the failed groups are kept in the buffer; the
|
|
24
26
|
* successful ones are purged.
|
|
25
27
|
*
|
|
28
|
+
* Refused groups are held back (BACK-240 L2):
|
|
29
|
+
* - A group the gateway refuses for good (400 / 403 / 404 / 422) used to be
|
|
30
|
+
* re-posted by every flush, i.e. on every tool call, forever. It is now
|
|
31
|
+
* held back for an hour (`guards-violations-holds.json`, next to the
|
|
32
|
+
* buffer), then tried again. Its records are NOT purged: a 403 caused by
|
|
33
|
+
* the organisation's `writes_blocked` goes away once it upgrades.
|
|
34
|
+
* - `vibedefend login` lifts every hold (`liftHolds`), so the records of a
|
|
35
|
+
* user who just re-authenticated are posted by the next flush.
|
|
36
|
+
* - A 401 holds the group back 1, then 5, then 15 minutes (consecutive 401s
|
|
37
|
+
* with the same token); a new token is tried at once.
|
|
38
|
+
* - Any other failure (5xx, 429, a timeout, no network) holds the group back
|
|
39
|
+
* a minute (a 429's `Retry-After` when longer, at most an hour), then the
|
|
40
|
+
* next flush retries it: no flush process is started on every tool call
|
|
41
|
+
* for the length of an outage.
|
|
42
|
+
*
|
|
43
|
+
* Bounded, one flush at a time (BACK-240 L2):
|
|
44
|
+
* - A flush keeps at most the newest `MAX_BUFFERED_RECORDS` records, none
|
|
45
|
+
* older than `MAX_RECORD_AGE_MS`: a group held back for good can no
|
|
46
|
+
* longer grow the file (and every POST) without limit.
|
|
47
|
+
* - Flushes take a lock file (`guards-violations-flush.lock`); a second
|
|
48
|
+
* flush started meanwhile returns at once instead of posting the same
|
|
49
|
+
* records again. The flush refreshes it before each POST; a lock older
|
|
50
|
+
* than `FLUSH_LOCK_STALE_MS` is a crashed flush's and is taken over.
|
|
51
|
+
* - The rewrite keeps whatever a concurrent hook appended while the flush
|
|
52
|
+
* was posting (it used to erase it).
|
|
53
|
+
*
|
|
26
54
|
* Violation semantics:
|
|
27
55
|
* - `deny` → outcome = 'denied'
|
|
28
56
|
* - `warn` → outcome = 'warned'
|
|
29
57
|
* - `allow` → no violation recorded
|
|
30
58
|
*/
|
|
31
|
-
import { appendFileSync, existsSync, readFileSync, writeFileSync, mkdirSync, } from 'node:fs';
|
|
59
|
+
import { appendFileSync, closeSync, existsSync, openSync, readFileSync, writeFileSync, writeSync, mkdirSync, rmSync, statSync, utimesSync, } from 'node:fs';
|
|
32
60
|
import { dirname } from 'node:path';
|
|
33
61
|
import { homedir } from 'node:os';
|
|
34
62
|
import { join } from 'node:path';
|
|
63
|
+
import { httpStatusOf, retryAfterOf } from './gateway-http-error.js';
|
|
64
|
+
import { tokenFingerprint, transientRetryMs, unauthorizedBackoffMs, } from './retry-policy.js';
|
|
35
65
|
export const DEFAULT_BUFFER_FILE = join(homedir(), '.cybedefend', 'guards-violations-buffer.jsonl');
|
|
66
|
+
/** Statuses the gateway gives for good: the group is held back, not replayed. */
|
|
67
|
+
export const REFUSED_STATUSES = new Set([400, 403, 404, 422]);
|
|
68
|
+
/** How long a refused group is held back before it is tried again. */
|
|
69
|
+
export const REFUSED_RETRY_MS = 60 * 60 * 1000;
|
|
70
|
+
/** The buffer keeps at most this many records (the newest)... */
|
|
71
|
+
export const MAX_BUFFERED_RECORDS = 500;
|
|
72
|
+
/** ...none older than this. */
|
|
73
|
+
export const MAX_RECORD_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
74
|
+
/** A flush lock older than this was left by a crashed flush. */
|
|
75
|
+
export const FLUSH_LOCK_STALE_MS = 60_000;
|
|
36
76
|
/**
|
|
37
77
|
* Create an injectable violations buffer (testable via custom bufferFile).
|
|
38
78
|
*
|
|
@@ -41,11 +81,14 @@ export const DEFAULT_BUFFER_FILE = join(homedir(), '.cybedefend', 'guards-violat
|
|
|
41
81
|
*/
|
|
42
82
|
export function makeViolationsBuffer(opts = {}) {
|
|
43
83
|
const bufferFile = opts.bufferFile ?? DEFAULT_BUFFER_FILE;
|
|
84
|
+
const holdsFile = opts.holdsFile ?? join(dirname(bufferFile), 'guards-violations-holds.json');
|
|
85
|
+
const lockFile = opts.lockFile ?? join(dirname(bufferFile), 'guards-violations-flush.lock');
|
|
86
|
+
const now = opts.now ?? Date.now;
|
|
44
87
|
function bufferViolation(ctx, v) {
|
|
45
88
|
const record = {
|
|
46
89
|
...v,
|
|
47
90
|
projectId: ctx.projectId,
|
|
48
|
-
timestamp: new Date().toISOString(),
|
|
91
|
+
timestamp: new Date(now()).toISOString(),
|
|
49
92
|
};
|
|
50
93
|
try {
|
|
51
94
|
ensureDirFor(bufferFile);
|
|
@@ -58,44 +101,23 @@ export function makeViolationsBuffer(opts = {}) {
|
|
|
58
101
|
async function flushViolations(ctx, postFn) {
|
|
59
102
|
if (!existsSync(bufferFile))
|
|
60
103
|
return;
|
|
61
|
-
|
|
104
|
+
if (!acquireLock())
|
|
105
|
+
return; // another flush is posting these records
|
|
62
106
|
try {
|
|
63
|
-
|
|
107
|
+
await flushLocked(ctx, postFn);
|
|
64
108
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
if (!content)
|
|
69
|
-
return;
|
|
70
|
-
const records = [];
|
|
71
|
-
for (const line of content.split('\n')) {
|
|
72
|
-
const trimmed = line.trim();
|
|
73
|
-
if (!trimmed)
|
|
74
|
-
continue;
|
|
75
|
-
try {
|
|
76
|
-
const parsed = JSON.parse(trimmed);
|
|
77
|
-
// Drop records that pre-date the projectId field or are malformed
|
|
78
|
-
// beyond recovery — keeping them would block the flush forever
|
|
79
|
-
// since they cannot be addressed to a project.
|
|
80
|
-
if (typeof parsed.projectId === 'string' && parsed.projectId) {
|
|
81
|
-
records.push(parsed);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
// Corrupt line — drop it
|
|
86
|
-
}
|
|
109
|
+
finally {
|
|
110
|
+
releaseLock();
|
|
87
111
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
writeFileSync(bufferFile, '', 'utf8');
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
// Best-effort
|
|
96
|
-
}
|
|
112
|
+
}
|
|
113
|
+
async function flushLocked(ctx, postFn) {
|
|
114
|
+
const snapshot = readBuffer();
|
|
115
|
+
if (!snapshot || !snapshot.content.trim())
|
|
97
116
|
return;
|
|
98
|
-
|
|
117
|
+
const flushedAt = now();
|
|
118
|
+
// Unreadable lines, records without a project and records past the cap
|
|
119
|
+
// are dropped here: the rewrite below only writes back what is kept.
|
|
120
|
+
const records = capRecords(parseRecords(snapshot.content), flushedAt);
|
|
99
121
|
// Group by projectId, preserving original insertion order within each group.
|
|
100
122
|
const groups = new Map();
|
|
101
123
|
for (const r of records) {
|
|
@@ -107,39 +129,288 @@ export function makeViolationsBuffer(opts = {}) {
|
|
|
107
129
|
}
|
|
108
130
|
const BATCH_SIZE = 100;
|
|
109
131
|
const failed = [];
|
|
132
|
+
const holds = readHolds();
|
|
133
|
+
const fingerprint = tokenFingerprint(ctx.token);
|
|
110
134
|
for (const [projectId, group] of groups) {
|
|
135
|
+
if (!isDue(holds[projectId], flushedAt, fingerprint)) {
|
|
136
|
+
// Refused a moment ago: keep it, do not ask again yet.
|
|
137
|
+
failed.push(...group);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
let groupError = null;
|
|
111
141
|
let groupFailed = false;
|
|
112
142
|
for (let i = 0; i < group.length; i += BATCH_SIZE) {
|
|
113
143
|
const batch = group.slice(i, i + BATCH_SIZE);
|
|
144
|
+
touchLock();
|
|
114
145
|
try {
|
|
115
146
|
await postFn(ctx, projectId, batch);
|
|
116
147
|
}
|
|
117
|
-
catch {
|
|
148
|
+
catch (e) {
|
|
149
|
+
groupError = e;
|
|
118
150
|
groupFailed = true;
|
|
119
151
|
break;
|
|
120
152
|
}
|
|
121
153
|
}
|
|
122
|
-
if (groupFailed) {
|
|
123
|
-
|
|
154
|
+
if (!groupFailed) {
|
|
155
|
+
delete holds[projectId];
|
|
156
|
+
continue;
|
|
124
157
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
158
|
+
failed.push(...group);
|
|
159
|
+
const status = httpStatusOf(groupError);
|
|
160
|
+
const previous = holds[projectId];
|
|
161
|
+
if (status !== null && REFUSED_STATUSES.has(status)) {
|
|
162
|
+
holds[projectId] = {
|
|
163
|
+
status,
|
|
164
|
+
failedAt: flushedAt,
|
|
165
|
+
retryAt: flushedAt + REFUSED_RETRY_MS,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
else if (status === 401) {
|
|
169
|
+
const unauthorized = previous?.status === 401 && previous.token === fingerprint
|
|
170
|
+
? (previous.unauthorized ?? 0) + 1
|
|
171
|
+
: 1;
|
|
172
|
+
holds[projectId] = {
|
|
173
|
+
status,
|
|
174
|
+
failedAt: flushedAt,
|
|
175
|
+
retryAt: flushedAt + unauthorizedBackoffMs(unauthorized),
|
|
176
|
+
unauthorized,
|
|
177
|
+
token: fingerprint,
|
|
178
|
+
};
|
|
130
179
|
}
|
|
131
180
|
else {
|
|
132
|
-
|
|
133
|
-
|
|
181
|
+
// Transient: wait a little (or what a 429 asked for), then retry.
|
|
182
|
+
holds[projectId] = {
|
|
183
|
+
status,
|
|
184
|
+
failedAt: flushedAt,
|
|
185
|
+
retryAt: flushedAt + transientRetryMs(retryAfterOf(groupError)),
|
|
186
|
+
};
|
|
134
187
|
}
|
|
135
188
|
}
|
|
189
|
+
// A hold only matters while its project still has records.
|
|
190
|
+
for (const projectId of Object.keys(holds)) {
|
|
191
|
+
if (!groups.has(projectId))
|
|
192
|
+
delete holds[projectId];
|
|
193
|
+
}
|
|
194
|
+
writeHolds(holds);
|
|
195
|
+
// Rewrite the file with only the failed groups, plus whatever concurrent
|
|
196
|
+
// hooks appended while we were posting (appends only ever grow the file,
|
|
197
|
+
// so it is everything past the bytes we read).
|
|
198
|
+
try {
|
|
199
|
+
const serialised = failed.map((r) => JSON.stringify(r) + '\n').join('');
|
|
200
|
+
writeFileSync(bufferFile, serialised + appendedSince(snapshot.bytes), 'utf8');
|
|
201
|
+
}
|
|
136
202
|
catch {
|
|
137
203
|
// Best-effort — if we can't rewrite, the worst case is that successful
|
|
138
204
|
// groups are re-flushed on the next attempt (the API push is idempotent
|
|
139
205
|
// at the (project_id, rule_id, target_hash, session_id) level).
|
|
140
206
|
}
|
|
141
207
|
}
|
|
142
|
-
|
|
208
|
+
function hasDueViolations(ctx) {
|
|
209
|
+
try {
|
|
210
|
+
const snapshot = readBuffer();
|
|
211
|
+
if (!snapshot || !snapshot.content.trim())
|
|
212
|
+
return false;
|
|
213
|
+
if (existsSync(lockFile) && !lockIsStale())
|
|
214
|
+
return false; // being flushed
|
|
215
|
+
const checkedAt = now();
|
|
216
|
+
const records = parseRecords(snapshot.content);
|
|
217
|
+
// Records to drop (unreadable lines, past the cap): a flush rewrites
|
|
218
|
+
// the file even when every group is held back.
|
|
219
|
+
if (records.length === 0 || records.length > MAX_BUFFERED_RECORDS)
|
|
220
|
+
return true;
|
|
221
|
+
if (capRecords(records, checkedAt).length !== records.length)
|
|
222
|
+
return true;
|
|
223
|
+
const holds = readHolds();
|
|
224
|
+
const fingerprint = tokenFingerprint(ctx.token);
|
|
225
|
+
return records.some((r) => isDue(holds[r.projectId], checkedAt, fingerprint));
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/** The buffer's content and byte length, or null when unreadable. */
|
|
232
|
+
function readBuffer() {
|
|
233
|
+
try {
|
|
234
|
+
const raw = readFileSync(bufferFile);
|
|
235
|
+
return { content: raw.toString('utf8'), bytes: raw.length };
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/** What was appended to the buffer after its first `bytes` bytes. */
|
|
242
|
+
function appendedSince(bytes) {
|
|
243
|
+
try {
|
|
244
|
+
const raw = readFileSync(bufferFile);
|
|
245
|
+
return raw.length > bytes ? raw.subarray(bytes).toString('utf8') : '';
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return '';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Take the flush lock (`O_EXCL` create). False when another flush holds a
|
|
253
|
+
* fresh one, or when the lock cannot be created at all.
|
|
254
|
+
*/
|
|
255
|
+
function acquireLock() {
|
|
256
|
+
try {
|
|
257
|
+
ensureDirFor(lockFile);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
263
|
+
try {
|
|
264
|
+
const fd = openSync(lockFile, 'wx');
|
|
265
|
+
try {
|
|
266
|
+
writeSync(fd, String(process.pid));
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
closeSync(fd);
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
if (e.code !== 'EEXIST')
|
|
275
|
+
return false;
|
|
276
|
+
if (!lockIsStale())
|
|
277
|
+
return false;
|
|
278
|
+
// Left behind by a flush that crashed: take it over.
|
|
279
|
+
try {
|
|
280
|
+
rmSync(lockFile, { force: true });
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
/** File mtimes are wall-clock time, hence Date.now() and not `now`. */
|
|
290
|
+
function lockIsStale() {
|
|
291
|
+
try {
|
|
292
|
+
return Date.now() - statSync(lockFile).mtimeMs > FLUSH_LOCK_STALE_MS;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/** Still flushing: keep the lock from looking stale to the next flush. */
|
|
299
|
+
function touchLock() {
|
|
300
|
+
try {
|
|
301
|
+
const t = new Date();
|
|
302
|
+
utimesSync(lockFile, t, t);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
// Best-effort
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function releaseLock() {
|
|
309
|
+
try {
|
|
310
|
+
rmSync(lockFile, { force: true });
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
// Best-effort — a lock left behind goes stale after a minute.
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function liftHolds() {
|
|
317
|
+
try {
|
|
318
|
+
rmSync(holdsFile, { force: true });
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
// Best-effort
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function readHolds() {
|
|
325
|
+
try {
|
|
326
|
+
if (!existsSync(holdsFile))
|
|
327
|
+
return {};
|
|
328
|
+
const parsed = JSON.parse(readFileSync(holdsFile, 'utf8'));
|
|
329
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
330
|
+
return {};
|
|
331
|
+
}
|
|
332
|
+
const holds = {};
|
|
333
|
+
for (const [projectId, raw] of Object.entries(parsed)) {
|
|
334
|
+
const h = raw;
|
|
335
|
+
if (h &&
|
|
336
|
+
(typeof h.status === 'number' || h.status === null) &&
|
|
337
|
+
typeof h.failedAt === 'number' &&
|
|
338
|
+
typeof h.retryAt === 'number') {
|
|
339
|
+
holds[projectId] = {
|
|
340
|
+
status: h.status,
|
|
341
|
+
failedAt: h.failedAt,
|
|
342
|
+
retryAt: h.retryAt,
|
|
343
|
+
...(typeof h.unauthorized === 'number' ? { unauthorized: h.unauthorized } : {}),
|
|
344
|
+
...(typeof h.token === 'string' ? { token: h.token } : {}),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return holds;
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// Unreadable holds: every group is due, as before holds existed.
|
|
352
|
+
return {};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function writeHolds(holds) {
|
|
356
|
+
try {
|
|
357
|
+
if (Object.keys(holds).length === 0) {
|
|
358
|
+
rmSync(holdsFile, { force: true });
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
ensureDirFor(holdsFile);
|
|
362
|
+
writeFileSync(holdsFile, JSON.stringify(holds), 'utf8');
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
// Best-effort — the worst case is one more POST of a refused group.
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return { bufferViolation, flushViolations, hasDueViolations, liftHolds };
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* A group may be posted when it is not held back, when its hold is over, or
|
|
372
|
+
* when it was held back for a 401 and the token is no longer the one refused.
|
|
373
|
+
*/
|
|
374
|
+
function isDue(hold, now, tokenFingerprint) {
|
|
375
|
+
if (!hold || now >= hold.retryAt)
|
|
376
|
+
return true;
|
|
377
|
+
return hold.status === 401 && hold.token !== tokenFingerprint;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Parse the buffer's JSON lines. Unreadable lines and records without a
|
|
381
|
+
* projectId (written before that field existed) are dropped: kept, they
|
|
382
|
+
* would block the flush forever since they cannot be addressed to a project.
|
|
383
|
+
*/
|
|
384
|
+
function parseRecords(content) {
|
|
385
|
+
const records = [];
|
|
386
|
+
for (const line of content.split('\n')) {
|
|
387
|
+
const trimmed = line.trim();
|
|
388
|
+
if (!trimmed)
|
|
389
|
+
continue;
|
|
390
|
+
try {
|
|
391
|
+
const parsed = JSON.parse(trimmed);
|
|
392
|
+
if (typeof parsed.projectId === 'string' && parsed.projectId) {
|
|
393
|
+
records.push(parsed);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
// Corrupt line — drop it
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return records;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* The records a flush keeps: none older than `MAX_RECORD_AGE_MS` (a record
|
|
404
|
+
* whose timestamp cannot be read cannot be aged and is dropped too), and at
|
|
405
|
+
* most the newest `MAX_BUFFERED_RECORDS`, in chronological order.
|
|
406
|
+
*/
|
|
407
|
+
function capRecords(records, now) {
|
|
408
|
+
const dated = records
|
|
409
|
+
.map((record) => ({ record, at: Date.parse(record.timestamp) }))
|
|
410
|
+
.filter(({ at }) => Number.isFinite(at) && now - at <= MAX_RECORD_AGE_MS);
|
|
411
|
+
// Stable sort: records of the same instant keep their buffer order.
|
|
412
|
+
dated.sort((a, b) => a.at - b.at);
|
|
413
|
+
return dated.slice(-MAX_BUFFERED_RECORDS).map(({ record }) => record);
|
|
143
414
|
}
|
|
144
415
|
/** Ensure the parent directory of a file exists. */
|
|
145
416
|
function ensureDirFor(filePath) {
|
|
@@ -152,4 +423,6 @@ function ensureDirFor(filePath) {
|
|
|
152
423
|
const _defaultBuffer = makeViolationsBuffer();
|
|
153
424
|
export const bufferViolation = _defaultBuffer.bufferViolation.bind(_defaultBuffer);
|
|
154
425
|
export const flushViolations = _defaultBuffer.flushViolations.bind(_defaultBuffer);
|
|
426
|
+
/** Lift every hold of the default buffer (called by `vibedefend login`). */
|
|
427
|
+
export const liftViolationHolds = _defaultBuffer.liftHolds.bind(_defaultBuffer);
|
|
155
428
|
//# sourceMappingURL=guard-violations-buffer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard-violations-buffer.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-violations-buffer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"guard-violations-buffer.js","sourceRoot":"","sources":["../../../src/hooks/runtime/guard-violations-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,7 @@ export function makeJudgeCache(opts = {}) {
|
|
|
18
18
|
const cacheFile = opts.cacheFile ?? DEFAULT_JUDGE_CACHE_FILE;
|
|
19
19
|
const ttlMs = opts.ttlMs ?? DEFAULT_JUDGE_TTL_MS;
|
|
20
20
|
const now = opts.now ?? (() => Date.now());
|
|
21
|
+
const maxEntries = opts.maxEntries;
|
|
21
22
|
function readAll() {
|
|
22
23
|
if (!existsSync(cacheFile))
|
|
23
24
|
return {};
|
|
@@ -46,6 +47,11 @@ export function makeJudgeCache(opts = {}) {
|
|
|
46
47
|
delete all[k];
|
|
47
48
|
}
|
|
48
49
|
all[key] = { res, at: t };
|
|
50
|
+
if (maxEntries !== undefined && maxEntries > 0) {
|
|
51
|
+
const keys = Object.keys(all).sort((a, b) => all[a].at - all[b].at);
|
|
52
|
+
for (const k of keys.slice(0, Math.max(0, keys.length - maxEntries)))
|
|
53
|
+
delete all[k];
|
|
54
|
+
}
|
|
49
55
|
ensureDirFor(cacheFile);
|
|
50
56
|
writeFileSync(cacheFile, JSON.stringify(all), 'utf8');
|
|
51
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"judge-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAC1C,OAAO,EAAE,EACT,aAAa,EACb,yBAAyB,CAC1B,CAAC;AACF,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"judge-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge-cache.ts"],"names":[],"mappings":"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"}
|