@cybedefend/vibedefend 1.5.0 → 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.
Files changed (246) hide show
  1. package/README.md +67 -2
  2. package/dist/api/gateway-request.js +49 -0
  3. package/dist/api/gateway-request.js.map +1 -0
  4. package/dist/api/projects.js +67 -0
  5. package/dist/api/projects.js.map +1 -1
  6. package/dist/api/repository-link.js +157 -0
  7. package/dist/api/repository-link.js.map +1 -0
  8. package/dist/auth/auth-store.js +107 -25
  9. package/dist/auth/auth-store.js.map +1 -1
  10. package/dist/auth/auth.js +21 -0
  11. package/dist/auth/auth.js.map +1 -1
  12. package/dist/clients/cursor.js +5 -1
  13. package/dist/clients/cursor.js.map +1 -1
  14. package/dist/clients/vscode.js +38 -29
  15. package/dist/clients/vscode.js.map +1 -1
  16. package/dist/commands/mcp/allow.js +219 -0
  17. package/dist/commands/mcp/allow.js.map +1 -0
  18. package/dist/commands/mcp/connect.js +337 -0
  19. package/dist/commands/mcp/connect.js.map +1 -0
  20. package/dist/commands/mcp/index.js +170 -0
  21. package/dist/commands/mcp/index.js.map +1 -0
  22. package/dist/commands/mcp/proxy.js +264 -0
  23. package/dist/commands/mcp/proxy.js.map +1 -0
  24. package/dist/commands/mcp/scan.js +349 -0
  25. package/dist/commands/mcp/scan.js.map +1 -0
  26. package/dist/commands/mcp/sync.js +215 -0
  27. package/dist/commands/mcp/sync.js.map +1 -0
  28. package/dist/config.js +6 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/diagnostics.js +78 -12
  31. package/dist/diagnostics.js.map +1 -1
  32. package/dist/doctor.js +19 -0
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/guards-evaluator/analysis-types.js +27 -0
  35. package/dist/guards-evaluator/analysis-types.js.map +1 -0
  36. package/dist/guards-evaluator/command-analysis.js +572 -0
  37. package/dist/guards-evaluator/command-analysis.js.map +1 -0
  38. package/dist/guards-evaluator/command-view.js +586 -0
  39. package/dist/guards-evaluator/command-view.js.map +1 -0
  40. package/dist/guards-evaluator/env.js +11 -0
  41. package/dist/guards-evaluator/env.js.map +1 -0
  42. package/dist/guards-evaluator/evaluate.js +91 -41
  43. package/dist/guards-evaluator/evaluate.js.map +1 -1
  44. package/dist/guards-evaluator/index.js +2 -1
  45. package/dist/guards-evaluator/index.js.map +1 -1
  46. package/dist/guards-evaluator/inline-code.js +259 -0
  47. package/dist/guards-evaluator/inline-code.js.map +1 -0
  48. package/dist/guards-evaluator/normalize.js +716 -0
  49. package/dist/guards-evaluator/normalize.js.map +1 -0
  50. package/dist/guards-evaluator/preprocess.js +13 -5
  51. package/dist/guards-evaluator/preprocess.js.map +1 -1
  52. package/dist/guards-evaluator/redact.js +19 -0
  53. package/dist/guards-evaluator/redact.js.map +1 -1
  54. package/dist/guards-evaluator/regex.js +25 -3
  55. package/dist/guards-evaluator/regex.js.map +1 -1
  56. package/dist/guards-evaluator/safe-commands.js +155 -0
  57. package/dist/guards-evaluator/safe-commands.js.map +1 -0
  58. package/dist/guards-evaluator/triage.js +315 -0
  59. package/dist/guards-evaluator/triage.js.map +1 -0
  60. package/dist/hook-runner.js +24679 -5079
  61. package/dist/hooks/install.js +38 -0
  62. package/dist/hooks/install.js.map +1 -1
  63. package/dist/hooks/runtime/config.js +38 -0
  64. package/dist/hooks/runtime/config.js.map +1 -1
  65. package/dist/hooks/runtime/emit.js +94 -61
  66. package/dist/hooks/runtime/emit.js.map +1 -1
  67. package/dist/hooks/runtime/fetch-rules.js +22 -7
  68. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  69. package/dist/hooks/runtime/gateway-http-error.js +34 -0
  70. package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
  71. package/dist/hooks/runtime/guard-rules-cache.js +139 -17
  72. package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
  73. package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
  74. package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
  75. package/dist/hooks/runtime/judge-cache.js +6 -0
  76. package/dist/hooks/runtime/judge-cache.js.map +1 -1
  77. package/dist/hooks/runtime/judge-triage.js +193 -0
  78. package/dist/hooks/runtime/judge-triage.js.map +1 -0
  79. package/dist/hooks/runtime/judge.js +7 -1
  80. package/dist/hooks/runtime/judge.js.map +1 -1
  81. package/dist/hooks/runtime/pre-compact.js +12 -6
  82. package/dist/hooks/runtime/pre-compact.js.map +1 -1
  83. package/dist/hooks/runtime/resolve.js +90 -8
  84. package/dist/hooks/runtime/resolve.js.map +1 -1
  85. package/dist/hooks/runtime/retry-policy.js +57 -0
  86. package/dist/hooks/runtime/retry-policy.js.map +1 -0
  87. package/dist/hooks/runtime/review-sessions.js +74 -0
  88. package/dist/hooks/runtime/review-sessions.js.map +1 -0
  89. package/dist/hooks/runtime/script-resolve.js +695 -0
  90. package/dist/hooks/runtime/script-resolve.js.map +1 -0
  91. package/dist/hooks/runtime/session-activation.js +5 -1
  92. package/dist/hooks/runtime/session-activation.js.map +1 -1
  93. package/dist/hooks/runtime/session-review.js +163 -45
  94. package/dist/hooks/runtime/session-review.js.map +1 -1
  95. package/dist/hooks/runtime/session-start.js +2 -1
  96. package/dist/hooks/runtime/session-start.js.map +1 -1
  97. package/dist/hooks/runtime/session-writes.js +232 -0
  98. package/dist/hooks/runtime/session-writes.js.map +1 -0
  99. package/dist/hooks/runtime/sniff.js +26 -7
  100. package/dist/hooks/runtime/sniff.js.map +1 -1
  101. package/dist/hooks/runtime/target-resolve.js +336 -0
  102. package/dist/hooks/runtime/target-resolve.js.map +1 -0
  103. package/dist/hooks/runtime/unmapped-tools.js +93 -0
  104. package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
  105. package/dist/hooks/runtime/usage-block.js +4 -0
  106. package/dist/hooks/runtime/usage-block.js.map +1 -1
  107. package/dist/hooks/runtime/user-prompt-submit.js +2 -1
  108. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  109. package/dist/hooks/runtime/wire-text.js +41 -0
  110. package/dist/hooks/runtime/wire-text.js.map +1 -0
  111. package/dist/hooks/runtime/work-dir.js +84 -0
  112. package/dist/hooks/runtime/work-dir.js.map +1 -0
  113. package/dist/index.js +45 -12
  114. package/dist/index.js.map +1 -1
  115. package/dist/install.js +174 -11
  116. package/dist/install.js.map +1 -1
  117. package/dist/link.js +74 -48
  118. package/dist/link.js.map +1 -1
  119. package/dist/login.js +77 -11
  120. package/dist/login.js.map +1 -1
  121. package/dist/mcp/auth/agent-sign-ins.js +174 -0
  122. package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
  123. package/dist/mcp/auth/callback.js +200 -0
  124. package/dist/mcp/auth/callback.js.map +1 -0
  125. package/dist/mcp/auth/connect.js +392 -0
  126. package/dist/mcp/auth/connect.js.map +1 -0
  127. package/dist/mcp/auth/discovery.js +399 -0
  128. package/dist/mcp/auth/discovery.js.map +1 -0
  129. package/dist/mcp/auth/oauth.js +326 -0
  130. package/dist/mcp/auth/oauth.js.map +1 -0
  131. package/dist/mcp/auth/probe.js +128 -0
  132. package/dist/mcp/auth/probe.js.map +1 -0
  133. package/dist/mcp/auth/secrets.js +446 -0
  134. package/dist/mcp/auth/secrets.js.map +1 -0
  135. package/dist/mcp/auth/store.js +260 -0
  136. package/dist/mcp/auth/store.js.map +1 -0
  137. package/dist/mcp/auth/tokenSource.js +55 -0
  138. package/dist/mcp/auth/tokenSource.js.map +1 -0
  139. package/dist/mcp/config/atomicWrite.js +98 -0
  140. package/dist/mcp/config/atomicWrite.js.map +1 -0
  141. package/dist/mcp/config/clients.js +171 -0
  142. package/dist/mcp/config/clients.js.map +1 -0
  143. package/dist/mcp/config/cybedefend-servers.js +48 -0
  144. package/dist/mcp/config/cybedefend-servers.js.map +1 -0
  145. package/dist/mcp/config/discover.js +114 -0
  146. package/dist/mcp/config/discover.js.map +1 -0
  147. package/dist/mcp/config/hook.js +123 -0
  148. package/dist/mcp/config/hook.js.map +1 -0
  149. package/dist/mcp/config/index.js +11 -0
  150. package/dist/mcp/config/index.js.map +1 -0
  151. package/dist/mcp/config/install.js +132 -0
  152. package/dist/mcp/config/install.js.map +1 -0
  153. package/dist/mcp/config/installed.js +37 -0
  154. package/dist/mcp/config/installed.js.map +1 -0
  155. package/dist/mcp/config/jsonEdit.js +119 -0
  156. package/dist/mcp/config/jsonEdit.js.map +1 -0
  157. package/dist/mcp/config/lock.js +102 -0
  158. package/dist/mcp/config/lock.js.map +1 -0
  159. package/dist/mcp/config/proxyBinary.js +211 -0
  160. package/dist/mcp/config/proxyBinary.js.map +1 -0
  161. package/dist/mcp/config/rewrite.js +388 -0
  162. package/dist/mcp/config/rewrite.js.map +1 -0
  163. package/dist/mcp/config/types.js +34 -0
  164. package/dist/mcp/config/types.js.map +1 -0
  165. package/dist/mcp/proxy/audit.js +83 -0
  166. package/dist/mcp/proxy/audit.js.map +1 -0
  167. package/dist/mcp/proxy/authInterceptor.js +119 -0
  168. package/dist/mcp/proxy/authInterceptor.js.map +1 -0
  169. package/dist/mcp/proxy/expand.js +93 -0
  170. package/dist/mcp/proxy/expand.js.map +1 -0
  171. package/dist/mcp/proxy/inject.js +397 -0
  172. package/dist/mcp/proxy/inject.js.map +1 -0
  173. package/dist/mcp/proxy/intercept.js +37 -0
  174. package/dist/mcp/proxy/intercept.js.map +1 -0
  175. package/dist/mcp/proxy/jsonrpc.js +153 -0
  176. package/dist/mcp/proxy/jsonrpc.js.map +1 -0
  177. package/dist/mcp/proxy/log.js +109 -0
  178. package/dist/mcp/proxy/log.js.map +1 -0
  179. package/dist/mcp/proxy/paths.js +53 -0
  180. package/dist/mcp/proxy/paths.js.map +1 -0
  181. package/dist/mcp/proxy/proxy.js +510 -0
  182. package/dist/mcp/proxy/proxy.js.map +1 -0
  183. package/dist/mcp/proxy/spec.js +203 -0
  184. package/dist/mcp/proxy/spec.js.map +1 -0
  185. package/dist/mcp/proxy/sse.js +77 -0
  186. package/dist/mcp/proxy/sse.js.map +1 -0
  187. package/dist/mcp/proxy/upstream.js +2 -0
  188. package/dist/mcp/proxy/upstream.js.map +1 -0
  189. package/dist/mcp/proxy/upstreamHttp.js +499 -0
  190. package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
  191. package/dist/mcp/proxy/upstreamStdio.js +188 -0
  192. package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
  193. package/dist/mcp/proxy/upstreams.js +143 -0
  194. package/dist/mcp/proxy/upstreams.js.map +1 -0
  195. package/dist/mcp/proxy/verifyInterceptor.js +559 -0
  196. package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
  197. package/dist/mcp/proxy/windowsCommand.js +99 -0
  198. package/dist/mcp/proxy/windowsCommand.js.map +1 -0
  199. package/dist/mcp/scan/args.js +228 -0
  200. package/dist/mcp/scan/args.js.map +1 -0
  201. package/dist/mcp/scan/results.js +253 -0
  202. package/dist/mcp/scan/results.js.map +1 -0
  203. package/dist/mcp/scan/types.js +40 -0
  204. package/dist/mcp/scan/types.js.map +1 -0
  205. package/dist/mcp/verify/api.js +475 -0
  206. package/dist/mcp/verify/api.js.map +1 -0
  207. package/dist/mcp/verify/backend.js +143 -0
  208. package/dist/mcp/verify/backend.js.map +1 -0
  209. package/dist/mcp/verify/cache.js +182 -0
  210. package/dist/mcp/verify/cache.js.map +1 -0
  211. package/dist/mcp/verify/contract-errors.js +198 -0
  212. package/dist/mcp/verify/contract-errors.js.map +1 -0
  213. package/dist/mcp/verify/digest.js +91 -0
  214. package/dist/mcp/verify/digest.js.map +1 -0
  215. package/dist/mcp/verify/factory.js +56 -0
  216. package/dist/mcp/verify/factory.js.map +1 -0
  217. package/dist/mcp/verify/identity.js +173 -0
  218. package/dist/mcp/verify/identity.js.map +1 -0
  219. package/dist/mcp/verify/policy-store.js +63 -0
  220. package/dist/mcp/verify/policy-store.js.map +1 -0
  221. package/dist/mcp/verify/policy.js +158 -0
  222. package/dist/mcp/verify/policy.js.map +1 -0
  223. package/dist/mcp/verify/pool.js +27 -0
  224. package/dist/mcp/verify/pool.js.map +1 -0
  225. package/dist/mcp/verify/token-refresh.js +44 -0
  226. package/dist/mcp/verify/token-refresh.js.map +1 -0
  227. package/dist/mcp/verify/token.js +67 -0
  228. package/dist/mcp/verify/token.js.map +1 -0
  229. package/dist/mcp/verify/verifier.js +1009 -0
  230. package/dist/mcp/verify/verifier.js.map +1 -0
  231. package/dist/org-gate.js +1 -1
  232. package/dist/org-gate.js.map +1 -1
  233. package/dist/org.js +146 -0
  234. package/dist/org.js.map +1 -0
  235. package/dist/project-create.js +129 -0
  236. package/dist/project-create.js.map +1 -0
  237. package/dist/prompts.js +21 -0
  238. package/dist/prompts.js.map +1 -1
  239. package/dist/re2.wasm +0 -0
  240. package/dist/status.js +61 -0
  241. package/dist/status.js.map +1 -1
  242. package/dist/uninstall.js +49 -4
  243. package/dist/uninstall.js.map +1 -1
  244. package/dist/utils.js +62 -6
  245. package/dist/utils.js.map +1 -1
  246. 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 on demand by the hook before it returns.
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
- let content;
104
+ if (!acquireLock())
105
+ return; // another flush is posting these records
62
106
  try {
63
- content = readFileSync(bufferFile, 'utf8').trim();
107
+ await flushLocked(ctx, postFn);
64
108
  }
