{{ system.name }}
Version {{ system.version }}
Content digest (SHA-256){{ rmf.sha256_hash }}
Purpose: {{ system.purpose }}
Annex III category: {{ category_label }}
Self-classification documented: {{ 'Yes' if system.annex_iii_self_classification_documented else 'No, see gate G2' }}
Risk items: {{ register.items | length }} in total. Before treatment, {{ register.items_above_appetite() | length }} scored above the risk appetite threshold of {{ register.risk_appetite_threshold }}; after treatment, {{ register.open_items() | length }} remain open.
Knowledge gaps: {{ register.knowledge_gaps() | length }}
| Field | Value |
|---|---|
| System ID | {{ system.id }} |
| Name | {{ system.name }} |
| Version | {{ system.version }} |
| Provider | {{ system.provider_name }} |
| Provider contact | {{ or_na(system.provider_contact) }} |
| Intended users | {{ or_na(system.intended_users | join(', ')) }} |
| Inputs | {{ or_na(system.inputs | join(', ')) }} |
| Outputs | {{ or_na(system.outputs | join(', ')) }} |
| Deployment context | {{ or_na(system.deployment_context) }} |
{{ rmf.disclosure }}
The assessment uses the RiskForge question bank, version {{ register.question_bank_version }}, across {{ dimensions | length }} risk dimensions: {{ dimensions | map('replace', '_', ' ') | join(', ') }}.
Each risk is scored for likelihood and severity on a five-point scale. The risk score is likelihood times severity, from 1 to 25. Bands: low 1 to 4, medium 5 to 9, high 10 to 16, critical 17 to 25. Likelihood and severity are scored again after mitigation to give the residual score.
A risk is open while its residual score is above the risk appetite threshold of {{ register.risk_appetite_threshold }} and it has not been accepted with a written rationale. Gate G3 fails while any risk is open.
Risk patterns applied: {{ patterns_used | join(', ') if patterns_used else 'none' }}.
Readiness gates G1 to G8 are the checks riskforge validate runs. A FAIL gate
blocks export unless the export is forced. Results at export:
{% for gate in gates %}{{ gate.gate_id }} {{ gate.status.value }}{% if not loop.last %}, {% endif %}{% endfor %}
Risk appetite threshold: {{ register.risk_appetite_threshold }} (residual scores above it need mitigation or acceptance).
{% for dim in dimensions %} {% set dim_items = items | selectattr('dimension.value', 'equalto', dim) | list %}{{ item.description }}
| Likelihood | {{ item.likelihood.name }} ({{ item.likelihood.value }}) | Severity | {{ item.severity.name }} ({{ item.severity.value }}) |
| Residual likelihood | {{ item.residual_likelihood.name }} ({{ item.residual_likelihood.value }}) | Residual severity | {{ item.residual_severity.name }} ({{ item.residual_severity.value }}) |
| Source | {{ item.source }} | Regulatory status | {{ item.regulatory_status }} |
Article refs: {{ item.article_refs | join(', ') }}
{% endif %} {% set nist = item.nist_rmf_refs or ([item.nist_rmf_ref] if item.nist_rmf_ref else []) %} {% set iso = item.iso42001_refs or ([item.iso42001_ref] if item.iso42001_ref else []) %} {% if nist or iso %}{% if nist %}NIST AI RMF: {{ nist | join(', ') }}{% endif %}{% if nist and iso %} | {% endif %}{% if iso %}ISO/IEC 42001: {{ iso | join(', ') }}{% endif %}
{% endif %} {% if item.mitigations %}No risk items recorded for this dimension.
{% endif %} {% endfor %}| Risk | Inherent | Residual | Mitigations | Decision and rationale |
|---|---|---|---|---|
| {{ item.title | display_title }} | {{ item.risk_score }} ({{ item.risk_band }}) | {{ item.residual_risk_score }} ({{ item.residual_risk_band }}) | {{ item.mitigations | length }} | {% if item.accepted %}Accepted: {{ item.acceptance_rationale }}{% elif item.residual_risk_score > register.risk_appetite_threshold %}Open{% else %}Within appetite{% endif %} |
| Risk item | Metric | Threshold | Article |
|---|---|---|---|
{{ t.risk_item_id | string | truncate(8, True, '') }} |
{{ t.metric_type }} | {{ t.threshold_range }} | {{ t.article_ref }} |
No test requirements saved. Run riskforge tests generate to derive them from the risk items.
Every change to this register is recorded in a SHA-256 hash-chained audit trail
stored in .riskforge/audit.jsonl. The JSON, PDF and Markdown exports of
one register state show the same content digest. The rmf.exported entry
of this export, recorded after the file was written, holds the content digest and the
SHA-256 of this file.
| Content digest (SHA-256) | {{ rmf.sha256_hash }} |
| RMF schema version | {{ rmf.rmf_schema_version }} |
| Question bank version | {{ register.question_bank_version }} |
| Generated by | RiskForge {{ riskforge_version }} |
| Generated at | {{ rmf.generated_at.strftime('%d %B %Y %H:%M UTC') }} |
| Chain proof | {% if rmf.chain_proof %}{{ rmf.chain_proof.entries | length }} entries of the {{ rmf.chain_proof.scope }} audit chain, seq {{ rmf.chain_proof.entries[0].seq }} to {{ rmf.chain_proof.entries[-1].seq }}{% else %}Not included{% endif %} |
| Receipt | {% if rmf.receipt %}seq {{ rmf.receipt.seq }}, entry hash {{ rmf.receipt.entry_hash }}{% if rmf.receipt.key_id %}, signed by {{ rmf.receipt.key_id }}{% endif %}{% else %}Not included{% endif %} |
| Signatures | {% if rmf.signatures %}{% for s in rmf.signatures %}{{ s.key_id }} ({{ s.algorithm }}){% if not loop.last %}, {% endif %}{% endfor %}{% else %}Unsigned{% endif %} |
| Sign-offs | {% if rmf.signoffs %}{% for s in rmf.signoffs %}{{ s.approver }}: {{ s.decision }} (version {{ s.version_number }}){% if not loop.last %}; {% endif %}{% endfor %}{% else %}None recorded{% endif %} |
Entries of the chain proof for this system and for the project.
| Seq | Time (UTC) | Event | Actor |
|---|---|---|---|
| {{ e.seq }} | {{ e.timestamp.strftime('%Y-%m-%d %H:%M') }} | {{ e.event }} | {{ e.actor.identity }} |
This export carries no chain proof.
{% endif %}Verify integrity at any time: riskforge verify. Check the JSON export of this
file with riskforge verify --file.