@telora/daemon 0.15.36 → 0.15.40
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/build-info.json +2 -2
- package/dist/assembly-resolvers.d.ts +1 -1
- package/dist/assembly-resolvers.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/delivery-lifecycle.d.ts +3 -0
- package/dist/delivery-lifecycle.d.ts.map +1 -1
- package/dist/delivery-lifecycle.js +13 -1
- package/dist/delivery-lifecycle.js.map +1 -1
- package/dist/drift-eval-loop.d.ts +63 -0
- package/dist/drift-eval-loop.d.ts.map +1 -0
- package/dist/drift-eval-loop.js +215 -0
- package/dist/drift-eval-loop.js.map +1 -0
- package/dist/drift-evaluator.d.ts +51 -0
- package/dist/drift-evaluator.d.ts.map +1 -0
- package/dist/drift-evaluator.js +62 -0
- package/dist/drift-evaluator.js.map +1 -0
- package/dist/feeds/ghsa.d.ts +88 -0
- package/dist/feeds/ghsa.d.ts.map +1 -0
- package/dist/feeds/ghsa.js +219 -0
- package/dist/feeds/ghsa.js.map +1 -0
- package/dist/feeds/local.d.ts +55 -0
- package/dist/feeds/local.d.ts.map +1 -0
- package/dist/feeds/local.js +196 -0
- package/dist/feeds/local.js.map +1 -0
- package/dist/feeds/osv.d.ts +89 -0
- package/dist/feeds/osv.d.ts.map +1 -0
- package/dist/feeds/osv.js +266 -0
- package/dist/feeds/osv.js.map +1 -0
- package/dist/focus-completion-event.d.ts +2 -0
- package/dist/focus-completion-event.d.ts.map +1 -1
- package/dist/focus-completion-event.js +51 -13
- package/dist/focus-completion-event.js.map +1 -1
- package/dist/focus-completion.d.ts +1 -1
- package/dist/focus-completion.js +7 -7
- package/dist/focus-completion.js.map +1 -1
- package/dist/focus-engine.d.ts.map +1 -1
- package/dist/focus-engine.js +71 -0
- package/dist/focus-engine.js.map +1 -1
- package/dist/focus-executor.d.ts +53 -0
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +41 -26
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-loop.d.ts +1 -1
- package/dist/focus-loop.js +2 -2
- package/dist/focus-loop.js.map +1 -1
- package/dist/focus-phase.js +1 -1
- package/dist/focus-phase.js.map +1 -1
- package/dist/focus-prompt-builder.d.ts +1 -1
- package/dist/focus-prompt-builder.js +1 -1
- package/dist/listener-auto-advance.d.ts +3 -3
- package/dist/listener-auto-advance.js +10 -10
- package/dist/listener-auto-advance.js.map +1 -1
- package/dist/listener.js +1 -1
- package/dist/listener.js.map +1 -1
- package/dist/queries/deliveries.d.ts +20 -1
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +8 -1
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/drift.d.ts +50 -0
- package/dist/queries/drift.d.ts.map +1 -0
- package/dist/queries/drift.js +28 -0
- package/dist/queries/drift.js.map +1 -0
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +1 -0
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/index.d.ts +2 -0
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +1 -0
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/schemas.d.ts +2 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +1 -0
- package/dist/queries/schemas.js.map +1 -1
- package/dist/scanners/deps.d.ts +101 -0
- package/dist/scanners/deps.d.ts.map +1 -0
- package/dist/scanners/deps.js +242 -0
- package/dist/scanners/deps.js.map +1 -0
- package/dist/scanners/signatures.d.ts +44 -0
- package/dist/scanners/signatures.d.ts.map +1 -0
- package/dist/scanners/signatures.js +140 -0
- package/dist/scanners/signatures.js.map +1 -0
- package/dist/scanners/workflow.d.ts +34 -0
- package/dist/scanners/workflow.d.ts.map +1 -0
- package/dist/scanners/workflow.js +239 -0
- package/dist/scanners/workflow.js.map +1 -0
- package/dist/security-auto-inject.d.ts +114 -0
- package/dist/security-auto-inject.d.ts.map +1 -0
- package/dist/security-auto-inject.js +148 -0
- package/dist/security-auto-inject.js.map +1 -0
- package/dist/security-rescan-resolution.d.ts +84 -0
- package/dist/security-rescan-resolution.d.ts.map +1 -0
- package/dist/security-rescan-resolution.js +114 -0
- package/dist/security-rescan-resolution.js.map +1 -0
- package/dist/security-scan-engine.d.ts +96 -0
- package/dist/security-scan-engine.d.ts.map +1 -0
- package/dist/security-scan-engine.js +189 -0
- package/dist/security-scan-engine.js.map +1 -0
- package/dist/stage-classifier.d.ts +2 -2
- package/dist/stage-classifier.d.ts.map +1 -1
- package/dist/stage-classifier.js +7 -7
- package/dist/stage-classifier.js.map +1 -1
- package/dist/state-cascade.d.ts +1 -1
- package/dist/state-cascade.js +1 -1
- package/dist/team-prompt-base.d.ts.map +1 -1
- package/dist/team-prompt-base.js +15 -0
- package/dist/team-prompt-base.js.map +1 -1
- package/dist/types/focus.d.ts +6 -0
- package/dist/types/focus.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OSV advisory feed adapter.
|
|
3
|
+
*
|
|
4
|
+
* Cross-references installed dependencies against OSV.dev (Open Source
|
|
5
|
+
* Vulnerabilities) and returns enriched advisory metadata. Used by the
|
|
6
|
+
* deps scanner to enrich raw npm-audit output with full advisory bodies
|
|
7
|
+
* (summary, references, severity vectors, affected ranges).
|
|
8
|
+
*
|
|
9
|
+
* Resilience contract: any network or parsing failure is captured as a
|
|
10
|
+
* string in `warnings`. The function ALWAYS resolves; it never throws.
|
|
11
|
+
* OSV downtime degrades the scanner to "raw npm-audit only", not failure.
|
|
12
|
+
*
|
|
13
|
+
* Two-stage protocol:
|
|
14
|
+
* 1. POST /v1/querybatch -- one round-trip lists matching advisory ids
|
|
15
|
+
* per query (package@version pair).
|
|
16
|
+
* 2. GET /v1/vulns/{id} -- per-advisory body fetch; ids are deduped
|
|
17
|
+
* across the batch before the fan-out.
|
|
18
|
+
*
|
|
19
|
+
* TTL caches:
|
|
20
|
+
* - Querybatch results are cached per ${name}@${version}@${ecosystem}
|
|
21
|
+
* for 15 minutes -- the typical scan cadence.
|
|
22
|
+
* - Advisory bodies are cached per id separately so a freshly-seen
|
|
23
|
+
* package that maps to an already-known advisory skips the body GET.
|
|
24
|
+
*
|
|
25
|
+
* @module feeds/osv
|
|
26
|
+
*/
|
|
27
|
+
export interface OsvAdvisory {
|
|
28
|
+
id: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
details?: string;
|
|
31
|
+
aliases: string[];
|
|
32
|
+
severity?: Array<{
|
|
33
|
+
type: string;
|
|
34
|
+
score: string;
|
|
35
|
+
}>;
|
|
36
|
+
affected: Array<{
|
|
37
|
+
package: {
|
|
38
|
+
name: string;
|
|
39
|
+
ecosystem: string;
|
|
40
|
+
};
|
|
41
|
+
versions?: string[];
|
|
42
|
+
ranges?: unknown[];
|
|
43
|
+
}>;
|
|
44
|
+
references?: Array<{
|
|
45
|
+
type: string;
|
|
46
|
+
url: string;
|
|
47
|
+
}>;
|
|
48
|
+
modified: string;
|
|
49
|
+
published: string;
|
|
50
|
+
}
|
|
51
|
+
export interface OsvQueryResult {
|
|
52
|
+
advisories: OsvAdvisory[];
|
|
53
|
+
warnings: string[];
|
|
54
|
+
}
|
|
55
|
+
export interface OsvQueryInput {
|
|
56
|
+
packages: Array<{
|
|
57
|
+
name: string;
|
|
58
|
+
version: string;
|
|
59
|
+
ecosystem: 'npm' | 'PyPI' | 'Go' | 'crates.io';
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
export type FetchFn = (input: string, init?: {
|
|
63
|
+
method?: string;
|
|
64
|
+
headers?: Record<string, string>;
|
|
65
|
+
body?: string;
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
}) => Promise<{
|
|
68
|
+
ok: boolean;
|
|
69
|
+
status: number;
|
|
70
|
+
statusText: string;
|
|
71
|
+
json: () => Promise<unknown>;
|
|
72
|
+
}>;
|
|
73
|
+
export interface OsvClient {
|
|
74
|
+
queryOsv(input: OsvQueryInput): Promise<OsvQueryResult>;
|
|
75
|
+
}
|
|
76
|
+
export interface OsvClientOptions {
|
|
77
|
+
fetchFn?: FetchFn;
|
|
78
|
+
/** Override the wall clock (testing). */
|
|
79
|
+
now?: () => number;
|
|
80
|
+
/** Override the per-request timeout. */
|
|
81
|
+
timeoutMs?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build an OSV client with an injectable fetch. The default `queryOsv`
|
|
85
|
+
* export uses `globalThis.fetch`.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createOsvClient(opts?: OsvClientOptions): OsvClient;
|
|
88
|
+
export declare function queryOsv(input: OsvQueryInput): Promise<OsvQueryResult>;
|
|
89
|
+
//# sourceMappingURL=osv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osv.d.ts","sourceRoot":"","sources":["../../src/feeds/osv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAYH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,QAAQ,EAAE,KAAK,CAAC;QACd,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;KACpB,CAAC,CAAC;IACH,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,WAAW,CAAC;KAChD,CAAC,CAAC;CACJ;AAQD,MAAM,MAAM,OAAO,GAAG,CACpB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,KAC9F,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAAC;AAuJhG,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,SAAS,CAsGtE;AAQD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAE5E"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OSV advisory feed adapter.
|
|
3
|
+
*
|
|
4
|
+
* Cross-references installed dependencies against OSV.dev (Open Source
|
|
5
|
+
* Vulnerabilities) and returns enriched advisory metadata. Used by the
|
|
6
|
+
* deps scanner to enrich raw npm-audit output with full advisory bodies
|
|
7
|
+
* (summary, references, severity vectors, affected ranges).
|
|
8
|
+
*
|
|
9
|
+
* Resilience contract: any network or parsing failure is captured as a
|
|
10
|
+
* string in `warnings`. The function ALWAYS resolves; it never throws.
|
|
11
|
+
* OSV downtime degrades the scanner to "raw npm-audit only", not failure.
|
|
12
|
+
*
|
|
13
|
+
* Two-stage protocol:
|
|
14
|
+
* 1. POST /v1/querybatch -- one round-trip lists matching advisory ids
|
|
15
|
+
* per query (package@version pair).
|
|
16
|
+
* 2. GET /v1/vulns/{id} -- per-advisory body fetch; ids are deduped
|
|
17
|
+
* across the batch before the fan-out.
|
|
18
|
+
*
|
|
19
|
+
* TTL caches:
|
|
20
|
+
* - Querybatch results are cached per ${name}@${version}@${ecosystem}
|
|
21
|
+
* for 15 minutes -- the typical scan cadence.
|
|
22
|
+
* - Advisory bodies are cached per id separately so a freshly-seen
|
|
23
|
+
* package that maps to an already-known advisory skips the body GET.
|
|
24
|
+
*
|
|
25
|
+
* @module feeds/osv
|
|
26
|
+
*/
|
|
27
|
+
const OSV_BASE_URL = 'https://api.osv.dev';
|
|
28
|
+
const QUERY_BATCH_PATH = '/v1/querybatch';
|
|
29
|
+
const VULNS_PATH = '/v1/vulns';
|
|
30
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
31
|
+
const CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Internal helpers
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
function isRecord(value) {
|
|
36
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
37
|
+
}
|
|
38
|
+
function cacheKey(name, version, ecosystem) {
|
|
39
|
+
return `${name}@${version}@${ecosystem}`;
|
|
40
|
+
}
|
|
41
|
+
class TtlCache {
|
|
42
|
+
ttlMs;
|
|
43
|
+
now;
|
|
44
|
+
store = new Map();
|
|
45
|
+
constructor(ttlMs, now = () => Date.now()) {
|
|
46
|
+
this.ttlMs = ttlMs;
|
|
47
|
+
this.now = now;
|
|
48
|
+
}
|
|
49
|
+
get(key) {
|
|
50
|
+
const entry = this.store.get(key);
|
|
51
|
+
if (!entry)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (entry.expiresAt <= this.now()) {
|
|
54
|
+
this.store.delete(key);
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return entry.value;
|
|
58
|
+
}
|
|
59
|
+
set(key, value) {
|
|
60
|
+
this.store.set(key, { value, expiresAt: this.now() + this.ttlMs });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Wrap fetch with an AbortSignal-based timeout. Resolves to the response
|
|
65
|
+
* on success; throws on timeout, network error, or non-2xx status.
|
|
66
|
+
*/
|
|
67
|
+
async function fetchWithTimeout(fetchFn, url, init, timeoutMs) {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
70
|
+
try {
|
|
71
|
+
const res = await fetchFn(url, { ...init, signal: controller.signal });
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
74
|
+
}
|
|
75
|
+
return await res.json();
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
clearTimeout(timer);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Response parsing -- shallow, defensive narrowing on the unknown payload.
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/** Extract advisory ids from one querybatch result entry. */
|
|
85
|
+
function parseQuerybatchEntry(entry) {
|
|
86
|
+
if (!isRecord(entry))
|
|
87
|
+
return [];
|
|
88
|
+
const vulns = entry.vulns;
|
|
89
|
+
if (!Array.isArray(vulns))
|
|
90
|
+
return [];
|
|
91
|
+
const ids = [];
|
|
92
|
+
for (const v of vulns) {
|
|
93
|
+
if (isRecord(v) && typeof v.id === 'string' && v.id.length > 0) {
|
|
94
|
+
ids.push(v.id);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return ids;
|
|
98
|
+
}
|
|
99
|
+
/** Parse a single OSV advisory body. */
|
|
100
|
+
function parseAdvisory(payload) {
|
|
101
|
+
if (!isRecord(payload))
|
|
102
|
+
return null;
|
|
103
|
+
if (typeof payload.id !== 'string')
|
|
104
|
+
return null;
|
|
105
|
+
const aliases = [];
|
|
106
|
+
if (Array.isArray(payload.aliases)) {
|
|
107
|
+
for (const a of payload.aliases) {
|
|
108
|
+
if (typeof a === 'string')
|
|
109
|
+
aliases.push(a);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const affected = [];
|
|
113
|
+
if (Array.isArray(payload.affected)) {
|
|
114
|
+
for (const a of payload.affected) {
|
|
115
|
+
if (!isRecord(a))
|
|
116
|
+
continue;
|
|
117
|
+
const pkg = a.package;
|
|
118
|
+
if (!isRecord(pkg) || typeof pkg.name !== 'string' || typeof pkg.ecosystem !== 'string') {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const entry = {
|
|
122
|
+
package: { name: pkg.name, ecosystem: pkg.ecosystem },
|
|
123
|
+
};
|
|
124
|
+
if (Array.isArray(a.versions)) {
|
|
125
|
+
entry.versions = a.versions.filter((v) => typeof v === 'string');
|
|
126
|
+
}
|
|
127
|
+
if (Array.isArray(a.ranges)) {
|
|
128
|
+
entry.ranges = a.ranges;
|
|
129
|
+
}
|
|
130
|
+
affected.push(entry);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
let severity;
|
|
134
|
+
if (Array.isArray(payload.severity)) {
|
|
135
|
+
const out = [];
|
|
136
|
+
for (const s of payload.severity) {
|
|
137
|
+
if (isRecord(s) && typeof s.type === 'string' && typeof s.score === 'string') {
|
|
138
|
+
out.push({ type: s.type, score: s.score });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (out.length > 0)
|
|
142
|
+
severity = out;
|
|
143
|
+
}
|
|
144
|
+
let references;
|
|
145
|
+
if (Array.isArray(payload.references)) {
|
|
146
|
+
const out = [];
|
|
147
|
+
for (const r of payload.references) {
|
|
148
|
+
if (isRecord(r) && typeof r.type === 'string' && typeof r.url === 'string') {
|
|
149
|
+
out.push({ type: r.type, url: r.url });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (out.length > 0)
|
|
153
|
+
references = out;
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
id: payload.id,
|
|
157
|
+
summary: typeof payload.summary === 'string' ? payload.summary : '',
|
|
158
|
+
details: typeof payload.details === 'string' ? payload.details : undefined,
|
|
159
|
+
aliases,
|
|
160
|
+
severity,
|
|
161
|
+
affected,
|
|
162
|
+
references,
|
|
163
|
+
modified: typeof payload.modified === 'string' ? payload.modified : '',
|
|
164
|
+
published: typeof payload.published === 'string' ? payload.published : '',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build an OSV client with an injectable fetch. The default `queryOsv`
|
|
169
|
+
* export uses `globalThis.fetch`.
|
|
170
|
+
*/
|
|
171
|
+
export function createOsvClient(opts = {}) {
|
|
172
|
+
const fetchFn = opts.fetchFn ?? globalThis.fetch;
|
|
173
|
+
const now = opts.now ?? (() => Date.now());
|
|
174
|
+
const timeoutMs = opts.timeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
175
|
+
// Two caches:
|
|
176
|
+
// - querybatchCache: package@version@ecosystem -> advisory id list
|
|
177
|
+
// - advisoryCache: id -> OsvAdvisory body
|
|
178
|
+
const querybatchCache = new TtlCache(CACHE_TTL_MS, now);
|
|
179
|
+
const advisoryCache = new TtlCache(CACHE_TTL_MS, now);
|
|
180
|
+
async function queryOsv(input) {
|
|
181
|
+
const warnings = [];
|
|
182
|
+
if (input.packages.length === 0) {
|
|
183
|
+
return { advisories: [], warnings };
|
|
184
|
+
}
|
|
185
|
+
// Stage 1: determine advisory ids per package, using the cache where
|
|
186
|
+
// possible. Build the uncached subset for the batch POST.
|
|
187
|
+
const idsByIndex = new Array(input.packages.length);
|
|
188
|
+
const uncached = [];
|
|
189
|
+
input.packages.forEach((p, i) => {
|
|
190
|
+
const cached = querybatchCache.get(cacheKey(p.name, p.version, p.ecosystem));
|
|
191
|
+
if (cached !== undefined) {
|
|
192
|
+
idsByIndex[i] = cached;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
uncached.push({ index: i, name: p.name, ecosystem: p.ecosystem, version: p.version });
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
if (uncached.length > 0) {
|
|
199
|
+
const body = JSON.stringify({
|
|
200
|
+
queries: uncached.map((q) => ({
|
|
201
|
+
package: { name: q.name, ecosystem: q.ecosystem },
|
|
202
|
+
version: q.version,
|
|
203
|
+
})),
|
|
204
|
+
});
|
|
205
|
+
try {
|
|
206
|
+
const payload = await fetchWithTimeout(fetchFn, `${OSV_BASE_URL}${QUERY_BATCH_PATH}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body }, timeoutMs);
|
|
207
|
+
if (!isRecord(payload) || !Array.isArray(payload.results)) {
|
|
208
|
+
warnings.push('OSV querybatch returned unexpected response shape');
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
// Results align positionally with the queries we sent.
|
|
212
|
+
const results = payload.results;
|
|
213
|
+
uncached.forEach((q, batchIdx) => {
|
|
214
|
+
const ids = parseQuerybatchEntry(results[batchIdx]);
|
|
215
|
+
idsByIndex[q.index] = ids;
|
|
216
|
+
querybatchCache.set(cacheKey(q.name, q.version, q.ecosystem), ids);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
warnings.push(`OSV querybatch failed: ${err.message}`);
|
|
222
|
+
// Leave uncached entries as undefined -- they contribute no ids
|
|
223
|
+
// but the function still returns whatever cached hits we have.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Stage 2: dedupe ids across all queries and fetch each advisory body.
|
|
227
|
+
const uniqueIds = new Set();
|
|
228
|
+
for (const ids of idsByIndex) {
|
|
229
|
+
if (!ids)
|
|
230
|
+
continue;
|
|
231
|
+
for (const id of ids)
|
|
232
|
+
uniqueIds.add(id);
|
|
233
|
+
}
|
|
234
|
+
const advisories = [];
|
|
235
|
+
for (const id of uniqueIds) {
|
|
236
|
+
const cachedAdvisory = advisoryCache.get(id);
|
|
237
|
+
if (cachedAdvisory) {
|
|
238
|
+
advisories.push(cachedAdvisory);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const payload = await fetchWithTimeout(fetchFn, `${OSV_BASE_URL}${VULNS_PATH}/${encodeURIComponent(id)}`, { method: 'GET' }, timeoutMs);
|
|
243
|
+
const advisory = parseAdvisory(payload);
|
|
244
|
+
if (!advisory) {
|
|
245
|
+
warnings.push(`OSV advisory ${id} returned unexpected response shape`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
advisoryCache.set(id, advisory);
|
|
249
|
+
advisories.push(advisory);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
warnings.push(`OSV advisory ${id} lookup failed: ${err.message}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return { advisories, warnings };
|
|
256
|
+
}
|
|
257
|
+
return { queryOsv };
|
|
258
|
+
}
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
// Default singleton -- uses global fetch.
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
const defaultClient = createOsvClient();
|
|
263
|
+
export async function queryOsv(input) {
|
|
264
|
+
return defaultClient.queryOsv(input);
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=osv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osv.js","sourceRoot":"","sources":["../../src/feeds/osv.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-completion-event.d.ts","sourceRoot":"","sources":["../src/focus-completion-event.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEtG,OAAO,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAQnF,yEAAyE;AACzE,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAE/E,gFAAgF;AAChF,eAAO,MAAM,6BAA6B,yDACc,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,EAAE,MAK3C,CAAC;AAIL,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,cAAc,CAAC;IAC1B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACtE,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/D,gBAAgB,EAAE,CAAC,MAAM,EAAE;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"focus-completion-event.d.ts","sourceRoot":"","sources":["../src/focus-completion-event.ts"],"names":[],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ export async function handleCompletionEvent(ctx, deps = defaultDeps) {
|
|
|
113
113
|
// Scope-coverage guard: only terminate when EVERY delivery is in a
|
|
114
114
|
// terminal-for-the-team state (verify, in_review, done, cancelled). The
|
|
115
115
|
// existing isStatusCascadable() classifier matches that set; non-terminal
|
|
116
|
-
// states (planning, queued,
|
|
116
|
+
// states (planning, queued, awaiting_verify, coding, paused) block termination
|
|
117
117
|
// so the team is re-engaged on remaining work instead of idle-quitting
|
|
118
118
|
// while unfinished deliveries are still in flight.
|
|
119
119
|
const nonTerminal = currentDeliveries.filter(d => !isStatusCascadable(d.executionStatus ?? ''));
|
|
@@ -161,7 +161,7 @@ export async function handleCompletionEvent(ctx, deps = defaultDeps) {
|
|
|
161
161
|
// If actionable deliveries with open issues remain, the existing wake
|
|
162
162
|
// message handles them. Otherwise the team needs a re-engagement nudge
|
|
163
163
|
// for non-actionable but still non-terminal deliveries (planning,
|
|
164
|
-
//
|
|
164
|
+
// awaiting_verify).
|
|
165
165
|
const actionableDeliveryIds = new Set(currentDeliveries
|
|
166
166
|
.filter(d => isStatusAgentActionable(d.executionStatus ?? ''))
|
|
167
167
|
.map(d => d.id));
|
|
@@ -228,26 +228,64 @@ export async function escalateNoProgress(params, deps = defaultDeps) {
|
|
|
228
228
|
.sort((a, b) => a.priorityRank - b.priorityRank)
|
|
229
229
|
.map(d => `- "${d.name}" [${d.executionStatus ?? 'draft'}] (rank ${d.priorityRank})`)
|
|
230
230
|
.join('\n');
|
|
231
|
+
// Cause classification: if every remaining non-terminal delivery is
|
|
232
|
+
// sitting on a populated gate_state, the team didn't fail -- the daemon's
|
|
233
|
+
// gate refused to advance them. Route as daemon_gate_stuck so substantive
|
|
234
|
+
// team-failure signals don't drown in daemon-gap noise. Otherwise fall
|
|
235
|
+
// back to the explicit team_failure kind.
|
|
236
|
+
const gateStuckDeliveries = params.remaining.filter(d => d.gateState != null);
|
|
237
|
+
const allDaemonGateStuck = params.remaining.length > 0 && gateStuckDeliveries.length === params.remaining.length;
|
|
238
|
+
const escalationKind = allDaemonGateStuck ? 'daemon_gate_stuck' : 'team_failure';
|
|
239
|
+
const metadata = {
|
|
240
|
+
focusId: params.focusId,
|
|
241
|
+
focusName: params.focusName,
|
|
242
|
+
cycles: params.cycles,
|
|
243
|
+
cause: escalationKind,
|
|
244
|
+
};
|
|
245
|
+
if (allDaemonGateStuck) {
|
|
246
|
+
metadata.gateStates = gateStuckDeliveries.map(d => ({
|
|
247
|
+
deliveryId: d.id,
|
|
248
|
+
deliveryName: d.name,
|
|
249
|
+
executionStatus: d.executionStatus,
|
|
250
|
+
gateState: d.gateState,
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
const description = allDaemonGateStuck
|
|
254
|
+
? `Team for focus "${params.focusName}" terminated because the daemon's verify gate ` +
|
|
255
|
+
`has not advanced any of the ${params.remaining.length} remaining delivery(ies) ` +
|
|
256
|
+
`across ${params.cycles} re-engagement cycles. This is a daemon-side gap, not a team failure.\n\n` +
|
|
257
|
+
`**Focus:** ${params.focusName}\n` +
|
|
258
|
+
`**Focus ID:** ${params.focusId}\n` +
|
|
259
|
+
`**Agent role:** ${params.agentRoleId}\n` +
|
|
260
|
+
`**Remaining (all gate-stuck):**\n${remainingList}\n\n` +
|
|
261
|
+
`Inspect each delivery's gate_state to determine the specific blocking condition. ` +
|
|
262
|
+
`See docs/runbook-verify-gate.md.`
|
|
263
|
+
: `Team for focus "${params.focusName}" has been re-engaged ${params.cycles} ` +
|
|
264
|
+
`consecutive cycles without measurable progress. Reason: ${NO_PROGRESS_ESCALATION_REASON}.\n\n` +
|
|
265
|
+
`**Focus:** ${params.focusName}\n` +
|
|
266
|
+
`**Focus ID:** ${params.focusId}\n` +
|
|
267
|
+
`**Agent role:** ${params.agentRoleId}\n` +
|
|
268
|
+
`**Remaining non-terminal deliveries:**\n${remainingList}\n\n` +
|
|
269
|
+
`The team has been terminated. A human must intervene to unblock the focus.`;
|
|
231
270
|
try {
|
|
232
271
|
await withRetry(() => deps.createEscalation({
|
|
233
272
|
organizationId: params.organizationId,
|
|
234
273
|
sessionId: params.sessionId,
|
|
235
274
|
issueId: null,
|
|
236
275
|
reasonType: ESCALATION_REASONS.BLOCKED_BY_EXTERNAL,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
`**Focus ID:** ${params.focusId}\n` +
|
|
241
|
-
`**Agent role:** ${params.agentRoleId}\n` +
|
|
242
|
-
`**Remaining non-terminal deliveries:**\n${remainingList}\n\n` +
|
|
243
|
-
`The team has been terminated. A human must intervene to unblock the focus.`,
|
|
276
|
+
escalationKind,
|
|
277
|
+
metadata,
|
|
278
|
+
description,
|
|
244
279
|
whatWasTried: `Re-engaged the team via the daemon-push channel (${params.cycles} cycles). ` +
|
|
245
280
|
`No delivery status transitions and no new issues were observed between cycles.`,
|
|
246
|
-
helpNeeded:
|
|
247
|
-
`the
|
|
248
|
-
|
|
281
|
+
helpNeeded: allDaemonGateStuck
|
|
282
|
+
? `Inspect the gate_state on each delivery to identify the specific blocking ` +
|
|
283
|
+
`condition. The condition is documented in docs/runbook-verify-gate.md.`
|
|
284
|
+
: `Inspect the remaining deliveries above. Either scope missing issues, cancel ` +
|
|
285
|
+
`the deliveries that should not proceed, or update the focus intent so the ` +
|
|
286
|
+
`next team can complete the work.`,
|
|
249
287
|
}), { maxAttempts: 3, label: `escalation-no-progress-${params.focusId}` });
|
|
250
|
-
console.log(`[focus-executor] Created
|
|
288
|
+
console.log(`[focus-executor] Created ${escalationKind} escalation for "${params.focusName}" ` +
|
|
251
289
|
`(reason: ${NO_PROGRESS_ESCALATION_REASON})`);
|
|
252
290
|
}
|
|
253
291
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-completion-event.js","sourceRoot":"","sources":["../src/focus-completion-event.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,aAAa,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAElF,yEAAyE;AACzE,MAAM,CAAC,MAAM,6BAA6B,GAAG,iCAAiC,CAAC;AAE/E,gFAAgF;AAChF,MAAM,CAAC,MAAM,6BAA6B,GACxC,sDAAsD,CAAC;AAEzD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAW,CAAC,GAAG,EAAE;IAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;IAChE,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"focus-completion-event.js","sourceRoot":"","sources":["../src/focus-completion-event.ts"],"names":[],"mappings":"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"}
|
|
@@ -122,7 +122,7 @@ export interface ReviewExitParams {
|
|
|
122
122
|
* the focus in reviewing phase so it does not silently auto-complete on
|
|
123
123
|
* an absent report.
|
|
124
124
|
* 4. With a report present, route in_review deliveries (open issues ->
|
|
125
|
-
*
|
|
125
|
+
* awaiting_verify, none -> done), clear review_requested_at, emit the
|
|
126
126
|
* review_completed loop trigger.
|
|
127
127
|
*
|
|
128
128
|
* Exported with injectable deps for unit testing.
|
package/dist/focus-completion.js
CHANGED
|
@@ -135,7 +135,7 @@ const defaultReviewExitDeps = {
|
|
|
135
135
|
* the focus in reviewing phase so it does not silently auto-complete on
|
|
136
136
|
* an absent report.
|
|
137
137
|
* 4. With a report present, route in_review deliveries (open issues ->
|
|
138
|
-
*
|
|
138
|
+
* awaiting_verify, none -> done), clear review_requested_at, emit the
|
|
139
139
|
* review_completed loop trigger.
|
|
140
140
|
*
|
|
141
141
|
* Exported with injectable deps for unit testing.
|
|
@@ -212,9 +212,9 @@ export async function runReviewExitHandler(params, deps = defaultReviewExitDeps)
|
|
|
212
212
|
const workIssues = filterWorkIssues(issues);
|
|
213
213
|
const openWork = workIssues.filter(i => ACTIVE_WORK_STATUSES.has(i.status));
|
|
214
214
|
if (openWork.length > 0) {
|
|
215
|
-
const
|
|
216
|
-
await deps.updateDeliveryStatus(d.id, '
|
|
217
|
-
console.log(`[focus-executor] Delivery "${d.name}" moved from in_review to
|
|
215
|
+
const awaitingVerifyStage = dWorkflow.stages.find(s => s.name === 'awaiting_verify');
|
|
216
|
+
await deps.updateDeliveryStatus(d.id, 'awaiting_verify', awaitingVerifyStage?.id ?? null);
|
|
217
|
+
console.log(`[focus-executor] Delivery "${d.name}" moved from in_review to awaiting_verify: ${openWork.length} open issue(s)`);
|
|
218
218
|
}
|
|
219
219
|
else {
|
|
220
220
|
const doneStage = dWorkflow.stages.find(s => s.name === 'done');
|
|
@@ -580,11 +580,11 @@ export async function advanceDeliveryStatuses(config, teamState, sessionId, deps
|
|
|
580
580
|
console.warn(`[focus-executor] Failed to sweep issue ${issueId} to Done:`, err.message);
|
|
581
581
|
}
|
|
582
582
|
}
|
|
583
|
-
// If delivery is queued or
|
|
584
|
-
// (workflow doesn't allow queued/
|
|
583
|
+
// If delivery is queued or awaiting_verify, step through coding first
|
|
584
|
+
// (workflow doesn't allow queued/awaiting_verify -> verify directly).
|
|
585
585
|
// Update the stage ID for the subsequent advance call.
|
|
586
586
|
let effectiveStageId = currentStageId;
|
|
587
|
-
if (delivery.executionStatus === 'queued' || delivery.executionStatus === '
|
|
587
|
+
if (delivery.executionStatus === 'queued' || delivery.executionStatus === 'awaiting_verify') {
|
|
588
588
|
const codingStage = workflow.stages.find(s => s.name === 'coding');
|
|
589
589
|
if (codingStage) {
|
|
590
590
|
console.log(`[focus-executor] Delivery ${delivery.id}: stepping ${delivery.executionStatus} -> coding before verify advance`);
|