65
- catch {
66
- return;
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
- if (records.length === 0) {
89
- // Nothing salvageable — clear the file so corrupt content doesn't
90
- // grow unboundedly.
91
- try {
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
- failed.push(...group);
154
+ if (!groupFailed) {
155
+ delete holds[projectId];
156
+ continue;
124
157
  }
125
- }
126
- // Rewrite the file with only the failed groups (or wipe it on full success).
127
- try {
128
- if (failed.length === 0) {
129
- writeFileSync(bufferFile, '', 'utf8');
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
- const serialised = failed.map((r) => JSON.stringify(r)).join('\n') + '\n';
133
- writeFileSync(bufferFile, serialised, 'utf8');
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
- return { bufferViolation, flushViolations };
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;AAiB5C,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,wBAAwB,CAAC;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,oBAAoB,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAE3C,SAAS,OAAO;QACd,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAe,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,SAAS,GAAG,CAAC,GAAW;QACtB,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,GAAG,KAAK;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,KAAK,CAAC,GAAG,CAAC;IACnB,CAAC;IAED,SAAS,GAAG,CAAC,GAAW,EAAE,GAAgB;QACxC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;YAChB,0DAA0D;YAC1D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK;oBAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1B,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,sDAAsD;QACxD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"judge-cache.js","sourceRoot":"","sources":["../../../src/hooks/runtime/judge-cache.ts"],"names":[],"mappings":"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"}