@pinta-ai/pinta-cc 1.3.0 → 1.3.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pinta-cc",
3
3
  "description": "Generic OTLP forwarder for Claude Code hook events. Converts hook events into OTLP/HTTP spans and sends them to any OpenTelemetry-compatible collector.",
4
- "version": "1.2.0",
4
+ "version": "1.3.2",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "userConfig": {
7
7
  "endpoint": {
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  All notable changes to pinta-cc are documented here.
4
4
 
5
+ ## [1.3.2] - 2026-06-12
6
+
7
+ ### Changed
8
+
9
+ - Guard request timeout raised from `50ms` to `10s` in `src/core/guard.ts`. The
10
+ previous 50ms window caused PreToolUse guard requests to fail open (`ALLOW`)
11
+ before the manager's `/guard/evaluate` could respond. The endpoint now has
12
+ time to actually evaluate. Fail-open behavior on timeout is unchanged.
13
+
14
+ ## [1.3.1] - 2026-05-31
15
+
16
+ ### Added
17
+
18
+ - `GuardResult.userMessage` — the PreToolUse guard now reads a pre-formatted
19
+ `userMessage` field from the manager's `/guard/evaluate` response and
20
+ surfaces it as the `permissionDecisionReason` on a DENY. This carries the
21
+ "Blocked by Pinta AI" brand text + rule name straight to the LLM/user.
22
+
23
+ ### Changed
24
+
25
+ - On a guard DENY, `permissionDecisionReason` now prefers `userMessage`, then
26
+ falls back to the raw `reason`, then to the `'guard_deny'` literal.
27
+
28
+ ### Compatibility
29
+
30
+ - Forward-compatible. Older managers that don't emit `userMessage` leave the
31
+ field as `null`, and the handler falls back to `reason` exactly as before.
32
+
5
33
  ## [1.3.0] - 2026-05-26
6
34
 
7
35
  ### Added
@@ -7,6 +7,7 @@ export interface GuardInput {
7
7
  export interface GuardResult {
8
8
  decision: 'ALLOW' | 'DENY' | 'REVIEW';
9
9
  reason: string | null;
10
+ userMessage: string | null;
10
11
  durationMs: number;
11
12
  failOpenReason?: 'timeout' | 'refused' | 'error';
12
13
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.evaluateGuard = evaluateGuard;
4
- const TIMEOUT_MS = 50;
4
+ const TIMEOUT_MS = 10_000;
5
5
  function sleep(ms) {
6
6
  return new Promise((_, reject) => setTimeout(() => {
7
7
  const err = new Error('Guard request timed out');
@@ -28,14 +28,19 @@ async function evaluateGuard(input, endpoint) {
28
28
  sleep(TIMEOUT_MS),
29
29
  ]);
30
30
  if (res.status !== 200) {
31
- return { decision: 'ALLOW', reason: null, durationMs: Date.now() - start, failOpenReason: 'error' };
31
+ return { decision: 'ALLOW', reason: null, userMessage: null, durationMs: Date.now() - start, failOpenReason: 'error' };
32
32
  }
33
33
  const body = (await res.json());
34
- return { decision: body.decision, reason: body.reason, durationMs: body.durationMs ?? (Date.now() - start) };
34
+ return {
35
+ decision: body.decision,
36
+ reason: body.reason,
37
+ userMessage: body.userMessage ?? null,
38
+ durationMs: body.durationMs ?? (Date.now() - start),
39
+ };
35
40
  }
36
41
  catch (err) {
37
42
  const reason = err.name === 'TimeoutError' ? 'timeout' : 'error';
38
- return { decision: 'ALLOW', reason: null, durationMs: Date.now() - start, failOpenReason: reason };
43
+ return { decision: 'ALLOW', reason: null, userMessage: null, durationMs: Date.now() - start, failOpenReason: reason };
39
44
  }
40
45
  }
41
46
  //# sourceMappingURL=guard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":";;AA0BA,sCA4BC;AAxCD,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CACP,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,KAAiB,EACjB,QAA4B;IAE5B,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC7B,KAAK,CAAC,QAAQ,EAAE;gBACd,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;iBAC3D;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;aAChC,CAAC;YACF,KAAK,CAAC,UAAU,CAAC;SAClB,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;QACtG,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsF,CAAC;QACrH,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IAC/G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAmC,GAAa,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3G,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IACrG,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/core/guard.ts"],"names":[],"mappings":";;AA8BA,sCAsCC;AAlDD,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjD,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,CAAC,EAAE,EAAE,CAAC,CACP,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,KAAiB,EACjB,QAA4B;IAE5B,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC7B,KAAK,CAAC,QAAQ,EAAE;gBACd,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;iBAC3D;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;aAChC,CAAC;YACF,KAAK,CAAC,UAAU,CAAC;SAClB,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;QACzH,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAK7B,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;YACrC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAmC,GAAa,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3G,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IACxH,CAAC;AACH,CAAC"}
@@ -22,11 +22,15 @@ async function handlePreToolUse(event, config) {
22
22
  const payload = (0, otlp_js_1.buildOtlpPayload)({ event, traceId, guard });
23
23
  await transport.send(payload);
24
24
  if (guard?.decision === 'DENY') {
25
+ // Prefer manager-supplied userMessage (carries the "Blocked by Pinta AI"
26
+ // brand text + rule). Fall back to raw rule name for older managers, and
27
+ // to 'guard_deny' literal if even reason is missing.
28
+ const reason = guard.userMessage ?? guard.reason ?? 'guard_deny';
25
29
  const out = {
26
30
  hookSpecificOutput: {
27
31
  hookEventName: 'PreToolUse',
28
32
  permissionDecision: 'deny',
29
- permissionDecisionReason: guard.reason ?? 'guard_deny',
33
+ permissionDecisionReason: reason,
30
34
  },
31
35
  };
32
36
  process.stdout.write(JSON.stringify(out) + '\n');
@@ -1 +1 @@
1
- {"version":3,"file":"pre-tool-use.js","sourceRoot":"","sources":["../../src/handlers/pre-tool-use.ts"],"names":[],"mappings":";;AAOA,4CAmCC;AAxCD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AACnD,+CAAiD;AAE1C,KAAK,UAAU,gBAAgB,CACpC,KAAsB,EACtB,MAAmB;IAEnB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACvD,CAAC,CAAC,KAAK,CAAC,UAAU;QAClB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAa,EAC/B;QACE,MAAM,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS;QACrC,QAAQ,EAAE,KAAK,CAAC,SAAS;QACzB,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,aAAa,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE;KAC3C,EACD,aAAa,CACd,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE9B,IAAI,KAAK,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG;YACV,kBAAkB,EAAE;gBAClB,aAAa,EAAE,YAAY;gBAC3B,kBAAkB,EAAE,MAAe;gBACnC,wBAAwB,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY;aACvD;SACF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"pre-tool-use.js","sourceRoot":"","sources":["../../src/handlers/pre-tool-use.ts"],"names":[],"mappings":";;AAOA,4CAuCC;AA5CD,uDAAiD;AACjD,+CAAgD;AAChD,6CAAmD;AACnD,+CAAiD;AAE1C,KAAK,UAAU,gBAAgB,CACpC,KAAsB,EACtB,MAAmB;IAEnB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACvD,CAAC,CAAC,KAAK,CAAC,UAAU;QAClB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAa,EAC/B;QACE,MAAM,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS;QACrC,QAAQ,EAAE,KAAK,CAAC,SAAS;QACzB,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,aAAa,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE;KAC3C,EACD,aAAa,CACd,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE9B,IAAI,KAAK,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,yEAAyE;QACzE,yEAAyE;QACzE,qDAAqD;QACrD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,IAAI,YAAY,CAAC;QACjE,MAAM,GAAG,GAAG;YACV,kBAAkB,EAAE;gBAClB,aAAa,EAAE,YAAY;gBAC3B,kBAAkB,EAAE,MAAe;gBACnC,wBAAwB,EAAE,MAAM;aACjC;SACF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinta-ai/pinta-cc",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Generic OTLP forwarder for Claude Code hook events",
5
5
  "main": "dist/index.js",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",