@zivis/cli 0.1.0-alpha.34 → 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 +0 -19
- package/dist/commands/auth/login.d.ts +0 -1
- package/dist/commands/auth/login.js +0 -6
- 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 +0 -18
- package/dist/commands/check/index.js +1 -37
- 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 +9 -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 +0 -19
- package/dist/internal/github-linkage-prompt.js +1 -27
- 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 +22 -13
- 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/check/index.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/github-linkage-prompt.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
|
@@ -1,32 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build a RepoGraphArtifactV1 from an ExtractionResult.
|
|
3
|
-
*
|
|
4
|
-
* The existing extractor emits an entity-list shape (components,
|
|
5
|
-
* externalServices, dataStores, manifests). This builder is the canonical
|
|
6
|
-
* translator from that internal intermediate into the graph artifact that
|
|
7
|
-
* downstream pattern matching, threat modeling, and evidence storage all
|
|
8
|
-
* consume.
|
|
9
|
-
*
|
|
10
|
-
* Plan: docs/plans/LOCAL-REPO-GRAPH-IMPLEMENTATION.md (Phase 1)
|
|
11
|
-
* Schema: schemas/repo-graph-artifact.schema.json
|
|
12
|
-
*
|
|
13
|
-
* v1 scope (locked): three node types (service, endpoint, external_dependency)
|
|
14
|
-
* and two edge types (exposes, depends_on). Datastores and the corresponding
|
|
15
|
-
* reads/writes edges are deferred to Phase 1.5.
|
|
16
|
-
*
|
|
17
|
-
* Lane assignment for v1: every node and edge produced by deterministic
|
|
18
|
-
* adapter output is `trusted`. Inferred-lane nodes are introduced later by
|
|
19
|
-
* the matching engine (Phase 3), not by extraction.
|
|
20
|
-
*/
|
|
21
1
|
const TRUSTED_LANE = "trusted";
|
|
22
2
|
const TRUSTED_SOURCE = "inspect.trusted";
|
|
23
3
|
export function buildRepoGraphArtifact(result, opts = {}) {
|
|
24
4
|
const nodes = [];
|
|
25
5
|
const edges = [];
|
|
26
|
-
// Service nodes — every component that isn't an external service or pure datastore.
|
|
27
|
-
// The existing extractor models datastores via `dataStores` and external SDKs via
|
|
28
|
-
// `externalServices`; `components` covers code-defined services and frontends.
|
|
29
|
-
// Skip components that arrive with empty evidence — schema requires minItems: 1.
|
|
30
6
|
const serviceById = new Map();
|
|
31
7
|
for (const component of result.components) {
|
|
32
8
|
if (component.kind === "external_service" || component.kind === "data_store") {
|
|
@@ -38,10 +14,6 @@ export function buildRepoGraphArtifact(result, opts = {}) {
|
|
|
38
14
|
serviceById.set(node.id, node);
|
|
39
15
|
nodes.push(node);
|
|
40
16
|
}
|
|
41
|
-
// Endpoint nodes + exposes edges — derived from each service's http_route evidence.
|
|
42
|
-
// Non-canonical methods (e.g. Express `app.use()` mounts emitted by the TS adapter)
|
|
43
|
-
// are dropped here — they're middleware mounts, not endpoints. Fixing them belongs
|
|
44
|
-
// upstream in the adapter; the graph-builder enforces the contract.
|
|
45
17
|
for (const component of result.components) {
|
|
46
18
|
const owningServiceId = serviceIdFor(component);
|
|
47
19
|
if (!serviceById.has(owningServiceId))
|
|
@@ -61,9 +33,6 @@ export function buildRepoGraphArtifact(result, opts = {}) {
|
|
|
61
33
|
edges.push(buildExposesEdge(owningServiceId, endpointNode.id, ev));
|
|
62
34
|
}
|
|
63
35
|
}
|
|
64
|
-
// External dependency nodes — one per (registry, package) tuple.
|
|
65
|
-
// Manifest-only deps (no callSites) fall back to manifest evidence so they still
|
|
66
|
-
// satisfy the schema's evidence: minItems: 1 invariant.
|
|
67
36
|
const manifestEvidenceByPackage = indexManifestsByPackage(result);
|
|
68
37
|
const depById = new Map();
|
|
69
38
|
for (const ext of result.externalServices) {
|
|
@@ -71,11 +40,10 @@ export function buildRepoGraphArtifact(result, opts = {}) {
|
|
|
71
40
|
if (depById.has(node.id))
|
|
72
41
|
continue;
|
|
73
42
|
if (node.evidence.length === 0)
|
|
74
|
-
continue;
|
|
43
|
+
continue;
|
|
75
44
|
depById.set(node.id, node);
|
|
76
45
|
nodes.push(node);
|
|
77
46
|
}
|
|
78
|
-
// File-to-service index for resolving callSites into depends_on edges.
|
|
79
47
|
const fileToServiceId = buildFileToServiceIndex(result.components, serviceById);
|
|
80
48
|
for (const ext of result.externalServices) {
|
|
81
49
|
const depId = externalDepId(ext);
|
|
@@ -119,7 +87,6 @@ export function buildRepoGraphArtifact(result, opts = {}) {
|
|
|
119
87
|
edges,
|
|
120
88
|
};
|
|
121
89
|
}
|
|
122
|
-
// ── Node builders ──
|
|
123
90
|
function buildServiceNode(component) {
|
|
124
91
|
const id = serviceIdFor(component);
|
|
125
92
|
return {
|
|
@@ -208,7 +175,6 @@ function buildDependsOnEdge(serviceId, depId, evidence) {
|
|
|
208
175
|
evidence,
|
|
209
176
|
};
|
|
210
177
|
}
|
|
211
|
-
// ── Helpers ──
|
|
212
178
|
function serviceIdFor(component) {
|
|
213
179
|
return `service::${component.language}::${component.name}`;
|
|
214
180
|
}
|
|
@@ -217,12 +183,9 @@ function externalDepId(ext) {
|
|
|
217
183
|
return `external_dependency::${registry}::${ext.package}`;
|
|
218
184
|
}
|
|
219
185
|
function registryFor(ext) {
|
|
220
|
-
// Heuristic — the existing extractor doesn't tag registry, so derive from package shape.
|
|
221
186
|
if (ext.package.startsWith("github.com/"))
|
|
222
187
|
return "go";
|
|
223
188
|
if (ext.package.startsWith("@") || /^[a-z0-9-]+$/.test(ext.package)) {
|
|
224
|
-
// npm + pypi share many shapes; lean npm by default since most ai_sdks live there.
|
|
225
|
-
// PyPI-only packages can be retagged once adapters expose registry directly.
|
|
226
189
|
return "npm";
|
|
227
190
|
}
|
|
228
191
|
return "npm";
|
|
@@ -280,4 +243,3 @@ function toImportEvidence(loc, pkg) {
|
|
|
280
243
|
function stripPrefix(value, prefix) {
|
|
281
244
|
return value.startsWith(prefix) ? value.slice(prefix.length) : value;
|
|
282
245
|
}
|
|
283
|
-
//# sourceMappingURL=graph-builder.js.map
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypeScript interfaces for RepoGraphArtifactV1.
|
|
3
|
-
*
|
|
4
|
-
* Canonical source: schemas/repo-graph-artifact.schema.json
|
|
5
|
-
* Plan: docs/plans/LOCAL-REPO-GRAPH-IMPLEMENTATION.md (Phase 1)
|
|
6
|
-
*
|
|
7
|
-
* The JSON schema is authoritative — these types must stay in sync. A
|
|
8
|
-
* repo-level test (planned) validates extractor output against the schema
|
|
9
|
-
* to catch drift.
|
|
10
|
-
*/
|
|
11
1
|
export type Lane = "trusted" | "inferred";
|
|
12
2
|
export type Source = "inspect.trusted" | "inspect.inferred";
|
|
13
3
|
export type GraphLanguage = "typescript" | "javascript" | "python" | "go";
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypeScript interfaces for RepoGraphArtifactV1.
|
|
3
|
-
*
|
|
4
|
-
* Canonical source: schemas/repo-graph-artifact.schema.json
|
|
5
|
-
* Plan: docs/plans/LOCAL-REPO-GRAPH-IMPLEMENTATION.md (Phase 1)
|
|
6
|
-
*
|
|
7
|
-
* The JSON schema is authoritative — these types must stay in sync. A
|
|
8
|
-
* repo-level test (planned) validates extractor output against the schema
|
|
9
|
-
* to catch drift.
|
|
10
|
-
*/
|
|
11
1
|
export {};
|
|
12
|
-
//# sourceMappingURL=graph-types.js.map
|
|
@@ -1,22 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extractor orchestrator.
|
|
3
|
-
*
|
|
4
|
-
* Walks the customer's repo, dispatches matched files to per-language
|
|
5
|
-
* adapters, merges their findings into a single ExtractionResult.
|
|
6
|
-
*
|
|
7
|
-
* Adapters register their own file extensions + manifest filenames; the
|
|
8
|
-
* walker only reads files those filters claim. So adding a Go or Python
|
|
9
|
-
* adapter doesn't change anything here — register the adapter and the
|
|
10
|
-
* orchestrator picks up its files.
|
|
11
|
-
*/
|
|
12
1
|
import type { ExtractionResult } from "./types.js";
|
|
13
2
|
export interface RunOptions {
|
|
14
3
|
rootDir: string;
|
|
15
|
-
/** Subset of language adapters to run; defaults to all registered. */
|
|
16
4
|
languages?: Array<"typescript" | "go" | "python">;
|
|
17
|
-
/** Extra ignore patterns from --ignore flags. */
|
|
18
5
|
extraIgnores?: string[];
|
|
19
|
-
/** Version string for the extractor — usually @zivis/cli's package version. */
|
|
20
6
|
extractorVersion: string;
|
|
21
7
|
}
|
|
22
8
|
export declare function runExtractor(opts: RunOptions): Promise<ExtractionResult>;
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extractor orchestrator.
|
|
3
|
-
*
|
|
4
|
-
* Walks the customer's repo, dispatches matched files to per-language
|
|
5
|
-
* adapters, merges their findings into a single ExtractionResult.
|
|
6
|
-
*
|
|
7
|
-
* Adapters register their own file extensions + manifest filenames; the
|
|
8
|
-
* walker only reads files those filters claim. So adding a Go or Python
|
|
9
|
-
* adapter doesn't change anything here — register the adapter and the
|
|
10
|
-
* orchestrator picks up its files.
|
|
11
|
-
*/
|
|
12
1
|
import * as path from "node:path";
|
|
13
2
|
import { walk } from "./walker.js";
|
|
14
3
|
import { typescriptAdapter } from "./adapters/typescript/index.js";
|
|
@@ -25,7 +14,6 @@ export async function runExtractor(opts) {
|
|
|
25
14
|
const adapters = opts.languages
|
|
26
15
|
? ADAPTERS.filter((a) => opts.languages.includes(a.language))
|
|
27
16
|
: ADAPTERS;
|
|
28
|
-
// Aggregate the file filters from each adapter so we walk the tree once.
|
|
29
17
|
const extensions = new Set();
|
|
30
18
|
const manifests = new Set();
|
|
31
19
|
for (const a of adapters) {
|
|
@@ -104,4 +92,3 @@ function dedupeExternalServices(items) {
|
|
|
104
92
|
}
|
|
105
93
|
return [...out.values()];
|
|
106
94
|
}
|
|
107
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,29 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extractor output schema.
|
|
3
|
-
*
|
|
4
|
-
* Matches `THREAT-MODEL-PHASE-J.md`'s J.2 output shape, with additions
|
|
5
|
-
* for privacy-audit metadata. The shape is the contract between the CLI
|
|
6
|
-
* and the eventual `--apply` endpoint that maps into ThreatModelComponent
|
|
7
|
-
* / OrgComponent records (RECON.3-gated).
|
|
8
|
-
*
|
|
9
|
-
* Privacy invariant — what's IN the JSON:
|
|
10
|
-
* component names ("auth-service")
|
|
11
|
-
* file paths ("src/auth/login.ts")
|
|
12
|
-
* line numbers (42)
|
|
13
|
-
* framework + SDK identifiers ("express", "@anthropic-ai/sdk")
|
|
14
|
-
* detected protocols / methods (POST /login)
|
|
15
|
-
* dependency versions (from package.json / go.mod / pyproject.toml)
|
|
16
|
-
*
|
|
17
|
-
* What's NOT:
|
|
18
|
-
* function bodies, file contents, code snippets
|
|
19
|
-
* variable names from inside functions
|
|
20
|
-
* comments
|
|
21
|
-
* raw AST nodes
|
|
22
|
-
*
|
|
23
|
-
* `zivis tm extract --privacy-audit` prints this whole object to stdout
|
|
24
|
-
* before any network call, so the customer can see exactly what would
|
|
25
|
-
* be sent.
|
|
26
|
-
*/
|
|
27
1
|
export type Language = "typescript" | "javascript" | "go" | "python";
|
|
28
2
|
export interface EvidenceLocation {
|
|
29
3
|
file: string;
|
|
@@ -44,21 +18,16 @@ export interface ConfigEvidence extends EvidenceLocation {
|
|
|
44
18
|
export type Evidence = HttpRouteEvidence | ImportEvidence | ConfigEvidence;
|
|
45
19
|
export type ComponentKind = "process" | "data_store" | "external_service" | "frontend";
|
|
46
20
|
export interface ExtractedComponent {
|
|
47
|
-
/** Stable name derived from path / module — never a value from inside a function. */
|
|
48
21
|
name: string;
|
|
49
22
|
kind: ComponentKind;
|
|
50
23
|
language: Language;
|
|
51
|
-
/** Detected web framework, if any (express | fastify | nextjs | trpc | hono | gin | echo | …). */
|
|
52
24
|
framework?: string;
|
|
53
25
|
sourceFiles: string[];
|
|
54
26
|
evidence: Evidence[];
|
|
55
27
|
}
|
|
56
28
|
export interface ExtractedExternalService {
|
|
57
|
-
/** Vendor / SDK name — "Anthropic", "OpenAI", "WorkOS". */
|
|
58
29
|
name: string;
|
|
59
|
-
/** What kind of integration: ai_sdk, payments, auth, observability, etc. */
|
|
60
30
|
kind: string;
|
|
61
|
-
/** npm/PyPI/Go module identifier ("@anthropic-ai/sdk"). */
|
|
62
31
|
package: string;
|
|
63
32
|
version?: string;
|
|
64
33
|
callSites: EvidenceLocation[];
|
|
@@ -84,30 +53,16 @@ export interface ExtractionResult {
|
|
|
84
53
|
components: ExtractedComponent[];
|
|
85
54
|
externalServices: ExtractedExternalService[];
|
|
86
55
|
dataStores: ExtractedDataStore[];
|
|
87
|
-
/**
|
|
88
|
-
* Per-language manifests detected in the scope. Surfaces dependency-only
|
|
89
|
-
* findings (e.g., "this repo uses @anthropic-ai/sdk@^0.30") even when
|
|
90
|
-
* we can't yet match call sites.
|
|
91
|
-
*/
|
|
92
56
|
manifests: ManifestSummary[];
|
|
93
57
|
}
|
|
94
58
|
export interface ManifestSummary {
|
|
95
59
|
language: Language;
|
|
96
60
|
file: string;
|
|
97
|
-
/** Direct dependency names → version (verbatim from manifest). */
|
|
98
61
|
dependencies: Record<string, string>;
|
|
99
62
|
}
|
|
100
|
-
/**
|
|
101
|
-
* Adapter contract — one per language. Each adapter is fed the list of
|
|
102
|
-
* source files matched for it (already filtered by .gitignore + .zivisignore)
|
|
103
|
-
* plus any manifest files (package.json, go.mod, pyproject.toml). Returns
|
|
104
|
-
* structured findings the framework merges into the final ExtractionResult.
|
|
105
|
-
*/
|
|
106
63
|
export interface LanguageAdapter {
|
|
107
64
|
language: Language;
|
|
108
|
-
/** File extensions this adapter handles. */
|
|
109
65
|
extensions: string[];
|
|
110
|
-
/** Manifest filenames this adapter cares about. */
|
|
111
66
|
manifests: string[];
|
|
112
67
|
extract(input: AdapterInput): Promise<AdapterOutput>;
|
|
113
68
|
}
|
|
@@ -1,28 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extractor output schema.
|
|
3
|
-
*
|
|
4
|
-
* Matches `THREAT-MODEL-PHASE-J.md`'s J.2 output shape, with additions
|
|
5
|
-
* for privacy-audit metadata. The shape is the contract between the CLI
|
|
6
|
-
* and the eventual `--apply` endpoint that maps into ThreatModelComponent
|
|
7
|
-
* / OrgComponent records (RECON.3-gated).
|
|
8
|
-
*
|
|
9
|
-
* Privacy invariant — what's IN the JSON:
|
|
10
|
-
* component names ("auth-service")
|
|
11
|
-
* file paths ("src/auth/login.ts")
|
|
12
|
-
* line numbers (42)
|
|
13
|
-
* framework + SDK identifiers ("express", "@anthropic-ai/sdk")
|
|
14
|
-
* detected protocols / methods (POST /login)
|
|
15
|
-
* dependency versions (from package.json / go.mod / pyproject.toml)
|
|
16
|
-
*
|
|
17
|
-
* What's NOT:
|
|
18
|
-
* function bodies, file contents, code snippets
|
|
19
|
-
* variable names from inside functions
|
|
20
|
-
* comments
|
|
21
|
-
* raw AST nodes
|
|
22
|
-
*
|
|
23
|
-
* `zivis tm extract --privacy-audit` prints this whole object to stdout
|
|
24
|
-
* before any network call, so the customer can see exactly what would
|
|
25
|
-
* be sent.
|
|
26
|
-
*/
|
|
27
1
|
export {};
|
|
28
|
-
//# sourceMappingURL=types.js.map
|
|
@@ -1,24 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filesystem walker — yields source files relative to the scan root,
|
|
3
|
-
* filtered by .gitignore + .zivisignore + per-extractor extension filters.
|
|
4
|
-
*
|
|
5
|
-
* Uses the `ignore` npm package (the same engine git ships with) so the
|
|
6
|
-
* matching semantics mirror what developers expect from .gitignore.
|
|
7
|
-
*
|
|
8
|
-
* Hard limits:
|
|
9
|
-
* - Skips node_modules, dist, build, .next, .git, .yarn, vendor — even
|
|
10
|
-
* if not in .gitignore. These exist by convention and contain
|
|
11
|
-
* third-party code that pollutes the inventory.
|
|
12
|
-
* - Caps total files at 50_000 to refuse to scan a generated monorepo
|
|
13
|
-
* by accident (extractor would take forever; user should narrow scope).
|
|
14
|
-
*/
|
|
15
1
|
export interface WalkOptions {
|
|
16
2
|
rootDir: string;
|
|
17
|
-
/** Extensions to include (with the leading dot, e.g. [".ts", ".tsx"]). */
|
|
18
3
|
extensions: string[];
|
|
19
|
-
/** Manifest basenames to capture regardless of extension (e.g. ["package.json"]). */
|
|
20
4
|
manifests: string[];
|
|
21
|
-
/** Extra ignore patterns from --ignore CLI flags. */
|
|
22
5
|
extraIgnores?: string[];
|
|
23
6
|
}
|
|
24
7
|
export interface WalkResult {
|
|
@@ -28,5 +11,4 @@ export interface WalkResult {
|
|
|
28
11
|
filesSkipped: number;
|
|
29
12
|
}
|
|
30
13
|
export declare function walk(opts: WalkOptions): Promise<WalkResult>;
|
|
31
|
-
/** Convert an absolute path to a posix-style repo-relative path. */
|
|
32
14
|
export declare function repoRelative(rootDir: string, absPath: string): string;
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filesystem walker — yields source files relative to the scan root,
|
|
3
|
-
* filtered by .gitignore + .zivisignore + per-extractor extension filters.
|
|
4
|
-
*
|
|
5
|
-
* Uses the `ignore` npm package (the same engine git ships with) so the
|
|
6
|
-
* matching semantics mirror what developers expect from .gitignore.
|
|
7
|
-
*
|
|
8
|
-
* Hard limits:
|
|
9
|
-
* - Skips node_modules, dist, build, .next, .git, .yarn, vendor — even
|
|
10
|
-
* if not in .gitignore. These exist by convention and contain
|
|
11
|
-
* third-party code that pollutes the inventory.
|
|
12
|
-
* - Caps total files at 50_000 to refuse to scan a generated monorepo
|
|
13
|
-
* by accident (extractor would take forever; user should narrow scope).
|
|
14
|
-
*/
|
|
15
1
|
import * as fs from "node:fs/promises";
|
|
16
2
|
import * as path from "node:path";
|
|
17
3
|
import ignore from "ignore";
|
|
@@ -64,7 +50,6 @@ export async function walk(opts) {
|
|
|
64
50
|
filesSkipped++;
|
|
65
51
|
continue;
|
|
66
52
|
}
|
|
67
|
-
// ignore() expects gitignore-style paths with trailing /
|
|
68
53
|
if (ig.ignores(childRel + "/")) {
|
|
69
54
|
filesSkipped++;
|
|
70
55
|
continue;
|
|
@@ -99,12 +84,9 @@ async function loadIgnoreFile(ig, filePath) {
|
|
|
99
84
|
ig.add(content);
|
|
100
85
|
}
|
|
101
86
|
catch {
|
|
102
|
-
// No ignore file — fine.
|
|
103
87
|
}
|
|
104
88
|
}
|
|
105
|
-
/** Convert an absolute path to a posix-style repo-relative path. */
|
|
106
89
|
export function repoRelative(rootDir, absPath) {
|
|
107
90
|
const rel = path.relative(rootDir, absPath);
|
|
108
91
|
return rel.split(path.sep).join("/");
|
|
109
92
|
}
|
|
110
|
-
//# sourceMappingURL=walker.js.map
|
|
@@ -1,26 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lane-2 conversion prompts — nudges the user to install the ZIVIS
|
|
3
|
-
* GitHub App and / or link a repo to a specific Application.
|
|
4
|
-
*
|
|
5
|
-
* Surfaced from `zivis auth login`, `zivis auth init`, and `zivis check`
|
|
6
|
-
* so the next step is obvious right after a developer signs in.
|
|
7
|
-
*
|
|
8
|
-
* Best-effort by design: any fetch failure returns `null` so we don't
|
|
9
|
-
* fail an otherwise-successful auth or check run on a transient API
|
|
10
|
-
* blip.
|
|
11
|
-
*/
|
|
12
1
|
import type { ZivisConfig } from "@zivis/mcp/types";
|
|
13
2
|
export interface BuildLinkagePromptOpts {
|
|
14
3
|
config: ZivisConfig;
|
|
15
|
-
/** Optional. When provided we also check whether THIS app has linked repos. */
|
|
16
4
|
applicationId?: string;
|
|
17
|
-
/** Format hint: "short" omits the explanatory why-line. Default "full". */
|
|
18
5
|
style?: "short" | "full";
|
|
19
6
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Fetch GitHub App status + (if applicationId given) per-app repo
|
|
22
|
-
* linkage status, then return a multi-line printable prompt suggesting
|
|
23
|
-
* the next step. Returns null when nothing actionable is missing
|
|
24
|
-
* (fully linked) or when we couldn't determine the state.
|
|
25
|
-
*/
|
|
26
7
|
export declare function buildLinkagePrompt(opts: BuildLinkagePromptOpts): Promise<string | null>;
|
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lane-2 conversion prompts — nudges the user to install the ZIVIS
|
|
3
|
-
* GitHub App and / or link a repo to a specific Application.
|
|
4
|
-
*
|
|
5
|
-
* Surfaced from `zivis auth login`, `zivis auth init`, and `zivis check`
|
|
6
|
-
* so the next step is obvious right after a developer signs in.
|
|
7
|
-
*
|
|
8
|
-
* Best-effort by design: any fetch failure returns `null` so we don't
|
|
9
|
-
* fail an otherwise-successful auth or check run on a transient API
|
|
10
|
-
* blip.
|
|
11
|
-
*/
|
|
12
1
|
import { resolveAuth } from "@zivis/mcp/auth";
|
|
13
|
-
/**
|
|
14
|
-
* Fetch GitHub App status + (if applicationId given) per-app repo
|
|
15
|
-
* linkage status, then return a multi-line printable prompt suggesting
|
|
16
|
-
* the next step. Returns null when nothing actionable is missing
|
|
17
|
-
* (fully linked) or when we couldn't determine the state.
|
|
18
|
-
*/
|
|
19
2
|
export async function buildLinkagePrompt(opts) {
|
|
20
3
|
const creds = await resolveAuth(opts.config);
|
|
21
4
|
if (creds.method === "none")
|
|
@@ -23,24 +6,19 @@ export async function buildLinkagePrompt(opts) {
|
|
|
23
6
|
const appStatus = await fetchGitHubAppStatus(opts.config, creds);
|
|
24
7
|
if (!appStatus)
|
|
25
8
|
return null;
|
|
26
|
-
// Case 1: GitHub App not installed at all → install URL.
|
|
27
9
|
if (!appStatus.installed) {
|
|
28
10
|
if (!appStatus.installUrl)
|
|
29
|
-
return null;
|
|
11
|
+
return null;
|
|
30
12
|
return formatInstallPrompt(appStatus.installUrl, opts.style ?? "full");
|
|
31
13
|
}
|
|
32
|
-
// Case 2: App installed but caller has a specific applicationId and
|
|
33
|
-
// that app has no linked repo → web link-repo prompt.
|
|
34
14
|
if (opts.applicationId) {
|
|
35
15
|
const repoStatus = await fetchAppRepoStatus(opts.config, creds, opts.applicationId);
|
|
36
16
|
if (repoStatus && !repoStatus.linked) {
|
|
37
17
|
return formatLinkRepoPrompt(opts.config, opts.applicationId, opts.style ?? "full");
|
|
38
18
|
}
|
|
39
19
|
}
|
|
40
|
-
// Case 3: All good (or no applicationId to check at app-level).
|
|
41
20
|
return null;
|
|
42
21
|
}
|
|
43
|
-
// ── HTTP helpers ──
|
|
44
22
|
async function fetchGitHubAppStatus(config, creds) {
|
|
45
23
|
try {
|
|
46
24
|
const res = await fetch(`${config.apiBaseUrl}/api/github-app/status`, {
|
|
@@ -78,7 +56,6 @@ function authHeaders(creds) {
|
|
|
78
56
|
}
|
|
79
57
|
return base;
|
|
80
58
|
}
|
|
81
|
-
// ── Formatters ──
|
|
82
59
|
function formatInstallPrompt(installUrl, style) {
|
|
83
60
|
if (style === "short") {
|
|
84
61
|
return `Next: install the ZIVIS GitHub App — ${installUrl}`;
|
|
@@ -104,18 +81,15 @@ function formatLinkRepoPrompt(config, applicationId, style) {
|
|
|
104
81
|
].join("\n");
|
|
105
82
|
}
|
|
106
83
|
function guessAppUrlFromApi(apiBaseUrl) {
|
|
107
|
-
// Standard mapping: api.* ⇄ app.* on the same root domain.
|
|
108
84
|
try {
|
|
109
85
|
const u = new URL(apiBaseUrl);
|
|
110
86
|
if (u.host.startsWith("api.")) {
|
|
111
87
|
u.host = "app." + u.host.slice(4);
|
|
112
88
|
return `${u.protocol}//${u.host}`;
|
|
113
89
|
}
|
|
114
|
-
// localhost / non-standard hosts → fall back to the api URL itself.
|
|
115
90
|
return apiBaseUrl;
|
|
116
91
|
}
|
|
117
92
|
catch {
|
|
118
93
|
return "https://app.zivis.ai";
|
|
119
94
|
}
|
|
120
95
|
}
|
|
121
|
-
//# sourceMappingURL=github-linkage-prompt.js.map
|
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
export type GuidanceClient = "cursor" | "claude-code-cli" | "vscode-copilot" | "vscode-claude" | "cline" | "windsurf";
|
|
2
2
|
export interface GuidanceOptions {
|
|
3
|
-
/** Workspace root to write guidance files into */
|
|
4
3
|
cwd: string;
|
|
5
|
-
/** Which IDE client to write guidance for */
|
|
6
4
|
client: GuidanceClient;
|
|
7
5
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Write IDE guidance files for the given client.
|
|
10
|
-
*
|
|
11
|
-
* The guidance files teach the host AI (Cursor, Claude Code, etc.)
|
|
12
|
-
* when to suggest ZIVIS tools — no security knowledge required from the user.
|
|
13
|
-
*
|
|
14
|
-
* All writes are idempotent: re-running replaces only the ZIVIS-managed
|
|
15
|
-
* block, never user content.
|
|
16
|
-
*
|
|
17
|
-
* Returns the list of file paths written.
|
|
18
|
-
*/
|
|
19
6
|
export declare function writeGuidance(opts: GuidanceOptions): string[];
|
|
20
|
-
/**
|
|
21
|
-
* Detect which IDE configs are present in the given workspace.
|
|
22
|
-
* Returns client identifiers whose config files/dirs were found.
|
|
23
|
-
*/
|
|
24
7
|
export declare function detectIdesInRepo(cwd: string): GuidanceClient[];
|
|
25
8
|
export declare function setupCursor(): Promise<void>;
|
|
26
|
-
/**
|
|
27
|
-
* Write a workspace-level .cursor/mcp.json with `--workspace <cwd>` so Cursor
|
|
28
|
-
* starts an isolated MCP process bound to this specific repo.
|
|
29
|
-
* One process = one org = zero cross-tenant risk, regardless of what other
|
|
30
|
-
* repos are open in Cursor.
|
|
31
|
-
*/
|
|
32
9
|
export declare function setupCursorWorkspace(): Promise<void>;
|
|
33
10
|
export declare function setupVsCodeCopilot(): Promise<void>;
|
|
34
11
|
export declare function setupVsCodeClaude(): Promise<void>;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
const SERVER_NAME = "zivis";
|
|
4
|
-
// ── Idempotent block append ──
|
|
5
|
-
/**
|
|
6
|
-
* Append (or replace) a ZIVIS-managed block inside a text file.
|
|
7
|
-
* The block is wrapped in <!-- BEGIN ZIVIS:key --> / <!-- END ZIVIS:key -->
|
|
8
|
-
* markers so future calls replace only this section without touching user content.
|
|
9
|
-
*/
|
|
10
4
|
function appendBlock(filePath, blockKey, content) {
|
|
11
5
|
const begin = `<!-- BEGIN ZIVIS:${blockKey} -->`;
|
|
12
6
|
const end = `<!-- END ZIVIS:${blockKey} -->`;
|
|
@@ -31,8 +25,6 @@ function appendBlock(filePath, blockKey, content) {
|
|
|
31
25
|
function escapeRegex(s) {
|
|
32
26
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
27
|
}
|
|
34
|
-
// ── Content templates ──
|
|
35
|
-
/** Full Cursor .mdc rule — uses globs so it only attaches when relevant files are open */
|
|
36
28
|
function cursorRuleContent() {
|
|
37
29
|
return `---
|
|
38
30
|
description: ZIVIS security guidance — quietly suggest security checks at the right moments
|
|
@@ -117,7 +109,6 @@ might break in", "security plan", "categories of attacks".
|
|
|
117
109
|
|
|
118
110
|
<!-- END ZIVIS:guidance -->`;
|
|
119
111
|
}
|
|
120
|
-
/** Short block for CLAUDE.md / AGENTS.md — must be concise (read every turn) */
|
|
121
112
|
function claudeBlockContent() {
|
|
122
113
|
return `## ZIVIS Security (MCP)
|
|
123
114
|
|
|
@@ -135,7 +126,6 @@ ZIVIS is connected to this project. Use its tools sparingly — only for securit
|
|
|
135
126
|
|
|
136
127
|
**Slash commands:** /zivis-getting-started /zivis-secure-my-app /zivis-audit-dependencies /zivis-prep-for-launch`;
|
|
137
128
|
}
|
|
138
|
-
/** .clinerules / .windsurfrules content */
|
|
139
129
|
function ruleFileContent() {
|
|
140
130
|
return `# ZIVIS Security Guidance
|
|
141
131
|
|
|
@@ -168,7 +158,6 @@ Say "security plan" not "threat model".
|
|
|
168
158
|
/zivis-prep-for-launch — pre-launch checklist
|
|
169
159
|
/zivis-weekly-check — weekly status update`;
|
|
170
160
|
}
|
|
171
|
-
/** GitHub Copilot instructions block */
|
|
172
161
|
function copilotBlockContent() {
|
|
173
162
|
return `## ZIVIS Security Integration
|
|
174
163
|
|
|
@@ -186,7 +175,6 @@ Use ZIVIS only for security-related user requests. Never proactively run scans o
|
|
|
186
175
|
|
|
187
176
|
**Language:** Avoid security jargon (threat model, STRIDE, attack vector) unless user uses it first.`;
|
|
188
177
|
}
|
|
189
|
-
// ── Per-IDE writers ──
|
|
190
178
|
function writeCursorGuidance(cwd) {
|
|
191
179
|
const rulesDir = path.join(cwd, ".cursor", "rules");
|
|
192
180
|
if (!fs.existsSync(rulesDir))
|
|
@@ -225,24 +213,12 @@ function writeWindsurfGuidance(cwd) {
|
|
|
225
213
|
fs.writeFileSync(rulesPath, ruleFileContent());
|
|
226
214
|
return rulesPath;
|
|
227
215
|
}
|
|
228
|
-
/**
|
|
229
|
-
* Write IDE guidance files for the given client.
|
|
230
|
-
*
|
|
231
|
-
* The guidance files teach the host AI (Cursor, Claude Code, etc.)
|
|
232
|
-
* when to suggest ZIVIS tools — no security knowledge required from the user.
|
|
233
|
-
*
|
|
234
|
-
* All writes are idempotent: re-running replaces only the ZIVIS-managed
|
|
235
|
-
* block, never user content.
|
|
236
|
-
*
|
|
237
|
-
* Returns the list of file paths written.
|
|
238
|
-
*/
|
|
239
216
|
export function writeGuidance(opts) {
|
|
240
217
|
const { cwd, client } = opts;
|
|
241
218
|
const written = [];
|
|
242
219
|
switch (client) {
|
|
243
220
|
case "cursor": {
|
|
244
221
|
written.push(writeCursorGuidance(cwd));
|
|
245
|
-
// Also write CLAUDE.md/AGENTS.md block if those files exist
|
|
246
222
|
const extraPaths = writeClaudeBlockGuidance(cwd).filter((p) => fs.existsSync(p));
|
|
247
223
|
written.push(...extraPaths);
|
|
248
224
|
break;
|
|
@@ -267,46 +243,25 @@ export function writeGuidance(opts) {
|
|
|
267
243
|
}
|
|
268
244
|
return written.filter(Boolean);
|
|
269
245
|
}
|
|
270
|
-
/**
|
|
271
|
-
* Detect which IDE configs are present in the given workspace.
|
|
272
|
-
* Returns client identifiers whose config files/dirs were found.
|
|
273
|
-
*/
|
|
274
246
|
export function detectIdesInRepo(cwd) {
|
|
275
247
|
const found = [];
|
|
276
|
-
// Cursor
|
|
277
248
|
if (fs.existsSync(path.join(cwd, ".cursor"))) {
|
|
278
249
|
found.push("cursor");
|
|
279
250
|
}
|
|
280
|
-
// Claude Code (CLAUDE.md)
|
|
281
251
|
if (fs.existsSync(path.join(cwd, "CLAUDE.md"))) {
|
|
282
252
|
found.push("claude-code-cli");
|
|
283
253
|
}
|
|
284
|
-
// VS Code (check for .vscode directory)
|
|
285
254
|
if (fs.existsSync(path.join(cwd, ".vscode"))) {
|
|
286
|
-
// Assume Copilot by default for VS Code
|
|
287
255
|
found.push("vscode-copilot");
|
|
288
256
|
}
|
|
289
|
-
// Cline (.clinerules)
|
|
290
257
|
if (fs.existsSync(path.join(cwd, ".clinerules"))) {
|
|
291
258
|
found.push("cline");
|
|
292
259
|
}
|
|
293
|
-
// Windsurf (.windsurfrules)
|
|
294
260
|
if (fs.existsSync(path.join(cwd, ".windsurfrules"))) {
|
|
295
261
|
found.push("windsurf");
|
|
296
262
|
}
|
|
297
263
|
return found;
|
|
298
264
|
}
|
|
299
|
-
/**
|
|
300
|
-
* Build the MCP server config for an IDE config file.
|
|
301
|
-
*
|
|
302
|
-
* When workspacePath is provided, we pass it as `--workspace <path>` so the
|
|
303
|
-
* MCP server process resolves its session from `.zivis/project.json` at that
|
|
304
|
-
* path — not from an env var that can drift or be accidentally reused across
|
|
305
|
-
* tenants. This gives us one-process-per-org isolation at the IDE level.
|
|
306
|
-
*
|
|
307
|
-
* ZIVIS_SESSION is intentionally NOT used here. The workspace path is the
|
|
308
|
-
* canonical, immutable tenant binding for an MCP process.
|
|
309
|
-
*/
|
|
310
265
|
function buildServerConfig(workspacePath, extra) {
|
|
311
266
|
const args = ["mcp", "serve"];
|
|
312
267
|
if (workspacePath) {
|
|
@@ -342,17 +297,10 @@ async function updateMcpConfig(configPath, serverName, serverConfig, rootKey) {
|
|
|
342
297
|
export async function setupCursor() {
|
|
343
298
|
const homeDir = process.env.HOME || "";
|
|
344
299
|
const configPath = path.join(homeDir, ".cursor", "mcp.json");
|
|
345
|
-
// Global config has no workspace path — serves repos without .zivis/project.json
|
|
346
300
|
await updateMcpConfig(configPath, SERVER_NAME, buildServerConfig(), "mcpServers");
|
|
347
301
|
console.log(`✓ Cursor global MCP config updated: ${configPath}`);
|
|
348
302
|
console.log(" Restart Cursor for changes to take effect");
|
|
349
303
|
}
|
|
350
|
-
/**
|
|
351
|
-
* Write a workspace-level .cursor/mcp.json with `--workspace <cwd>` so Cursor
|
|
352
|
-
* starts an isolated MCP process bound to this specific repo.
|
|
353
|
-
* One process = one org = zero cross-tenant risk, regardless of what other
|
|
354
|
-
* repos are open in Cursor.
|
|
355
|
-
*/
|
|
356
304
|
export async function setupCursorWorkspace() {
|
|
357
305
|
const workspacePath = process.cwd();
|
|
358
306
|
const configPath = path.join(workspacePath, ".cursor", "mcp.json");
|
|
@@ -446,4 +394,3 @@ export function printClaudeCodeManual() {
|
|
|
446
394
|
console.log("");
|
|
447
395
|
console.log("Then restart Claude Code for changes to take effect");
|
|
448
396
|
}
|
|
449
|
-
//# sourceMappingURL=ide-setup.js.map
|
package/dist/internal/orgs.js
CHANGED
|
@@ -7,7 +7,6 @@ export interface EnsureBindingOpts {
|
|
|
7
7
|
cwd: string;
|
|
8
8
|
autoBind: boolean;
|
|
9
9
|
skipBind: boolean;
|
|
10
|
-
/** Overwrite an existing conflicting binding without erroring (used by `zivis auth init`). */
|
|
11
10
|
force?: boolean;
|
|
12
11
|
}
|
|
13
12
|
export declare function ensureProjectBinding(opts: EnsureBindingOpts): Promise<void>;
|