@astrasyncai/verification-gateway 3.9.0 → 3.10.1
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/adapter-interface/interface.d.mts +3 -2
- package/dist/adapter-interface/interface.d.ts +3 -2
- package/dist/adapters/express.d.mts +3 -2
- package/dist/adapters/express.d.ts +3 -2
- package/dist/adapters/express.js +151 -2
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +151 -2
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +2 -1
- package/dist/adapters/mcp.d.ts +2 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +3 -2
- package/dist/adapters/nextjs.d.ts +3 -2
- package/dist/adapters/nextjs.js +151 -2
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +151 -2
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +3 -2
- package/dist/adapters/sdk.d.ts +3 -2
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +3 -2
- package/dist/agent/index.d.ts +3 -2
- package/dist/bin/astrasync-claude-hook.js +276 -25
- package/dist/bin/astrasync-guard.js +258 -23
- package/dist/bin/astrasync.js +282 -24
- package/dist/browser/background.js +257 -22
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +257 -22
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +3 -2
- package/dist/browser/browser-adapter.d.ts +3 -2
- package/dist/claude-code/claude-code-adapter.d.mts +3 -2
- package/dist/claude-code/claude-code-adapter.d.ts +3 -2
- package/dist/cli/index.d.mts +3 -2
- package/dist/cli/index.d.ts +3 -2
- package/dist/cursor/cursor-adapter.d.mts +3 -2
- package/dist/cursor/cursor-adapter.d.ts +3 -2
- package/dist/cursor/extension.d.mts +3 -2
- package/dist/cursor/extension.d.ts +3 -2
- package/dist/cursor/extension.js +257 -22
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +257 -22
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +2 -1
- package/dist/edge-config.d.ts +2 -1
- package/dist/{express-sGXhDdd0.d.ts → express-ClNtDhhc.d.ts} +1 -1
- package/dist/{express-DXUyvv7t.d.mts → express-DCXa1oqj.d.mts} +1 -1
- package/dist/gateway/gateway.d.mts +29 -3
- package/dist/gateway/gateway.d.ts +29 -3
- package/dist/gateway/gateway.js +257 -22
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +257 -22
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +3 -2
- package/dist/git-trigger/git-hooks.d.ts +3 -2
- package/dist/{index-Dalih3EB.d.mts → index-BrNKDmiR.d.mts} +1 -1
- package/dist/{index-C61VL_OW.d.ts → index-CfHurO1P.d.ts} +1 -1
- package/dist/{index-CMg-vjEK.d.ts → index-D2ztkumS.d.ts} +1 -1
- package/dist/{index-DmmdehNu.d.mts → index-Dr_XiN65.d.mts} +1 -1
- package/dist/index.d.mts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.js +218 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -11
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +3 -2
- package/dist/local-evaluator/evaluator.d.ts +3 -2
- package/dist/local-evaluator/evaluator.js +165 -7
- package/dist/local-evaluator/evaluator.js.map +1 -1
- package/dist/local-evaluator/evaluator.mjs +165 -7
- package/dist/local-evaluator/evaluator.mjs.map +1 -1
- package/dist/metadata-capture.d.mts +87 -0
- package/dist/metadata-capture.d.ts +87 -0
- package/dist/metadata-capture.js +184 -0
- package/dist/metadata-capture.js.map +1 -0
- package/dist/metadata-capture.mjs +154 -0
- package/dist/metadata-capture.mjs.map +1 -0
- package/dist/{nextjs-DwUW-Nm1.d.ts → nextjs-CEBVBsdi.d.ts} +1 -1
- package/dist/{nextjs-F_2pbPIA.d.mts → nextjs-DcQIk6Zj.d.mts} +1 -1
- package/dist/platform-signatures.d.mts +60 -10
- package/dist/platform-signatures.d.ts +60 -10
- package/dist/platform-signatures.js +37 -10
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs +35 -9
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/{sdk-Clob2-0A.d.mts → sdk-CZkbSOeO.d.mts} +1 -1
- package/dist/{sdk-CfHANs4A.d.ts → sdk-H0JCLW2y.d.ts} +1 -1
- package/dist/transport/index.d.mts +3 -2
- package/dist/transport/index.d.ts +3 -2
- package/dist/{types-ACMsV07B.d.mts → types-9tns4wyl.d.ts} +12 -0
- package/dist/{types-DmSDgPpG.d.ts → types-BV6abBnF.d.mts} +7 -1
- package/dist/{types-BtqUvK8v.d.mts → types-C23_uaY8.d.ts} +7 -1
- package/dist/{types-ACMsV07B.d.ts → types-sy3tq8lp.d.mts} +12 -0
- package/dist/ui/index.d.mts +2 -1
- package/dist/ui/index.d.ts +2 -1
- package/dist/verify.d.mts +8 -1
- package/dist/verify.d.ts +8 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +6 -1
package/dist/edge-config.d.mts
CHANGED
package/dist/edge-config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RequestHandler, Request } from 'express';
|
|
2
|
-
import { r as VerificationResult, f as ExpressMiddlewareOptions, c as AstraSyncCredentials } from './types-
|
|
2
|
+
import { r as VerificationResult, f as ExpressMiddlewareOptions, c as AstraSyncCredentials } from './types-9tns4wyl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* AstraSync Universal Verification Gateway - Express Middleware
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RequestHandler, Request } from 'express';
|
|
2
|
-
import { r as VerificationResult, f as ExpressMiddlewareOptions, c as AstraSyncCredentials } from './types-
|
|
2
|
+
import { r as VerificationResult, f as ExpressMiddlewareOptions, c as AstraSyncCredentials } from './types-sy3tq8lp.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* AstraSync Universal Verification Gateway - Express Middleware
|
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-
|
|
2
|
-
import '../types-
|
|
1
|
+
import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-BV6abBnF.mjs';
|
|
2
|
+
import '../types-sy3tq8lp.mjs';
|
|
3
|
+
import '../metadata-capture.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.
|
|
7
|
+
*
|
|
8
|
+
* Immediate: local PDLSS evaluation (< 1ms)
|
|
9
|
+
* Async: queued API verification for audit trail and trust score updates
|
|
10
|
+
*
|
|
11
|
+
* Queue entries are persisted to disk so they survive process restarts.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface FlushOptions {
|
|
15
|
+
/** Max entries to attempt this flush (default: all pending). */
|
|
16
|
+
limit?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Per-entry time budget in ms. A timed-out entry stays pending (no retry
|
|
19
|
+
* penalty — slow network is not a failure) and ends the flush early.
|
|
20
|
+
* Stateless callers (the Claude Code hook) use this to keep sync off the
|
|
21
|
+
* tool-call critical path.
|
|
22
|
+
*/
|
|
23
|
+
perEntryTimeoutMs?: number;
|
|
24
|
+
}
|
|
3
25
|
|
|
4
26
|
/**
|
|
5
27
|
* AstraSyncGateway — Primary API surface for agent verification.
|
|
@@ -36,8 +58,12 @@ declare class AstraSyncGateway {
|
|
|
36
58
|
initialize(): Promise<void>;
|
|
37
59
|
/**
|
|
38
60
|
* Graceful shutdown. Flushes sync queue and cleans up resources.
|
|
61
|
+
* Stateless callers (hooks) pass bounded flush options so sync never
|
|
62
|
+
* sits on a tool call's critical path.
|
|
39
63
|
*/
|
|
40
|
-
shutdown(
|
|
64
|
+
shutdown(options?: {
|
|
65
|
+
syncFlush?: FlushOptions;
|
|
66
|
+
}): Promise<void>;
|
|
41
67
|
/**
|
|
42
68
|
* Evaluate an action against the verification policy.
|
|
43
69
|
* Routes to the appropriate mode handler.
|
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-
|
|
2
|
-
import '../types-
|
|
1
|
+
import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-C23_uaY8.js';
|
|
2
|
+
import '../types-9tns4wyl.js';
|
|
3
|
+
import '../metadata-capture.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.
|
|
7
|
+
*
|
|
8
|
+
* Immediate: local PDLSS evaluation (< 1ms)
|
|
9
|
+
* Async: queued API verification for audit trail and trust score updates
|
|
10
|
+
*
|
|
11
|
+
* Queue entries are persisted to disk so they survive process restarts.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface FlushOptions {
|
|
15
|
+
/** Max entries to attempt this flush (default: all pending). */
|
|
16
|
+
limit?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Per-entry time budget in ms. A timed-out entry stays pending (no retry
|
|
19
|
+
* penalty — slow network is not a failure) and ends the flush early.
|
|
20
|
+
* Stateless callers (the Claude Code hook) use this to keep sync off the
|
|
21
|
+
* tool-call critical path.
|
|
22
|
+
*/
|
|
23
|
+
perEntryTimeoutMs?: number;
|
|
24
|
+
}
|
|
3
25
|
|
|
4
26
|
/**
|
|
5
27
|
* AstraSyncGateway — Primary API surface for agent verification.
|
|
@@ -36,8 +58,12 @@ declare class AstraSyncGateway {
|
|
|
36
58
|
initialize(): Promise<void>;
|
|
37
59
|
/**
|
|
38
60
|
* Graceful shutdown. Flushes sync queue and cleans up resources.
|
|
61
|
+
* Stateless callers (hooks) pass bounded flush options so sync never
|
|
62
|
+
* sits on a tool call's critical path.
|
|
39
63
|
*/
|
|
40
|
-
shutdown(
|
|
64
|
+
shutdown(options?: {
|
|
65
|
+
syncFlush?: FlushOptions;
|
|
66
|
+
}): Promise<void>;
|
|
41
67
|
/**
|
|
42
68
|
* Evaluate an action against the verification policy.
|
|
43
69
|
* Routes to the appropriate mode handler.
|
package/dist/gateway/gateway.js
CHANGED
|
@@ -44,7 +44,9 @@ var HIGH_RISK_COMMANDS = [
|
|
|
44
44
|
"git push",
|
|
45
45
|
"npm publish",
|
|
46
46
|
"docker",
|
|
47
|
-
"kubectl"
|
|
47
|
+
"kubectl",
|
|
48
|
+
"gh pr create",
|
|
49
|
+
"gh pr merge"
|
|
48
50
|
];
|
|
49
51
|
var SENSITIVE_PATHS = [
|
|
50
52
|
".ssh",
|
|
@@ -63,6 +65,164 @@ var SENSITIVE_PATHS = [
|
|
|
63
65
|
".pypirc"
|
|
64
66
|
];
|
|
65
67
|
|
|
68
|
+
// src/local-evaluator/command-matcher.ts
|
|
69
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
70
|
+
"sudo",
|
|
71
|
+
"doas",
|
|
72
|
+
"env",
|
|
73
|
+
"nohup",
|
|
74
|
+
"time",
|
|
75
|
+
"timeout",
|
|
76
|
+
"nice",
|
|
77
|
+
"ionice",
|
|
78
|
+
"stdbuf",
|
|
79
|
+
"xargs",
|
|
80
|
+
"command",
|
|
81
|
+
"exec",
|
|
82
|
+
"builtin"
|
|
83
|
+
]);
|
|
84
|
+
var ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;
|
|
85
|
+
var MAX_WRAPPER_HOPS = 4;
|
|
86
|
+
var MAX_RECURSION_DEPTH = 3;
|
|
87
|
+
var MAX_COMMAND_LENGTH = 1e5;
|
|
88
|
+
var LOCAL_HOST_RE = /^(localhost|127\.0\.0\.1|::1|[a-z0-9.-]*\.localhost)$/;
|
|
89
|
+
function buildRiskList(entries) {
|
|
90
|
+
const singleWord = /* @__PURE__ */ new Set();
|
|
91
|
+
const multiWord = [];
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
const words = entry.toLowerCase().trim().split(/\s+/);
|
|
94
|
+
if (words.length === 1) singleWord.add(words[0]);
|
|
95
|
+
else multiWord.push(words);
|
|
96
|
+
}
|
|
97
|
+
multiWord.sort((a, b) => b.length - a.length);
|
|
98
|
+
return { singleWord, multiWord };
|
|
99
|
+
}
|
|
100
|
+
function stripHeredocBodies(text) {
|
|
101
|
+
const lines = text.split("\n");
|
|
102
|
+
const kept = [];
|
|
103
|
+
let terminator = null;
|
|
104
|
+
for (const line of lines) {
|
|
105
|
+
if (terminator !== null) {
|
|
106
|
+
if (line.trim() === terminator) terminator = null;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
kept.push(line);
|
|
110
|
+
const heredoc = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
111
|
+
if (heredoc) terminator = heredoc[1];
|
|
112
|
+
}
|
|
113
|
+
return kept.join("\n");
|
|
114
|
+
}
|
|
115
|
+
function extractDollarSubstitutions(text, collect) {
|
|
116
|
+
let result = text;
|
|
117
|
+
let start = result.indexOf("$(");
|
|
118
|
+
let iterations = 0;
|
|
119
|
+
while (start !== -1 && iterations < 50) {
|
|
120
|
+
iterations++;
|
|
121
|
+
let depth = 0;
|
|
122
|
+
let end = result.length;
|
|
123
|
+
for (let i = start + 1; i < result.length; i++) {
|
|
124
|
+
if (result[i] === "(") depth++;
|
|
125
|
+
else if (result[i] === ")") {
|
|
126
|
+
depth--;
|
|
127
|
+
if (depth === 0) {
|
|
128
|
+
end = i;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
collect(result.slice(start + 2, end));
|
|
134
|
+
result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;
|
|
135
|
+
start = result.indexOf("$(");
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
function extractBacktickSubstitutions(text, collect) {
|
|
140
|
+
if (!text.includes("`")) return text;
|
|
141
|
+
const chunks = text.split("`");
|
|
142
|
+
const kept = [];
|
|
143
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
144
|
+
if (i % 2 === 1) collect(chunks[i]);
|
|
145
|
+
else kept.push(chunks[i]);
|
|
146
|
+
}
|
|
147
|
+
return kept.join(" ");
|
|
148
|
+
}
|
|
149
|
+
function basename(token) {
|
|
150
|
+
const slash = token.lastIndexOf("/");
|
|
151
|
+
return slash === -1 ? token : token.slice(slash + 1);
|
|
152
|
+
}
|
|
153
|
+
function matchSegment(segment, list) {
|
|
154
|
+
const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
|
|
155
|
+
let i = 0;
|
|
156
|
+
let hops = 0;
|
|
157
|
+
while (i < tokens.length) {
|
|
158
|
+
while (i < tokens.length && (tokens[i] === "export" || ASSIGN_RE.test(tokens[i]))) i++;
|
|
159
|
+
if (i >= tokens.length) return null;
|
|
160
|
+
const cmd = basename(tokens[i]);
|
|
161
|
+
const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith("-"))];
|
|
162
|
+
for (const entry of list.multiWord) {
|
|
163
|
+
if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {
|
|
164
|
+
return entry.join(" ");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (list.singleWord.has(cmd)) return cmd;
|
|
168
|
+
if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {
|
|
169
|
+
hops++;
|
|
170
|
+
i++;
|
|
171
|
+
while (i < tokens.length && (tokens[i].startsWith("-") || ASSIGN_RE.test(tokens[i]))) i++;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
function collectMatches(command, list, matches, depth) {
|
|
179
|
+
if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;
|
|
180
|
+
let text = command.toLowerCase();
|
|
181
|
+
text = stripHeredocBodies(text);
|
|
182
|
+
const recurse = (inner) => collectMatches(inner, list, matches, depth + 1);
|
|
183
|
+
text = extractDollarSubstitutions(text, recurse);
|
|
184
|
+
text = extractBacktickSubstitutions(text, recurse);
|
|
185
|
+
text = text.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
|
|
186
|
+
text = text.replace(/(^|\s)#[^\n]*/g, " ");
|
|
187
|
+
const segments = text.split(/\|\||&&|[;|&\n]|[({]/);
|
|
188
|
+
for (const segment of segments) {
|
|
189
|
+
const matched = matchSegment(segment, list);
|
|
190
|
+
if (matched) matches.add(matched);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function matchHighRiskCommands(command, highRiskCommands = HIGH_RISK_COMMANDS) {
|
|
194
|
+
if (!command) return [];
|
|
195
|
+
const matches = /* @__PURE__ */ new Set();
|
|
196
|
+
collectMatches(command, buildRiskList(highRiskCommands), matches, 0);
|
|
197
|
+
return [...matches];
|
|
198
|
+
}
|
|
199
|
+
function isLocalhostOnlyNetworkCommand(command) {
|
|
200
|
+
const text = command.toLowerCase();
|
|
201
|
+
const tokens = text.split(/\s+/).map((t) => t.replace(/^["'`]+|["'`,;)]+$/g, ""));
|
|
202
|
+
let localCount = 0;
|
|
203
|
+
for (const token of tokens) {
|
|
204
|
+
let host = null;
|
|
205
|
+
if (token.includes("://")) {
|
|
206
|
+
let rest = token.slice(token.indexOf("://") + 3);
|
|
207
|
+
const at = rest.indexOf("@");
|
|
208
|
+
if (at !== -1) rest = rest.slice(at + 1);
|
|
209
|
+
host = rest.split(/[/?#]/)[0];
|
|
210
|
+
} else if (/^[a-z0-9.[\]:-]+:\d+(\/.*)?$/.test(token)) {
|
|
211
|
+
host = token.split("/")[0];
|
|
212
|
+
} else if (/^(localhost|127\.0\.0\.1|\[?::1\]?)(\/.*)?$/.test(token)) {
|
|
213
|
+
host = token.split("/")[0];
|
|
214
|
+
}
|
|
215
|
+
if (host === null) continue;
|
|
216
|
+
const bare = host.replace(/:\d+$/, "").replace(/^\[|\]$/g, "");
|
|
217
|
+
if (LOCAL_HOST_RE.test(bare)) {
|
|
218
|
+
localCount++;
|
|
219
|
+
} else {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return localCount > 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
66
226
|
// src/local-evaluator/evaluator.ts
|
|
67
227
|
var LocalEvaluator = class {
|
|
68
228
|
constructor(policy) {
|
|
@@ -213,12 +373,10 @@ var LocalEvaluator = class {
|
|
|
213
373
|
return score;
|
|
214
374
|
}
|
|
215
375
|
if (context.purpose === "shell.exec" && context.target) {
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
376
|
+
const matched = matchHighRiskCommands(context.target);
|
|
377
|
+
const localProbeOnly = matched.length > 0 && matched.every((cmd) => cmd === "curl" || cmd === "wget") && isLocalhostOnlyNetworkCommand(context.target);
|
|
378
|
+
if (matched.length > 0 && !localProbeOnly) {
|
|
379
|
+
score = Math.max(score, 80);
|
|
222
380
|
}
|
|
223
381
|
}
|
|
224
382
|
if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
|
|
@@ -3529,7 +3687,7 @@ function getTrustLevel(score) {
|
|
|
3529
3687
|
}
|
|
3530
3688
|
|
|
3531
3689
|
// src/version.ts
|
|
3532
|
-
var SDK_VERSION = "3.
|
|
3690
|
+
var SDK_VERSION = "3.10.1";
|
|
3533
3691
|
|
|
3534
3692
|
// src/well-known.ts
|
|
3535
3693
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -3945,6 +4103,9 @@ async function verify(config, request, options) {
|
|
|
3945
4103
|
// src/adapters/stepup-poll.ts
|
|
3946
4104
|
var FALLBACK_MAX_WAIT_MS = 5 * 60 * 1e3;
|
|
3947
4105
|
|
|
4106
|
+
// src/metadata-capture.ts
|
|
4107
|
+
var MAX_TOTAL_BYTES = 16 * 1024;
|
|
4108
|
+
|
|
3948
4109
|
// src/adapters/express.ts
|
|
3949
4110
|
var DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
|
|
3950
4111
|
|
|
@@ -4084,8 +4245,75 @@ async function verifyOnline(config, context, astraId) {
|
|
|
4084
4245
|
// src/gateway/modes/hybrid.ts
|
|
4085
4246
|
var import_fs2 = require("fs");
|
|
4086
4247
|
var import_path = require("path");
|
|
4248
|
+
|
|
4249
|
+
// src/gateway/redact.ts
|
|
4250
|
+
var marker = (type2) => `[REDACTED:${type2}]`;
|
|
4251
|
+
var REDACTION_PATTERNS = [
|
|
4252
|
+
// Multi-line blocks first so later single-line patterns don't shred them.
|
|
4253
|
+
{
|
|
4254
|
+
type: "private-key",
|
|
4255
|
+
re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g
|
|
4256
|
+
},
|
|
4257
|
+
// URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).
|
|
4258
|
+
{
|
|
4259
|
+
type: "url-credentials",
|
|
4260
|
+
re: /([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,
|
|
4261
|
+
replacement: `$1${marker("url-credentials")}@`
|
|
4262
|
+
},
|
|
4263
|
+
// Known token formats.
|
|
4264
|
+
{ type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,255}\b/g },
|
|
4265
|
+
{ type: "github-token", re: /\bgithub_pat_[A-Za-z0-9_]{20,255}\b/g },
|
|
4266
|
+
{ type: "astrasync-key", re: /\bkya_[A-Fa-f0-9]{32,128}\b/g },
|
|
4267
|
+
{ type: "openai-key", re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
4268
|
+
{ type: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
4269
|
+
{ type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
|
|
4270
|
+
// Bearer/token headers.
|
|
4271
|
+
{
|
|
4272
|
+
type: "bearer-token",
|
|
4273
|
+
re: /\b(bearer\s+)[a-z0-9._~+/=-]{16,}/gi,
|
|
4274
|
+
replacement: `$1${marker("bearer-token")}`
|
|
4275
|
+
},
|
|
4276
|
+
// Generic KEY=value / key: value assignments with secret-ish names.
|
|
4277
|
+
{
|
|
4278
|
+
type: "assigned-secret",
|
|
4279
|
+
re: /\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[=:]\s*)(['"]?)[^\s'"&;]{8,}\2/gi,
|
|
4280
|
+
replacement: `$1$2${marker("assigned-secret")}$2`
|
|
4281
|
+
}
|
|
4282
|
+
];
|
|
4283
|
+
function redactSecrets(text) {
|
|
4284
|
+
let result = text;
|
|
4285
|
+
for (const { type: type2, re, replacement } of REDACTION_PATTERNS) {
|
|
4286
|
+
result = result.replace(re, replacement ?? marker(type2));
|
|
4287
|
+
}
|
|
4288
|
+
return result;
|
|
4289
|
+
}
|
|
4290
|
+
function redactDeep(value) {
|
|
4291
|
+
if (typeof value === "string") {
|
|
4292
|
+
return redactSecrets(value);
|
|
4293
|
+
}
|
|
4294
|
+
if (Array.isArray(value)) {
|
|
4295
|
+
return value.map((item) => redactDeep(item));
|
|
4296
|
+
}
|
|
4297
|
+
if (value !== null && typeof value === "object" && !(value instanceof Date)) {
|
|
4298
|
+
const out = {};
|
|
4299
|
+
for (const [k, v] of Object.entries(value)) {
|
|
4300
|
+
out[k] = redactDeep(v);
|
|
4301
|
+
}
|
|
4302
|
+
return out;
|
|
4303
|
+
}
|
|
4304
|
+
return value;
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
// src/gateway/modes/hybrid.ts
|
|
4087
4308
|
var MAX_QUEUE_SIZE = 1e3;
|
|
4088
4309
|
var MAX_RETRIES = 3;
|
|
4310
|
+
var FLUSH_TIMEOUT = /* @__PURE__ */ Symbol("flush-timeout");
|
|
4311
|
+
function delay(ms) {
|
|
4312
|
+
return new Promise((resolve) => {
|
|
4313
|
+
const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);
|
|
4314
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
4315
|
+
});
|
|
4316
|
+
}
|
|
4089
4317
|
var HybridSyncQueue = class {
|
|
4090
4318
|
constructor(config, persistPath) {
|
|
4091
4319
|
this.queue = [];
|
|
@@ -4106,12 +4334,12 @@ var HybridSyncQueue = class {
|
|
|
4106
4334
|
/**
|
|
4107
4335
|
* Stop periodic sync and flush remaining entries.
|
|
4108
4336
|
*/
|
|
4109
|
-
async stop() {
|
|
4337
|
+
async stop(flushOptions = {}) {
|
|
4110
4338
|
if (this.timer) {
|
|
4111
4339
|
clearInterval(this.timer);
|
|
4112
4340
|
this.timer = null;
|
|
4113
4341
|
}
|
|
4114
|
-
await this.flush();
|
|
4342
|
+
await this.flush(flushOptions);
|
|
4115
4343
|
this.saveToDisk();
|
|
4116
4344
|
}
|
|
4117
4345
|
/**
|
|
@@ -4123,8 +4351,8 @@ var HybridSyncQueue = class {
|
|
|
4123
4351
|
}
|
|
4124
4352
|
this.queue.push({
|
|
4125
4353
|
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
4126
|
-
context,
|
|
4127
|
-
decision,
|
|
4354
|
+
context: redactDeep(context),
|
|
4355
|
+
decision: redactDeep(decision),
|
|
4128
4356
|
timestamp: /* @__PURE__ */ new Date(),
|
|
4129
4357
|
retryCount: 0,
|
|
4130
4358
|
status: "pending"
|
|
@@ -4134,16 +4362,21 @@ var HybridSyncQueue = class {
|
|
|
4134
4362
|
/**
|
|
4135
4363
|
* Flush pending entries to the API.
|
|
4136
4364
|
*/
|
|
4137
|
-
async flush() {
|
|
4365
|
+
async flush(options = {}) {
|
|
4138
4366
|
if (this.processing) return;
|
|
4139
4367
|
this.processing = true;
|
|
4140
4368
|
try {
|
|
4141
4369
|
const pending = this.queue.filter((e) => e.status === "pending");
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4370
|
+
const batch = typeof options.limit === "number" ? pending.slice(0, options.limit) : pending;
|
|
4371
|
+
for (const entry of batch) {
|
|
4372
|
+
const attempt = verifyOnline(this.config, entry.context, this.config.agentId).then(() => "synced").catch(() => "error");
|
|
4373
|
+
const result = options.perEntryTimeoutMs ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)]) : await attempt;
|
|
4374
|
+
if (result === FLUSH_TIMEOUT) {
|
|
4375
|
+
break;
|
|
4376
|
+
}
|
|
4377
|
+
if (result === "synced") {
|
|
4145
4378
|
entry.status = "synced";
|
|
4146
|
-
}
|
|
4379
|
+
} else {
|
|
4147
4380
|
entry.retryCount++;
|
|
4148
4381
|
if (entry.retryCount >= MAX_RETRIES) {
|
|
4149
4382
|
entry.status = "failed";
|
|
@@ -4220,8 +4453,8 @@ var TraceLogger = class {
|
|
|
4220
4453
|
id: this.generateId(),
|
|
4221
4454
|
timestamp: /* @__PURE__ */ new Date(),
|
|
4222
4455
|
type: "evaluation",
|
|
4223
|
-
context,
|
|
4224
|
-
decision
|
|
4456
|
+
context: redactDeep(context),
|
|
4457
|
+
decision: redactDeep(decision)
|
|
4225
4458
|
});
|
|
4226
4459
|
}
|
|
4227
4460
|
/**
|
|
@@ -4338,10 +4571,12 @@ var AstraSyncGateway = class {
|
|
|
4338
4571
|
}
|
|
4339
4572
|
/**
|
|
4340
4573
|
* Graceful shutdown. Flushes sync queue and cleans up resources.
|
|
4574
|
+
* Stateless callers (hooks) pass bounded flush options so sync never
|
|
4575
|
+
* sits on a tool call's critical path.
|
|
4341
4576
|
*/
|
|
4342
|
-
async shutdown() {
|
|
4577
|
+
async shutdown(options) {
|
|
4343
4578
|
if (this.syncQueue) {
|
|
4344
|
-
await this.syncQueue.stop();
|
|
4579
|
+
await this.syncQueue.stop(options?.syncFlush ?? {});
|
|
4345
4580
|
this.syncQueue = null;
|
|
4346
4581
|
}
|
|
4347
4582
|
this.evaluator = null;
|
|
@@ -4364,7 +4599,7 @@ var AstraSyncGateway = class {
|
|
|
4364
4599
|
let decision;
|
|
4365
4600
|
switch (this.config.mode) {
|
|
4366
4601
|
case "online":
|
|
4367
|
-
decision = await verifyOnline(this.config, context, astraId);
|
|
4602
|
+
decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);
|
|
4368
4603
|
break;
|
|
4369
4604
|
case "local":
|
|
4370
4605
|
if (!this.evaluator) throw new Error("Local evaluator not initialized");
|