Manual Test Runbook — S4: Compliance Scorecard Generator¶
Owner: Sagar | Time: ~5 min (offline only — S4 is a pure scorecard generator, no live phase)
Overview¶
S4 turns one E0 ComplianceSnapshot (+ optionally an S2 ComplianceDashboard
for framework rollups and trend) into a versioned, branded one-page
scorecard — markdown + a self-contained HTML page (+ optional Pandoc PDF). It
is the sales/client-facing counterpart to S2's detailed technical dashboard.
S4 measures nothing and re-derives nothing from Azure: every figure is a
re-presentation of an E0/S2 number, with one transparent extra — a documented
A–F grading band, with its derivation printed inline (the same "never
fabricate, show your work" stance as L5/S3). Pure adapt → render + jest,
mirroring E0/S1/S2/L4/L5 — there is no live Azure phase to test (the tool only
reads JSON and writes markdown/HTML/PDF).
Part A — Build, typecheck, unit tests (~3 min)¶
Expect: 2 suites, 24 tests pass — grading-band derivation (incl. the "—"
not-yet-measured case and the never-fabricate guarantees), branding resolution
+ neutral defaults, framework-badge 1:1 re-presentation, trend-direction
derivation purely from delta sign (incl. the conservative "any decline reads as
declining" rule and the regressed-flag override), highlight generation, the
always-present methodology section, markdown section ordering, HTML
self-containment + escaping + branding application.
Part B — Offline CLI demo (~2 min)¶
B1. Generate a full scorecard (snapshot + dashboard + branding)¶
node dist/index.js \
--snapshot examples/snapshot.json \
--dashboard examples/dashboard.json \
--branding examples/branding.json \
--output /tmp/s4out
cat /tmp/s4out/scorecard.md
Expect: stdout wrote /tmp/s4out/scorecard.md, .../scorecard.html,
.../model.json (grade B for Contoso Logistics). The markdown contains, in
order:
- A branded header — "Q2 2026 Compliance & Security Posture Scorecard", "Prepared for: Contoso Logistics", "Prepared by: SnowOps Cloud".
## Overall posture: B — 88.2%with a measurement table (policy compliance 95.3%, Secure Score 81%) and an inline derivation blockquote: "Overall 88.2% = mean of policy compliance 95.3% and Secure Score 81%, banded to grade 'B' (Good) per the documented grading scale."## Frameworks— a 4-row table (SOC 2 ✅, ISO 27001 ⚠️, CIS Azure ✅, HIPAA ⚠️) matching the fixture's S2 rollup exactly.## Trend— ↑ Improving, quoting the real deltas verbatim ("Secure Score +3, policy compliance +1.2%, non-compliant resources -5").## Highlights— bullets naming the highest-impact framework needing attention (ISO 27001) by non-compliant-resource count.## Methodology— always present; restates the grading band table and explains the framework-badge / trend derivations.
open /tmp/s4out/scorecard.html # or: python3 -m http.server --directory /tmp/s4out
cat /tmp/s4out/model.json | head -5 # versioned model.json (schema v1.0)
Expect the HTML: a self-contained styled page (inline CSS only, no external
script/stylesheet refs), the B grade tile in green, the client's accent
color (#0b5fff) applied to headings/borders, a text wordmark "Contoso
Logistics" (the fixture has no logoUrl).
B2. Headline-only run (no dashboard — honest "not supplied" sections)¶
node dist/index.js --snapshot examples/snapshot.json --client-name "Solo Run Inc" --output /tmp/s4solo
grep -A1 "## Frameworks" /tmp/s4solo/scorecard.md
grep -A1 "## Trend" /tmp/s4solo/scorecard.md
Expect: both sections render and state plainly that no S2 rollup/delta was supplied — they are not silently omitted. The methodology section omits the framework-badge and trend-derivation paragraphs (nothing to explain).
B3. Optional PDF (best-effort)¶
node dist/index.js --snapshot examples/snapshot.json --branding examples/branding.json --output /tmp/s4pdf --pdf
ls /tmp/s4pdf/
Expect: scorecard.pdf present if Pandoc/TeX Live is installed; otherwise a
PDF render failed (continuing — markdown/HTML are still written) message on
stderr and a successful exit (the markdown/HTML are still written either way —
PDF is opt-in and best-effort, same stance as G3).
B4. CLI help / required-flag guards¶
node dist/index.js --help
node dist/index.js --output /tmp/x # missing --snapshot
node dist/index.js --snapshot examples/snapshot.json --output /tmp/x # missing clientName
Expect: usage text on --help; clear error: --snapshot <file> is required
and error: branding.clientName is required … messages (exit 1) on the other
two.
Pass criteria¶
- Part A — builds, typechecks; 24 tests pass
- Part B1 — full-input run renders the branded header, grade B with visible
derivation, all four framework rows, the improving-trend callout with
real numbers, and a methodology section; HTML is self-contained and
branded;
model.json(schema v1.0) written - Part B2 — missing-dashboard sections are stated honestly, not omitted
- Part B3 — PDF render attempted; failure (if Pandoc absent) does not fail the run
- Part B4 —
--helpand required-flag error messages behave as documented
Sign-off¶
- Tester: _ | Date: _ | Result: PASS / FAIL / N/A
- Notes: