@zivis/cli 0.1.0-alpha.32 → 0.1.0-alpha.34
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/commands/auth/init.js +18 -0
- package/dist/commands/auth/init.js.map +1 -1
- package/dist/commands/auth/login.js +11 -0
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/check/index.d.ts +20 -0
- package/dist/commands/check/index.js +499 -0
- package/dist/commands/check/index.js.map +1 -0
- package/dist/commands/inspect/index.d.ts +17 -0
- package/dist/commands/inspect/index.js +159 -0
- package/dist/commands/inspect/index.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/extractor/adapters/go/manifest.js +18 -0
- package/dist/internal/extractor/adapters/go/manifest.js.map +1 -1
- package/dist/internal/extractor/adapters/python/manifest.js +18 -0
- package/dist/internal/extractor/adapters/python/manifest.js.map +1 -1
- package/dist/internal/extractor/adapters/typescript/manifest.js +28 -0
- package/dist/internal/extractor/adapters/typescript/manifest.js.map +1 -1
- package/dist/internal/extractor/graph-builder.d.ts +35 -0
- package/dist/internal/extractor/graph-builder.js +283 -0
- package/dist/internal/extractor/graph-builder.js.map +1 -0
- package/dist/internal/extractor/graph-types.d.ts +99 -0
- package/dist/internal/extractor/graph-types.js +12 -0
- package/dist/internal/extractor/graph-types.js.map +1 -0
- package/dist/internal/github-linkage-prompt.d.ts +26 -0
- package/dist/internal/github-linkage-prompt.js +121 -0
- package/dist/internal/github-linkage-prompt.js.map +1 -0
- package/dist/internal/pattern-pack/index.d.ts +123 -0
- package/dist/internal/pattern-pack/index.js +230 -0
- package/dist/internal/pattern-pack/index.js.map +1 -0
- package/dist/pattern-packs/zivis-public-0.1.0/capsules/agents/privilege-separation.yaml +228 -0
- package/dist/pattern-packs/zivis-public-0.1.0/manifest.json +31 -0
- package/dist/pattern-packs/zivis-public-0.1.0/prompts/agents/privilege-separation/identify.md +54 -0
- package/package.json +17 -12
|
@@ -0,0 +1,283 @@
|
|
|
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
|
+
const TRUSTED_LANE = "trusted";
|
|
22
|
+
const TRUSTED_SOURCE = "inspect.trusted";
|
|
23
|
+
export function buildRepoGraphArtifact(result, opts = {}) {
|
|
24
|
+
const nodes = [];
|
|
25
|
+
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
|
+
const serviceById = new Map();
|
|
31
|
+
for (const component of result.components) {
|
|
32
|
+
if (component.kind === "external_service" || component.kind === "data_store") {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (component.evidence.length === 0)
|
|
36
|
+
continue;
|
|
37
|
+
const node = buildServiceNode(component);
|
|
38
|
+
serviceById.set(node.id, node);
|
|
39
|
+
nodes.push(node);
|
|
40
|
+
}
|
|
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
|
+
for (const component of result.components) {
|
|
46
|
+
const owningServiceId = serviceIdFor(component);
|
|
47
|
+
if (!serviceById.has(owningServiceId))
|
|
48
|
+
continue;
|
|
49
|
+
const seenEndpoints = new Set();
|
|
50
|
+
for (const ev of component.evidence) {
|
|
51
|
+
if (ev.kind !== "http_route")
|
|
52
|
+
continue;
|
|
53
|
+
const method = canonicalMethod(ev.method);
|
|
54
|
+
if (!method)
|
|
55
|
+
continue;
|
|
56
|
+
const endpointNode = buildEndpointNode(owningServiceId, component.language, ev, method);
|
|
57
|
+
if (seenEndpoints.has(endpointNode.id))
|
|
58
|
+
continue;
|
|
59
|
+
seenEndpoints.add(endpointNode.id);
|
|
60
|
+
nodes.push(endpointNode);
|
|
61
|
+
edges.push(buildExposesEdge(owningServiceId, endpointNode.id, ev));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
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
|
+
const manifestEvidenceByPackage = indexManifestsByPackage(result);
|
|
68
|
+
const depById = new Map();
|
|
69
|
+
for (const ext of result.externalServices) {
|
|
70
|
+
const node = buildExternalDependencyNode(ext, manifestEvidenceByPackage.get(ext.package) ?? []);
|
|
71
|
+
if (depById.has(node.id))
|
|
72
|
+
continue;
|
|
73
|
+
if (node.evidence.length === 0)
|
|
74
|
+
continue; // truly orphaned — skip
|
|
75
|
+
depById.set(node.id, node);
|
|
76
|
+
nodes.push(node);
|
|
77
|
+
}
|
|
78
|
+
// File-to-service index for resolving callSites into depends_on edges.
|
|
79
|
+
const fileToServiceId = buildFileToServiceIndex(result.components, serviceById);
|
|
80
|
+
for (const ext of result.externalServices) {
|
|
81
|
+
const depId = externalDepId(ext);
|
|
82
|
+
const seenServiceIds = new Set();
|
|
83
|
+
const evidenceByService = new Map();
|
|
84
|
+
for (const callSite of ext.callSites) {
|
|
85
|
+
const serviceId = fileToServiceId.get(callSite.file);
|
|
86
|
+
if (!serviceId)
|
|
87
|
+
continue;
|
|
88
|
+
seenServiceIds.add(serviceId);
|
|
89
|
+
const list = evidenceByService.get(serviceId) ?? [];
|
|
90
|
+
list.push(toImportEvidence(callSite, ext.package));
|
|
91
|
+
evidenceByService.set(serviceId, list);
|
|
92
|
+
}
|
|
93
|
+
for (const serviceId of seenServiceIds) {
|
|
94
|
+
edges.push(buildDependsOnEdge(serviceId, depId, evidenceByService.get(serviceId) ?? []));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const provenance = {
|
|
98
|
+
root_dir: result.scope.rootDir,
|
|
99
|
+
analysis_mode: opts.analysisMode ?? "local",
|
|
100
|
+
...(opts.repoId ? { repo_id: opts.repoId } : {}),
|
|
101
|
+
...(opts.commitSha ? { commit_sha: opts.commitSha } : {}),
|
|
102
|
+
...(opts.branch ? { branch: opts.branch } : {}),
|
|
103
|
+
...(opts.applicationId ? { application_id: opts.applicationId } : {}),
|
|
104
|
+
};
|
|
105
|
+
const languagesFromManifests = new Set(result.manifests.map((m) => normalizeLanguage(m.language)).filter(Boolean));
|
|
106
|
+
return {
|
|
107
|
+
version: "1.0.0",
|
|
108
|
+
kind: "repo_graph_artifact",
|
|
109
|
+
extracted_at: result.extractedAt,
|
|
110
|
+
extractor: result.extractor,
|
|
111
|
+
provenance,
|
|
112
|
+
scope: {
|
|
113
|
+
files_scanned: result.scope.filesScanned,
|
|
114
|
+
files_skipped: result.scope.filesSkipped,
|
|
115
|
+
duration_ms: result.scope.durationMs,
|
|
116
|
+
languages: [...languagesFromManifests],
|
|
117
|
+
},
|
|
118
|
+
nodes,
|
|
119
|
+
edges,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// ── Node builders ──
|
|
123
|
+
function buildServiceNode(component) {
|
|
124
|
+
const id = serviceIdFor(component);
|
|
125
|
+
return {
|
|
126
|
+
id,
|
|
127
|
+
type: "service",
|
|
128
|
+
name: component.name,
|
|
129
|
+
lane: TRUSTED_LANE,
|
|
130
|
+
source: TRUSTED_SOURCE,
|
|
131
|
+
confidence: 1,
|
|
132
|
+
language: normalizeLanguage(component.language),
|
|
133
|
+
evidence: component.evidence.map(toEvidenceSpan),
|
|
134
|
+
attributes: {
|
|
135
|
+
...(component.framework ? { framework: component.framework } : {}),
|
|
136
|
+
source_files: component.sourceFiles,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function buildEndpointNode(serviceId, language, ev, method) {
|
|
141
|
+
const id = `endpoint::${stripPrefix(serviceId, "service::")}::${method}::${ev.path}`;
|
|
142
|
+
return {
|
|
143
|
+
id,
|
|
144
|
+
type: "endpoint",
|
|
145
|
+
name: `${method} ${ev.path}`,
|
|
146
|
+
lane: TRUSTED_LANE,
|
|
147
|
+
source: TRUSTED_SOURCE,
|
|
148
|
+
confidence: 1,
|
|
149
|
+
language: normalizeLanguage(language),
|
|
150
|
+
evidence: [toEvidenceSpan(ev)],
|
|
151
|
+
attributes: { method, path: ev.path },
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function buildExternalDependencyNode(ext, manifestFallback) {
|
|
155
|
+
const registry = registryFor(ext);
|
|
156
|
+
const evidence = ext.callSites.length > 0
|
|
157
|
+
? ext.callSites.map((cs) => toImportEvidence(cs, ext.package))
|
|
158
|
+
: manifestFallback;
|
|
159
|
+
return {
|
|
160
|
+
id: externalDepId(ext),
|
|
161
|
+
type: "external_dependency",
|
|
162
|
+
name: ext.name,
|
|
163
|
+
lane: TRUSTED_LANE,
|
|
164
|
+
source: TRUSTED_SOURCE,
|
|
165
|
+
confidence: 1,
|
|
166
|
+
evidence,
|
|
167
|
+
attributes: {
|
|
168
|
+
package: ext.package,
|
|
169
|
+
registry,
|
|
170
|
+
...(ext.version ? { version: ext.version } : {}),
|
|
171
|
+
...(ext.kind ? { kind: ext.kind } : {}),
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function indexManifestsByPackage(result) {
|
|
176
|
+
const idx = new Map();
|
|
177
|
+
for (const m of result.manifests) {
|
|
178
|
+
for (const pkg of Object.keys(m.dependencies)) {
|
|
179
|
+
const span = { file: m.file, kind: "manifest", detail: { package: pkg } };
|
|
180
|
+
const list = idx.get(pkg) ?? [];
|
|
181
|
+
list.push(span);
|
|
182
|
+
idx.set(pkg, list);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return idx;
|
|
186
|
+
}
|
|
187
|
+
function buildExposesEdge(serviceId, endpointId, ev) {
|
|
188
|
+
return {
|
|
189
|
+
id: `exposes::${serviceId}::${endpointId}`,
|
|
190
|
+
type: "exposes",
|
|
191
|
+
source_id: serviceId,
|
|
192
|
+
target_id: endpointId,
|
|
193
|
+
lane: TRUSTED_LANE,
|
|
194
|
+
source: TRUSTED_SOURCE,
|
|
195
|
+
confidence: 1,
|
|
196
|
+
evidence: [toEvidenceSpan(ev)],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function buildDependsOnEdge(serviceId, depId, evidence) {
|
|
200
|
+
return {
|
|
201
|
+
id: `depends_on::${serviceId}::${depId}`,
|
|
202
|
+
type: "depends_on",
|
|
203
|
+
source_id: serviceId,
|
|
204
|
+
target_id: depId,
|
|
205
|
+
lane: TRUSTED_LANE,
|
|
206
|
+
source: TRUSTED_SOURCE,
|
|
207
|
+
confidence: 1,
|
|
208
|
+
evidence,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
// ── Helpers ──
|
|
212
|
+
function serviceIdFor(component) {
|
|
213
|
+
return `service::${component.language}::${component.name}`;
|
|
214
|
+
}
|
|
215
|
+
function externalDepId(ext) {
|
|
216
|
+
const registry = registryFor(ext);
|
|
217
|
+
return `external_dependency::${registry}::${ext.package}`;
|
|
218
|
+
}
|
|
219
|
+
function registryFor(ext) {
|
|
220
|
+
// Heuristic — the existing extractor doesn't tag registry, so derive from package shape.
|
|
221
|
+
if (ext.package.startsWith("github.com/"))
|
|
222
|
+
return "go";
|
|
223
|
+
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
|
+
return "npm";
|
|
227
|
+
}
|
|
228
|
+
return "npm";
|
|
229
|
+
}
|
|
230
|
+
const CANONICAL_METHODS = new Set([
|
|
231
|
+
"GET",
|
|
232
|
+
"POST",
|
|
233
|
+
"PUT",
|
|
234
|
+
"PATCH",
|
|
235
|
+
"DELETE",
|
|
236
|
+
"HEAD",
|
|
237
|
+
"OPTIONS",
|
|
238
|
+
"WS",
|
|
239
|
+
"SSE",
|
|
240
|
+
"RPC",
|
|
241
|
+
]);
|
|
242
|
+
function canonicalMethod(method) {
|
|
243
|
+
const upper = method.toUpperCase();
|
|
244
|
+
return CANONICAL_METHODS.has(upper) ? upper : undefined;
|
|
245
|
+
}
|
|
246
|
+
function normalizeLanguage(lang) {
|
|
247
|
+
return lang;
|
|
248
|
+
}
|
|
249
|
+
function buildFileToServiceIndex(components, servicesById) {
|
|
250
|
+
const idx = new Map();
|
|
251
|
+
for (const component of components) {
|
|
252
|
+
const id = serviceIdFor(component);
|
|
253
|
+
if (!servicesById.has(id))
|
|
254
|
+
continue;
|
|
255
|
+
for (const file of component.sourceFiles) {
|
|
256
|
+
if (!idx.has(file))
|
|
257
|
+
idx.set(file, id);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return idx;
|
|
261
|
+
}
|
|
262
|
+
function toEvidenceSpan(ev) {
|
|
263
|
+
const base = { file: ev.file, start_line: ev.line, kind: ev.kind };
|
|
264
|
+
if (ev.kind === "http_route") {
|
|
265
|
+
return { ...base, detail: { method: ev.method, path: ev.path } };
|
|
266
|
+
}
|
|
267
|
+
if (ev.kind === "import") {
|
|
268
|
+
return { ...base, detail: { package: ev.package } };
|
|
269
|
+
}
|
|
270
|
+
return base;
|
|
271
|
+
}
|
|
272
|
+
function toImportEvidence(loc, pkg) {
|
|
273
|
+
return {
|
|
274
|
+
file: loc.file,
|
|
275
|
+
start_line: loc.line,
|
|
276
|
+
kind: "import",
|
|
277
|
+
detail: { package: pkg },
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function stripPrefix(value, prefix) {
|
|
281
|
+
return value.startsWith(prefix) ? value.slice(prefix.length) : value;
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=graph-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-builder.js","sourceRoot":"","sources":["../../../src/internal/extractor/graph-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
export type Lane = "trusted" | "inferred";
|
|
12
|
+
export type Source = "inspect.trusted" | "inspect.inferred";
|
|
13
|
+
export type GraphLanguage = "typescript" | "javascript" | "python" | "go";
|
|
14
|
+
export type AnalysisMode = "local" | "cloud";
|
|
15
|
+
export type EvidenceKind = "import" | "http_route" | "config" | "manifest" | "decorator" | "annotation";
|
|
16
|
+
export type NodeType = "service" | "endpoint" | "external_dependency";
|
|
17
|
+
export type EdgeType = "exposes" | "depends_on";
|
|
18
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" | "WS" | "SSE" | "RPC";
|
|
19
|
+
export type DependencyRegistry = "npm" | "pypi" | "go";
|
|
20
|
+
export interface EvidenceSpan {
|
|
21
|
+
file: string;
|
|
22
|
+
start_line?: number;
|
|
23
|
+
end_line?: number;
|
|
24
|
+
kind: EvidenceKind;
|
|
25
|
+
detail?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export interface ServiceAttributes {
|
|
28
|
+
framework?: string;
|
|
29
|
+
source_files?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface EndpointAttributes {
|
|
32
|
+
method: HttpMethod;
|
|
33
|
+
path: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ExternalDependencyAttributes {
|
|
36
|
+
package: string;
|
|
37
|
+
version?: string;
|
|
38
|
+
registry: DependencyRegistry;
|
|
39
|
+
kind?: string;
|
|
40
|
+
}
|
|
41
|
+
export type NodeAttributes = ServiceAttributes | EndpointAttributes | ExternalDependencyAttributes;
|
|
42
|
+
interface BaseNode {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
lane: Lane;
|
|
46
|
+
source: Source;
|
|
47
|
+
confidence?: number;
|
|
48
|
+
language?: GraphLanguage;
|
|
49
|
+
evidence: EvidenceSpan[];
|
|
50
|
+
}
|
|
51
|
+
export interface ServiceNode extends BaseNode {
|
|
52
|
+
type: "service";
|
|
53
|
+
attributes?: ServiceAttributes;
|
|
54
|
+
}
|
|
55
|
+
export interface EndpointNode extends BaseNode {
|
|
56
|
+
type: "endpoint";
|
|
57
|
+
attributes: EndpointAttributes;
|
|
58
|
+
}
|
|
59
|
+
export interface ExternalDependencyNode extends BaseNode {
|
|
60
|
+
type: "external_dependency";
|
|
61
|
+
attributes: ExternalDependencyAttributes;
|
|
62
|
+
}
|
|
63
|
+
export type GraphNode = ServiceNode | EndpointNode | ExternalDependencyNode;
|
|
64
|
+
export interface GraphEdge {
|
|
65
|
+
id: string;
|
|
66
|
+
type: EdgeType;
|
|
67
|
+
source_id: string;
|
|
68
|
+
target_id: string;
|
|
69
|
+
lane: Lane;
|
|
70
|
+
source: Source;
|
|
71
|
+
confidence?: number;
|
|
72
|
+
evidence?: EvidenceSpan[];
|
|
73
|
+
attributes?: Record<string, unknown>;
|
|
74
|
+
}
|
|
75
|
+
export interface GraphProvenance {
|
|
76
|
+
root_dir: string;
|
|
77
|
+
repo_id?: string;
|
|
78
|
+
commit_sha?: string;
|
|
79
|
+
branch?: string;
|
|
80
|
+
application_id?: string;
|
|
81
|
+
analysis_mode: AnalysisMode;
|
|
82
|
+
}
|
|
83
|
+
export interface GraphScope {
|
|
84
|
+
files_scanned: number;
|
|
85
|
+
files_skipped: number;
|
|
86
|
+
duration_ms: number;
|
|
87
|
+
languages?: GraphLanguage[];
|
|
88
|
+
}
|
|
89
|
+
export interface RepoGraphArtifactV1 {
|
|
90
|
+
version: "1.0.0";
|
|
91
|
+
kind: "repo_graph_artifact";
|
|
92
|
+
extracted_at: string;
|
|
93
|
+
extractor: string;
|
|
94
|
+
provenance: GraphProvenance;
|
|
95
|
+
scope: GraphScope;
|
|
96
|
+
nodes: GraphNode[];
|
|
97
|
+
edges: GraphEdge[];
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=graph-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-types.js","sourceRoot":"","sources":["../../../src/internal/extractor/graph-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
import type { ZivisConfig } from "@zivis/mcp/types";
|
|
13
|
+
export interface BuildLinkagePromptOpts {
|
|
14
|
+
config: ZivisConfig;
|
|
15
|
+
/** Optional. When provided we also check whether THIS app has linked repos. */
|
|
16
|
+
applicationId?: string;
|
|
17
|
+
/** Format hint: "short" omits the explanatory why-line. Default "full". */
|
|
18
|
+
style?: "short" | "full";
|
|
19
|
+
}
|
|
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
|
+
export declare function buildLinkagePrompt(opts: BuildLinkagePromptOpts): Promise<string | null>;
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
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
|
+
export async function buildLinkagePrompt(opts) {
|
|
20
|
+
const creds = await resolveAuth(opts.config);
|
|
21
|
+
if (creds.method === "none")
|
|
22
|
+
return null;
|
|
23
|
+
const appStatus = await fetchGitHubAppStatus(opts.config, creds);
|
|
24
|
+
if (!appStatus)
|
|
25
|
+
return null;
|
|
26
|
+
// Case 1: GitHub App not installed at all → install URL.
|
|
27
|
+
if (!appStatus.installed) {
|
|
28
|
+
if (!appStatus.installUrl)
|
|
29
|
+
return null; // env not configured; don't show a broken link
|
|
30
|
+
return formatInstallPrompt(appStatus.installUrl, opts.style ?? "full");
|
|
31
|
+
}
|
|
32
|
+
// Case 2: App installed but caller has a specific applicationId and
|
|
33
|
+
// that app has no linked repo → web link-repo prompt.
|
|
34
|
+
if (opts.applicationId) {
|
|
35
|
+
const repoStatus = await fetchAppRepoStatus(opts.config, creds, opts.applicationId);
|
|
36
|
+
if (repoStatus && !repoStatus.linked) {
|
|
37
|
+
return formatLinkRepoPrompt(opts.config, opts.applicationId, opts.style ?? "full");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Case 3: All good (or no applicationId to check at app-level).
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// ── HTTP helpers ──
|
|
44
|
+
async function fetchGitHubAppStatus(config, creds) {
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${config.apiBaseUrl}/api/github-app/status`, {
|
|
47
|
+
headers: authHeaders(creds),
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
return null;
|
|
51
|
+
return (await res.json());
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function fetchAppRepoStatus(config, creds, applicationId) {
|
|
58
|
+
try {
|
|
59
|
+
const res = await fetch(`${config.apiBaseUrl}/api/applications/${encodeURIComponent(applicationId)}/repos/status`, { headers: authHeaders(creds) });
|
|
60
|
+
if (!res.ok)
|
|
61
|
+
return null;
|
|
62
|
+
return (await res.json());
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function authHeaders(creds) {
|
|
69
|
+
const base = {
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
"User-Agent": "@zivis/cli",
|
|
72
|
+
};
|
|
73
|
+
if (creds.method === "oauth" && creds.accessToken) {
|
|
74
|
+
base.Authorization = `Bearer ${creds.accessToken}`;
|
|
75
|
+
}
|
|
76
|
+
else if (creds.method === "apikey" && creds.apiKey) {
|
|
77
|
+
base["X-API-Key"] = creds.apiKey;
|
|
78
|
+
}
|
|
79
|
+
return base;
|
|
80
|
+
}
|
|
81
|
+
// ── Formatters ──
|
|
82
|
+
function formatInstallPrompt(installUrl, style) {
|
|
83
|
+
if (style === "short") {
|
|
84
|
+
return `Next: install the ZIVIS GitHub App — ${installUrl}`;
|
|
85
|
+
}
|
|
86
|
+
return [
|
|
87
|
+
"",
|
|
88
|
+
"Next: install the ZIVIS GitHub App",
|
|
89
|
+
` ${installUrl}`,
|
|
90
|
+
" Enables continuous monitoring + automatic threat-model updates on push.",
|
|
91
|
+
].join("\n");
|
|
92
|
+
}
|
|
93
|
+
function formatLinkRepoPrompt(config, applicationId, style) {
|
|
94
|
+
const appBase = process.env.ZIVIS_APP_URL || guessAppUrlFromApi(config.apiBaseUrl);
|
|
95
|
+
const url = `${appBase}/applications/${applicationId}`;
|
|
96
|
+
if (style === "short") {
|
|
97
|
+
return `Next: link a GitHub repo to this application — ${url}`;
|
|
98
|
+
}
|
|
99
|
+
return [
|
|
100
|
+
"",
|
|
101
|
+
"Next: link a GitHub repo to this application",
|
|
102
|
+
` ${url}`,
|
|
103
|
+
" The GitHub App is installed but this app has no linked repo yet.",
|
|
104
|
+
].join("\n");
|
|
105
|
+
}
|
|
106
|
+
function guessAppUrlFromApi(apiBaseUrl) {
|
|
107
|
+
// Standard mapping: api.* ⇄ app.* on the same root domain.
|
|
108
|
+
try {
|
|
109
|
+
const u = new URL(apiBaseUrl);
|
|
110
|
+
if (u.host.startsWith("api.")) {
|
|
111
|
+
u.host = "app." + u.host.slice(4);
|
|
112
|
+
return `${u.protocol}//${u.host}`;
|
|
113
|
+
}
|
|
114
|
+
// localhost / non-standard hosts → fall back to the api URL itself.
|
|
115
|
+
return apiBaseUrl;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return "https://app.zivis.ai";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=github-linkage-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-linkage-prompt.js","sourceRoot":"","sources":["../../src/internal/github-linkage-prompt.ts"],"names":[],"mappings":"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"}
|