Skip to content

feat: opt-in known-issues data for KB lookups (include_known_issues)#17

Merged
jonnybottles merged 2 commits into
mainfrom
feat/kb-known-issues
Jul 11, 2026
Merged

feat: opt-in known-issues data for KB lookups (include_known_issues)#17
jonnybottles merged 2 commits into
mainfrom
feat/kb-known-issues

Conversation

@jonnybottles

Copy link
Copy Markdown
Owner

What

Sysadmins ask "what will this update break?" before "how urgent is it?". This PR extends msrc_search so KB lookups — single (kb="5094126") or batched (kb=[...]) — can opt into Microsoft's published known-issues data via a new include_known_issues=True parameter: per KB, each confirmed issue's title, symptoms, workaround, and the resolving update when Microsoft names one, plus the source URL. Default JSON output is byte-identical — the block only exists when requested.

"known_issues": {"status": "published", "issues": [{"title": ..., "symptoms": ...,
                 "workaround": ..., "resolved_by": "KB5095093"}], "source_url": ...}

Statuses are honest three ways: published / none_published (Microsoft publishes no known-issues data for this KB) / unavailable (retrieval or parse failure — never conflated with "no issues").

Source research (hard requirement: no credentials of any kind)

Chosen: the per-KB public support page (support.microsoft.com/en-us/help/{kb} → one same-host 301 → canonical article). Server-rendered HTML with a stable Known issues in this update section (ocpSection/ocpExpandoBody markup, bold Symptoms/Workaround/Resolution labels, resolving-KB links). No auth, no API key, no UA blocking (verified with httpx's default UA).

Rejected alternatives:

  • Microsoft Graph windowsupdates knownIssue API — the only structured source, but requires an AAD tenant + app registration + token. Disqualified by the project's "no API keys anywhere" promise.
  • Windows Release Health pages (learn.microsoft.com) — richer status lifecycle, but Windows-only, needs a maintained per-Windows-version page list, resolved issues roll off the status pages after ~30 days, and the backing repo (MicrosoftDocs/windows-release-pr) is private, so no raw markdown.
  • Third-party JSON rehosts — unmaintained trust/reliability risk.

Trade-offs accepted, and their mitigations (all verified against the live site during development):

  • Unstructured source; Microsoft redesigns these pages every few years. Parser is stdlib-only (regex slicing + html.parser) and degrades to unavailable with a pointer to the source URL when the layout drifts; a --run-live smoke test (test_live_kb_known_issues_statuses) is the drift canary.
  • The /help/{kb} resolver is fuzzy: bogus ids 301 to unrelated articles (9999999 → an MS16-062 page), and every landing page echoes the requested id in an awa-kb_id analytics meta tag, so in-body digit matches prove nothing. Published issues are only attributed when the URL slug or page <title> names the requested KB; unverifiable landings report "no per-KB support page". Pages that never self-reference (some .NET update pages) conservatively report the same — never another update's issues.
  • Redirects: repo policy is follow_redirects=False. A new http_client.get_location() reads the status+Location without the body, and exactly one hop is followed after validating the target is https://support.microsoft.com/....

Coverage boundary (documented in README/CLAUDE.md/docstring)

Known-issues sections are published mainly for Windows OS cumulative/preview updates (verified: KB5094126 → 2 issues incl. resolved_by KB5095093). Office/SharePoint (KB5002880), .NET (KB5097148), SQL, and most other products publish none → explicit none_published. The block also attaches to not_found KB results, because preview-only updates (e.g. KB5095093) publish known issues without being MSRC security entries.

This feature reports what Microsoft has confirmed an update breaks — it is not framed as predicting behavior in any specific environment.

Bounded upstream reads / memory envelope

Fetches go through the shared client's size-capped streaming (MCP_KNOWN_ISSUES_MAX_RESPONSE_BYTES, 4 MiB default; pages measure ~150–360 KB), concurrency is semaphore-bounded (3, shared by batch prefetch), and parsed results are TTL-cached 6 h (LRU-capped at 500 entries ≈ ≤2 MB; failures are never cached, so a transient error can't stick).

Testing

TDD throughout (failing tests written and observed first). 31 new offline tests (mocked, no network): parser fields/variants/junk-stripping, redirect policy, wrong-landing safety, honest-status mapping, cache TTL/LRU/negative-caching, bounded prefetch concurrency, tool-level wiring incl. per-entry batch blocks, fail-open (unavailable with the MSRC lookup intact), and default-shape regression guards. Plus 2 opt-in --run-live tests (drift canary + tool round-trip, both passing today).

  • pytest --cov: 286 passed, 94.75% (gate 90%); ruff check . clean.
  • Live verification: KB5094126 published (2 issues, resolved_by KB5095093), KB5002880/KB5097148 none_published, KB9999999 none_published (wrong landing refused), batch e2e through msrc_search, and default-output keys unchanged.

Release notes

Version 0.7.0 → 0.8.0 (pyproject, __init__.py, both server.json fields) + uv lock. Not deployed / not published — Docker/ACA/PyPI/MCP-registry publish are owner-handled per the deploy flow.

🤖 Generated with Claude Code

jonnybottles and others added 2 commits July 11, 2026 19:36
kb= lookups (single or batched) can now return the issues Microsoft has
publicly confirmed an update introduces — title, symptoms, workaround,
and the resolving KB when stated — scraped best-effort from the KB's
public support.microsoft.com page (no keyless API exists for this data).

Honest three-way status per KB: published / none_published /
unavailable; a fetch or parse failure is never reported as "no known
issues". Landing pages are only trusted when their URL slug or title
names the requested KB, because the /help/{kb} resolver fuzzily lands
bogus ids on unrelated articles. One same-host redirect hop is followed
manually after validation; the shared client still never follows
redirects. TTL cache 6h (LRU-capped, failures uncached), semaphore-
bounded fetches, 4 MiB body cap via MCP_KNOWN_ISSUES_MAX_RESPONSE_BYTES.

Default JSON output is unchanged; the block only appears with
include_known_issues=True, and also attaches to not_found results since
preview-only updates publish known issues without being MSRC entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Confirmed live 2026-07-11: the ACA endpoint is listed as a hosted
connector at glama.ai alongside the GitHub-sourced entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonnybottles
jonnybottles merged commit 9361d36 into main Jul 11, 2026
6 checks passed
@jonnybottles
jonnybottles deleted the feat/kb-known-issues branch July 12, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant