Release history
shyshlakov/pci-dss-mcp releases
PCI DSS v4.0.1 static-analysis MCP server for Go payment codebases. 12 scanners detect PAN/CVV exposure, weak crypto, missing audit logs, vulnerable deps, TLS misconfig, auth weaknesses, plus CycloneDX 1.6 SBOM generation - each finding mapped to the exact PCI requirement. AI-assisted triage via triage_findings. Keyless-signed multi-arch Docker image on ghcr.io.
All releases
14 shown
- Pass `limit=-1` to retrieve the pre‑v0.2.0 flat findings array (capped at 500).
- Use the `pagination.next_cursor` field to page through full findings in increments of 60.
- Handle new structured errors: `CURSOR_EXPIRED` and `CURSOR_MALFORMED`.
- Default response of `generate_compliance_report` now returns a summary‑first payload (`response_shape: "summary"`) with pagination; the previous flat `findings` array is no longer returned by default.
- `limit=-1` must be passed to restore the legacy flat findings array (capped at 500).
- New required input parameter `cursor` on `generate_compliance_report`, `triage_findings`, and `scan_pan_data`; empty or absent cursor starts a fresh scan, non‑empty resumes from server‑side session cache.
- Three‑layer hybrid response dispatcher for `generate_compliance_report` (summary‑first, cursor pagination, auto‑cap safety net).
- `OutputSchema` now a oneOf union of `SummaryResponse`, `FlatResponse`, and `CursorExpiredError` with `response_shape` discriminator.
- Session caches with 10‑minute TTL for cursor‑paginated follow‑up in memory (`sync.Map`).
Full changelog
v0.2.0 - 2026-04-17
Breaking Changes
-
generate_compliance_reportdefault response shape is now a summary-first
variant (response_shape: "summary"). Previously, unfiltered calls returned
a flatfindings: [...]array wrapped in aComplianceReportenvelope.
The new default response carries severity totals, per-requirement statuses,
up to 10 top findings per severity, and apagination.next_cursorthat the
client uses to drill down into the full findings list.Before (v0.1.5): unfiltered
generate_compliance_reportdefault response{ "metadata": {"target_path": "...", "duration_ms": 1210, "total_files": 72}, "summary": {"critical": 49, "high": 89, "medium": 27, "low": 0, "info": 59}, "findings": [ {"rule_id": "PAN-KEYWORD", "severity": "HIGH", "file_path": "...", ...}, "... all 178 active findings inline ..." ], "requirement_status": [...14 entries + 213 NOT_CHECKED...], "compliance_status": "FAIL", "active_findings": 178 }After (v0.2.0): same call, default response
{ "response_shape": "summary", "metadata": {"target_path": "...", "duration_ms": 1210, "total_files": 72}, "summary": {"critical": 49, "high": 89, "medium": 27, "low": 0, "info": 59}, "requirement_statuses": [...14 entries; NOT_CHECKED filtered out...], "top_findings": { "critical": ["...up to 10 findings (stripped code_snippet / fix_hint)..."], "high": ["...up to 10..."], "medium": ["...up to 10..."] }, "pagination": { "total_findings": 178, "returned": 30, "next_cursor": "eyJzaWQiOiI...", "hint": "call generate_compliance_report with cursor for the full flat page; pass limit=-1 to get legacy flat shape (capped at 500)", "auto_capped": false } } -
Migration. Pass
limit=-1on the next call togenerate_compliance_report
to restore the pre-v0.2.0 flat findings array (capped at 500 by safety net).
Alternatively, follow thepagination.next_cursorto page through findings
60 at a time. -
New
cursorinput parameter ongenerate_compliance_report,triage_findings,
andscan_pan_data. Empty string or absent = fresh scan. Non-empty = resume
from server-side session cache (10-minute TTL). Cursors are tool-scoped;
reusing agenerate_compliance_reportcursor ontriage_findings(or vice
versa) returns aCURSOR_MALFORMEDerror. -
New error responses: clients must handle the structured error shape.
CURSOR_EXPIRED— session cache entry expired (10-minute TTL) or server
restarted. Hint: re-run without cursor to start a fresh scan.CURSOR_MALFORMED— cursor failed to decode, or its embedded tool name
does not match the current tool.
Added
- Three-layer hybrid response dispatcher for
generate_compliance_report
(F-29, implemented viaSelectAndExecute):- Layer B — summary-first. Triggered on unfiltered calls
(limit == 0 && min_severity == "" && rule_filter == "" && cursor == "").
ReturnsSummaryResponse: severity totals, requirement statuses,
up to 10 top findings per severity (CRITICAL / HIGH / MEDIUM),
pagination.next_cursorset for drill-down. - Layer A — cursor pagination. Triggered when a cursor is present OR
any filter is set (rule_filter,min_severity, positivelimit).
ReturnsFlatResponsewith 60 findings per page plusnext_cursor
when more pages remain. - Layer C — auto-cap safety net. Triggered ONLY by explicit
limit=-1.
Returns a flatfindingsarray; if size exceeds 500 the response is
capped withpagination.auto_capped: true, total_before_cap, kept, hint.
- Layer B — summary-first. Triggered on unfiltered calls
cursorinput parameter ongenerate_compliance_report,triage_findings,
scan_pan_data.OutputSchemaforgenerate_compliance_reportis now aoneOfunion of
SummaryResponse,FlatResponse, andCursorExpiredErrorvariants with
a requiredresponse_shapeconst discriminator ("summary","flat",
"error").- Session caches for cursor-paginated follow-up — in-memory
sync.Map,
10-minute TTL, 60-second lazy eviction sweep via background ticker. Each
tool owns a typed cache:generate_compliance_reportstores
[]ReportFindinginscanner/reportscanner;scan_pan_dataand
triage_findingsshare[]scanner.Findingviascanner/hybridcache.
Both caches follow the same TTL, eviction, and fake-clock test contract.
Internal
- New
scanner/reportscanner/session.go— package-levelsync.Map, injected
Clockinterface,sync.Once-gated background evictor. Mirrors the
internal/taint/engine.gosession-cache pattern. - New
scanner/reportscanner/cursor.go— opaquebase64.RawURLEncodingJSON
cursor ({sid, off, tool}) with cross-tool namespace guard. - New
scanner/reportscanner/hybrid.go— D-01 layer selector
SelectAndExecute; Layer A/B/C buildersbuildSummary,
buildFlatPage,buildAutoCapFlat; top-finding stripping
(stripSummaryFindingsdropscode_snippet/fix_hint/
related_requirementsfor the summary panel). - New
scanner/reportscanner/output_schema.go—buildOutputSchemaUnionpinResponseShapehelper that overrides the inferred property's
constfield per variant (jsonschema-go has no const struct tag).
- New
scanner/hybridcache/hybridcache.go— cross-package cursor + session
cache for the single-scanner tools (scan_pan_data,triage_findings).
Introduced to break thereportscanner ↔ panscannerimport cycle that
would otherwise arise from sharing reportscanner's Wave 1 primitives
with the two single-scanner tools.generate_compliance_reportkeeps
its own typed cache inscanner/reportscanner/session.gobecause the
payload type ([]ReportFinding) diverges from the shared cache's
[]scanner.Findingshape. - New
scanner/reportscanner/format_stability_test.go+
scanner/reportscanner/testdata/format_golden.txt— byte-identical CLI
output regression guard.FormatHumanReadableis unchanged by this
release and must remain unchanged going forward. - Extended
scanner/tool_output_schema_test.gowith
TestOutputSchema_GenerateReport_HasOneOfUnion— walks registered
tools, asserts the union is declared with exactly three variants. scanner/tooloutput.go:ScannerToolOutputgrowsTotalFindingsand
NextCursorfields so single-scanner tools can paginate through the
hybridcachesession store.scanner/triagescanner/types.go:TriageResultgrows aNextCursor
field (omitempty) for paginated responses.
Docs
docs/tools.mdupdated with a top-of-file v0.2.0 migration note and
per-tool "Pagination and cursor" subsections for
generate_compliance_report,triage_findings, andscan_pan_data.
Known limitations
- Persistent disk cache is deferred (tracked as backlog item F-30).
Process restart invalidates all outstanding cursors; clients see
CURSOR_EXPIREDand must re-run without a cursor. - HMAC-signed cursors are an optional defense-in-depth item; this release
ships opaque-but-unsigned cursors. The threat surface is a
single-process stdio MCP server, which is low exposure. chi-style inline middleware (r.With(...).Post(...)) is not yet
recognised by the shared hybrid middleware crawler; use route-group
registration viar.Use(...)to remain detectable.
Metrics
- Layer B response size on the golden fixture: 19,986 bytes (budget
25,600).TestLayerB_FixtureBudget25KBlocks this invariant. - Golden fixture
make test-fixturecounts unchanged
(CRITICAL=49 HIGH=89 MEDIUM=27 LOW=0 INFO=59) — this release adds no
detection logic, only reshapes how findings are wrapped on the wire.