Skip to content

Commit 7b217fe

Browse files
feat(128): add executive threat architecture infographic with early-page PDF positioning (#131)
* feat(128): add executive threat architecture infographic with early-page PDF positioning Adds the executive-architecture infographic template that produces a layered architecture diagram with Critical/High threat callouts for non-technical executives, positioned immediately after the Executive Summary in the security report PDF. User Stories delivered (spec.md): - US-1 (P1): extract an executive-architecture payload from threat model output - US-2 (P1): render the page between Executive Summary and Attack Path Analysis - US-3 (P2): include in the `all` shorthand; add `exec` alias - US-4 (P2): graceful skip when no Critical/High findings exist Implementation touches: - `scripts/extract-infographic-data.py` - 4 new helpers + dispatch branch - `scripts/extract-report-data.py` - detect_images + Typst writers - `templates/tachi/security-report/main.typ` - conditional page block - `schemas/infographic.yaml` - template enumeration - `.claude/agents/tachi/threat-infographic.md`, report-assembler.md - `.claude/commands/tachi.infographic.md` - template list, exec alias, all expansion - `.claude/skills/tachi-infographics/` - reference doc + SKILL.md index Pytest harness bootstrapped (Wave 1): tests/, conftest.py with importlib shim, pyproject.toml pytest config, requirements-dev.txt, Makefile test target. 39 tests total, all green. Scope-bleed bundled into this PR (see decisions.md Decision 4): - `scripts/extract-report-data.py` - attack-tree H1 heading fallback and component/title enrichment (required to parse mermaid-agentic-app) - `templates/tachi/security-report/attack-path.typ` - defensive string->array coercion for `remediation` (prevents character-by-character iteration bug) Known post-merge follow-up: portrait infographic images (such as the generated executive architecture JPEG) produce extra blank pages in `infographic-page()` because the function was tuned for landscape aspect ratios. Fix is either Gemini prompt tuning (generate landscape) or a Typst template refinement (max-height constraint). Tracked in code-review.md INFO-1. Governance: PM + Architect + Team-Lead signed-off tasks.md. P0 APPROVED_WITH_CONCERNS (0 blocking). P1 APPROVED_WITH_CONCERNS (0 blocking). T035 code-review APPROVED_WITH_CONCERNS (0 blocking, 4 INFO). T036 architect-checkpoint APPROVED_WITH_CONCERNS (cites P1). T037 security-review APPROVED_WITH_CONCERNS (0 blocking, 1 INFO). T038 usability deferred to post-merge per 5-day SLA. Refs: closes #128 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * security(128): run security scan [01d3e85] SAST: 12 code files scanned (2 production scripts + 10 test files). Zero OWASP P0 findings. No SQL injection, command injection, hardcoded secrets, weak crypto, path traversal, or insecure randomness patterns. Both production scripts are CLI tools that parse markdown files — no network I/O, no shell execution, no cryptographic primitives. SCA: 2 manifests audited (pyproject.toml, requirements-dev.txt). Zero findings. Packages: setuptools>=61 (build-system), pytest>=8.0 and pytest-cov>=4.1 (dev-only). No production runtime dependencies added by F-128. No known CVEs at declared versions. Artifacts written: - .security/scan-log.jsonl (chain_hash 540fc7a6a4...) - .security/reports/01d3e8587191.sarif (empty results array) - .security/reports/sca-2026-04-10.cdx.json (CycloneDX SBOM, 3 components) - specs/128-prd-128-executive/security-scan.md Scan status: PASSED Scan ID: ba390e43-68fd-4627-b3c4-92e79c24141a Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(128): mark T035-T039 complete in tasks.md Updates tasks.md to reflect that Wave 6 Phase 7 tasks are complete: - T035 code-reviewer APPROVED_WITH_CONCERNS - T036 architect-checkpoint APPROVED_WITH_CONCERNS (cites P1) - T037 security-analyst APPROVED_WITH_CONCERNS - T038 PM usability DEFERRED per post-merge SLA - T039 PR #131 created All 51 F-128 tasks now marked [X]. Wave 6 complete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(128): add architecture section, PRD INDEX entry, regenerate BACKLOG Document Feature 128 (Executive Threat Architecture Infographic) in the system design architecture doc, register it in the PRD INDEX, and refresh BACKLOG.md to reflect current GitHub Issue state. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3276a46 commit 7b217fe

File tree

81 files changed

+100987
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+100987
-21
lines changed

.claude/agents/tachi/report-assembler.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,13 @@ When the extraction script detects baseline data in `threats.md` frontmatter, `r
229229
2. **Active findings table**: Annotate findings with `delta_status: "NEW"` using a visual indicator (e.g., bold or badge) to highlight newly discovered threats.
230230
3. **Resolved findings section**: When `resolved-findings` is non-empty, render a separate "Resolved Findings" section after the active findings table. This section lists remediated threats for audit trail.
231231
4. **No-baseline behavior**: When `has-baseline` is false, render findings as before (no separation, no annotations, no resolved section). All delta variables default to zero/empty.
232+
233+
### Executive Threat Architecture Page
234+
235+
When the extraction script detects a `threat-executive-architecture.jpg` image in the target directory, `report-data.typ` includes an additional image flag and path for the executive architecture infographic page:
236+
237+
| Artifact | Typst flag | Presence rule | Consumed by |
238+
|----------|-----------|---------------|-------------|
239+
| `threat-executive-architecture.jpg` | `has-executive-architecture` (boolean) | File exists in target directory AND file size > 0 | `infographic-page()` call in `main.typ`, positioned immediately after the Executive Summary page and immediately before the Attack Path Analysis conditional block |
240+
241+
The Executive Threat Architecture infographic, when present, is rendered on a full-bleed portrait page immediately after the Executive Summary and before any Attack Path Analysis pages, placing the visual threat narrative within an executive reader's normal attention window. When the image is absent (for example, because no Critical or High findings qualified for callouts), the `has-executive-architecture` conditional is false and the page is omitted entirely, preserving byte-identical output against pre-existing baselines.

.claude/agents/tachi/threat-infographic.md

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,25 @@ You must not require any other input -- you run in a fresh context with only the
6868
| `baseball-card` | `threat-baseball-card-spec.md` + `threat-baseball-card.jpg` | Compact risk summary dashboard: donut chart, STRIDE+AI heat map, critical finding cards, architecture overlay strip |
6969
| `system-architecture` | `threat-system-architecture-spec.md` + `threat-system-architecture.jpg` | Annotated architecture diagram: trust zones, components with attack surface badges, data flow arrows colored by severity, finding IDs overlaid |
7070
| `risk-funnel` | `threat-risk-funnel-spec.md` + `threat-risk-funnel.jpg` | 4-tier vertical funnel showing progressive risk reduction: threats identified, inherent risk scored, controls applied, residual risk |
71-
| `all` | All three sets of files | Generate all three templates (default) |
71+
| `executive-architecture` | `threat-executive-architecture-spec.md` + `threat-executive-architecture.jpg` | Executive-audience layered architecture diagram with narrative threat callouts for Critical/High findings, rendered in portrait orientation for the security report's early pages |
72+
| `all` | All sets of files | Generate all templates (default) |
7273

73-
**Alias**: `corporate-white` maps to `baseball-card`.
74+
**Aliases**: `corporate-white` maps to `baseball-card`; `exec` maps to `executive-architecture`.
7475

75-
When template is `all`, produce all three templates sequentially -- first Baseball Card, then System Architecture, then Risk Funnel. Each produces its own spec + image.
76+
When template is `all`, produce all templates sequentially -- Baseball Card, System Architecture, Risk Funnel, Executive Architecture. Each produces its own spec + image.
77+
78+
### executive-architecture Template Specification
79+
80+
The spec file `threat-executive-architecture-spec.md` is rendered from the JSON payload emitted by `scripts/extract-infographic-data.py --template executive-architecture`. The payload shape is defined in `specs/128-prd-128-executive/data-model.md` (`ExecutiveArchitecturePayload`).
81+
82+
The spec MUST contain six sections matching the schema enumeration in `schemas/infographic.yaml`:
83+
84+
1. **Metadata** -- Rendered from `metadata`: template_name, tier_source, source_file, generation_timestamp, qualifying_layer_count, total_filtered_count, skip_image, fallback_used.
85+
2. **Architecture Layers** -- Rendered from `layers[]`: each layer's name, position, components list, component_count, source_kind. Layers are already ordered with the most-exposed (untrusted or lowest-trust zone) at position 0 when `source_kind == "trust_zone"`.
86+
3. **Threat Callouts** -- Rendered from `callouts[]`: each callout's layer_name, finding_id, severity, raw_description, composite_score, affected_component. The raw_description is the unmodified source text; the Gemini prompt is responsible for rewriting it to ≤25 words of plain English.
87+
4. **Severity Distribution** -- Rendered from `severity_distribution`: Critical and High counts only (Medium/Low/Note are not shown in this template).
88+
5. **Visual Layout Directives** -- Portrait orientation, pastel layer bands untrusted-first, red dashed-border callouts. Derived from `visual_directives` in `schemas/infographic.yaml`.
89+
6. **Gemini Prompt Construction Notes** -- Embedded prompt text for the optional JPEG rendering step.
7690

7791
### Output
7892

@@ -199,6 +213,31 @@ The output `threat-{template-name}-spec.md` contains YAML frontmatter and 6 requ
199213

200214
---
201215

216+
## Executive-Architecture Gemini Prompt Construction
217+
218+
When generating the `threat-executive-architecture.jpg` image via Gemini API, the prompt MUST instruct Gemini to:
219+
220+
- **Render in portrait orientation** with an 8.5x11 aspect ratio suitable for embedding as a full-bleed page in the security report PDF.
221+
- **Arrange architectural layers as horizontal bands** stacked vertically, with the most exposed layer (position 0) at the TOP of the diagram and the most trusted layer at the BOTTOM. Untrusted zones and public-facing components belong at the top.
222+
- **Use pastel fills** for each layer band, cycling from the color palette defined in `schemas/infographic.yaml` under `visual_directives`: `#F0F4FF`, `#FFF4F0`, `#F0FFF4`, `#FFF0F8`, `#F8F0FF`. Cycle through the palette if there are more layers than colors.
223+
- **Place red dashed-border callout boxes** (2pt border weight, color `#DC2626`) with warning triangle icons next to each layer. Each callout box is connected to its associated `affected_component` within the layer via a leader line.
224+
- **Rewrite each callout's `raw_description`** to ≤25 words in plain English with no technical jargon. The goal is an executive audience who reads one sentence per callout in under 5 seconds. Avoid terms like "endpoint," "payload," "injection," "JWT," or "RBAC" without explanation. Prefer verbs like "attacker could steal," "system could leak," "user could impersonate."
225+
- **Use large readable typography** for layer names (24pt+) and callout text (14pt+); the infographic must be legible when printed on a letter-size page.
226+
- **Reference the `visual_directives` block** from `schemas/infographic.yaml` for the exact color palette, border weights, and orientation constraints.
227+
228+
The prompt must be constructed from the JSON payload fields, not hardcoded. Layer names, component lists, and callout text all come from the emitted payload.
229+
230+
### Skip Image Edge Case
231+
232+
When the payload's `metadata.skip_image == True` (i.e., the threat model contains zero Critical and zero High severity findings), the agent MUST:
233+
234+
1. **Render the spec file** with a clear explanatory note in the Threat Callouts section: "No Critical or High severity findings were identified in this threat model; the executive architecture diagram is omitted for this report run. Layer composition is preserved below for reference."
235+
2. **NOT invoke the Gemini API** for this run. No JPEG file is produced. Downstream PDF compilation will omit the executive architecture page entirely because the `threat-executive-architecture.jpg` file does not exist.
236+
237+
This graceful degradation preserves the report structure while avoiding a misleading "no-threats" diagram.
238+
239+
---
240+
202241
## Quality Standards
203242

204243
### Output Structural Validation Checklist

.claude/commands/tachi.infographic.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ Consider user input before proceeding (if not empty).
1414

1515
1. If `$ARGUMENTS` contains `--template <value>`:
1616
- Set `template` to the specified value
17-
- Valid values: `baseball-card`, `system-architecture`, `risk-funnel`, `maestro-stack`, `maestro-heatmap`, `all`, `maestro`, `corporate-white`
17+
- Valid values: `baseball-card`, `system-architecture`, `risk-funnel`, `maestro-stack`, `maestro-heatmap`, `executive-architecture`, `all`, `maestro`, `corporate-white`, `exec`
1818
- If value is `corporate-white`: resolve alias to `baseball-card`
19+
- If value is `exec`: resolve alias to `executive-architecture`
1920
- If value is `maestro`: expand shorthand to `["maestro-stack", "maestro-heatmap"]` — generate both sequentially
2021
- If value is not in the valid list, display:
2122
```
2223
INVALID TEMPLATE: {value}
23-
Valid templates: baseball-card, system-architecture, risk-funnel, maestro-stack, maestro-heatmap, all, maestro
24-
Aliases: corporate-white → baseball-card, maestro → maestro-stack + maestro-heatmap
24+
Valid templates: baseball-card, system-architecture, risk-funnel, maestro-stack, maestro-heatmap, executive-architecture, all, maestro
25+
Aliases: corporate-white → baseball-card, exec → executive-architecture, maestro → maestro-stack + maestro-heatmap
2526
```
2627
- Halt if invalid.
2728
- Strip `--template <value>` from `$ARGUMENTS` (trim extra whitespace)
@@ -160,9 +161,10 @@ Single-command entry point for tachi threat infographic generation — the visua
160161
--output /tmp/infographic-{template_name}.json
161162

162163
Template expansion:
163-
- "all" expands to: baseball-card, system-architecture, risk-funnel. Then check if data source contains MAESTRO layer data (grep for "MAESTRO Layer" or "maestro_layer" in the data source file) — if present, also append maestro-stack and maestro-heatmap (up to 5 runs total).
164+
- "all" expands to: baseball-card, system-architecture, risk-funnel, executive-architecture. Then check if data source contains MAESTRO layer data (grep for "MAESTRO Layer" or "maestro_layer" in the data source file) — if present, also append maestro-stack and maestro-heatmap (up to 6 runs total).
164165
- "maestro" expands to: maestro-stack, maestro-heatmap (2 runs, sequential)
165-
- Individual templates (baseball-card, system-architecture, risk-funnel, maestro-stack, maestro-heatmap): 1 run
166+
- "exec" resolves to: executive-architecture (alias, 1 run)
167+
- Individual templates (baseball-card, system-architecture, risk-funnel, maestro-stack, maestro-heatmap, executive-architecture): 1 run
166168

167169
Step 2: Read the JSON output and generate the spec file per your methodology.
168170
- If the JSON contains a "delta" object (has_baseline: true), include delta context
@@ -235,6 +237,10 @@ Where:
235237
/infographic --template baseball-card
236238
/infographic --template system-architecture
237239
240+
# Executive architecture template (Feature 128 — placed after Executive Summary in PDF)
241+
/infographic --template executive-architecture
242+
/infographic --template exec # alias: resolves to executive-architecture
243+
238244
# MAESTRO templates (require MAESTRO layer data from Feature 084)
239245
/infographic --template maestro-stack
240246
/infographic --template maestro-heatmap

.claude/skills/tachi-infographics/SKILL.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The infographic generation pipeline transforms structured threat model output in
1414
1. **Infographic Specification** (`threat-{template-name}-spec.md`) -- A 6-section structured document containing all data points, color coding, layout instructions, and text content needed to render a presentation-ready infographic. This is the primary deliverable.
1515
2. **Infographic Image** (`threat-{template-name}.jpg`) -- A JPEG image rendered from the specification via Gemini API. This is a best-effort deliverable, conditional on API key availability.
1616

17-
The pipeline supports five templates:
17+
The pipeline supports six templates:
1818

1919
| Template | Purpose | Audience |
2020
|----------|---------|----------|
@@ -23,19 +23,23 @@ The pipeline supports five templates:
2323
| Risk Funnel | 4-tier vertical funnel showing progressive risk reduction through the pipeline | Risk management |
2424
| MAESTRO Stack | Vertical seven-layer stack diagram showing finding counts and highest severities per MAESTRO layer (L1-L7) | CISO / security management |
2525
| MAESTRO Heatmap | Component-by-layer grid with severity coloring at each intersection | Security engineers |
26+
| Executive Architecture | Portrait layered architecture diagram with Critical/High threat callouts, positioned immediately after the Executive Summary in the compiled PDF | CISO / board / executive sponsors |
2627

27-
Each template shares the same Sections 1-4 format (metadata, risk distribution, coverage heat map, top findings) but has a unique Section 5 (Architecture Threat Overlay) layout.
28+
The first five templates share the same Sections 1-4 format (metadata, risk distribution, coverage heat map, top findings) but have a unique Section 5 (Architecture Threat Overlay) layout. Executive Architecture uses a distinct six-section structure (Metadata, Architecture Layers, Threat Callouts, Severity Distribution, Visual Layout Directives, Gemini Prompt Construction Notes) and is the only template rendered in portrait orientation — see `references/executive-architecture.md` for the full specification.
2829

2930
### Template Shorthands
3031

3132
| Shorthand | Expands To | Description |
3233
|-----------|-----------|-------------|
33-
| `all` | `baseball-card`, `system-architecture`, `risk-funnel` | Generate all three core templates |
34+
| `all` | `baseball-card`, `system-architecture`, `risk-funnel`, `executive-architecture` | Generate all four core templates (conditionally extends with MAESTRO templates when MAESTRO data is present) |
3435
| `maestro` | `maestro-stack`, `maestro-heatmap` | Generate both MAESTRO templates sequentially |
36+
| `exec` | `executive-architecture` | Single-template alias (not a compound expansion) |
3537
| `corporate-white` | `baseball-card` | Legacy alias |
3638

3739
When the infographic command receives `maestro` as the template value, it expands to `["maestro-stack", "maestro-heatmap"]` and generates both sequentially. The MAESTRO templates require MAESTRO layer data in threats.md (Feature 084); when MAESTRO data is absent, a graceful empty state is rendered.
3840

41+
The `executive-architecture` template (and its `exec` alias) is distinct from the other templates in two ways: it is rendered in portrait orientation rather than 16:9 landscape, and it uses a six-section structure instead of the shared Sections 1-5 format. When no Critical or High severity findings exist in the threat model, the spec file is still produced but the image is not — see `references/executive-architecture.md` for the full skip behavior specification.
42+
3943
## Data Source Types
4044

4145
The infographic agent consumes one of three data source types, auto-detected by richness:
@@ -52,7 +56,8 @@ Reference files are loaded on-demand by the threat-infographic agent at specific
5256

5357
| Reference | File | Load When |
5458
|-----------|------|-----------|
55-
| Infographic Specifications | `references/infographic-specifications.md` | Generating Sections 1-4 of any template specification |
56-
| Template-Specific Formats | `references/template-specific-formats.md` | Generating Section 5 for any template (Baseball Card, System Architecture, or Risk Funnel) |
59+
| Infographic Specifications | `references/infographic-specifications.md` | Generating Sections 1-4 of any shared-format template (Baseball Card, System Architecture, Risk Funnel, MAESTRO Stack, MAESTRO Heatmap) |
60+
| Template-Specific Formats | `references/template-specific-formats.md` | Generating Section 5 for any shared-format template |
61+
| Executive Architecture | `references/executive-architecture.md` | Generating the full six-section spec for the `executive-architecture` template (or its `exec` alias) — distinct section structure, portrait orientation, and PDF positioning rules |
5762
| Gemini Prompt Construction | `references/gemini-prompt-construction.md` | Constructing the Gemini API image generation prompt after specification is complete |
58-
| Visual Design System | `references/visual-design-system.md` | Generating Section 6 (Visual Design Directives) and populating template styling |
63+
| Visual Design System | `references/visual-design-system.md` | Generating Section 6 (Visual Design Directives) and populating template styling for the shared-format templates |

0 commit comments

Comments
 (0)