@zivis/cli 0.1.0-alpha.33 → 0.1.0-alpha.35
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/LICENSE +201 -0
- package/README.md +31 -0
- package/dist/commands/app/index.d.ts +0 -8
- package/dist/commands/app/index.js +0 -12
- package/dist/commands/auth/bind.d.ts +0 -10
- package/dist/commands/auth/bind.js +0 -11
- package/dist/commands/auth/index.js +0 -1
- package/dist/commands/auth/init.js +12 -13
- package/dist/commands/auth/login.d.ts +0 -1
- package/dist/commands/auth/login.js +8 -3
- package/dist/commands/auth/logout.js +0 -3
- package/dist/commands/auth/sessions.js +0 -1
- package/dist/commands/auth/status.js +0 -2
- package/dist/commands/auth/token.d.ts +0 -13
- package/dist/commands/auth/token.js +0 -18
- package/dist/commands/check/index.d.ts +2 -0
- package/dist/commands/check/index.js +463 -0
- package/dist/commands/credits/index.js +0 -1
- package/dist/commands/inspect/index.d.ts +0 -15
- package/dist/commands/inspect/index.js +0 -23
- package/dist/commands/mcp/index.js +0 -9
- package/dist/commands/open/index.d.ts +0 -8
- package/dist/commands/open/index.js +0 -11
- package/dist/commands/scan/index.js +0 -6
- package/dist/commands/target/index.js +0 -3
- package/dist/commands/tm/index.js +0 -7
- package/dist/index.js +11 -1
- package/dist/internal/binding-token-mint.d.ts +0 -29
- package/dist/internal/binding-token-mint.js +0 -28
- package/dist/internal/extractor/adapters/go/index.d.ts +0 -4
- package/dist/internal/extractor/adapters/go/index.js +0 -6
- package/dist/internal/extractor/adapters/go/manifest.d.ts +0 -17
- package/dist/internal/extractor/adapters/go/manifest.js +1 -25
- package/dist/internal/extractor/adapters/go/parser.d.ts +0 -4
- package/dist/internal/extractor/adapters/go/parser.js +0 -5
- package/dist/internal/extractor/adapters/go/scanner.d.ts +0 -20
- package/dist/internal/extractor/adapters/go/scanner.js +0 -43
- package/dist/internal/extractor/adapters/python/index.d.ts +0 -3
- package/dist/internal/extractor/adapters/python/index.js +0 -4
- package/dist/internal/extractor/adapters/python/manifest.d.ts +0 -8
- package/dist/internal/extractor/adapters/python/manifest.js +3 -18
- package/dist/internal/extractor/adapters/python/parser.d.ts +0 -3
- package/dist/internal/extractor/adapters/python/parser.js +0 -4
- package/dist/internal/extractor/adapters/python/scanner.d.ts +0 -18
- package/dist/internal/extractor/adapters/python/scanner.js +1 -54
- package/dist/internal/extractor/adapters/typescript/index.d.ts +0 -7
- package/dist/internal/extractor/adapters/typescript/index.js +1 -21
- package/dist/internal/extractor/adapters/typescript/manifest.d.ts +0 -14
- package/dist/internal/extractor/adapters/typescript/manifest.js +1 -20
- package/dist/internal/extractor/adapters/typescript/parser.d.ts +0 -8
- package/dist/internal/extractor/adapters/typescript/parser.js +0 -9
- package/dist/internal/extractor/adapters/typescript/scanner.d.ts +0 -24
- package/dist/internal/extractor/adapters/typescript/scanner.js +0 -43
- package/dist/internal/extractor/graph-builder.d.ts +0 -25
- package/dist/internal/extractor/graph-builder.js +1 -39
- package/dist/internal/extractor/graph-types.d.ts +0 -10
- package/dist/internal/extractor/graph-types.js +0 -11
- package/dist/internal/extractor/index.d.ts +0 -14
- package/dist/internal/extractor/index.js +0 -13
- package/dist/internal/extractor/types.d.ts +0 -45
- package/dist/internal/extractor/types.js +0 -27
- package/dist/internal/extractor/walker.d.ts +0 -18
- package/dist/internal/extractor/walker.js +0 -18
- package/dist/internal/github-linkage-prompt.d.ts +7 -0
- package/dist/internal/github-linkage-prompt.js +95 -0
- package/dist/internal/ide-setup.d.ts +0 -23
- package/dist/internal/ide-setup.js +0 -53
- package/dist/internal/orgs.js +0 -1
- package/dist/internal/project-binding.d.ts +0 -1
- package/dist/internal/project-binding.js +0 -5
- package/dist/internal/target-auth/api-config.d.ts +0 -17
- package/dist/internal/target-auth/api-config.js +0 -18
- package/dist/internal/target-auth/config.d.ts +0 -12
- package/dist/internal/target-auth/config.js +0 -13
- package/dist/internal/target-auth/index.d.ts +0 -18
- package/dist/internal/target-auth/index.js +0 -19
- package/dist/internal/target-auth/keychain.d.ts +0 -18
- package/dist/internal/target-auth/keychain.js +3 -23
- package/dist/internal/target-auth/types.d.ts +0 -26
- package/dist/internal/target-auth/types.js +0 -10
- package/dist/internal/target-auth/workos.d.ts +0 -15
- package/dist/internal/target-auth/workos.js +0 -17
- package/package.json +13 -4
- package/dist/commands/app/index.js.map +0 -1
- package/dist/commands/auth/bind.js.map +0 -1
- package/dist/commands/auth/index.js.map +0 -1
- package/dist/commands/auth/init.js.map +0 -1
- package/dist/commands/auth/login.js.map +0 -1
- package/dist/commands/auth/logout.js.map +0 -1
- package/dist/commands/auth/sessions.js.map +0 -1
- package/dist/commands/auth/status.js.map +0 -1
- package/dist/commands/auth/token.js.map +0 -1
- package/dist/commands/credits/index.js.map +0 -1
- package/dist/commands/inspect/index.js.map +0 -1
- package/dist/commands/mcp/index.js.map +0 -1
- package/dist/commands/open/index.js.map +0 -1
- package/dist/commands/scan/index.js.map +0 -1
- package/dist/commands/target/index.js.map +0 -1
- package/dist/commands/tm/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/binding-token-mint.js.map +0 -1
- package/dist/internal/extractor/adapters/go/index.js.map +0 -1
- package/dist/internal/extractor/adapters/go/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/go/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/go/scanner.js.map +0 -1
- package/dist/internal/extractor/adapters/python/index.js.map +0 -1
- package/dist/internal/extractor/adapters/python/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/python/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/python/scanner.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/index.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/scanner.js.map +0 -1
- package/dist/internal/extractor/graph-builder.js.map +0 -1
- package/dist/internal/extractor/graph-types.js.map +0 -1
- package/dist/internal/extractor/index.js.map +0 -1
- package/dist/internal/extractor/types.js.map +0 -1
- package/dist/internal/extractor/walker.js.map +0 -1
- package/dist/internal/ide-setup.js.map +0 -1
- package/dist/internal/orgs.js.map +0 -1
- package/dist/internal/pattern-pack/index.d.ts +0 -123
- package/dist/internal/pattern-pack/index.js +0 -230
- package/dist/internal/pattern-pack/index.js.map +0 -1
- package/dist/internal/project-binding.js.map +0 -1
- package/dist/internal/target-auth/api-config.js.map +0 -1
- package/dist/internal/target-auth/config.js.map +0 -1
- package/dist/internal/target-auth/index.js.map +0 -1
- package/dist/internal/target-auth/keychain.js.map +0 -1
- package/dist/internal/target-auth/types.js.map +0 -1
- package/dist/internal/target-auth/workos.js.map +0 -1
- package/dist/pattern-packs/zivis-public-0.1.0/capsules/agents/privilege-separation.yaml +0 -228
- package/dist/pattern-packs/zivis-public-0.1.0/manifest.json +0 -31
- package/dist/pattern-packs/zivis-public-0.1.0/prompts/agents/privilege-separation/identify.md +0 -54
package/dist/index.js
CHANGED
|
@@ -4,10 +4,12 @@ import * as fs from "node:fs";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { registerAuthCommands } from "./commands/auth/index.js";
|
|
7
|
+
import { initCommand as authInitCommand } from "./commands/auth/init.js";
|
|
7
8
|
import { registerAppCommands } from "./commands/app/index.js";
|
|
8
9
|
import { registerTargetCommands } from "./commands/target/index.js";
|
|
9
10
|
import { registerTmCommands } from "./commands/tm/index.js";
|
|
10
11
|
import { registerScanCommands } from "./commands/scan/index.js";
|
|
12
|
+
import { registerCheckCommands } from "./commands/check/index.js";
|
|
11
13
|
import { registerInspectCommands } from "./commands/inspect/index.js";
|
|
12
14
|
import { registerMcpCommands } from "./commands/mcp/index.js";
|
|
13
15
|
import { registerCreditsCommands } from "./commands/credits/index.js";
|
|
@@ -27,7 +29,16 @@ program
|
|
|
27
29
|
.name("zivis")
|
|
28
30
|
.description("ZIVIS CLI — threat modeling, scans, and MCP server")
|
|
29
31
|
.version(getVersion(), "-v, --version", "show version");
|
|
32
|
+
program
|
|
33
|
+
.command("init")
|
|
34
|
+
.description("interactive setup: authenticate, pick org, and bind this repo (alias for `zivis auth init`)")
|
|
35
|
+
.option("-s, --session <name>", "named session for multi-tenant")
|
|
36
|
+
.option("--skip-mint-key", "skip MCP API key mint after successful OAuth")
|
|
37
|
+
.action(async (opts) => {
|
|
38
|
+
await authInitCommand(opts);
|
|
39
|
+
});
|
|
30
40
|
registerAuthCommands(program);
|
|
41
|
+
registerCheckCommands(program);
|
|
31
42
|
registerAppCommands(program);
|
|
32
43
|
registerTargetCommands(program);
|
|
33
44
|
registerTmCommands(program);
|
|
@@ -40,4 +51,3 @@ program.parseAsync(process.argv).catch((err) => {
|
|
|
40
51
|
console.error(err instanceof Error ? err.message : err);
|
|
41
52
|
process.exit(1);
|
|
42
53
|
});
|
|
43
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint a Local Project Binding Token via POST /api/auth/bind and store it as
|
|
3
|
-
* apikey.<session>. Shared by `zivis auth bind` and post-login auto-mint.
|
|
4
|
-
*/
|
|
5
1
|
import { type ZivisConfig } from "@zivis/mcp/types";
|
|
6
2
|
export type MintBindingTokenResult = {
|
|
7
3
|
ok: true;
|
|
@@ -13,10 +9,6 @@ export type MintBindingTokenResult = {
|
|
|
13
9
|
ok: false;
|
|
14
10
|
error: string;
|
|
15
11
|
};
|
|
16
|
-
/**
|
|
17
|
-
* Calls the bind API with a fresh access JWT and persists the minted WorkOS API key.
|
|
18
|
-
* Does not start OAuth nor update IDE configs.
|
|
19
|
-
*/
|
|
20
12
|
export declare function mintLocalProjectBindingToken(params: {
|
|
21
13
|
config: ZivisConfig;
|
|
22
14
|
session: string;
|
|
@@ -27,35 +19,14 @@ export interface TryAutoMintOptions {
|
|
|
27
19
|
cwd: string;
|
|
28
20
|
sessionName: string;
|
|
29
21
|
accessToken: string;
|
|
30
|
-
/** Caller flag (e.g. `zivis auth login --no-mint-key`). */
|
|
31
22
|
skip?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* When false (login after ensureProjectBinding): mint failures log a warning and return.
|
|
34
|
-
* When true (`zivis auth bind`): caller should exit 1 if result not ok — not handled here.
|
|
35
|
-
*/
|
|
36
23
|
warnOnFailure: boolean;
|
|
37
24
|
}
|
|
38
|
-
/**
|
|
39
|
-
* After OAuth login finishes, mint an MCP-friendly API key if the repo is bound
|
|
40
|
-
* and JWT org matches `.zivis/project.json`.
|
|
41
|
-
* Skips if `apikey.<session>` already exists (avoid spawning keys on every login).
|
|
42
|
-
*/
|
|
43
25
|
export declare function tryAutoMintBindingTokenAfterLogin(opts: TryAutoMintOptions): Promise<{
|
|
44
26
|
ran: boolean;
|
|
45
27
|
ok: boolean;
|
|
46
28
|
message?: string;
|
|
47
29
|
}>;
|
|
48
|
-
/**
|
|
49
|
-
* Drop the OAuth tokens stored under `oauth.<session>` (or `oauth` when no
|
|
50
|
-
* session). OAuth exists only to mint the MCP API key — once login finishes,
|
|
51
|
-
* MCP and tenant API calls go through `apikey.<session>`. Keeping the OAuth
|
|
52
|
-
* tokens around adds attack surface and risks org-drift if the refresh token
|
|
53
|
-
* outlives the binding.
|
|
54
|
-
*
|
|
55
|
-
* Verifies the delete actually emptied the keychain before returning — macOS
|
|
56
|
-
* keychain access prompts can be denied without surfacing an error code, and
|
|
57
|
-
* stale duplicates from older builds can mask a successful single delete.
|
|
58
|
-
*/
|
|
59
30
|
export declare function discardOauthAfterLogin(params: {
|
|
60
31
|
session: string | undefined;
|
|
61
32
|
config: ZivisConfig;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint a Local Project Binding Token via POST /api/auth/bind and store it as
|
|
3
|
-
* apikey.<session>. Shared by `zivis auth bind` and post-login auto-mint.
|
|
4
|
-
*/
|
|
5
1
|
import * as os from "node:os";
|
|
6
2
|
import * as crypto from "node:crypto";
|
|
7
3
|
import * as child_process from "node:child_process";
|
|
@@ -9,7 +5,6 @@ import { getSessionAccount, keychainClearSession, keychainRead, keychainStore, }
|
|
|
9
5
|
import { decodeJwtPayload } from "@zivis/mcp/auth/jwt";
|
|
10
6
|
import { DEFAULT_CONFIG, credentialStorageFromConfig } from "@zivis/mcp/types";
|
|
11
7
|
import { detectProjectBinding, resolveConfigFromBinding } from "@zivis/mcp/project-binding";
|
|
12
|
-
/** Same fingerprint strategy as bind command — stable-ish per-repo key name suffix. */
|
|
13
8
|
function getRepoFingerprint(cwd) {
|
|
14
9
|
try {
|
|
15
10
|
const remote = child_process
|
|
@@ -20,14 +15,9 @@ function getRepoFingerprint(cwd) {
|
|
|
20
15
|
}
|
|
21
16
|
}
|
|
22
17
|
catch {
|
|
23
|
-
/* no git or no remote */
|
|
24
18
|
}
|
|
25
19
|
return crypto.createHash("sha256").update(cwd).digest("hex").slice(0, 12);
|
|
26
20
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Calls the bind API with a fresh access JWT and persists the minted WorkOS API key.
|
|
29
|
-
* Does not start OAuth nor update IDE configs.
|
|
30
|
-
*/
|
|
31
21
|
export async function mintLocalProjectBindingToken(params) {
|
|
32
22
|
const { config, session, accessToken, cwd } = params;
|
|
33
23
|
const credentialStorage = credentialStorageFromConfig(config);
|
|
@@ -77,11 +67,6 @@ export async function mintLocalProjectBindingToken(params) {
|
|
|
77
67
|
workosOrgId: bindResult.workosOrgId,
|
|
78
68
|
};
|
|
79
69
|
}
|
|
80
|
-
/**
|
|
81
|
-
* After OAuth login finishes, mint an MCP-friendly API key if the repo is bound
|
|
82
|
-
* and JWT org matches `.zivis/project.json`.
|
|
83
|
-
* Skips if `apikey.<session>` already exists (avoid spawning keys on every login).
|
|
84
|
-
*/
|
|
85
70
|
export async function tryAutoMintBindingTokenAfterLogin(opts) {
|
|
86
71
|
if (opts.skip) {
|
|
87
72
|
return { ran: false, ok: true };
|
|
@@ -147,24 +132,12 @@ export async function tryAutoMintBindingTokenAfterLogin(opts) {
|
|
|
147
132
|
console.log(`✓ MCP API key stored (${result.keyName}; org: ${result.orgName})`);
|
|
148
133
|
return { ran: true, ok: true };
|
|
149
134
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Drop the OAuth tokens stored under `oauth.<session>` (or `oauth` when no
|
|
152
|
-
* session). OAuth exists only to mint the MCP API key — once login finishes,
|
|
153
|
-
* MCP and tenant API calls go through `apikey.<session>`. Keeping the OAuth
|
|
154
|
-
* tokens around adds attack surface and risks org-drift if the refresh token
|
|
155
|
-
* outlives the binding.
|
|
156
|
-
*
|
|
157
|
-
* Verifies the delete actually emptied the keychain before returning — macOS
|
|
158
|
-
* keychain access prompts can be denied without surfacing an error code, and
|
|
159
|
-
* stale duplicates from older builds can mask a successful single delete.
|
|
160
|
-
*/
|
|
161
135
|
export async function discardOauthAfterLogin(params) {
|
|
162
136
|
const storage = credentialStorageFromConfig(params.config);
|
|
163
137
|
try {
|
|
164
138
|
await keychainClearSession(params.session, storage);
|
|
165
139
|
}
|
|
166
140
|
catch {
|
|
167
|
-
/* No-op — see verify step below. */
|
|
168
141
|
}
|
|
169
142
|
const leftover = await keychainRead(getSessionAccount(params.session), storage).catch(() => null);
|
|
170
143
|
if (leftover) {
|
|
@@ -199,4 +172,3 @@ function printMintFailureBanner(message) {
|
|
|
199
172
|
console.error(bar);
|
|
200
173
|
console.error("");
|
|
201
174
|
}
|
|
202
|
-
//# sourceMappingURL=binding-token-mint.js.map
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Go language adapter. Same shape as the TypeScript adapter — manifest
|
|
3
|
-
* pass + AST pass — different parser + framework table.
|
|
4
|
-
*/
|
|
5
1
|
import type { LanguageAdapter } from "../../types.js";
|
|
6
2
|
export declare const goAdapter: LanguageAdapter;
|
|
7
3
|
export declare const _stdlibFrameworkSet: Set<string>;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Go language adapter. Same shape as the TypeScript adapter — manifest
|
|
3
|
-
* pass + AST pass — different parser + framework table.
|
|
4
|
-
*/
|
|
5
1
|
import * as path from "node:path";
|
|
6
2
|
import { readManifests, summarizeManifests, findExternalServices, findDataStores, detectFrameworkFromManifest, STDLIB_FRAMEWORKS, } from "./manifest.js";
|
|
7
3
|
import { scanFile, aggregate } from "./scanner.js";
|
|
@@ -66,6 +62,4 @@ function frameworkFromOwningManifest(sourceFile, manifests) {
|
|
|
66
62
|
.sort((a, b) => b.dir.length - a.dir.length);
|
|
67
63
|
return candidates[0] ? detectFrameworkFromManifest(candidates[0].m) : undefined;
|
|
68
64
|
}
|
|
69
|
-
// Used by orchestrator-side typing to widen the language union if needed.
|
|
70
65
|
export const _stdlibFrameworkSet = STDLIB_FRAMEWORKS;
|
|
71
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Go manifest analysis.
|
|
3
|
-
*
|
|
4
|
-
* Parses go.mod (line-based, no real grammar needed) to build the
|
|
5
|
-
* dependency map. Doesn't read go.sum — that's a hash list, not version
|
|
6
|
-
* authority. Direct vs indirect deps are both in the require block;
|
|
7
|
-
* we keep the // indirect annotation as a hint but don't filter on it.
|
|
8
|
-
*/
|
|
9
1
|
import type { ExtractedExternalService, ExtractedDataStore, ManifestSummary } from "../../types.js";
|
|
10
2
|
export declare const WEB_FRAMEWORK_MODULES: Record<string, string>;
|
|
11
|
-
/** stdlib router lives at "net/http"; not in go.mod, only detected via imports. */
|
|
12
3
|
export declare const STDLIB_FRAMEWORKS: Set<string>;
|
|
13
4
|
export declare const DATA_STORE_MODULES: Record<string, {
|
|
14
5
|
kind: ExtractedDataStore["kind"];
|
|
@@ -19,17 +10,9 @@ export interface ParsedGoMod {
|
|
|
19
10
|
filePath: string;
|
|
20
11
|
module?: string;
|
|
21
12
|
goVersion?: string;
|
|
22
|
-
/** module path → version. */
|
|
23
13
|
deps: Record<string, string>;
|
|
24
14
|
}
|
|
25
15
|
export declare function readManifests(rootDir: string, manifestFiles: string[]): Promise<ParsedGoMod[]>;
|
|
26
|
-
/**
|
|
27
|
-
* Minimal go.mod parser. Supports the two block forms:
|
|
28
|
-
* require modulePath v1.2.3
|
|
29
|
-
* require ( modulePath v1.2.3 \n other v0.0.1 )
|
|
30
|
-
* Strips trailing "// indirect" markers. Does NOT handle replace/exclude
|
|
31
|
-
* directives (out of scope for inventory).
|
|
32
|
-
*/
|
|
33
16
|
export declare function parseGoMod(filePath: string, rootDir: string, raw: string): ParsedGoMod;
|
|
34
17
|
export declare function summarizeManifests(parsed: ParsedGoMod[]): ManifestSummary[];
|
|
35
18
|
export declare function findExternalServices(parsed: ParsedGoMod[]): ExtractedExternalService[];
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Go manifest analysis.
|
|
3
|
-
*
|
|
4
|
-
* Parses go.mod (line-based, no real grammar needed) to build the
|
|
5
|
-
* dependency map. Doesn't read go.sum — that's a hash list, not version
|
|
6
|
-
* authority. Direct vs indirect deps are both in the require block;
|
|
7
|
-
* we keep the // indirect annotation as a hint but don't filter on it.
|
|
8
|
-
*/
|
|
9
1
|
import * as fs from "node:fs/promises";
|
|
10
2
|
import * as path from "node:path";
|
|
11
3
|
export const WEB_FRAMEWORK_MODULES = {
|
|
@@ -18,14 +10,13 @@ export const WEB_FRAMEWORK_MODULES = {
|
|
|
18
10
|
"github.com/gofiber/fiber/v2": "fiber",
|
|
19
11
|
"github.com/gorilla/mux": "gorilla-mux",
|
|
20
12
|
};
|
|
21
|
-
/** stdlib router lives at "net/http"; not in go.mod, only detected via imports. */
|
|
22
13
|
export const STDLIB_FRAMEWORKS = new Set(["net/http"]);
|
|
23
14
|
export const DATA_STORE_MODULES = {
|
|
24
15
|
"github.com/jackc/pgx": { kind: "postgres", client: "pgx" },
|
|
25
16
|
"github.com/jackc/pgx/v5": { kind: "postgres", client: "pgx" },
|
|
26
17
|
"github.com/jackc/pgx/v4": { kind: "postgres", client: "pgx" },
|
|
27
18
|
"github.com/lib/pq": { kind: "postgres", client: "pq" },
|
|
28
|
-
"gorm.io/gorm": { kind: "postgres", client: "gorm" },
|
|
19
|
+
"gorm.io/gorm": { kind: "postgres", client: "gorm" },
|
|
29
20
|
"go.mongodb.org/mongo-driver": { kind: "mongo", client: "mongo-driver" },
|
|
30
21
|
"github.com/redis/go-redis": { kind: "redis", client: "go-redis" },
|
|
31
22
|
"github.com/redis/go-redis/v9": { kind: "redis", client: "go-redis" },
|
|
@@ -48,18 +39,10 @@ export async function readManifests(rootDir, manifestFiles) {
|
|
|
48
39
|
out.push(parseGoMod(file, rootDir, raw));
|
|
49
40
|
}
|
|
50
41
|
catch {
|
|
51
|
-
// skip unreadable
|
|
52
42
|
}
|
|
53
43
|
}
|
|
54
44
|
return out;
|
|
55
45
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Minimal go.mod parser. Supports the two block forms:
|
|
58
|
-
* require modulePath v1.2.3
|
|
59
|
-
* require ( modulePath v1.2.3 \n other v0.0.1 )
|
|
60
|
-
* Strips trailing "// indirect" markers. Does NOT handle replace/exclude
|
|
61
|
-
* directives (out of scope for inventory).
|
|
62
|
-
*/
|
|
63
46
|
export function parseGoMod(filePath, rootDir, raw) {
|
|
64
47
|
const lines = raw.split("\n");
|
|
65
48
|
const result = {
|
|
@@ -92,7 +75,6 @@ export function parseGoMod(filePath, rootDir, raw) {
|
|
|
92
75
|
body = body.slice("require ".length).trim();
|
|
93
76
|
else if (!inBlock)
|
|
94
77
|
continue;
|
|
95
|
-
// Strip "// indirect" / other line comments
|
|
96
78
|
const commentAt = body.indexOf("//");
|
|
97
79
|
if (commentAt >= 0)
|
|
98
80
|
body = body.slice(0, commentAt).trim();
|
|
@@ -184,14 +166,9 @@ export function detectFrameworkFromManifest(m) {
|
|
|
184
166
|
}
|
|
185
167
|
return undefined;
|
|
186
168
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Match a module path including its versioned variants (mod, mod/v2, etc.).
|
|
189
|
-
* Returns the version of the first match.
|
|
190
|
-
*/
|
|
191
169
|
function matchModuleVersion(deps, modulePath) {
|
|
192
170
|
if (deps[modulePath])
|
|
193
171
|
return deps[modulePath];
|
|
194
|
-
// Try versioned variants
|
|
195
172
|
for (const [k, v] of Object.entries(deps)) {
|
|
196
173
|
if (k === modulePath)
|
|
197
174
|
return v;
|
|
@@ -214,4 +191,3 @@ function relPosix(rootDir, abs) {
|
|
|
214
191
|
const rel = path.relative(rootDir, abs);
|
|
215
192
|
return rel.split(path.sep).join("/");
|
|
216
193
|
}
|
|
217
|
-
//# sourceMappingURL=manifest.js.map
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* tree-sitter-go loader. Lazy-init, reuses the same WASM directory as
|
|
3
|
-
* the TypeScript adapter (both come from @vscode/tree-sitter-wasm).
|
|
4
|
-
*/
|
|
5
1
|
import { createRequire } from "node:module";
|
|
6
2
|
import * as path from "node:path";
|
|
7
3
|
import { Parser, Language } from "web-tree-sitter";
|
|
@@ -20,4 +16,3 @@ export function getGoParser() {
|
|
|
20
16
|
}
|
|
21
17
|
return parserPromise;
|
|
22
18
|
}
|
|
23
|
-
//# sourceMappingURL=parser.js.map
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AST scanner for Go source files.
|
|
3
|
-
*
|
|
4
|
-
* Walks tree-sitter-go for two things:
|
|
5
|
-
*
|
|
6
|
-
* 1. import declarations naming any tracked module (AI SDKs, web
|
|
7
|
-
* frameworks, DB clients) → ImportEvidence
|
|
8
|
-
* 2. HTTP route calls. Three flavors:
|
|
9
|
-
* net/http : http.HandleFunc("/path", h)
|
|
10
|
-
* chi : r.Get("/path", h), r.Post(…) (TitleCase)
|
|
11
|
-
* echo/gin : e.GET("/path", h), r.POST(…) (UPPER)
|
|
12
|
-
* fiber : app.Get("/path", h), app.Post(…) (TitleCase)
|
|
13
|
-
*
|
|
14
|
-
* Method-name normalization happens after we identify the call-shape;
|
|
15
|
-
* output is always UPPERCASE in the JSON.
|
|
16
|
-
*
|
|
17
|
-
* Privacy invariant: same as the TS adapter — only identifier names,
|
|
18
|
-
* file paths, line numbers, package paths, and route method/path strings.
|
|
19
|
-
* Function bodies are never read.
|
|
20
|
-
*/
|
|
21
1
|
import type { EvidenceLocation, Evidence, HttpRouteEvidence, ImportEvidence } from "../../types.js";
|
|
22
2
|
export interface FileScanResult {
|
|
23
3
|
file: string;
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AST scanner for Go source files.
|
|
3
|
-
*
|
|
4
|
-
* Walks tree-sitter-go for two things:
|
|
5
|
-
*
|
|
6
|
-
* 1. import declarations naming any tracked module (AI SDKs, web
|
|
7
|
-
* frameworks, DB clients) → ImportEvidence
|
|
8
|
-
* 2. HTTP route calls. Three flavors:
|
|
9
|
-
* net/http : http.HandleFunc("/path", h)
|
|
10
|
-
* chi : r.Get("/path", h), r.Post(…) (TitleCase)
|
|
11
|
-
* echo/gin : e.GET("/path", h), r.POST(…) (UPPER)
|
|
12
|
-
* fiber : app.Get("/path", h), app.Post(…) (TitleCase)
|
|
13
|
-
*
|
|
14
|
-
* Method-name normalization happens after we identify the call-shape;
|
|
15
|
-
* output is always UPPERCASE in the JSON.
|
|
16
|
-
*
|
|
17
|
-
* Privacy invariant: same as the TS adapter — only identifier names,
|
|
18
|
-
* file paths, line numbers, package paths, and route method/path strings.
|
|
19
|
-
* Function bodies are never read.
|
|
20
|
-
*/
|
|
21
1
|
import * as fs from "node:fs/promises";
|
|
22
2
|
import { getGoParser } from "./parser.js";
|
|
23
3
|
import { AI_SDK_MODULES, DATA_STORE_MODULES, WEB_FRAMEWORK_MODULES, STDLIB_FRAMEWORKS, } from "./manifest.js";
|
|
@@ -74,64 +54,45 @@ function walk(node, visit) {
|
|
|
74
54
|
walk(child, visit);
|
|
75
55
|
}
|
|
76
56
|
}
|
|
77
|
-
/** Pull the quoted module path out of an import_spec node. */
|
|
78
57
|
function extractImportPath(node) {
|
|
79
|
-
// import_spec → optional package_identifier + interpreted_string_literal
|
|
80
58
|
const stringNode = node.namedChildren.find((c) => c?.type === "interpreted_string_literal");
|
|
81
59
|
if (!stringNode)
|
|
82
60
|
return null;
|
|
83
|
-
// text is the quoted form; strip the surrounding quotes.
|
|
84
61
|
const text = stringNode.text;
|
|
85
62
|
return text.length >= 2 ? text.slice(1, -1) : null;
|
|
86
63
|
}
|
|
87
64
|
function trackedModuleMatch(pkg) {
|
|
88
65
|
if (TRACKED_MODULES.has(pkg))
|
|
89
66
|
return pkg;
|
|
90
|
-
// Sub-package import — e.g., "github.com/jackc/pgx/v5/pgxpool"
|
|
91
67
|
for (const tracked of TRACKED_MODULES) {
|
|
92
68
|
if (pkg.startsWith(tracked + "/"))
|
|
93
69
|
return tracked;
|
|
94
70
|
}
|
|
95
71
|
return null;
|
|
96
72
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Match an HTTP-route call by inspecting the call-expression shape.
|
|
99
|
-
* Two AST patterns to handle:
|
|
100
|
-
* - selector_expression(operand=identifier, field=field_identifier) called with args
|
|
101
|
-
* ⇒ http.HandleFunc, app.Get, e.GET, r.Post …
|
|
102
|
-
* - identifier called with args (rare for routes; ignored)
|
|
103
|
-
*/
|
|
104
73
|
function extractRouteCall(node) {
|
|
105
|
-
// call_expression has: function (selector_expression | identifier) + argument_list
|
|
106
74
|
const fn = node.namedChildren.find((c) => c?.type === "selector_expression");
|
|
107
75
|
const args = node.namedChildren.find((c) => c?.type === "argument_list");
|
|
108
76
|
if (!fn || !args)
|
|
109
77
|
return null;
|
|
110
|
-
// selector_expression: operand (any) . field (field_identifier)
|
|
111
78
|
const operand = fn.namedChildren[0];
|
|
112
79
|
const field = fn.namedChildren.find((c) => c?.type === "field_identifier");
|
|
113
80
|
if (!operand || !field)
|
|
114
81
|
return null;
|
|
115
82
|
const operandText = operand.text;
|
|
116
83
|
const fieldName = field.text;
|
|
117
|
-
// Determine the HTTP method from the field name + operand shape.
|
|
118
84
|
let method = null;
|
|
119
85
|
if (HTTP_METHODS_UPPER.has(fieldName)) {
|
|
120
|
-
// echo/gin: e.GET, r.POST … — operand is a router-like local var
|
|
121
86
|
method = fieldName === "ANY" ? "ALL" : fieldName;
|
|
122
87
|
}
|
|
123
88
|
else if (HTTP_METHODS_TITLE.has(fieldName)) {
|
|
124
|
-
// chi/fiber: r.Get, app.Post …
|
|
125
89
|
method = fieldName.toUpperCase();
|
|
126
90
|
}
|
|
127
91
|
else if (STDLIB_HANDLER_FNS.has(fieldName) && operandText === "http") {
|
|
128
|
-
// net/http: http.HandleFunc("/x", h) / http.Handle("/x", h)
|
|
129
|
-
// We don't know the HTTP verb statically — emit "ALL".
|
|
130
92
|
method = "ALL";
|
|
131
93
|
}
|
|
132
94
|
if (!method)
|
|
133
95
|
return null;
|
|
134
|
-
// First arg = string literal route path.
|
|
135
96
|
const firstArg = args.namedChildren[0];
|
|
136
97
|
if (!firstArg)
|
|
137
98
|
return null;
|
|
@@ -150,7 +111,6 @@ export function aggregate(scans) {
|
|
|
150
111
|
if (s.routes.length === 0 && s.imports.length === 0)
|
|
151
112
|
continue;
|
|
152
113
|
for (const imp of s.imports) {
|
|
153
|
-
// Match against the FULL tracked module (allowing sub-paths).
|
|
154
114
|
const matched = matchTracked(imp.package);
|
|
155
115
|
if (!matched)
|
|
156
116
|
continue;
|
|
@@ -191,8 +151,6 @@ function matchTracked(pkg) {
|
|
|
191
151
|
}
|
|
192
152
|
function deriveComponentName(filePath) {
|
|
193
153
|
const segs = filePath.split("/");
|
|
194
|
-
// Go convention: cmd/foo/main.go → "foo"; internal/auth/handler.go → "auth"
|
|
195
|
-
// Use the deepest directory that isn't a stdlib-ish folder name.
|
|
196
154
|
const skipPrefixes = new Set(["cmd", "internal", "pkg", "src", "app"]);
|
|
197
155
|
const start = skipPrefixes.has(segs[0]) ? 1 : 0;
|
|
198
156
|
if (segs.length - start >= 2)
|
|
@@ -213,4 +171,3 @@ function detectFrameworkFromImports(imports) {
|
|
|
213
171
|
}
|
|
214
172
|
return undefined;
|
|
215
173
|
}
|
|
216
|
-
//# sourceMappingURL=scanner.js.map
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python language adapter. Same shape as TS/Go.
|
|
3
|
-
*/
|
|
4
1
|
import * as path from "node:path";
|
|
5
2
|
import { readManifests, summarizeManifests, findExternalServices, findDataStores, detectFrameworkFromManifest, } from "./manifest.js";
|
|
6
3
|
import { scanFile, aggregate } from "./scanner.js";
|
|
@@ -65,4 +62,3 @@ function frameworkFromOwningManifest(sourceFile, manifests) {
|
|
|
65
62
|
.sort((a, b) => b.dir.length - a.dir.length);
|
|
66
63
|
return candidates[0] ? detectFrameworkFromManifest(candidates[0].m) : undefined;
|
|
67
64
|
}
|
|
68
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python manifest analysis.
|
|
3
|
-
*
|
|
4
|
-
* Reads pyproject.toml (PEP 621 + Poetry sections) and requirements.txt.
|
|
5
|
-
* Other formats (Pipfile, setup.py) deferred — they're either rare in
|
|
6
|
-
* modern projects (setup.py) or layer on top of these two.
|
|
7
|
-
*/
|
|
8
1
|
import type { ExtractedExternalService, ExtractedDataStore, ManifestSummary } from "../../types.js";
|
|
9
2
|
export declare const WEB_FRAMEWORK_PACKAGES: Record<string, string>;
|
|
10
3
|
export declare const DATA_STORE_PACKAGES: Record<string, {
|
|
@@ -15,7 +8,6 @@ export declare const AI_SDK_PACKAGES: Record<string, string>;
|
|
|
15
8
|
export interface ParsedPyManifest {
|
|
16
9
|
filePath: string;
|
|
17
10
|
format: "pyproject.toml" | "requirements.txt";
|
|
18
|
-
/** package name → version specifier (verbatim, e.g. "^0.30.0", ">=2.0,<3"). */
|
|
19
11
|
deps: Record<string, string>;
|
|
20
12
|
}
|
|
21
13
|
export declare function readManifests(rootDir: string, manifestFiles: string[]): Promise<ParsedPyManifest[]>;
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python manifest analysis.
|
|
3
|
-
*
|
|
4
|
-
* Reads pyproject.toml (PEP 621 + Poetry sections) and requirements.txt.
|
|
5
|
-
* Other formats (Pipfile, setup.py) deferred — they're either rare in
|
|
6
|
-
* modern projects (setup.py) or layer on top of these two.
|
|
7
|
-
*/
|
|
8
1
|
import * as fs from "node:fs/promises";
|
|
9
2
|
import * as path from "node:path";
|
|
10
3
|
import TOML from "@iarna/toml";
|
|
@@ -20,7 +13,7 @@ export const WEB_FRAMEWORK_PACKAGES = {
|
|
|
20
13
|
quart: "quart",
|
|
21
14
|
};
|
|
22
15
|
export const DATA_STORE_PACKAGES = {
|
|
23
|
-
sqlalchemy: { kind: "postgres", client: "sqlalchemy" },
|
|
16
|
+
sqlalchemy: { kind: "postgres", client: "sqlalchemy" },
|
|
24
17
|
asyncpg: { kind: "postgres", client: "asyncpg" },
|
|
25
18
|
psycopg: { kind: "postgres", client: "psycopg" },
|
|
26
19
|
psycopg2: { kind: "postgres", client: "psycopg2" },
|
|
@@ -45,7 +38,7 @@ export const AI_SDK_PACKAGES = {
|
|
|
45
38
|
vertexai: "Vertex AI",
|
|
46
39
|
"google-generativeai": "Google Generative AI",
|
|
47
40
|
cohere: "Cohere",
|
|
48
|
-
"boto3": "AWS (boto3)",
|
|
41
|
+
"boto3": "AWS (boto3)",
|
|
49
42
|
};
|
|
50
43
|
export async function readManifests(rootDir, manifestFiles) {
|
|
51
44
|
const out = [];
|
|
@@ -61,7 +54,6 @@ export async function readManifests(rootDir, manifestFiles) {
|
|
|
61
54
|
}
|
|
62
55
|
}
|
|
63
56
|
catch {
|
|
64
|
-
// skip unreadable / unparsable
|
|
65
57
|
}
|
|
66
58
|
}
|
|
67
59
|
return out;
|
|
@@ -79,7 +71,6 @@ function parsePyproject(filePath, rootDir, raw) {
|
|
|
79
71
|
catch {
|
|
80
72
|
return result;
|
|
81
73
|
}
|
|
82
|
-
// PEP 621: project.dependencies = ["fastapi >=0.100", ...]
|
|
83
74
|
const projectDeps = parsed?.project?.dependencies;
|
|
84
75
|
if (Array.isArray(projectDeps)) {
|
|
85
76
|
for (const spec of projectDeps) {
|
|
@@ -90,7 +81,6 @@ function parsePyproject(filePath, rootDir, raw) {
|
|
|
90
81
|
result.deps[name] = version;
|
|
91
82
|
}
|
|
92
83
|
}
|
|
93
|
-
// PEP 621: optional-dependencies = { test = [...], dev = [...] }
|
|
94
84
|
const opt = parsed?.project?.["optional-dependencies"];
|
|
95
85
|
if (opt && typeof opt === "object") {
|
|
96
86
|
for (const groupSpec of Object.values(opt)) {
|
|
@@ -105,7 +95,6 @@ function parsePyproject(filePath, rootDir, raw) {
|
|
|
105
95
|
}
|
|
106
96
|
}
|
|
107
97
|
}
|
|
108
|
-
// Poetry: tool.poetry.dependencies = { fastapi = "^0.100" } (also dev-dependencies)
|
|
109
98
|
const poetryDeps = parsed?.tool?.poetry?.dependencies;
|
|
110
99
|
if (poetryDeps && typeof poetryDeps === "object") {
|
|
111
100
|
for (const [name, value] of Object.entries(poetryDeps)) {
|
|
@@ -137,8 +126,7 @@ function parseRequirementsTxt(filePath, rootDir, raw) {
|
|
|
137
126
|
if (!line || line.startsWith("#"))
|
|
138
127
|
continue;
|
|
139
128
|
if (line.startsWith("-"))
|
|
140
|
-
continue;
|
|
141
|
-
// strip inline comments
|
|
129
|
+
continue;
|
|
142
130
|
const hashAt = line.indexOf(" #");
|
|
143
131
|
if (hashAt > 0)
|
|
144
132
|
line = line.slice(0, hashAt).trim();
|
|
@@ -148,9 +136,7 @@ function parseRequirementsTxt(filePath, rootDir, raw) {
|
|
|
148
136
|
}
|
|
149
137
|
return result;
|
|
150
138
|
}
|
|
151
|
-
/** "fastapi>=0.100,<0.110" → ["fastapi", ">=0.100,<0.110"] */
|
|
152
139
|
function splitPep508(spec) {
|
|
153
|
-
// strip extras like fastapi[all]
|
|
154
140
|
const cleaned = spec.replace(/\[[^\]]*\]/g, "").trim();
|
|
155
141
|
const m = cleaned.match(/^([A-Za-z0-9_.\-]+)\s*(.*)$/);
|
|
156
142
|
if (!m)
|
|
@@ -251,4 +237,3 @@ function relPosix(rootDir, abs) {
|
|
|
251
237
|
const rel = path.relative(rootDir, abs);
|
|
252
238
|
return rel.split(path.sep).join("/");
|
|
253
239
|
}
|
|
254
|
-
//# sourceMappingURL=manifest.js.map
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* tree-sitter-python loader.
|
|
3
|
-
*/
|
|
4
1
|
import { createRequire } from "node:module";
|
|
5
2
|
import * as path from "node:path";
|
|
6
3
|
import { Parser, Language } from "web-tree-sitter";
|
|
@@ -19,4 +16,3 @@ export function getPythonParser() {
|
|
|
19
16
|
}
|
|
20
17
|
return parserPromise;
|
|
21
18
|
}
|
|
22
|
-
//# sourceMappingURL=parser.js.map
|
|
@@ -1,21 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AST scanner for Python source files.
|
|
3
|
-
*
|
|
4
|
-
* Patterns covered:
|
|
5
|
-
* 1. import_statement / import_from_statement → tracked-package imports
|
|
6
|
-
* (AI SDKs, web frameworks, DB clients).
|
|
7
|
-
* 2. Decorator-based routes (FastAPI, Flask):
|
|
8
|
-
* @app.get("/path") → method=GET
|
|
9
|
-
* @app.post("/path") → method=POST
|
|
10
|
-
* @app.route("/path", …) → method=ALL (Flask default; verbs in `methods=` kw not parsed yet)
|
|
11
|
-
* @router.get("/x", …) → method=GET (FastAPI APIRouter convention)
|
|
12
|
-
* 3. Django urls.py-style call: path("/route", view, …) / re_path(…) → method=ALL
|
|
13
|
-
* 4. aiohttp: app.router.add_get("/path", h) / add_post(…) / etc.
|
|
14
|
-
*
|
|
15
|
-
* Privacy invariant: identifier names + dotted attribute names + string
|
|
16
|
-
* literals on routes only. Function bodies and decorator args beyond the
|
|
17
|
-
* route path are never inspected.
|
|
18
|
-
*/
|
|
19
1
|
import type { EvidenceLocation, Evidence, HttpRouteEvidence, ImportEvidence } from "../../types.js";
|
|
20
2
|
export interface FileScanResult {
|
|
21
3
|
file: string;
|