sdlc-agent-4-enterprise-server 1.53.4 → 1.53.12
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/config/schema.d.ts +192 -0
- package/dist/config/schema.js +70 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/unified-extensions.d.ts +1 -1
- package/dist/config/unified-extensions.js +1 -1
- package/dist/config/unified-extensions.js.map +1 -1
- package/dist/engine/indexer/file-scanner/languages.d.ts +15 -0
- package/dist/engine/indexer/file-scanner/languages.js +74 -0
- package/dist/engine/indexer/file-scanner/languages.js.map +1 -0
- package/dist/engine/indexer/project-type/resolver.js +2 -0
- package/dist/engine/indexer/project-type/resolver.js.map +1 -1
- package/dist/server/middleware/jwt-auth.js +31 -7
- package/dist/server/middleware/jwt-auth.js.map +1 -1
- package/dist/server/routes/admin/context.js +17 -9
- package/dist/server/routes/admin/context.js.map +1 -1
- package/package.json +1 -1
- package/src/config/__tests__/salesforce-extensions.test.ts +1 -1
- package/src/config/schema.ts +77 -0
- package/src/config/unified-extensions.ts +1 -1
- package/src/engine/indexer/__tests__/file-scanner.test.ts +2 -2
- package/src/engine/indexer/file-scanner/languages.ts +78 -0
- package/src/engine/indexer/project-type/__tests__/resolver.test.ts +2 -1
- package/src/engine/indexer/project-type/resolver.ts +2 -0
- package/src/server/middleware/jwt-auth.ts +34 -12
- package/src/server/routes/admin/context.ts +19 -9
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config schema + shared config constants (BR-18 split from index.ts).
|
|
3
|
+
* The Zod schema is the single source of truth for the backend config shape;
|
|
4
|
+
* index.ts assembles the raw object and parses it through this schema.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export declare const DEFAULT_EXCLUDE: string[];
|
|
8
|
+
export declare const DEFAULT_EXTENSIONS: string[];
|
|
9
|
+
export declare const UnifiedConfigSchema: z.ZodObject<{
|
|
10
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
host: z.ZodDefault<z.ZodString>;
|
|
12
|
+
onnxModelPath: z.ZodDefault<z.ZodString>;
|
|
13
|
+
embeddingModelId: z.ZodDefault<z.ZodString>;
|
|
14
|
+
embeddingCacheDir: z.ZodString;
|
|
15
|
+
embeddingQuantized: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
+
logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
|
|
17
|
+
viewerPort: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
watchEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
watchDebounceMs: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
ollamaUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
21
|
+
ollamaModel: z.ZodDefault<z.ZodString>;
|
|
22
|
+
maxFileSize: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
projectId: z.ZodDefault<z.ZodString>;
|
|
24
|
+
workspace: z.ZodString;
|
|
25
|
+
indexTempDir: z.ZodString;
|
|
26
|
+
dbPath: z.ZodString;
|
|
27
|
+
configPath: z.ZodString;
|
|
28
|
+
dataDir: z.ZodString;
|
|
29
|
+
sqliteDbPath: z.ZodString;
|
|
30
|
+
orchestrationConfigPath: z.ZodString;
|
|
31
|
+
excludePatterns: z.ZodArray<z.ZodString, "many">;
|
|
32
|
+
includeExtensions: z.ZodArray<z.ZodString, "many">;
|
|
33
|
+
sandbox: z.ZodObject<{
|
|
34
|
+
defaultMode: z.ZodDefault<z.ZodEnum<["docker", "local"]>>;
|
|
35
|
+
fallbackToLocal: z.ZodDefault<z.ZodBoolean>;
|
|
36
|
+
maxSessions: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
defaultTtl: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
defaultImage: z.ZodDefault<z.ZodString>;
|
|
39
|
+
reaperIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
maxOutputBytes: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
commandTimeoutDefault: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
commandTimeoutMax: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
mountExcludePatterns: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
44
|
+
defaultResources: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
memory: z.ZodDefault<z.ZodString>;
|
|
46
|
+
cpu: z.ZodDefault<z.ZodString>;
|
|
47
|
+
disk: z.ZodDefault<z.ZodString>;
|
|
48
|
+
pidsLimit: z.ZodDefault<z.ZodNumber>;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
memory: string;
|
|
51
|
+
cpu: string;
|
|
52
|
+
disk: string;
|
|
53
|
+
pidsLimit: number;
|
|
54
|
+
}, {
|
|
55
|
+
memory?: string | undefined;
|
|
56
|
+
cpu?: string | undefined;
|
|
57
|
+
disk?: string | undefined;
|
|
58
|
+
pidsLimit?: number | undefined;
|
|
59
|
+
}>>;
|
|
60
|
+
dockerSocket: z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
defaultMode: "docker" | "local";
|
|
63
|
+
fallbackToLocal: boolean;
|
|
64
|
+
maxSessions: number;
|
|
65
|
+
defaultTtl: number;
|
|
66
|
+
defaultImage: string;
|
|
67
|
+
reaperIntervalMs: number;
|
|
68
|
+
maxOutputBytes: number;
|
|
69
|
+
commandTimeoutDefault: number;
|
|
70
|
+
commandTimeoutMax: number;
|
|
71
|
+
mountExcludePatterns: string[];
|
|
72
|
+
defaultResources: {
|
|
73
|
+
memory: string;
|
|
74
|
+
cpu: string;
|
|
75
|
+
disk: string;
|
|
76
|
+
pidsLimit: number;
|
|
77
|
+
};
|
|
78
|
+
dockerSocket?: string | undefined;
|
|
79
|
+
}, {
|
|
80
|
+
defaultMode?: "docker" | "local" | undefined;
|
|
81
|
+
fallbackToLocal?: boolean | undefined;
|
|
82
|
+
maxSessions?: number | undefined;
|
|
83
|
+
defaultTtl?: number | undefined;
|
|
84
|
+
defaultImage?: string | undefined;
|
|
85
|
+
reaperIntervalMs?: number | undefined;
|
|
86
|
+
maxOutputBytes?: number | undefined;
|
|
87
|
+
commandTimeoutDefault?: number | undefined;
|
|
88
|
+
commandTimeoutMax?: number | undefined;
|
|
89
|
+
mountExcludePatterns?: string[] | undefined;
|
|
90
|
+
defaultResources?: {
|
|
91
|
+
memory?: string | undefined;
|
|
92
|
+
cpu?: string | undefined;
|
|
93
|
+
disk?: string | undefined;
|
|
94
|
+
pidsLimit?: number | undefined;
|
|
95
|
+
} | undefined;
|
|
96
|
+
dockerSocket?: string | undefined;
|
|
97
|
+
}>;
|
|
98
|
+
entra: z.ZodType<import("./EntraConfig.js").EntraSurface, z.ZodTypeDef, unknown>;
|
|
99
|
+
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
entra: import("./EntraConfig.js").EntraSurface;
|
|
101
|
+
host: string;
|
|
102
|
+
port: number;
|
|
103
|
+
onnxModelPath: string;
|
|
104
|
+
embeddingModelId: string;
|
|
105
|
+
embeddingCacheDir: string;
|
|
106
|
+
embeddingQuantized: boolean;
|
|
107
|
+
logLevel: "error" | "warn" | "info" | "debug";
|
|
108
|
+
viewerPort: number;
|
|
109
|
+
watchEnabled: boolean;
|
|
110
|
+
watchDebounceMs: number;
|
|
111
|
+
ollamaUrl: string | null;
|
|
112
|
+
ollamaModel: string;
|
|
113
|
+
maxFileSize: number;
|
|
114
|
+
projectId: string;
|
|
115
|
+
workspace: string;
|
|
116
|
+
indexTempDir: string;
|
|
117
|
+
dbPath: string;
|
|
118
|
+
configPath: string;
|
|
119
|
+
dataDir: string;
|
|
120
|
+
sqliteDbPath: string;
|
|
121
|
+
orchestrationConfigPath: string;
|
|
122
|
+
excludePatterns: string[];
|
|
123
|
+
includeExtensions: string[];
|
|
124
|
+
sandbox: {
|
|
125
|
+
defaultMode: "docker" | "local";
|
|
126
|
+
fallbackToLocal: boolean;
|
|
127
|
+
maxSessions: number;
|
|
128
|
+
defaultTtl: number;
|
|
129
|
+
defaultImage: string;
|
|
130
|
+
reaperIntervalMs: number;
|
|
131
|
+
maxOutputBytes: number;
|
|
132
|
+
commandTimeoutDefault: number;
|
|
133
|
+
commandTimeoutMax: number;
|
|
134
|
+
mountExcludePatterns: string[];
|
|
135
|
+
defaultResources: {
|
|
136
|
+
memory: string;
|
|
137
|
+
cpu: string;
|
|
138
|
+
disk: string;
|
|
139
|
+
pidsLimit: number;
|
|
140
|
+
};
|
|
141
|
+
dockerSocket?: string | undefined;
|
|
142
|
+
};
|
|
143
|
+
}, {
|
|
144
|
+
embeddingCacheDir: string;
|
|
145
|
+
workspace: string;
|
|
146
|
+
indexTempDir: string;
|
|
147
|
+
dbPath: string;
|
|
148
|
+
configPath: string;
|
|
149
|
+
dataDir: string;
|
|
150
|
+
sqliteDbPath: string;
|
|
151
|
+
orchestrationConfigPath: string;
|
|
152
|
+
excludePatterns: string[];
|
|
153
|
+
includeExtensions: string[];
|
|
154
|
+
sandbox: {
|
|
155
|
+
defaultMode?: "docker" | "local" | undefined;
|
|
156
|
+
fallbackToLocal?: boolean | undefined;
|
|
157
|
+
maxSessions?: number | undefined;
|
|
158
|
+
defaultTtl?: number | undefined;
|
|
159
|
+
defaultImage?: string | undefined;
|
|
160
|
+
reaperIntervalMs?: number | undefined;
|
|
161
|
+
maxOutputBytes?: number | undefined;
|
|
162
|
+
commandTimeoutDefault?: number | undefined;
|
|
163
|
+
commandTimeoutMax?: number | undefined;
|
|
164
|
+
mountExcludePatterns?: string[] | undefined;
|
|
165
|
+
defaultResources?: {
|
|
166
|
+
memory?: string | undefined;
|
|
167
|
+
cpu?: string | undefined;
|
|
168
|
+
disk?: string | undefined;
|
|
169
|
+
pidsLimit?: number | undefined;
|
|
170
|
+
} | undefined;
|
|
171
|
+
dockerSocket?: string | undefined;
|
|
172
|
+
};
|
|
173
|
+
entra?: unknown;
|
|
174
|
+
host?: string | undefined;
|
|
175
|
+
port?: number | undefined;
|
|
176
|
+
onnxModelPath?: string | undefined;
|
|
177
|
+
embeddingModelId?: string | undefined;
|
|
178
|
+
embeddingQuantized?: boolean | undefined;
|
|
179
|
+
logLevel?: "error" | "warn" | "info" | "debug" | undefined;
|
|
180
|
+
viewerPort?: number | undefined;
|
|
181
|
+
watchEnabled?: boolean | undefined;
|
|
182
|
+
watchDebounceMs?: number | undefined;
|
|
183
|
+
ollamaUrl?: string | null | undefined;
|
|
184
|
+
ollamaModel?: string | undefined;
|
|
185
|
+
maxFileSize?: number | undefined;
|
|
186
|
+
projectId?: string | undefined;
|
|
187
|
+
}>;
|
|
188
|
+
export type UnifiedConfig = z.infer<typeof UnifiedConfigSchema>;
|
|
189
|
+
export type AppConfig = UnifiedConfig;
|
|
190
|
+
export type BackendConfig = UnifiedConfig;
|
|
191
|
+
export declare function envBool(key: string, fallback: boolean): boolean;
|
|
192
|
+
export declare function envInt(key: string, fallback: number): number;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config schema + shared config constants (BR-18 split from index.ts).
|
|
3
|
+
* The Zod schema is the single source of truth for the backend config shape;
|
|
4
|
+
* index.ts assembles the raw object and parses it through this schema.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { SandboxConfigSchema } from './SandboxConfig.js';
|
|
8
|
+
import { EntraSurfaceSchema } from './EntraConfig.js';
|
|
9
|
+
export const DEFAULT_EXCLUDE = [
|
|
10
|
+
'node_modules', '.git', 'dist', 'build', '.gradle',
|
|
11
|
+
'.idea', '.vscode', '__pycache__', '.venv', 'target',
|
|
12
|
+
'.code-intel', 'coverage', '.next', '.nuxt',
|
|
13
|
+
'rules',
|
|
14
|
+
'.pega-cache',
|
|
15
|
+
];
|
|
16
|
+
export const DEFAULT_EXTENSIONS = [
|
|
17
|
+
'.ts', '.tsx', '.js', '.jsx', '.kt', '.java', '.py',
|
|
18
|
+
'.go', '.rs', '.c', '.cpp', '.h', '.hpp', '.cs',
|
|
19
|
+
'.rb', '.php', '.swift', '.scala', '.sql', '.sh',
|
|
20
|
+
'.yaml', '.yml', '.json', '.toml', '.gradle.kts',
|
|
21
|
+
'.cls', '.trigger',
|
|
22
|
+
// ---- SA4E-223: new Salesforce simple extensions (Gate 2) ----
|
|
23
|
+
'.apex', '.soql', '.page', '.component', '.cmp', '.app', '.evt', '.intf', '.tokens',
|
|
24
|
+
// ---- SA4E-225: un-skip PowerShell ----
|
|
25
|
+
'.ps1',
|
|
26
|
+
];
|
|
27
|
+
export const UnifiedConfigSchema = z.object({
|
|
28
|
+
port: z.number().min(1024).max(65535).default(48721),
|
|
29
|
+
host: z.string().default('0.0.0.0'),
|
|
30
|
+
// Legacy/deprecated — nothing loads a bare .onnx file anymore; kept for
|
|
31
|
+
// backward-compatible admin config output. See embeddingModelId below.
|
|
32
|
+
onnxModelPath: z.string().default('models/model.onnx'),
|
|
33
|
+
// SA4E-44 / AD-6 — real ONNX embeddings via transformers.js (EmbeddingService).
|
|
34
|
+
embeddingModelId: z.string().default('Xenova/paraphrase-multilingual-MiniLM-L12-v2'),
|
|
35
|
+
embeddingCacheDir: z.string(),
|
|
36
|
+
embeddingQuantized: z.boolean().default(true),
|
|
37
|
+
logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
|
|
38
|
+
viewerPort: z.number().default(3202),
|
|
39
|
+
watchEnabled: z.boolean().default(true),
|
|
40
|
+
watchDebounceMs: z.number().default(500),
|
|
41
|
+
ollamaUrl: z.string().nullable().default(null),
|
|
42
|
+
ollamaModel: z.string().default('nomic-embed-text'),
|
|
43
|
+
maxFileSize: z.number().default(512_000),
|
|
44
|
+
projectId: z.string().default('default'),
|
|
45
|
+
workspace: z.string(),
|
|
46
|
+
indexTempDir: z.string(),
|
|
47
|
+
dbPath: z.string(),
|
|
48
|
+
configPath: z.string(),
|
|
49
|
+
dataDir: z.string(),
|
|
50
|
+
sqliteDbPath: z.string(),
|
|
51
|
+
orchestrationConfigPath: z.string(),
|
|
52
|
+
excludePatterns: z.array(z.string()),
|
|
53
|
+
includeExtensions: z.array(z.string()),
|
|
54
|
+
sandbox: SandboxConfigSchema,
|
|
55
|
+
entra: EntraSurfaceSchema, // SA4E-264 — Entra ID SSO surface (gate: SSO_ENABLED)
|
|
56
|
+
});
|
|
57
|
+
export function envBool(key, fallback) {
|
|
58
|
+
const val = process.env[key];
|
|
59
|
+
if (val === undefined)
|
|
60
|
+
return fallback;
|
|
61
|
+
return val === '1' || val.toLowerCase() === 'true';
|
|
62
|
+
}
|
|
63
|
+
export function envInt(key, fallback) {
|
|
64
|
+
const val = process.env[key];
|
|
65
|
+
if (val === undefined)
|
|
66
|
+
return fallback;
|
|
67
|
+
const parsed = parseInt(val, 10);
|
|
68
|
+
return isNaN(parsed) ? fallback : parsed;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* SA4E-261 Unified extension whitelist — single source of truth.
|
|
3
3
|
* Used by backend resolver and contract test.
|
|
4
4
|
*/
|
|
5
|
-
export declare const UNIFIED_EXTENSIONS: readonly ["ts", "tsx", "js", "jsx", "kt", "java", "py", "go", "rs", "c", "cpp", "h", "hpp", "cs", "php", "rb", "scala", "swift", "cls", "trigger", "apex", "soql", "page", "component", "cmp", "app", "evt", "intf", "tokens", "
|
|
5
|
+
export declare const UNIFIED_EXTENSIONS: readonly ["ts", "tsx", "js", "jsx", "kt", "java", "py", "go", "rs", "c", "cpp", "h", "hpp", "cs", "php", "rb", "scala", "swift", "cls", "trigger", "apex", "soql", "page", "component", "cmp", "app", "evt", "intf", "tokens", "html", "jsp", "xml", "sql", "properties", "yml", "yaml", "css", "ps1"];
|
|
6
6
|
export type UnifiedExtension = typeof UNIFIED_EXTENSIONS[number];
|
|
7
7
|
/**
|
|
8
8
|
* Extension list with leading dot for file matching.
|
|
@@ -7,7 +7,7 @@ export const UNIFIED_EXTENSIONS = [
|
|
|
7
7
|
'kt', 'java', 'py', 'go', 'rs',
|
|
8
8
|
'c', 'cpp', 'h', 'hpp',
|
|
9
9
|
'cs', 'php', 'rb', 'scala', 'swift',
|
|
10
|
-
'cls', 'trigger', 'apex', 'soql', 'page', 'component', 'cmp', 'app', 'evt', 'intf', 'tokens',
|
|
10
|
+
'cls', 'trigger', 'apex', 'soql', 'page', 'component', 'cmp', 'app', 'evt', 'intf', 'tokens',
|
|
11
11
|
'html', 'jsp', 'xml', 'sql', 'properties', 'yml', 'yaml', 'css',
|
|
12
12
|
'ps1'
|
|
13
13
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-extensions.js","sourceRoot":"","sources":["../../src/config/unified-extensions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;IACxB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9B,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK;IACtB,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO;IACnC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ
|
|
1
|
+
{"version":3,"file":"unified-extensions.js","sourceRoot":"","sources":["../../src/config/unified-extensions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;IACxB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9B,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK;IACtB,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO;IACnC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ;IAC5F,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK;IAC/D,KAAK;CACG,CAAC;AAIX;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language detection for the file scanner (extension maps + compound suffixes).
|
|
3
|
+
* Extracted from file-scanner.ts (BR-18) — no behavior change.
|
|
4
|
+
*/
|
|
5
|
+
export declare const EXTENSION_LANGUAGE_MAP: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* SA4E-223 — Single source of truth for Salesforce `*-meta.xml` compound suffixes.
|
|
8
|
+
* Used by detectLanguage() so *.xml files are routed to the `salesforce-meta` parser.
|
|
9
|
+
* (Compound-suffix files have ext === '.xml' which is NOT in includeExtensions, but
|
|
10
|
+
* processFile/async-file-scanner exempt `language === 'salesforce-meta'`.)
|
|
11
|
+
*/
|
|
12
|
+
export declare const SALESFORCE_META_SUFFIXES: string[];
|
|
13
|
+
/** Detect language from file extension — supports compound extensions. */
|
|
14
|
+
export declare function detectLanguage(filePath: string): string | null;
|
|
15
|
+
export declare function getExtension(filePath: string): string;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language detection for the file scanner (extension maps + compound suffixes).
|
|
3
|
+
* Extracted from file-scanner.ts (BR-18) — no behavior change.
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
export const EXTENSION_LANGUAGE_MAP = {
|
|
7
|
+
'.ts': 'typescript', '.tsx': 'typescript',
|
|
8
|
+
'.js': 'javascript', '.jsx': 'javascript',
|
|
9
|
+
'.kt': 'kotlin', '.kts': 'kotlin',
|
|
10
|
+
'.java': 'java',
|
|
11
|
+
'.py': 'python',
|
|
12
|
+
'.go': 'go',
|
|
13
|
+
'.rs': 'rust',
|
|
14
|
+
'.c': 'c', '.h': 'c',
|
|
15
|
+
'.cpp': 'cpp', '.hpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp',
|
|
16
|
+
'.cs': 'csharp',
|
|
17
|
+
'.rb': 'ruby',
|
|
18
|
+
'.php': 'php',
|
|
19
|
+
'.swift': 'swift',
|
|
20
|
+
'.scala': 'scala',
|
|
21
|
+
'.sql': 'sql',
|
|
22
|
+
'.sh': 'bash',
|
|
23
|
+
'.yaml': 'yaml', '.yml': 'yaml',
|
|
24
|
+
'.json': 'json',
|
|
25
|
+
'.toml': 'toml',
|
|
26
|
+
'.cls': 'apex',
|
|
27
|
+
'.trigger': 'apex',
|
|
28
|
+
// ---- SA4E-223: new Salesforce simple extensions ----
|
|
29
|
+
'.apex': 'apex',
|
|
30
|
+
'.soql': 'apex',
|
|
31
|
+
'.page': 'visualforce',
|
|
32
|
+
'.component': 'visualforce',
|
|
33
|
+
'.cmp': 'aura',
|
|
34
|
+
'.app': 'aura',
|
|
35
|
+
'.evt': 'aura',
|
|
36
|
+
'.intf': 'aura',
|
|
37
|
+
'.tokens': 'aura',
|
|
38
|
+
// ---- SA4E-... LWC HTML template support ----
|
|
39
|
+
'.html': 'lwc-html',
|
|
40
|
+
// ---- SA4E-261: Tier B extensions for unified whitelist ----
|
|
41
|
+
'.jsp': 'jsp',
|
|
42
|
+
'.xml': 'xml',
|
|
43
|
+
'.properties': 'properties',
|
|
44
|
+
'.css': 'css',
|
|
45
|
+
'.ps1': 'powershell',
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* SA4E-223 — Single source of truth for Salesforce `*-meta.xml` compound suffixes.
|
|
49
|
+
* Used by detectLanguage() so *.xml files are routed to the `salesforce-meta` parser.
|
|
50
|
+
* (Compound-suffix files have ext === '.xml' which is NOT in includeExtensions, but
|
|
51
|
+
* processFile/async-file-scanner exempt `language === 'salesforce-meta'`.)
|
|
52
|
+
*/
|
|
53
|
+
export const SALESFORCE_META_SUFFIXES = [
|
|
54
|
+
'.flow-meta.xml', '.object-meta.xml', '.field-meta.xml', '.js-meta.xml', '.component-meta.xml',
|
|
55
|
+
'.flexipage-meta.xml', '.permissionset-meta.xml', '.profile-meta.xml', '.labels-meta.xml',
|
|
56
|
+
'.tab-meta.xml', '.layout-meta.xml', '.report-meta.xml', '.dashboard-meta.xml',
|
|
57
|
+
'.site-meta.xml', '.resource-meta.xml', '.email-meta.xml', '.testsuite-meta.xml',
|
|
58
|
+
];
|
|
59
|
+
/** Detect language from file extension — supports compound extensions. */
|
|
60
|
+
export function detectLanguage(filePath) {
|
|
61
|
+
// Check compound extensions first (Salesforce metadata)
|
|
62
|
+
const lowerPath = filePath.toLowerCase().replace(/\\/g, '/');
|
|
63
|
+
if (SALESFORCE_META_SUFFIXES.some(s => lowerPath.endsWith(s))) {
|
|
64
|
+
return 'salesforce-meta';
|
|
65
|
+
}
|
|
66
|
+
const ext = getExtension(filePath);
|
|
67
|
+
return EXTENSION_LANGUAGE_MAP[ext] ?? null;
|
|
68
|
+
}
|
|
69
|
+
export function getExtension(filePath) {
|
|
70
|
+
if (filePath.endsWith('.gradle.kts'))
|
|
71
|
+
return '.kts';
|
|
72
|
+
return path.extname(filePath).toLowerCase();
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.js","sourceRoot":"","sources":["../../../../src/engine/indexer/file-scanner/languages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,CAAC,MAAM,sBAAsB,GAA2B;IAC5D,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY;IACzC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY;IACzC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ;IACjC,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG;IACpB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK;IACzD,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,OAAO;IACjB,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,MAAM;IACb,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC/B,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,UAAU,EAAE,MAAM;IAClB,uDAAuD;IACvD,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,aAAa;IACtB,YAAY,EAAE,aAAa;IAC3B,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,SAAS,EAAE,MAAM;IACjB,+CAA+C;IAC/C,OAAO,EAAE,UAAU;IACnB,8DAA8D;IAC9D,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,aAAa,EAAE,YAAY;IAC3B,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,YAAY;CACrB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAa;IAChD,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB;IAC9F,qBAAqB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,kBAAkB;IACzF,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,qBAAqB;IAC9E,gBAAgB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,qBAAqB;CACjF,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,wDAAwD;IACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7D,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,sBAAsB,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,MAAM,CAAC;IACpD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -5,6 +5,8 @@ const BASE_EXCLUDES = ['.git', '.svn', '.hg'];
|
|
|
5
5
|
const FALLBACK_EXCLUDES = [
|
|
6
6
|
'node_modules', '.git', 'dist', 'build', '.gradle',
|
|
7
7
|
'.idea', '.vscode', '__pycache__', '.venv', 'target',
|
|
8
|
+
'rules',
|
|
9
|
+
'.pega-cache',
|
|
8
10
|
];
|
|
9
11
|
/** Fallback extensions aligned with unified whitelist (SA4E-261) */
|
|
10
12
|
export const FALLBACK_EXTENSIONS = [...UNIFIED_EXTENSIONS_WITH_DOT];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../src/engine/indexer/project-type/resolver.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAC;AAEpF,8DAA8D;AAC9D,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAE9C,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG;IACxB,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS;IAClD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../src/engine/indexer/project-type/resolver.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAC;AAEpF,8DAA8D;AAC9D,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAE9C,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG;IACxB,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS;IAClD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ;IACpD,OAAO;IACP,aAAa;CACd,CAAC;AAEF,oEAAoE;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,2BAA2B,CAAC,CAAC;AAEpE;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAEnC,oDAAoD;IACpD,OAAO,CAAC,SAA0B;QAChC,OAAO;YACL,WAAW,EAAE,SAAS,CAAC,YAAY;YACnC,eAAe,EAAE,CAAC,GAAG,aAAa,EAAE,GAAG,SAAS,CAAC,gBAAgB,CAAC;YAClE,iBAAiB,EAAE,SAAS,CAAC,UAAU;YACvC,SAAS,EAAE,SAAS,CAAC,UAAU;YAC/B,SAAS,EAAE,cAAc;SAC1B,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,WAAW;QACT,OAAO;YACL,WAAW,EAAE,EAAE;YACf,eAAe,EAAE,iBAAiB;YAClC,iBAAiB,EAAE,mBAAmB;YACtC,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,SAAS;SACrB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -12,6 +12,7 @@ import { createProjectContext } from '../../modules/memory/ProjectContext.js';
|
|
|
12
12
|
import { SessionService } from '../services/SessionService.js';
|
|
13
13
|
import { getEntraVerifier, isEntraToken, tryEntraVerification, validateEntraAuthConfig } from './verifiers/entra-auth.js';
|
|
14
14
|
import { getJwtSecret } from '../../admin/db/jwt.js';
|
|
15
|
+
import { getDbAdapter } from '../../admin/admin-db.js';
|
|
15
16
|
const REQUIRE_AUTH = process.env.CODE_INTEL_REQUIRE_AUTH === 'true';
|
|
16
17
|
const TOKEN_SECRET = process.env.KB_TOKEN_SECRET || '';
|
|
17
18
|
/** Validate startup config. */
|
|
@@ -25,6 +26,24 @@ export function validateJwtConfig() {
|
|
|
25
26
|
export function isJwtAuthRequired() {
|
|
26
27
|
return REQUIRE_AUTH;
|
|
27
28
|
}
|
|
29
|
+
/** SA4E-375: Auto-upsert project in project_registry to avoid PROJECT_NOT_REGISTERED. */
|
|
30
|
+
async function autoUpsertProject(projectId, workspaceRoot, userId) {
|
|
31
|
+
if (!projectId || projectId === 'default' || !projectId.trim())
|
|
32
|
+
return;
|
|
33
|
+
try {
|
|
34
|
+
const adapter = getDbAdapter();
|
|
35
|
+
const displayName = workspaceRoot ? workspaceRoot.split(/[\\/]/).pop() || projectId : projectId;
|
|
36
|
+
await adapter.runAsync(`INSERT INTO project_registry (project_id, display_name, workspace_path, created_by, last_seen)
|
|
37
|
+
VALUES (?, ?, ?, ?, current_timestamp)
|
|
38
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
39
|
+
display_name = COALESCE(EXCLUDED.display_name, display_name),
|
|
40
|
+
workspace_path = COALESCE(EXCLUDED.workspace_path, workspace_path),
|
|
41
|
+
last_seen = current_timestamp`, [projectId, displayName, workspaceRoot, userId || '']);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Non-fatal: ignore upsert errors, project may already exist or DB error
|
|
45
|
+
}
|
|
46
|
+
}
|
|
28
47
|
function decodeJwtPayload(token) {
|
|
29
48
|
try {
|
|
30
49
|
const parts = token.split('.');
|
|
@@ -64,11 +83,16 @@ function createJwtAuth(alwaysRequire = false) {
|
|
|
64
83
|
return async (c, next) => {
|
|
65
84
|
// X-Project-Id header is the mandatory source of project identity
|
|
66
85
|
const projectId = c.req.header('X-Project-Id') || '';
|
|
86
|
+
const workspaceRoot = c.req.header('X-Workspace-Root') || '';
|
|
67
87
|
const authHeader = c.req.header('Authorization');
|
|
68
88
|
const mustAuth = REQUIRE_AUTH || alwaysRequire;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
const commitContext = async (ctxProjectId, userId) => {
|
|
90
|
+
c.set('projectContext', createProjectContext(ctxProjectId, userId));
|
|
91
|
+
// SA4E-375: auto-upsert project on every authenticated request to ensure project_registry exists
|
|
92
|
+
await autoUpsertProject(ctxProjectId, workspaceRoot, userId);
|
|
93
|
+
};
|
|
94
|
+
const anonymous = async () => {
|
|
95
|
+
await commitContext(projectId, 'anonymous');
|
|
72
96
|
return next();
|
|
73
97
|
};
|
|
74
98
|
const unauthorized = (code, message) => c.json({ data: null, error: { code, message } }, 401);
|
|
@@ -107,8 +131,9 @@ function createJwtAuth(alwaysRequire = false) {
|
|
|
107
131
|
return anonymous();
|
|
108
132
|
return unauthorized('TOKEN_INVALID', 'Invalid or expired token');
|
|
109
133
|
}
|
|
110
|
-
const
|
|
111
|
-
|
|
134
|
+
const ctxProjectId = projectId || payload.pid || '';
|
|
135
|
+
const userId = payload.sub || 'anonymous';
|
|
136
|
+
await commitContext(ctxProjectId, userId);
|
|
112
137
|
return next();
|
|
113
138
|
}
|
|
114
139
|
const userAgent = c.req.header('user-agent') || '';
|
|
@@ -125,8 +150,7 @@ function createJwtAuth(alwaysRequire = false) {
|
|
|
125
150
|
return anonymous();
|
|
126
151
|
return unauthorized('TOKEN_INVALID', 'Invalid or expired token');
|
|
127
152
|
}
|
|
128
|
-
|
|
129
|
-
c.set('projectContext', ctx);
|
|
153
|
+
await commitContext(projectId, session.userId);
|
|
130
154
|
return next();
|
|
131
155
|
};
|
|
132
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-auth.js","sourceRoot":"","sources":["../../../src/server/middleware/jwt-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC1H,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"jwt-auth.js","sourceRoot":"","sources":["../../../src/server/middleware/jwt-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,15 +74,23 @@ export function createAdminContext(logger, registry) {
|
|
|
74
74
|
const row = await adapter.getAsync('SELECT project_id FROM project_registry WHERE project_id = ?', [projectId]);
|
|
75
75
|
if (row)
|
|
76
76
|
return projectId;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
// SA4E-375: Server-side auto-upsert project on first access to avoid PROJECT_NOT_REGISTERED
|
|
78
|
+
const workspaceRoot = c.req.header('X-Workspace-Root') || '';
|
|
79
|
+
const displayName = workspaceRoot ? workspaceRoot.split(/[\\/]/).pop() || projectId : projectId;
|
|
80
|
+
try {
|
|
81
|
+
await adapter.runAsync(`INSERT INTO project_registry (project_id, display_name, workspace_path, created_by, last_seen)
|
|
82
|
+
VALUES (?, ?, ?, ?, current_timestamp)
|
|
83
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
84
|
+
display_name = COALESCE(EXCLUDED.display_name, display_name),
|
|
85
|
+
workspace_path = COALESCE(EXCLUDED.workspace_path, workspace_path),
|
|
86
|
+
last_seen = current_timestamp`, [projectId, displayName, workspaceRoot, '']);
|
|
87
|
+
logger.info({ projectId, displayName, workspaceRoot }, '[ensureProjectRegistered] auto-upserted project');
|
|
88
|
+
}
|
|
89
|
+
catch (upsertErr) {
|
|
90
|
+
// Non-fatal: log and continue; subsequent requests may succeed
|
|
91
|
+
logger.warn({ err: upsertErr, projectId }, '[ensureProjectRegistered] auto-upsert failed, proceeding');
|
|
92
|
+
}
|
|
93
|
+
return projectId;
|
|
86
94
|
}
|
|
87
95
|
catch (err) {
|
|
88
96
|
logger.error({ err }, '[ensureProjectRegistered] check failed');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/server/routes/admin/context.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/server/routes/admin/context.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ describe('DEFAULT_EXTENSIONS (SA4E-223)', () => {
|
|
|
18
18
|
// regression: legacy extensions preserved
|
|
19
19
|
expect(cfg.includeExtensions).toContain('.cls');
|
|
20
20
|
expect(cfg.includeExtensions).toContain('.trigger');
|
|
21
|
-
expect(cfg.includeExtensions).toContain('.pega');
|
|
21
|
+
expect(cfg.includeExtensions).not.toContain('.pega');
|
|
22
22
|
} finally {
|
|
23
23
|
fs.rmSync(ws, { recursive: true, force: true });
|
|
24
24
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config schema + shared config constants (BR-18 split from index.ts).
|
|
3
|
+
* The Zod schema is the single source of truth for the backend config shape;
|
|
4
|
+
* index.ts assembles the raw object and parses it through this schema.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { SandboxConfigSchema } from './SandboxConfig.js';
|
|
9
|
+
import { EntraSurfaceSchema } from './EntraConfig.js';
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_EXCLUDE = [
|
|
12
|
+
'node_modules', '.git', 'dist', 'build', '.gradle',
|
|
13
|
+
'.idea', '.vscode', '__pycache__', '.venv', 'target',
|
|
14
|
+
'.code-intel', 'coverage', '.next', '.nuxt',
|
|
15
|
+
'rules',
|
|
16
|
+
'.pega-cache',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_EXTENSIONS = [
|
|
20
|
+
'.ts', '.tsx', '.js', '.jsx', '.kt', '.java', '.py',
|
|
21
|
+
'.go', '.rs', '.c', '.cpp', '.h', '.hpp', '.cs',
|
|
22
|
+
'.rb', '.php', '.swift', '.scala', '.sql', '.sh',
|
|
23
|
+
'.yaml', '.yml', '.json', '.toml', '.gradle.kts',
|
|
24
|
+
'.cls', '.trigger',
|
|
25
|
+
// ---- SA4E-223: new Salesforce simple extensions (Gate 2) ----
|
|
26
|
+
'.apex', '.soql', '.page', '.component', '.cmp', '.app', '.evt', '.intf', '.tokens',
|
|
27
|
+
// ---- SA4E-225: un-skip PowerShell ----
|
|
28
|
+
'.ps1',
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const UnifiedConfigSchema = z.object({
|
|
32
|
+
port: z.number().min(1024).max(65535).default(48721),
|
|
33
|
+
host: z.string().default('0.0.0.0'),
|
|
34
|
+
// Legacy/deprecated — nothing loads a bare .onnx file anymore; kept for
|
|
35
|
+
// backward-compatible admin config output. See embeddingModelId below.
|
|
36
|
+
onnxModelPath: z.string().default('models/model.onnx'),
|
|
37
|
+
// SA4E-44 / AD-6 — real ONNX embeddings via transformers.js (EmbeddingService).
|
|
38
|
+
embeddingModelId: z.string().default('Xenova/paraphrase-multilingual-MiniLM-L12-v2'),
|
|
39
|
+
embeddingCacheDir: z.string(),
|
|
40
|
+
embeddingQuantized: z.boolean().default(true),
|
|
41
|
+
logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
|
|
42
|
+
viewerPort: z.number().default(3202),
|
|
43
|
+
watchEnabled: z.boolean().default(true),
|
|
44
|
+
watchDebounceMs: z.number().default(500),
|
|
45
|
+
ollamaUrl: z.string().nullable().default(null),
|
|
46
|
+
ollamaModel: z.string().default('nomic-embed-text'),
|
|
47
|
+
maxFileSize: z.number().default(512_000),
|
|
48
|
+
projectId: z.string().default('default'),
|
|
49
|
+
workspace: z.string(),
|
|
50
|
+
indexTempDir: z.string(),
|
|
51
|
+
dbPath: z.string(),
|
|
52
|
+
configPath: z.string(),
|
|
53
|
+
dataDir: z.string(),
|
|
54
|
+
sqliteDbPath: z.string(),
|
|
55
|
+
orchestrationConfigPath: z.string(),
|
|
56
|
+
excludePatterns: z.array(z.string()),
|
|
57
|
+
includeExtensions: z.array(z.string()),
|
|
58
|
+
sandbox: SandboxConfigSchema,
|
|
59
|
+
entra: EntraSurfaceSchema, // SA4E-264 — Entra ID SSO surface (gate: SSO_ENABLED)
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export type UnifiedConfig = z.infer<typeof UnifiedConfigSchema>;
|
|
63
|
+
export type AppConfig = UnifiedConfig;
|
|
64
|
+
export type BackendConfig = UnifiedConfig;
|
|
65
|
+
|
|
66
|
+
export function envBool(key: string, fallback: boolean): boolean {
|
|
67
|
+
const val = process.env[key];
|
|
68
|
+
if (val === undefined) return fallback;
|
|
69
|
+
return val === '1' || val.toLowerCase() === 'true';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function envInt(key: string, fallback: number): number {
|
|
73
|
+
const val = process.env[key];
|
|
74
|
+
if (val === undefined) return fallback;
|
|
75
|
+
const parsed = parseInt(val, 10);
|
|
76
|
+
return isNaN(parsed) ? fallback : parsed;
|
|
77
|
+
}
|
|
@@ -7,7 +7,7 @@ export const UNIFIED_EXTENSIONS = [
|
|
|
7
7
|
'kt', 'java', 'py', 'go', 'rs',
|
|
8
8
|
'c', 'cpp', 'h', 'hpp',
|
|
9
9
|
'cs', 'php', 'rb', 'scala', 'swift',
|
|
10
|
-
'cls', 'trigger', 'apex', 'soql', 'page', 'component', 'cmp', 'app', 'evt', 'intf', 'tokens',
|
|
10
|
+
'cls', 'trigger', 'apex', 'soql', 'page', 'component', 'cmp', 'app', 'evt', 'intf', 'tokens',
|
|
11
11
|
'html', 'jsp', 'xml', 'sql', 'properties', 'yml', 'yaml', 'css',
|
|
12
12
|
'ps1'
|
|
13
13
|
] as const;
|
|
@@ -113,10 +113,10 @@ describe('detectLanguage', () => {
|
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
// ---- SA4E-223: regression — .cls/.trigger/.pega unchanged (TC-05) ----
|
|
116
|
-
it('keeps legacy apex
|
|
116
|
+
it('keeps legacy apex mappings, pega removed for SRP', () => {
|
|
117
117
|
expect(detectLanguage('/a/C.cls')).toBe('apex');
|
|
118
118
|
expect(detectLanguage('/a/T.trigger')).toBe('apex');
|
|
119
|
-
expect(detectLanguage('/a/R.pega')).
|
|
119
|
+
expect(detectLanguage('/a/R.pega')).toBeNull();
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
// ---- SA4E-223: unknown still null (TC-06) ----
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language detection for the file scanner (extension maps + compound suffixes).
|
|
3
|
+
* Extracted from file-scanner.ts (BR-18) — no behavior change.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
|
|
8
|
+
export const EXTENSION_LANGUAGE_MAP: Record<string, string> = {
|
|
9
|
+
'.ts': 'typescript', '.tsx': 'typescript',
|
|
10
|
+
'.js': 'javascript', '.jsx': 'javascript',
|
|
11
|
+
'.kt': 'kotlin', '.kts': 'kotlin',
|
|
12
|
+
'.java': 'java',
|
|
13
|
+
'.py': 'python',
|
|
14
|
+
'.go': 'go',
|
|
15
|
+
'.rs': 'rust',
|
|
16
|
+
'.c': 'c', '.h': 'c',
|
|
17
|
+
'.cpp': 'cpp', '.hpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp',
|
|
18
|
+
'.cs': 'csharp',
|
|
19
|
+
'.rb': 'ruby',
|
|
20
|
+
'.php': 'php',
|
|
21
|
+
'.swift': 'swift',
|
|
22
|
+
'.scala': 'scala',
|
|
23
|
+
'.sql': 'sql',
|
|
24
|
+
'.sh': 'bash',
|
|
25
|
+
'.yaml': 'yaml', '.yml': 'yaml',
|
|
26
|
+
'.json': 'json',
|
|
27
|
+
'.toml': 'toml',
|
|
28
|
+
'.cls': 'apex',
|
|
29
|
+
'.trigger': 'apex',
|
|
30
|
+
// ---- SA4E-223: new Salesforce simple extensions ----
|
|
31
|
+
'.apex': 'apex',
|
|
32
|
+
'.soql': 'apex',
|
|
33
|
+
'.page': 'visualforce',
|
|
34
|
+
'.component': 'visualforce',
|
|
35
|
+
'.cmp': 'aura',
|
|
36
|
+
'.app': 'aura',
|
|
37
|
+
'.evt': 'aura',
|
|
38
|
+
'.intf': 'aura',
|
|
39
|
+
'.tokens': 'aura',
|
|
40
|
+
// ---- SA4E-... LWC HTML template support ----
|
|
41
|
+
'.html': 'lwc-html',
|
|
42
|
+
// ---- SA4E-261: Tier B extensions for unified whitelist ----
|
|
43
|
+
'.jsp': 'jsp',
|
|
44
|
+
'.xml': 'xml',
|
|
45
|
+
'.properties': 'properties',
|
|
46
|
+
'.css': 'css',
|
|
47
|
+
'.ps1': 'powershell',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* SA4E-223 — Single source of truth for Salesforce `*-meta.xml` compound suffixes.
|
|
52
|
+
* Used by detectLanguage() so *.xml files are routed to the `salesforce-meta` parser.
|
|
53
|
+
* (Compound-suffix files have ext === '.xml' which is NOT in includeExtensions, but
|
|
54
|
+
* processFile/async-file-scanner exempt `language === 'salesforce-meta'`.)
|
|
55
|
+
*/
|
|
56
|
+
export const SALESFORCE_META_SUFFIXES: string[] = [
|
|
57
|
+
'.flow-meta.xml', '.object-meta.xml', '.field-meta.xml', '.js-meta.xml', '.component-meta.xml',
|
|
58
|
+
'.flexipage-meta.xml', '.permissionset-meta.xml', '.profile-meta.xml', '.labels-meta.xml',
|
|
59
|
+
'.tab-meta.xml', '.layout-meta.xml', '.report-meta.xml', '.dashboard-meta.xml',
|
|
60
|
+
'.site-meta.xml', '.resource-meta.xml', '.email-meta.xml', '.testsuite-meta.xml',
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/** Detect language from file extension — supports compound extensions. */
|
|
64
|
+
export function detectLanguage(filePath: string): string | null {
|
|
65
|
+
// Check compound extensions first (Salesforce metadata)
|
|
66
|
+
const lowerPath = filePath.toLowerCase().replace(/\\/g, '/');
|
|
67
|
+
if (SALESFORCE_META_SUFFIXES.some(s => lowerPath.endsWith(s))) {
|
|
68
|
+
return 'salesforce-meta';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const ext = getExtension(filePath);
|
|
72
|
+
return EXTENSION_LANGUAGE_MAP[ext] ?? null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getExtension(filePath: string): string {
|
|
76
|
+
if (filePath.endsWith('.gradle.kts')) return '.kts';
|
|
77
|
+
return path.extname(filePath).toLowerCase();
|
|
78
|
+
}
|
|
@@ -40,8 +40,9 @@ describe('IndexingStrategyResolver', () => {
|
|
|
40
40
|
|
|
41
41
|
it('SA4E-223: getFallback includes new Salesforce extensions', () => {
|
|
42
42
|
const exts = resolver.getFallback().includeExtensions;
|
|
43
|
-
for (const e of ['.apex', '.soql', '.page', '.component', '.cmp', '.app', '.evt', '.intf', '.tokens', '.cls', '.trigger'
|
|
43
|
+
for (const e of ['.apex', '.soql', '.page', '.component', '.cmp', '.app', '.evt', '.intf', '.tokens', '.cls', '.trigger']) {
|
|
44
44
|
expect(exts).toContain(e);
|
|
45
45
|
}
|
|
46
|
+
expect(exts).not.toContain('.pega');
|
|
46
47
|
});
|
|
47
48
|
});
|
|
@@ -12,6 +12,8 @@ const BASE_EXCLUDES = ['.git', '.svn', '.hg'];
|
|
|
12
12
|
const FALLBACK_EXCLUDES = [
|
|
13
13
|
'node_modules', '.git', 'dist', 'build', '.gradle',
|
|
14
14
|
'.idea', '.vscode', '__pycache__', '.venv', 'target',
|
|
15
|
+
'rules',
|
|
16
|
+
'.pega-cache',
|
|
15
17
|
];
|
|
16
18
|
|
|
17
19
|
/** Fallback extensions aligned with unified whitelist (SA4E-261) */
|
|
@@ -14,6 +14,7 @@ import { createProjectContext } from '../../modules/memory/ProjectContext.js';
|
|
|
14
14
|
import { SessionService } from '../services/SessionService.js';
|
|
15
15
|
import { getEntraVerifier, isEntraToken, tryEntraVerification, validateEntraAuthConfig } from './verifiers/entra-auth.js';
|
|
16
16
|
import { getJwtSecret } from '../../admin/db/jwt.js';
|
|
17
|
+
import { getDbAdapter } from '../../admin/admin-db.js';
|
|
17
18
|
|
|
18
19
|
const REQUIRE_AUTH = process.env.CODE_INTEL_REQUIRE_AUTH === 'true';
|
|
19
20
|
const TOKEN_SECRET = process.env.KB_TOKEN_SECRET || '';
|
|
@@ -31,6 +32,26 @@ export function isJwtAuthRequired(): boolean {
|
|
|
31
32
|
return REQUIRE_AUTH;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
/** SA4E-375: Auto-upsert project in project_registry to avoid PROJECT_NOT_REGISTERED. */
|
|
36
|
+
async function autoUpsertProject(projectId: string, workspaceRoot: string, userId: string) {
|
|
37
|
+
if (!projectId || projectId === 'default' || !projectId.trim()) return;
|
|
38
|
+
try {
|
|
39
|
+
const adapter = getDbAdapter();
|
|
40
|
+
const displayName = workspaceRoot ? workspaceRoot.split(/[\\/]/).pop() || projectId : projectId;
|
|
41
|
+
await adapter.runAsync(
|
|
42
|
+
`INSERT INTO project_registry (project_id, display_name, workspace_path, created_by, last_seen)
|
|
43
|
+
VALUES (?, ?, ?, ?, current_timestamp)
|
|
44
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
45
|
+
display_name = COALESCE(EXCLUDED.display_name, display_name),
|
|
46
|
+
workspace_path = COALESCE(EXCLUDED.workspace_path, workspace_path),
|
|
47
|
+
last_seen = current_timestamp`,
|
|
48
|
+
[projectId, displayName, workspaceRoot, userId || '']
|
|
49
|
+
);
|
|
50
|
+
} catch {
|
|
51
|
+
// Non-fatal: ignore upsert errors, project may already exist or DB error
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
function decodeJwtPayload(token: string): Record<string, any> | null {
|
|
35
56
|
try {
|
|
36
57
|
const parts = token.split('.');
|
|
@@ -69,12 +90,18 @@ function createJwtAuth(alwaysRequire = false): MiddlewareHandler {
|
|
|
69
90
|
return async (c, next) => {
|
|
70
91
|
// X-Project-Id header is the mandatory source of project identity
|
|
71
92
|
const projectId = c.req.header('X-Project-Id') || '';
|
|
93
|
+
const workspaceRoot = c.req.header('X-Workspace-Root') || '';
|
|
72
94
|
const authHeader = c.req.header('Authorization');
|
|
73
95
|
const mustAuth = REQUIRE_AUTH || alwaysRequire;
|
|
74
96
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
97
|
+
const commitContext = async (ctxProjectId: string, userId: string) => {
|
|
98
|
+
c.set('projectContext', createProjectContext(ctxProjectId, userId));
|
|
99
|
+
// SA4E-375: auto-upsert project on every authenticated request to ensure project_registry exists
|
|
100
|
+
await autoUpsertProject(ctxProjectId, workspaceRoot, userId);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const anonymous = async () => {
|
|
104
|
+
await commitContext(projectId, 'anonymous');
|
|
78
105
|
return next();
|
|
79
106
|
};
|
|
80
107
|
|
|
@@ -117,13 +144,9 @@ function createJwtAuth(alwaysRequire = false): MiddlewareHandler {
|
|
|
117
144
|
if (!mustAuth) return anonymous();
|
|
118
145
|
return unauthorized('TOKEN_INVALID', 'Invalid or expired token');
|
|
119
146
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
undefined,
|
|
124
|
-
payload.wid || undefined,
|
|
125
|
-
);
|
|
126
|
-
c.set('projectContext', ctx);
|
|
147
|
+
const ctxProjectId = projectId || payload.pid || '';
|
|
148
|
+
const userId = payload.sub || 'anonymous';
|
|
149
|
+
await commitContext(ctxProjectId, userId);
|
|
127
150
|
return next();
|
|
128
151
|
}
|
|
129
152
|
|
|
@@ -139,8 +162,7 @@ function createJwtAuth(alwaysRequire = false): MiddlewareHandler {
|
|
|
139
162
|
if (!mustAuth) return anonymous();
|
|
140
163
|
return unauthorized('TOKEN_INVALID', 'Invalid or expired token');
|
|
141
164
|
}
|
|
142
|
-
|
|
143
|
-
c.set('projectContext', ctx);
|
|
165
|
+
await commitContext(projectId, session.userId);
|
|
144
166
|
return next();
|
|
145
167
|
};
|
|
146
168
|
}
|
|
@@ -111,15 +111,25 @@ export function createAdminContext(logger: Logger, registry?: any): AdminContext
|
|
|
111
111
|
[projectId]
|
|
112
112
|
);
|
|
113
113
|
if (row) return projectId;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
114
|
+
// SA4E-375: Server-side auto-upsert project on first access to avoid PROJECT_NOT_REGISTERED
|
|
115
|
+
const workspaceRoot = c.req.header('X-Workspace-Root') || '';
|
|
116
|
+
const displayName = workspaceRoot ? workspaceRoot.split(/[\\/]/).pop() || projectId : projectId;
|
|
117
|
+
try {
|
|
118
|
+
await adapter.runAsync(
|
|
119
|
+
`INSERT INTO project_registry (project_id, display_name, workspace_path, created_by, last_seen)
|
|
120
|
+
VALUES (?, ?, ?, ?, current_timestamp)
|
|
121
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
122
|
+
display_name = COALESCE(EXCLUDED.display_name, display_name),
|
|
123
|
+
workspace_path = COALESCE(EXCLUDED.workspace_path, workspace_path),
|
|
124
|
+
last_seen = current_timestamp`,
|
|
125
|
+
[projectId, displayName, workspaceRoot, '']
|
|
126
|
+
);
|
|
127
|
+
logger.info({ projectId, displayName, workspaceRoot }, '[ensureProjectRegistered] auto-upserted project');
|
|
128
|
+
} catch (upsertErr: any) {
|
|
129
|
+
// Non-fatal: log and continue; subsequent requests may succeed
|
|
130
|
+
logger.warn({ err: upsertErr, projectId }, '[ensureProjectRegistered] auto-upsert failed, proceeding');
|
|
131
|
+
}
|
|
132
|
+
return projectId;
|
|
123
133
|
} catch (err: any) {
|
|
124
134
|
logger.error({ err }, '[ensureProjectRegistered] check failed');
|
|
125
135
|
return c.json({ __error: true, error: { code: 'INTERNAL_ERROR', message: err.message } }, 500);
|