progmune-runtime 3.7.17 → 3.7.18

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.
@@ -75,9 +75,10 @@ function extractJavaFile(filePath) {
75
75
  const name = m[1];
76
76
  if (JAVA_KEYWORDS.has(name))
77
77
  continue;
78
- // 前置字符过滤:方法名不应紧跟 '.'(调用)或 '='(赋值)等
78
+ // 前置字符过滤:排除 '.'/'='/'( ' 前导(调用/赋值/子表达式误匹配);
79
+ // '@' 允许——@Override protected void … 是注解修饰的合法方法
79
80
  const pre = code.slice(Math.max(0, m.index - 1), m.index);
80
- if (/[.=@(]/.test(pre))
81
+ if (/[.=(]/.test(pre))
81
82
  continue;
82
83
  // 可见性(近似):行内是否有 public/protected(或文件在接口里默认 public)
83
84
  const head = code.slice(m.index, m.index + 40);
@@ -101,12 +102,41 @@ function extractJavaFile(filePath) {
101
102
  }
102
103
  // 返回类型:方法名前的一段(简化取最近一个类型令牌)
103
104
  const returnType = "unknown";
105
+ // calls:方法体(自头正则消费的 '{' 起平衡到 '}')内的方法调用
106
+ // (词法近似:标识符 + '(',过滤关键字;obj.method → 取末段)
107
+ const calls = [];
108
+ const bodyStart = m.index + m[0].length; // 正则已含 '{'
109
+ let depth = 1;
110
+ let bodyEnd = bodyStart;
111
+ while (bodyEnd < code.length && depth > 0) {
112
+ const ch = code[bodyEnd];
113
+ if (ch === "{")
114
+ depth++;
115
+ else if (ch === "}")
116
+ depth--;
117
+ bodyEnd++;
118
+ }
119
+ const body = code.slice(bodyStart, Math.min(bodyEnd, bodyStart + 8000));
120
+ const callRe = /(?:^|[^\w$])([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\(/g;
121
+ let cm;
122
+ while ((cm = callRe.exec(body)) !== null) {
123
+ const full = cm[1];
124
+ const seg = full.split(".").pop() || "";
125
+ if (JAVA_KEYWORDS.has(seg))
126
+ continue;
127
+ if (/^(if|for|while|switch|catch|new|return|case|do)$/.test(seg))
128
+ continue;
129
+ // 排除声明后立即调用形态(如 new Foo( 里 Foo)——new 已过滤
130
+ if (calls.length < 400 && !calls.includes(seg))
131
+ calls.push(seg);
132
+ }
104
133
  out.push({
105
134
  name,
106
135
  params,
107
136
  returnType,
108
137
  file: filePath,
109
138
  exported,
139
+ calls,
110
140
  });
111
141
  }
112
142
  return out;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ /**
37
+ * extract-ir-java.test.ts — Java 提取器回归(纯字符串 + 临时目录)
38
+ */
39
+ const vitest_1 = require("vitest");
40
+ const fs = __importStar(require("fs"));
41
+ const os = __importStar(require("os"));
42
+ const path = __importStar(require("path"));
43
+ const extract_ir_java_1 = require("./extract-ir-java");
44
+ let dir;
45
+ (0, vitest_1.beforeEach)(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), "javair-")); });
46
+ (0, vitest_1.afterEach)(() => { fs.rmSync(dir, { recursive: true, force: true }); });
47
+ const SAMPLE = `package app;
48
+ public class JwtTokenFilter extends OncePerRequestFilter {
49
+ @Override
50
+ protected void doFilterInternal(
51
+ HttpServletRequest request, HttpServletResponse response, FilterChain chain)
52
+ throws ServletException, IOException {
53
+ getTokenString(request.getHeader("Authorization"))
54
+ .flatMap(token -> jwtService.getSubFromToken(token))
55
+ .ifPresent(id -> {
56
+ if (SecurityContextHolder.getContext().getAuthentication() == null) {
57
+ setAuthentication(id, request);
58
+ }
59
+ });
60
+ }
61
+ private Optional<String> getTokenString(String h) {
62
+ if (h == null) return Optional.empty();
63
+ return Optional.of(h.substring(7));
64
+ }
65
+ }`;
66
+ (0, vitest_1.describe)("extract-ir-java", () => {
67
+ (0, vitest_1.it)("@Override 注解方法被提取(不会被 @ 前导过滤误杀)", () => {
68
+ const fp = path.join(dir, "JwtTokenFilter.java");
69
+ fs.writeFileSync(fp, SAMPLE);
70
+ const fns = (0, extract_ir_java_1.extractJavaFile)(fp);
71
+ (0, vitest_1.expect)(fns.some((f) => f.name === "doFilterInternal")).toBe(true);
72
+ (0, vitest_1.expect)(fns.some((f) => f.name === "getTokenString")).toBe(true);
73
+ });
74
+ (0, vitest_1.it)("方法调用边(calls)被提取——JWT 认证链可见", () => {
75
+ const fp = path.join(dir, "JwtTokenFilter.java");
76
+ fs.writeFileSync(fp, SAMPLE);
77
+ const fns = (0, extract_ir_java_1.extractJavaFile)(fp);
78
+ const filter = fns.find((f) => f.name === "doFilterInternal");
79
+ (0, vitest_1.expect)(filter.calls).toContain("getSubFromToken");
80
+ (0, vitest_1.expect)(filter.calls).toContain("getAuthentication");
81
+ (0, vitest_1.expect)(filter.calls).toContain("setAuthentication");
82
+ // 关键字不算调用
83
+ (0, vitest_1.expect)(filter.calls).not.toContain("if");
84
+ });
85
+ (0, vitest_1.it)("基础方法提取", () => {
86
+ const fp = path.join(dir, "Plain.java");
87
+ fs.writeFileSync(fp, `package app;
88
+ public class Plain {
89
+ public Plain() {}
90
+ public int add(int a, int b) { return a + b; }
91
+ }`);
92
+ const fns = (0, extract_ir_java_1.extractJavaFile)(fp);
93
+ (0, vitest_1.expect)(fns.some((f) => f.name === "add")).toBe(true);
94
+ });
95
+ });
package/dist/sdk.js CHANGED
@@ -20,7 +20,7 @@ const risk_model_1 = require("./risk-model");
20
20
  const protocol_knowledge_1 = require("./protocol-knowledge");
21
21
  const evidence_repository_1 = require("./evidence-repository");
22
22
  /** Runtime version — stable public identifier. Internal layers evolve underneath. */
23
- exports.RUNTIME_VERSION = "3.7.17";
23
+ exports.RUNTIME_VERSION = "3.7.18";
24
24
  function verify(filePath) {
25
25
  const cert = (0, certify_1.certify)(filePath);
26
26
  const kb = (0, protocol_knowledge_1.buildKnowledgeBase)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "progmune-runtime",
3
- "version": "3.7.17",
3
+ "version": "3.7.18",
4
4
  "description": "Progmune — AI Trust Decision Engine. Verify AI-generated code before it reaches production. Outputs APPROVED / NEEDS_REVIEW / BLOCKED with evidence.",
5
5
  "files": [
6
6
  "dist/",