@bookedsolid/reagent 0.7.1 → 0.10.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 +277 -140
- package/agents/engineering/motion-designer-interactive.md +5 -4
- package/agents/engineering/pr-voice-reviewer.md +229 -0
- package/agents/engineering/qa-engineer-automation.md +5 -4
- package/agents/engineering/qa-engineer-manual.md +5 -4
- package/agents/engineering/qa-lead.md +5 -4
- package/agents/engineering/security-engineer-appsec.md +5 -4
- package/agents/engineering/security-engineer-compliance.md +5 -4
- package/agents/engineering/security-qa-engineer.md +5 -4
- package/agents/engineering/technical-writer.md +5 -4
- package/agents/product-owner.md +152 -0
- package/agents/reagent-orchestrator.md +8 -0
- package/commands/pm-status.md +230 -0
- package/commands/review-pr.md +197 -0
- package/dist/cli/commands/catalyze/gap-detector.d.ts.map +1 -1
- package/dist/cli/commands/catalyze/gap-detector.js +1 -3
- package/dist/cli/commands/catalyze/gap-detector.js.map +1 -1
- package/dist/cli/commands/daemon/index.d.ts +5 -0
- package/dist/cli/commands/daemon/index.d.ts.map +1 -0
- package/dist/cli/commands/daemon/index.js +59 -0
- package/dist/cli/commands/daemon/index.js.map +1 -0
- package/dist/cli/commands/daemon/restart.d.ts +10 -0
- package/dist/cli/commands/daemon/restart.d.ts.map +1 -0
- package/dist/cli/commands/daemon/restart.js +20 -0
- package/dist/cli/commands/daemon/restart.js.map +1 -0
- package/dist/cli/commands/daemon/start.d.ts +2 -0
- package/dist/cli/commands/daemon/start.d.ts.map +1 -0
- package/dist/cli/commands/daemon/start.js +143 -0
- package/dist/cli/commands/daemon/start.js.map +1 -0
- package/dist/cli/commands/daemon/status.d.ts +2 -0
- package/dist/cli/commands/daemon/status.d.ts.map +1 -0
- package/dist/cli/commands/daemon/status.js +90 -0
- package/dist/cli/commands/daemon/status.js.map +1 -0
- package/dist/cli/commands/daemon/stop.d.ts +2 -0
- package/dist/cli/commands/daemon/stop.d.ts.map +1 -0
- package/dist/cli/commands/daemon/stop.js +73 -0
- package/dist/cli/commands/daemon/stop.js.map +1 -0
- package/dist/cli/commands/init/claude-hooks.d.ts +1 -1
- package/dist/cli/commands/init/claude-hooks.d.ts.map +1 -1
- package/dist/cli/commands/init/claude-hooks.js +10 -4
- package/dist/cli/commands/init/claude-hooks.js.map +1 -1
- package/dist/cli/commands/init/index.d.ts.map +1 -1
- package/dist/cli/commands/init/index.js +5 -1
- package/dist/cli/commands/init/index.js.map +1 -1
- package/dist/cli/commands/init/policy.d.ts.map +1 -1
- package/dist/cli/commands/init/policy.js +21 -0
- package/dist/cli/commands/init/policy.js.map +1 -1
- package/dist/cli/commands/init/types.d.ts +16 -0
- package/dist/cli/commands/init/types.d.ts.map +1 -1
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/daemon-loader.d.ts +16 -0
- package/dist/config/daemon-loader.d.ts.map +1 -0
- package/dist/config/daemon-loader.js +76 -0
- package/dist/config/daemon-loader.js.map +1 -0
- package/dist/config/gateway-config.d.ts.map +1 -1
- package/dist/config/gateway-config.js +6 -0
- package/dist/config/gateway-config.js.map +1 -1
- package/dist/config/policy-loader.d.ts +27 -0
- package/dist/config/policy-loader.d.ts.map +1 -1
- package/dist/config/policy-loader.js +103 -10
- package/dist/config/policy-loader.js.map +1 -1
- package/dist/gateway/circuit-breaker.d.ts +60 -0
- package/dist/gateway/circuit-breaker.d.ts.map +1 -0
- package/dist/gateway/circuit-breaker.js +104 -0
- package/dist/gateway/circuit-breaker.js.map +1 -0
- package/dist/gateway/collision-detector.d.ts +31 -0
- package/dist/gateway/collision-detector.d.ts.map +1 -0
- package/dist/gateway/collision-detector.js +53 -0
- package/dist/gateway/collision-detector.js.map +1 -0
- package/dist/gateway/middleware/blocked-paths.js +2 -2
- package/dist/gateway/middleware/blocked-paths.js.map +1 -1
- package/dist/gateway/middleware/circuit-breaker.d.ts +12 -0
- package/dist/gateway/middleware/circuit-breaker.d.ts.map +1 -0
- package/dist/gateway/middleware/circuit-breaker.js +44 -0
- package/dist/gateway/middleware/circuit-breaker.js.map +1 -0
- package/dist/gateway/middleware/injection.d.ts +23 -0
- package/dist/gateway/middleware/injection.d.ts.map +1 -0
- package/dist/gateway/middleware/injection.js +129 -0
- package/dist/gateway/middleware/injection.js.map +1 -0
- package/dist/gateway/middleware/policy.js +2 -2
- package/dist/gateway/middleware/policy.js.map +1 -1
- package/dist/gateway/middleware/rate-limit.d.ts +13 -0
- package/dist/gateway/middleware/rate-limit.d.ts.map +1 -0
- package/dist/gateway/middleware/rate-limit.js +32 -0
- package/dist/gateway/middleware/rate-limit.js.map +1 -0
- package/dist/gateway/middleware/redact.d.ts.map +1 -1
- package/dist/gateway/middleware/redact.js +7 -0
- package/dist/gateway/middleware/redact.js.map +1 -1
- package/dist/gateway/middleware/result-size-cap.d.ts +14 -0
- package/dist/gateway/middleware/result-size-cap.d.ts.map +1 -0
- package/dist/gateway/middleware/result-size-cap.js +49 -0
- package/dist/gateway/middleware/result-size-cap.js.map +1 -0
- package/dist/gateway/native-tools.js +1 -1
- package/dist/gateway/native-tools.js.map +1 -1
- package/dist/gateway/rate-limiter.d.ts +47 -0
- package/dist/gateway/rate-limiter.d.ts.map +1 -0
- package/dist/gateway/rate-limiter.js +89 -0
- package/dist/gateway/rate-limiter.js.map +1 -0
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +27 -1
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/tool-proxy.js +1 -1
- package/dist/gateway/tool-proxy.js.map +1 -1
- package/dist/types/daemon.d.ts +45 -0
- package/dist/types/daemon.d.ts.map +1 -0
- package/dist/types/daemon.js +2 -0
- package/dist/types/daemon.js.map +1 -0
- package/dist/types/gateway.d.ts +9 -0
- package/dist/types/gateway.d.ts.map +1 -1
- package/dist/types/policy.d.ts +1 -0
- package/dist/types/policy.d.ts.map +1 -1
- package/hooks/_lib/discord.sh +75 -0
- package/hooks/blocked-paths-enforcer.sh +0 -1
- package/hooks/changeset-security-gate.sh +143 -0
- package/hooks/commit-review-gate.sh +12 -4
- package/hooks/import-guard.sh +14 -0
- package/hooks/network-exfil-guard.sh +20 -2
- package/hooks/pr-issue-link-gate.sh +65 -0
- package/hooks/push-review-gate.sh +17 -2
- package/hooks/rate-limit-guard.sh +26 -2
- package/hooks/reagent-notify.sh +65 -0
- package/hooks/security-disclosure-gate.sh +146 -0
- package/husky/pre-push.sh +84 -0
- package/package.json +10 -2
- package/profiles/bst-internal.json +12 -2
- package/profiles/client-engagement.json +12 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/gateway/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GvE"}
|
package/dist/gateway/server.js
CHANGED
|
@@ -10,9 +10,16 @@ import { createKillSwitchMiddleware } from './middleware/kill-switch.js';
|
|
|
10
10
|
import { createTierMiddleware } from './middleware/tier.js';
|
|
11
11
|
import { createPolicyMiddleware } from './middleware/policy.js';
|
|
12
12
|
import { redactMiddleware } from './middleware/redact.js';
|
|
13
|
+
import { createInjectionMiddleware } from './middleware/injection.js';
|
|
13
14
|
import { createAuditMiddleware } from './middleware/audit.js';
|
|
14
15
|
import { createBlockedPathsMiddleware } from './middleware/blocked-paths.js';
|
|
16
|
+
import { createResultSizeCapMiddleware } from './middleware/result-size-cap.js';
|
|
17
|
+
import { createRateLimitMiddleware } from './middleware/rate-limit.js';
|
|
18
|
+
import { createCircuitBreakerMiddleware } from './middleware/circuit-breaker.js';
|
|
19
|
+
import { RateLimiter } from './rate-limiter.js';
|
|
20
|
+
import { CircuitBreaker } from './circuit-breaker.js';
|
|
15
21
|
import { registerNativeTools } from './native-tools.js';
|
|
22
|
+
import { detectToolCollisions } from './collision-detector.js';
|
|
16
23
|
/**
|
|
17
24
|
* Starts the MCP gateway server.
|
|
18
25
|
*
|
|
@@ -33,7 +40,17 @@ export async function startGateway(options) {
|
|
|
33
40
|
// Build middleware chain
|
|
34
41
|
// SECURITY: Audit is outermost so it records ALL invocations, including kill-switch denials.
|
|
35
42
|
// SECURITY: blocked-paths runs before tool execution to prevent writes to protected paths.
|
|
36
|
-
//
|
|
43
|
+
// SECURITY: injection runs PostToolUse (after redact) to scan downstream results for prompt injection.
|
|
44
|
+
// SECURITY: result-size-cap runs PostToolUse after injection so it caps already-scanned output.
|
|
45
|
+
// SECURITY: rate-limit runs after policy (so denied calls don't burn rate budget) but before execution.
|
|
46
|
+
// SECURITY: circuit-breaker wraps the execute step so it can observe Error status and track failures.
|
|
47
|
+
// Placed after rate-limit so a rate-limited call doesn't count as a downstream failure.
|
|
48
|
+
// Order (onion): audit → session → kill-switch → tier → policy → blocked-paths → rate-limit → circuit-breaker → redact → injection → result-size-cap → [execute]
|
|
49
|
+
const injectionAction = policy.injection_detection === 'warn'
|
|
50
|
+
? 'warn'
|
|
51
|
+
: 'block';
|
|
52
|
+
const rateLimiter = new RateLimiter(gatewayConfig);
|
|
53
|
+
const circuitBreaker = new CircuitBreaker();
|
|
37
54
|
const middlewares = [
|
|
38
55
|
createAuditMiddleware(baseDir, policy),
|
|
39
56
|
createSessionMiddleware(),
|
|
@@ -41,13 +58,22 @@ export async function startGateway(options) {
|
|
|
41
58
|
createTierMiddleware(gatewayConfig),
|
|
42
59
|
createPolicyMiddleware(policy, gatewayConfig, baseDir),
|
|
43
60
|
createBlockedPathsMiddleware(policy, baseDir),
|
|
61
|
+
createRateLimitMiddleware(rateLimiter),
|
|
62
|
+
createCircuitBreakerMiddleware(circuitBreaker),
|
|
44
63
|
redactMiddleware,
|
|
64
|
+
createInjectionMiddleware(injectionAction),
|
|
65
|
+
createResultSizeCapMiddleware(gatewayConfig),
|
|
45
66
|
];
|
|
46
67
|
// Create gateway MCP server
|
|
47
68
|
const gateway = new McpServer({ name: 'reagent', version: getPkgVersion() }, { capabilities: { tools: {} } });
|
|
48
69
|
// Connect to downstream servers
|
|
49
70
|
const clientManager = new ClientManager();
|
|
50
71
|
await clientManager.connectAll(gatewayConfig);
|
|
72
|
+
// Detect tool name collisions before accepting connections (GHSA-4j9r)
|
|
73
|
+
const { collisions } = await detectToolCollisions(clientManager);
|
|
74
|
+
if (collisions.length > 0) {
|
|
75
|
+
console.error(`[reagent] ${collisions.length} tool name collision(s) detected — shadowed tools will be registered with server-prefixed names`);
|
|
76
|
+
}
|
|
51
77
|
// Register native (first-party) tools
|
|
52
78
|
const nativeCount = registerNativeTools(gateway, baseDir, middlewares);
|
|
53
79
|
// Discover and register proxied tools
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/gateway/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-proxy.js","sourceRoot":"","sources":["../../src/gateway/tool-proxy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAUrD;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,WAAoC;IACjE,MAAM,SAAS,GAA8B,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,WAAW,CAAC,UAAiD,CAAC;IACjF,MAAM,QAAQ,GAAI,WAAW,CAAC,QAAqB,IAAI,EAAE,CAAC;IAE1D,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1C,SAAS,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;QACjF,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,SAAS;IACZ,KAAK,GAAqB,EAAE,CAAC;IAErC,KAAK,CAAC,mBAAmB,CACvB,OAAkB,EAClB,aAA4B,EAC5B,WAAyB;QAEzB,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC;QAE9C,KAAK,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBAChD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBAChC,MAAM,cAAc,GAAG,GAAG,UAAU,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;oBAErD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,cAAc;wBACpB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;wBACnC,WAAW,EAAE,IAAI,CAAC,WAAsC;wBACxD,UAAU;wBACV,MAAM,EAAE,OAAO;qBAChB,CAAC,CAAC;oBAEH,sDAAsD;oBACtD,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,WAAsC,CAAC,CAAC;oBAErF,sDAAsD;oBACtD,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;wBAC/E,yEAAyE;wBACzE,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAA6B,CAAC;wBACtD,0CAA0C;wBAC1C,OAAO,IAAI,CAAC,YAAY,CAAC;wBAEzB,MAAM,GAAG,GAAsB;4BAC7B,SAAS,EAAE,IAAI,CAAC,IAAI;4BACpB,WAAW,EAAE,UAAU;4BACvB,SAAS,EAAE,IAAI;4BACf,UAAU,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"tool-proxy.js","sourceRoot":"","sources":["../../src/gateway/tool-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DaemonConfig — global daemon settings loaded from ~/.reagent/daemon.yaml.
|
|
3
|
+
*
|
|
4
|
+
* This file is the source of truth for daemon configuration shape on the
|
|
5
|
+
* TypeScript side. The Rust daemon reads the same YAML file; keep field names
|
|
6
|
+
* in sync with daemon/src/config.rs.
|
|
7
|
+
*/
|
|
8
|
+
export interface DaemonConfig {
|
|
9
|
+
/** TCP port the daemon listens on. Default: 7777 */
|
|
10
|
+
port: number;
|
|
11
|
+
/** Bind address. Default: '127.0.0.1' */
|
|
12
|
+
bind: string;
|
|
13
|
+
/** Idle session TTL in minutes. Default: 30 */
|
|
14
|
+
session_ttl_minutes: number;
|
|
15
|
+
/** Log verbosity passed to the Rust daemon via RUST_LOG. Default: 'info' */
|
|
16
|
+
log_level: 'debug' | 'info' | 'warn' | 'error';
|
|
17
|
+
/** Optional API key authentication for the daemon HTTP surface. */
|
|
18
|
+
auth?: DaemonAuth;
|
|
19
|
+
}
|
|
20
|
+
export interface DaemonAuth {
|
|
21
|
+
/** List of accepted bearer tokens. If empty or absent, auth is disabled. */
|
|
22
|
+
api_keys?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/** Represents a single active session as returned by GET /sessions.
|
|
25
|
+
*
|
|
26
|
+
* Field names match the Rust SessionSummary struct in daemon/src/session.rs.
|
|
27
|
+
*/
|
|
28
|
+
export interface DaemonSession {
|
|
29
|
+
session_id: string;
|
|
30
|
+
project_root: string;
|
|
31
|
+
/** Seconds elapsed since last MCP activity on this session. */
|
|
32
|
+
last_activity_elapsed_secs: number;
|
|
33
|
+
}
|
|
34
|
+
/** Shape of GET /health response body. */
|
|
35
|
+
export interface DaemonHealthResponse {
|
|
36
|
+
status: 'ok';
|
|
37
|
+
version: string;
|
|
38
|
+
sessions: number;
|
|
39
|
+
uptime_seconds: number;
|
|
40
|
+
}
|
|
41
|
+
/** Shape of GET /sessions response body. */
|
|
42
|
+
export interface DaemonSessionsResponse {
|
|
43
|
+
sessions: readonly DaemonSession[];
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/types/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/C,mEAAmE;IACnE,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,0BAA0B,EAAE,MAAM,CAAC;CACpC;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/types/daemon.ts"],"names":[],"mappings":""}
|
package/dist/types/gateway.d.ts
CHANGED
|
@@ -8,9 +8,18 @@ export interface DownstreamServer {
|
|
|
8
8
|
args: string[];
|
|
9
9
|
env?: Record<string, string>;
|
|
10
10
|
tool_overrides?: Record<string, ToolOverride>;
|
|
11
|
+
/** Max concurrent in-flight calls to this server (0 = unlimited) */
|
|
12
|
+
max_concurrent_calls?: number;
|
|
13
|
+
/** Max calls per minute to this server (0 = unlimited) */
|
|
14
|
+
calls_per_minute?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface GatewayOptions {
|
|
17
|
+
/** Cap on tool result size in KB. Results exceeding this are truncated. Default: 512 */
|
|
18
|
+
max_result_size_kb?: number;
|
|
11
19
|
}
|
|
12
20
|
export interface GatewayConfig {
|
|
13
21
|
version: string;
|
|
14
22
|
servers: Record<string, DownstreamServer>;
|
|
23
|
+
gateway?: GatewayOptions;
|
|
15
24
|
}
|
|
16
25
|
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/types/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/types/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9C,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B"}
|
package/dist/types/policy.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/types/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,aAAa,CAAC;IAClC,iCAAiC,EAAE,OAAO,CAAC;IAC3C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/types/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,aAAa,CAAC;IAClC,iCAAiC,EAAE,OAAO,CAAC;IAC3C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAE7B,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACxC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# hooks/_lib/discord.sh — Discord notification helpers for local git hooks
|
|
3
|
+
# Source this file; do not execute it directly.
|
|
4
|
+
#
|
|
5
|
+
# Requires: curl (for webhook delivery), gateway.yaml (for channel config)
|
|
6
|
+
# Design: always silently no-ops when Discord isn't configured — hooks must
|
|
7
|
+
# never block or add perceptible latency because of a missing notification setup.
|
|
8
|
+
|
|
9
|
+
# Post an embed message to a Discord webhook.
|
|
10
|
+
# Usage: discord_notify <channel_type> <message> [<color>]
|
|
11
|
+
# channel_type: dev | alert | release | task
|
|
12
|
+
# color: green | red | yellow | blue (default: blue)
|
|
13
|
+
#
|
|
14
|
+
# Webhook resolution order:
|
|
15
|
+
# 1. REAGENT_DISCORD_WEBHOOK env var (overrides everything)
|
|
16
|
+
# 2. Per-channel env vars: REAGENT_DISCORD_WEBHOOK_DEV, _ALERT, _RELEASE, _TASK
|
|
17
|
+
# 3. gateway.yaml channel webhook entries (parsed with grep/awk, no jq needed)
|
|
18
|
+
#
|
|
19
|
+
# The curl call runs in the background so it never stalls the hook.
|
|
20
|
+
discord_notify() {
|
|
21
|
+
local channel_type="$1"
|
|
22
|
+
local message="$2"
|
|
23
|
+
local color="${3:-blue}"
|
|
24
|
+
|
|
25
|
+
# Bail immediately if curl isn't present — no point continuing
|
|
26
|
+
if ! command -v curl >/dev/null 2>&1; then
|
|
27
|
+
return 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
local repo_root
|
|
31
|
+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || return 0
|
|
32
|
+
|
|
33
|
+
local gateway_yaml="${repo_root}/.reagent/gateway.yaml"
|
|
34
|
+
|
|
35
|
+
# Resolve webhook: env override first, then per-channel env, then gateway.yaml
|
|
36
|
+
local webhook="${REAGENT_DISCORD_WEBHOOK:-}"
|
|
37
|
+
|
|
38
|
+
if [ -z "$webhook" ]; then
|
|
39
|
+
local upper_type
|
|
40
|
+
upper_type="$(printf '%s' "$channel_type" | tr '[:lower:]' '[:upper:]')"
|
|
41
|
+
local env_var="REAGENT_DISCORD_WEBHOOK_${upper_type}"
|
|
42
|
+
webhook="${!env_var:-}"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [ -z "$webhook" ] && [ -f "$gateway_yaml" ]; then
|
|
46
|
+
# Expect a block like:
|
|
47
|
+
# dev_channel:
|
|
48
|
+
# webhook: "https://discord.com/api/webhooks/..."
|
|
49
|
+
webhook=$(grep -A2 "${channel_type}_channel:" "$gateway_yaml" 2>/dev/null \
|
|
50
|
+
| grep "webhook:" \
|
|
51
|
+
| awk '{print $2}' \
|
|
52
|
+
| tr -d '"'"'" 2>/dev/null || true)
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Nothing configured for this channel — silent no-op
|
|
56
|
+
[ -z "$webhook" ] && return 0
|
|
57
|
+
|
|
58
|
+
local color_int
|
|
59
|
+
case "$color" in
|
|
60
|
+
green) color_int=3066993 ;;
|
|
61
|
+
red) color_int=15158332 ;;
|
|
62
|
+
yellow) color_int=16776960 ;;
|
|
63
|
+
*) color_int=3447003 ;; # blue
|
|
64
|
+
esac
|
|
65
|
+
|
|
66
|
+
# Escape the message for JSON: backslashes, double-quotes, and control chars
|
|
67
|
+
local escaped_message
|
|
68
|
+
escaped_message="$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g' 2>/dev/null || printf '%s' "$message")"
|
|
69
|
+
|
|
70
|
+
# Fire-and-forget: run in the background so the hook returns immediately
|
|
71
|
+
curl -s -X POST "$webhook" \
|
|
72
|
+
-H "Content-Type: application/json" \
|
|
73
|
+
-d "{\"embeds\":[{\"description\":\"${escaped_message}\",\"color\":${color_int}}]}" \
|
|
74
|
+
>/dev/null 2>&1 &
|
|
75
|
+
}
|
|
@@ -138,7 +138,6 @@ for blocked in "${BLOCKED_PATHS[@]}"; do
|
|
|
138
138
|
# Glob pattern match (contains *)
|
|
139
139
|
if [[ "$blocked" == *'*'* ]]; then
|
|
140
140
|
# Convert glob to regex: . → \., * → .*
|
|
141
|
-
local regex
|
|
142
141
|
regex=$(printf '%s' "$LOWER_BLOCKED" | sed 's/\./\\./g; s/\*/.*/g')
|
|
143
142
|
if printf '%s' "$LOWER_NORM" | grep -qE "^${regex}$"; then
|
|
144
143
|
{
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# changeset-security-gate.sh — PreToolUse: Write|Edit
|
|
3
|
+
#
|
|
4
|
+
# Guards .changeset/*.md files against two failure modes:
|
|
5
|
+
#
|
|
6
|
+
# 1. SECURITY DISCLOSURE LEAK — GHSA IDs or CVE numbers written to a changeset
|
|
7
|
+
# file before the advisory is published. Changeset files are committed to git
|
|
8
|
+
# and appear verbatim in CHANGELOG.md — referencing a GHSA ID pre-publish
|
|
9
|
+
# creates public pre-disclosure in git history.
|
|
10
|
+
#
|
|
11
|
+
# 2. MISSING OR MALFORMED FRONTMATTER — changeset files without proper frontmatter
|
|
12
|
+
# are silently ignored by the changesets tool, wasting the release entry.
|
|
13
|
+
#
|
|
14
|
+
# Triggered by: PreToolUse — Write and Edit tools
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# shellcheck source=_lib/common.sh
|
|
19
|
+
source "$(dirname "$0")/_lib/common.sh"
|
|
20
|
+
|
|
21
|
+
check_halt
|
|
22
|
+
|
|
23
|
+
INPUT="$(cat)"
|
|
24
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
25
|
+
|
|
26
|
+
# Only handle Write and Edit
|
|
27
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
|
|
32
|
+
|
|
33
|
+
# Only care about .changeset/*.md files — exclude README.md (changeset tool metadata)
|
|
34
|
+
if ! echo "$FILE_PATH" | grep -qE '\.changeset/[^/]+\.md$' || echo "$FILE_PATH" | grep -qE '\.changeset/README\.md$'; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
require_jq
|
|
39
|
+
|
|
40
|
+
# Extract the content being written
|
|
41
|
+
if [[ "$TOOL_NAME" == "Write" ]]; then
|
|
42
|
+
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
|
|
43
|
+
else
|
|
44
|
+
# For Edit: check the new_string being inserted
|
|
45
|
+
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""')
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# ─── 1. SECURITY DISCLOSURE CHECK ───────────────────────────────────────────
|
|
49
|
+
#
|
|
50
|
+
# These patterns in a changeset mean security details are about to be committed
|
|
51
|
+
# to git history BEFORE the advisory is published — creating pre-disclosure.
|
|
52
|
+
# GHSA IDs and CVE numbers must NEVER appear in changeset files.
|
|
53
|
+
|
|
54
|
+
DISCLOSURE_PATTERNS=(
|
|
55
|
+
'GHSA-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}'
|
|
56
|
+
'CVE-[0-9]{4}-[0-9]+'
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
MATCHED_PATTERN=""
|
|
60
|
+
for PATTERN in "${DISCLOSURE_PATTERNS[@]}"; do
|
|
61
|
+
if echo "$CONTENT" | grep -qE "$PATTERN"; then
|
|
62
|
+
MATCHED_PATTERN="$PATTERN"
|
|
63
|
+
break
|
|
64
|
+
fi
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
if [[ -n "$MATCHED_PATTERN" ]]; then
|
|
68
|
+
json_output "block" \
|
|
69
|
+
"CHANGESET SECURITY GATE: This changeset contains a security advisory identifier (matched: '${MATCHED_PATTERN}').
|
|
70
|
+
|
|
71
|
+
Do NOT reference GHSA IDs or CVE numbers in changeset files before the advisory is published.
|
|
72
|
+
Changeset files are committed to git — this creates pre-disclosure in public history and CHANGELOG.
|
|
73
|
+
|
|
74
|
+
CORRECT approach for security fix changesets:
|
|
75
|
+
Use vague language only — no identifiers, no vulnerability details.
|
|
76
|
+
|
|
77
|
+
WRONG: 'fix(hooks): patch GHSA-3w3m-7gg4-f82g — symlink-guard now covers Edit tool'
|
|
78
|
+
RIGHT: 'security: extend symlink protection to cover all write-capable tools'
|
|
79
|
+
|
|
80
|
+
WRONG: 'security: fix CVE-2026-1234 prompt injection via tool descriptions'
|
|
81
|
+
RIGHT: 'security: harden middleware chain against indirect instruction attacks'
|
|
82
|
+
|
|
83
|
+
After the release ships:
|
|
84
|
+
1. Publish the GitHub Security Advisory (Security tab → Advisories → Publish)
|
|
85
|
+
2. The GHSA becomes the detailed public disclosure document
|
|
86
|
+
3. Optionally update CHANGELOG.md post-publish to add the GHSA reference"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# ─── 2. FRONTMATTER VALIDATION ───────────────────────────────────────────────
|
|
90
|
+
#
|
|
91
|
+
# A changeset without valid frontmatter is silently ignored by the changesets
|
|
92
|
+
# tool — the package bump and CHANGELOG entry never appear in the release.
|
|
93
|
+
|
|
94
|
+
# Must start with ---
|
|
95
|
+
if ! echo "$CONTENT" | head -1 | grep -qE '^---'; then
|
|
96
|
+
json_output "block" \
|
|
97
|
+
"CHANGESET FORMAT GATE: Missing frontmatter block.
|
|
98
|
+
|
|
99
|
+
Every changeset must start with a frontmatter block specifying which package to bump:
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
'@bookedsolid/reagent': patch
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
Brief description of what changed and why (close #N if applicable).
|
|
106
|
+
|
|
107
|
+
Bump types: patch (bug fix/security), minor (new feature), major (breaking change)"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Must have at least one package bump entry and a closing ---
|
|
111
|
+
FRONTMATTER=$(echo "$CONTENT" | awk '/^---/{count++; if(count==2){exit} next} count==1{print}')
|
|
112
|
+
if ! echo "$FRONTMATTER" | grep -qE "^'.+': (patch|minor|major)"; then
|
|
113
|
+
json_output "block" \
|
|
114
|
+
"CHANGESET FORMAT GATE: Frontmatter does not contain a valid package bump entry.
|
|
115
|
+
|
|
116
|
+
The frontmatter must include at least one package/bump pair:
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
'@bookedsolid/reagent': patch
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
Valid bump types: patch | minor | major"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# Must have a non-empty description after the closing ---
|
|
126
|
+
DESCRIPTION=$(echo "$CONTENT" | awk 'BEGIN{count=0} /^---/{count++; next} count>=2{print}' | grep -v '^[[:space:]]*$' | head -1 || true)
|
|
127
|
+
if [[ -z "$DESCRIPTION" ]]; then
|
|
128
|
+
json_output "block" \
|
|
129
|
+
"CHANGESET FORMAT GATE: Missing description after frontmatter.
|
|
130
|
+
|
|
131
|
+
Add a meaningful description explaining what changed and why:
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
'@bookedsolid/reagent': patch
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
fix(gateway): policy-loader now uses async I/O with 500ms TTL cache
|
|
138
|
+
|
|
139
|
+
Previously, loadPolicy used fs.readFileSync on every tool invocation, blocking
|
|
140
|
+
the event loop under concurrency. Closes #34."
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
exit 0
|
|
@@ -97,15 +97,23 @@ if [[ "$SCORE" == "trivial" ]]; then
|
|
|
97
97
|
exit 0
|
|
98
98
|
fi
|
|
99
99
|
|
|
100
|
-
# ── 9.
|
|
101
|
-
|
|
100
|
+
# ── 9. Resolve reagent CLI (node_modules/.bin first, dist fallback) ───────────
|
|
101
|
+
REAGENT_CLI_ARGS=()
|
|
102
|
+
if [[ -f "${REAGENT_ROOT}/node_modules/.bin/reagent" ]]; then
|
|
103
|
+
REAGENT_CLI_ARGS=(node "${REAGENT_ROOT}/node_modules/.bin/reagent")
|
|
104
|
+
elif [[ -f "${REAGENT_ROOT}/dist/cli/index.js" ]]; then
|
|
105
|
+
REAGENT_CLI_ARGS=(node "${REAGENT_ROOT}/dist/cli/index.js")
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# ── 10. Standard + Significant → check review cache ───────────────────────────
|
|
109
|
+
if [[ "$SCORE" == "standard" ]] || [[ "$SCORE" == "significant" ]]; then
|
|
102
110
|
# Compute SHA of staged content for cache lookup
|
|
103
111
|
STAGED_SHA=$(cd "$REAGENT_ROOT" && git diff --cached | shasum -a 256 | cut -d' ' -f1 2>/dev/null || echo "")
|
|
104
112
|
BRANCH=$(cd "$REAGENT_ROOT" && git branch --show-current 2>/dev/null || echo "")
|
|
105
113
|
|
|
106
|
-
if [[ -n "$STAGED_SHA" ]]; then
|
|
114
|
+
if [[ -n "$STAGED_SHA" ]] && [[ ${#REAGENT_CLI_ARGS[@]} -gt 0 ]]; then
|
|
107
115
|
# Check review cache via reagent CLI
|
|
108
|
-
CACHE_RESULT=$(
|
|
116
|
+
CACHE_RESULT=$("${REAGENT_CLI_ARGS[@]}" cache check "$STAGED_SHA" --branch "$BRANCH" 2>/dev/null || echo '{"hit":false}')
|
|
109
117
|
if printf '%s' "$CACHE_RESULT" | jq -e '.hit == true' >/dev/null 2>&1; then
|
|
110
118
|
exit 0
|
|
111
119
|
fi
|
package/hooks/import-guard.sh
CHANGED
|
@@ -83,6 +83,20 @@ if printf '%s' "$CONTENT" | grep -qE "require\([^'\"][^)]*\)"; then
|
|
|
83
83
|
WARNINGS+=("Dynamic require(variable) — loading modules by variable name can be exploited for path traversal. Prefer static imports.")
|
|
84
84
|
fi
|
|
85
85
|
|
|
86
|
+
# ESM dynamic import() of dangerous modules: await import('child_process'), import('vm').then(...)
|
|
87
|
+
if printf '%s' "$CONTENT" | grep -qE "import\(['\"]child_process['\"]"; then
|
|
88
|
+
WARNINGS+=("import('child_process') — ESM dynamic import grants shell execution capability. Use safer alternatives or document the necessity.")
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if printf '%s' "$CONTENT" | grep -qE "import\(['\"]vm['\"]"; then
|
|
92
|
+
WARNINGS+=("import('vm') — ESM dynamic import of Node.js VM module allows dynamic code execution. Ensure input is fully trusted and sandboxed.")
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Dynamic import() with a variable or template literal: import(variable), import(\`...\`)
|
|
96
|
+
if printf '%s' "$CONTENT" | grep -qE "import\([^'\"(][^)]*\)"; then
|
|
97
|
+
WARNINGS+=("Dynamic import(variable) — loading modules by variable name or template literal can be exploited for path traversal. Prefer static imports.")
|
|
98
|
+
fi
|
|
99
|
+
|
|
86
100
|
if [[ ${#WARNINGS[@]} -eq 0 ]]; then
|
|
87
101
|
exit 0
|
|
88
102
|
fi
|
|
@@ -65,7 +65,25 @@ if printf '%s' "$CMD" | grep -qiE '(curl|wget).*-d[[:space:]]+@'; then
|
|
|
65
65
|
exit 2
|
|
66
66
|
fi
|
|
67
67
|
|
|
68
|
-
# ── Check 3:
|
|
68
|
+
# ── Check 3: Shell variable URL interpolation ─────────────────────────────────
|
|
69
|
+
# Detect curl/wget with variable-interpolated URLs that cannot be inspected at hook time.
|
|
70
|
+
# Patterns: curl $VAR, curl ${VAR}, curl "$VAR/path", curl "${VAR}/api", wget $VAR, etc.
|
|
71
|
+
# Uses two sub-patterns:
|
|
72
|
+
# 1. Bare variable argument (space before $VAR, ends with space or EOL)
|
|
73
|
+
# 2. Quoted variable as URL start (space before "$VAR...")
|
|
74
|
+
if printf '%s' "$CMD" | grep -qiE '(curl|wget)[^|]*[[:space:]][$][{]?[A-Za-z_][A-Za-z0-9_]*[}]?([[:space:]]|$)' || \
|
|
75
|
+
printf '%s' "$CMD" | grep -qiE '(curl|wget)[^|]*[[:space:]]"[$][{]?[A-Za-z_][A-Za-z0-9_]*[}]?[^"]*"'; then
|
|
76
|
+
printf 'NETWORK-EXFIL-GUARD: Shell variable URL interpolation detected\n' >&2
|
|
77
|
+
printf ' Pattern: curl/wget with a shell variable as the URL argument\n' >&2
|
|
78
|
+
printf ' Command: %s\n' "$(printf '%s' "$CMD" | head -c 200)" >&2
|
|
79
|
+
printf 'Warning: The destination URL cannot be inspected at hook time because it is stored in a variable.\n' >&2
|
|
80
|
+
printf 'Please confirm the variable resolves to an allowlisted host before proceeding.\n' >&2
|
|
81
|
+
printf 'Allowlisted hosts: registry.npmjs.org, github.com, api.github.com, raw.githubusercontent.com\n' >&2
|
|
82
|
+
printf 'If you are certain the destination is safe, replace the variable with a literal URL.\n' >&2
|
|
83
|
+
exit 2
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# ── Check 4: Host allowlist ───────────────────────────────────────────────────
|
|
69
87
|
ALLOWLIST=(
|
|
70
88
|
"registry.npmjs.org"
|
|
71
89
|
"github.com"
|
|
@@ -80,7 +98,7 @@ ALLOWLIST=(
|
|
|
80
98
|
URLS=$(printf '%s' "$CMD" | grep -oE 'https?://[^[:space:]"'"'"']+' | head -20)
|
|
81
99
|
|
|
82
100
|
if [[ -z "$URLS" ]]; then
|
|
83
|
-
# No parseable URLs
|
|
101
|
+
# No parseable literal URLs found (variable-based URLs already caught above)
|
|
84
102
|
exit 0
|
|
85
103
|
fi
|
|
86
104
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pr-issue-link-gate.sh — PreToolUse: Bash
|
|
3
|
+
#
|
|
4
|
+
# Ensures every `gh pr create` command references at least one GitHub issue
|
|
5
|
+
# via closes/fixes/resolves #N syntax in the PR body. When the magic keyword
|
|
6
|
+
# is present, GitHub automatically closes the linked issue when the PR merges
|
|
7
|
+
# to the default branch and creates a cross-reference in the issue timeline.
|
|
8
|
+
#
|
|
9
|
+
# This gate is ADVISORY (exit 0) — it warns but does not block. Some PRs
|
|
10
|
+
# legitimately have no linked issue (chores, hotfixes, release PRs). The
|
|
11
|
+
# advisory gives the agent an opportunity to add the link before proceeding.
|
|
12
|
+
#
|
|
13
|
+
# Only active for Bash tool calls containing `gh pr create`.
|
|
14
|
+
# JSONL-only projects (no GitHub) are unaffected — gh is unavailable there.
|
|
15
|
+
#
|
|
16
|
+
# Triggered by: PreToolUse — Bash tool
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# shellcheck source=_lib/common.sh
|
|
21
|
+
source "$(dirname "$0")/_lib/common.sh"
|
|
22
|
+
|
|
23
|
+
check_halt
|
|
24
|
+
|
|
25
|
+
INPUT="$(cat)"
|
|
26
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
27
|
+
|
|
28
|
+
if [[ "$TOOL_NAME" != "Bash" ]]; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
|
|
33
|
+
|
|
34
|
+
# Only intercept gh pr create
|
|
35
|
+
if ! echo "$COMMAND" | grep -qE 'gh\s+pr\s+create'; then
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
require_jq
|
|
40
|
+
|
|
41
|
+
# Check for closing keywords followed by an issue number
|
|
42
|
+
# Accepted: closes #N, fixes #N, resolves #N (case-insensitive, any spacing)
|
|
43
|
+
if echo "$COMMAND" | grep -qiE '(closes|fixes|resolves)\s+#[0-9]+'; then
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Advisory — warn but do not block.
|
|
48
|
+
# Chore PRs, release PRs, and hotfixes may legitimately have no linked issue.
|
|
49
|
+
printf 'PR ISSUE LINK ADVISORY: This PR does not reference a GitHub issue.\n' >&2
|
|
50
|
+
printf '\n' >&2
|
|
51
|
+
printf 'When a PR body includes a closing reference, GitHub automatically:\n' >&2
|
|
52
|
+
printf ' - Closes the issue when the PR merges to the default branch\n' >&2
|
|
53
|
+
printf ' - Creates a cross-reference in the issue timeline\n' >&2
|
|
54
|
+
printf ' - Links the PR in the CHANGELOG context\n' >&2
|
|
55
|
+
printf '\n' >&2
|
|
56
|
+
printf 'Add to the --body:\n' >&2
|
|
57
|
+
printf ' closes #N closes one issue\n' >&2
|
|
58
|
+
printf ' fixes #N same effect\n' >&2
|
|
59
|
+
printf ' resolves #N same effect\n' >&2
|
|
60
|
+
printf ' closes #N, closes #M closes multiple issues\n' >&2
|
|
61
|
+
printf '\n' >&2
|
|
62
|
+
printf 'If this is a chore, release, or hotfix PR with no upstream issue, you may proceed.\n' >&2
|
|
63
|
+
|
|
64
|
+
# Exit 0 — advisory only, does not block the PR creation
|
|
65
|
+
exit 0
|
|
@@ -79,9 +79,24 @@ LINE_COUNT=$(printf '%s' "$DIFF_FULL" | grep -cE '^\+[^+]|^-[^-]' 2>/dev/null ||
|
|
|
79
79
|
# ── 8. Check review cache ────────────────────────────────────────────────────
|
|
80
80
|
PUSH_SHA=$(printf '%s' "$DIFF_FULL" | shasum -a 256 | cut -d' ' -f1 2>/dev/null || echo "")
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
# Resolve reagent CLI (node_modules/.bin first, dist fallback)
|
|
83
|
+
REAGENT_CLI_ARGS=()
|
|
84
|
+
if [[ -f "${REAGENT_ROOT}/node_modules/.bin/reagent" ]]; then
|
|
85
|
+
REAGENT_CLI_ARGS=(node "${REAGENT_ROOT}/node_modules/.bin/reagent")
|
|
86
|
+
elif [[ -f "${REAGENT_ROOT}/dist/cli/index.js" ]]; then
|
|
87
|
+
REAGENT_CLI_ARGS=(node "${REAGENT_ROOT}/dist/cli/index.js")
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if [[ -n "$PUSH_SHA" ]] && [[ ${#REAGENT_CLI_ARGS[@]} -gt 0 ]]; then
|
|
91
|
+
CACHE_RESULT=$("${REAGENT_CLI_ARGS[@]}" cache check "$PUSH_SHA" --branch "$CURRENT_BRANCH" --base "$TARGET_BRANCH" 2>/dev/null || echo '{"hit":false}')
|
|
84
92
|
if printf '%s' "$CACHE_RESULT" | jq -e '.hit == true' >/dev/null 2>&1; then
|
|
93
|
+
# Review was already approved — notify and allow the push through
|
|
94
|
+
DISCORD_LIB="${REAGENT_ROOT}/hooks/_lib/discord.sh"
|
|
95
|
+
if [ -f "$DISCORD_LIB" ]; then
|
|
96
|
+
# shellcheck source=/dev/null
|
|
97
|
+
source "$DISCORD_LIB"
|
|
98
|
+
discord_notify "dev" "Push passed quality gates on \`${CURRENT_BRANCH}\` -- $(cd "$REAGENT_ROOT" && git log -1 --oneline 2>/dev/null)" "green"
|
|
99
|
+
fi
|
|
85
100
|
exit 0
|
|
86
101
|
fi
|
|
87
102
|
fi
|