@inerrata-corporation/errata 2.0.16 → 2.0.17-dev.3407

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.
@@ -802,6 +802,12 @@ function identityId(input) {
802
802
  }
803
803
  case "Claim":
804
804
  return canonicalClaimId(input.text, input.scope);
805
+ case "WitnessedVulnerability":
806
+ return genericCanonicalId("dvuln", {
807
+ workspaceId: input.workspaceId,
808
+ target: input.target.replace(/\\/g, "/").replace(/^\.\//, ""),
809
+ statement: canonicalClaimId(input.statement.trim())
810
+ });
805
811
  case "DesignProblem":
806
812
  return `${DESIGN_PROBLEM_PREFIX}${canonicalClaimId(input.statement.trim())}`.slice(
807
813
  0,
@@ -15258,7 +15264,7 @@ var init_edge_rules = __esm({
15258
15264
  // anchor anything at anything, e.g. at a public `Package`, quietly re-creating
15259
15265
  // the code↔collective bridge the membrane exists to prevent.
15260
15266
  ANCHORED_AT: {
15261
- from: ["Problem", "Solution", "RootCause", "Claim"],
15267
+ from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim"],
15262
15268
  to: ["Symbol"]
15263
15269
  },
15264
15270
  // ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
@@ -15303,7 +15309,7 @@ var init_edge_rules = __esm({
15303
15309
  // `Component` joined the target set with OM-agent-anchors: an agent-named
15304
15310
  // component ("React Router") is the same knowledge→named-unit anchor shape as
15305
15311
  // a Tool — the knowledge is ABOUT it, not dependent on it.
15306
- CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15312
+ CONCERNS: { from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15307
15313
  OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
15308
15314
  INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
15309
15315
  // ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
@@ -16210,12 +16216,13 @@ function installHistoryCacheFloor(db) {
16210
16216
  }
16211
16217
 
16212
16218
  // ../../packages/local-graph/src/session-evidence.ts
16219
+ var arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
16220
+ var scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
16221
+ var SESSION_EVIDENCE_FIELDS = [...arrays, ...scalars, "citeAnchorHints"];
16213
16222
  function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
16214
16223
  const mapping = new Map(aliases);
16215
16224
  const uuid3 = "[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}";
16216
16225
  const codex = new RegExp(`^codex:(?:rollout-.*?)?(${uuid3})$`, "i");
16217
- const arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
16218
- const scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
16219
16226
  const discover = (value, key = "") => {
16220
16227
  if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
16221
16228
  const match = value.match(codex);
@@ -16313,6 +16320,7 @@ function localEdgeViolation(fromLabel, type, toLabel) {
16313
16320
  return verdict.ok ? null : verdict.reason ?? "edge rule violation";
16314
16321
  }
16315
16322
  var SCHEMA_VERSION = 6;
16323
+ var SESSION_EVIDENCE_PREDICATE = SESSION_EVIDENCE_FIELDS.map((field) => `instr(attrs_json, '${JSON.stringify(field)}') > 0`).join(" OR ");
16316
16324
  var SCHEMA_SQL = `
16317
16325
  CREATE TABLE IF NOT EXISTS schema_version (
16318
16326
  version INTEGER PRIMARY KEY
@@ -16405,12 +16413,17 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
16405
16413
  `;
16406
16414
  var TEMPORAL_INDEX_SQL = `
16407
16415
  CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
16416
+ CREATE INDEX IF NOT EXISTS nodes_live_count ON nodes(valid_to);
16417
+ CREATE INDEX IF NOT EXISTS nodes_live_recent ON nodes(label, last_updated_at DESC) WHERE valid_to IS NULL;
16418
+ CREATE INDEX IF NOT EXISTS nodes_session_evidence ON nodes(id) WHERE ${SESSION_EVIDENCE_PREDICATE};
16419
+ CREATE INDEX IF NOT EXISTS edges_session_evidence ON edges(id) WHERE ${SESSION_EVIDENCE_PREDICATE};
16408
16420
  -- Covering + partial index for labelFingerprint over the instance labels: the
16409
16421
  -- live-push probe runs it per workspace on a timer, and each hit used to read
16410
16422
  -- its table row. Partial, so it maintains a few thousand rows instead of adding
16411
16423
  -- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
16412
16424
  DROP INDEX IF EXISTS nodes_live_fingerprint;
16413
- CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause');
16425
+ DROP INDEX IF EXISTS nodes_instance_fingerprint;
16426
+ CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
16414
16427
  CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
16415
16428
  CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
16416
16429
  -- Expression index on the per-node relPath (stored in attrs_json) so the
@@ -16481,7 +16494,7 @@ function rowToEdge(r) {
16481
16494
  attrs: JSON.parse(r.attrs_json)
16482
16495
  };
16483
16496
  }
16484
- var FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
16497
+ var FINGERPRINT_INDEXED_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
16485
16498
  var SqliteGraphStore = class {
16486
16499
  db;
16487
16500
  // Typed edge lookups build their SQL from the number of types asked for, and
@@ -16773,12 +16786,13 @@ var SqliteGraphStore = class {
16773
16786
  });
16774
16787
  }
16775
16788
  repairSessionAliases(canonical, aliases = []) {
16789
+ if (canonical && aliases.length === 0) return 0;
16776
16790
  const mapping = new Map(aliases.map((alias) => [alias, canonical]));
16777
16791
  let changed = 0;
16778
16792
  for (const table of ["nodes", "edges"]) {
16779
16793
  const predicates = canonical ? aliases.map(() => "instr(attrs_json, ?) > 0") : ["instr(attrs_json, 'codex:') > 0", "instr(attrs_json, 'discriminatorSource') > 0"];
16780
16794
  if (!predicates.length) continue;
16781
- const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE ${predicates.join(" OR ")}`).all(...canonical ? aliases : []);
16795
+ const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE (${SESSION_EVIDENCE_PREDICATE}) AND (${predicates.join(" OR ")})`).all(...canonical ? aliases.map((alias) => JSON.stringify(alias)) : []);
16782
16796
  const update = this.db.prepare(`UPDATE ${table} SET attrs_json = ?${table === "edges" ? ", type = CASE WHEN type = 'CONFIRMS' AND json_extract(?, '$.provisional') = 1 THEN 'INDICATES' ELSE type END" : ""} WHERE id = ?`);
16783
16797
  for (const row of rows) {
16784
16798
  const attrs = JSON.stringify(repairSessionEvidence(JSON.parse(row.attrs_json), mapping));
@@ -17004,6 +17018,25 @@ var SqliteGraphStore = class {
17004
17018
  const rows = this.db.prepare("SELECT id FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY last_updated_at DESC LIMIT ?").all(label, Math.max(0, limit));
17005
17019
  return rows.map((r) => r.id);
17006
17020
  }
17021
+ recentOpenProblemCandidates(opts) {
17022
+ if (!Number.isSafeInteger(opts.limit) || opts.limit < 0) {
17023
+ throw new RangeError("candidate limit must be a non-negative safe integer");
17024
+ }
17025
+ return this.db.prepare(`SELECT id, description FROM nodes
17026
+ WHERE label = 'Problem' AND valid_to IS NULL
17027
+ AND json_extract(attrs_json, '$.resolvedAt') IS NULL
17028
+ AND json_type(attrs_json, '$.mergedInto') IS NULL
17029
+ AND (? IS NULL OR id != ?)
17030
+ AND (json_type(attrs_json, '$.workspaceId') IS NULL OR json_extract(attrs_json, '$.workspaceId') = ?)
17031
+ AND COALESCE(json_extract(attrs_json, '$.kind') = 'constraint', 0) = ?
17032
+ ORDER BY last_updated_at DESC, rowid ASC LIMIT ?`).all(
17033
+ opts.excludeId ?? null,
17034
+ opts.excludeId ?? null,
17035
+ opts.workspaceId,
17036
+ opts.constraint ? 1 : 0,
17037
+ opts.limit
17038
+ );
17039
+ }
17007
17040
  hasLiveNodes() {
17008
17041
  const r = this.db.prepare("SELECT EXISTS(SELECT 1 FROM nodes WHERE valid_to IS NULL) AS e").get();
17009
17042
  return r.e === 1;
@@ -17159,8 +17192,8 @@ var SqliteGraphStore = class {
17159
17192
  const r2 = this.db.prepare(
17160
17193
  `SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
17161
17194
  MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
17162
- FROM nodes INDEXED BY nodes_instance_fingerprint
17163
- WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
17195
+ FROM nodes INDEXED BY nodes_instance_fingerprint_v2
17196
+ WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause')`
17164
17197
  ).get();
17165
17198
  return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
17166
17199
  }
@@ -19389,7 +19422,7 @@ function generalizeFileRefs(text, fileLexicon, level = 1) {
19389
19422
  }
19390
19423
 
19391
19424
  // src/instance-ingest.ts
19392
- var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
19425
+ var INSTANCE_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
19393
19426
  var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
19394
19427
  var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
19395
19428
  var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
@@ -19509,6 +19542,10 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19509
19542
  attrs: {
19510
19543
  scope: stripCodebaseScope(n.attrs["scope"]),
19511
19544
  ...n.attrs["kind"] ? { kind: n.attrs["kind"] } : {},
19545
+ ...n.attrs["privateFinding"] ? { privateFinding: true } : {},
19546
+ ...n.attrs["assessment"] ? { assessment: n.attrs["assessment"] } : {},
19547
+ ...n.attrs["sourceClass"] ? { sourceClass: n.attrs["sourceClass"] } : {},
19548
+ ...n.attrs["resolutionWitnessed"] ? { resolutionWitnessed: true, resolvedAt: n.attrs["resolvedAt"] } : {},
19512
19549
  ...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
19513
19550
  ...preserved.length > 0 ? { preservedSymbols: preserved } : {},
19514
19551
  ...internal.length > 0 ? { internalSymbols: internal } : {}
@@ -19523,6 +19560,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19523
19560
  const semanticEndpoints = /* @__PURE__ */ new Map();
19524
19561
  const includedByLabel = /* @__PURE__ */ new Map();
19525
19562
  const composition = {
19563
+ privateTargetMissing: 0,
19526
19564
  candidates: 0,
19527
19565
  shipped: 0,
19528
19566
  cloudSourced: 0,
@@ -19568,11 +19606,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19568
19606
  if (walked.has(n.id)) continue;
19569
19607
  walked.add(n.id);
19570
19608
  composition.candidates++;
19609
+ if ((n.attrs["privateFinding"] || n.label === "Vulnerability") && !opts.project) {
19610
+ composition.privateTargetMissing++;
19611
+ continue;
19612
+ }
19571
19613
  if (n.attrs["source"] === "cloud") {
19572
19614
  composition.cloudSourced++;
19573
19615
  continue;
19574
19616
  }
19575
- if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
19617
+ if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
19576
19618
  composition.falsePositive++;
19577
19619
  continue;
19578
19620
  }
@@ -19595,7 +19637,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19595
19637
  composition.terminalRefused++;
19596
19638
  continue;
19597
19639
  }
19598
- if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
19640
+ if (!n.attrs["privateFinding"] && !noveltyAgainst(n, ref, noveltyOpts).ready) {
19599
19641
  composition.notNovel++;
19600
19642
  continue;
19601
19643
  }
@@ -19638,7 +19680,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19638
19680
  }
19639
19681
  if (targets.length === 0) continue;
19640
19682
  const shipped = shippedById.get(sourceId);
19641
- if (shipped) {
19683
+ if (shipped && !shipped.attrs["privateFinding"]) {
19642
19684
  const anchors = (label) => targets.filter((x) => x.t.label === label).map(
19643
19685
  (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
19644
19686
  ).filter((a) => a != null).sort();