# Console Consumption of LNM Linksets (Sprint 110) Goal: unblock CONCELIER-CONSOLE-23-001..003 by defining how Console reads Link-Not-Merge (LNM) data now that the schema is frozen (2025-11-17) and cache plan exists. ## Data sources - Primary collection: `advisory_linksets` (see `docs/modules/concelier/link-not-merge-schema.md`). - Cache: `advisory_linkset_cache` (see `docs/modules/concelier/operations/lnm-cache-plan.md`). Console should read from cache when present; fall back to live rebuild otherwise. ## API shape (WebService) - Endpoint to expose via Console: `GET /v1/lnm/linksets/{advisoryId}` - Query: `source` (required), `tenant`, optional `includeConflicts=true|false` (default true). - Response JSON (deterministic key order): ```json { "advisoryId": "GHSA-123", "source": "ghsa", "observations": ["", ""], "normalized": { "purls": ["pkg:npm/foo@1.0.0"], "versions": ["1.0.0"], "ranges": [], "severities": [{"system":"cvssv3","score":7.5}] }, "conflicts": [ {"field":"severities","reason":"disagreement","values":["7.5","9.8"]} ], "provenance": { "observationHashes": ["..."], "toolVersion": "lnm-1.0" }, "createdAt": "2025-11-20T00:00:00Z" } ``` - Sorting: observations sorted by `source, advisoryId, fetchedAt` before hashing; response preserves that order. - Caching: when cache hit, return cached document; when miss, rebuild, write cache, then return. ## Console rendering contract - Fields to surface: - `normalized.purls` (list) and `normalized.versions` - `conflicts` if non-empty: show field + reason text; keep order as returned. - `provenance.observationHashes` as “evidence anchors” (list); do not prettify. - Tenant header required; no cross-tenant leakage. Scope `concelier:lnm.read`. ## Error handling - 404 when linkset missing for advisory/source. - 409 when tenant header missing/invalid. - Deterministic error body: `{ "error": "", "message": "..." }`. ## Telemetry (reuse existing meters) - Increment `lnm.cache.hit_total` / `lnm.cache.write_total` as defined in cache plan. - Log template on returns: `lnm_console_success tenant={Tenant} advisoryId={AdvisoryId} source={Source} cached={Cached}`. ## Owners - Concelier Console Guild (primary) - Concelier Core Guild (review) This document is authoritative for CONCELIER-CONSOLE-23-001..003 in Sprint 110.