@metasession.co/devaudit-cli 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +85 -34
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/scripts/upload-evidence.sh +12 -0
- package/sdlc/files/_common/governance/ai-disclosure.md.template +91 -0
- package/sdlc/files/_common/governance/dpia.md.template +78 -0
- package/sdlc/files/_common/governance/incident-report.md.template +111 -0
- package/sdlc/files/_common/governance/periodic-review.md.template +107 -0
- package/sdlc/files/_common/governance/ropa.md.template +59 -0
- package/sdlc/files/_common/scripts/derive-release-version.sh +36 -0
- package/sdlc/files/_common/scripts/derive-release-version.test.sh +83 -0
- package/sdlc/files/_common/scripts/validate-commits.sh +4 -1
- package/sdlc/files/ci/ci.yml.template +61 -3
- package/sdlc/files/ci/python/ci.yml.template +61 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metasession.co/devaudit-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "DevAudit CLI — installs, syncs, and operates the Metasession SDLC across consumer projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^0.8.2",
|
|
36
|
-
"@metasession.co/devaudit-plugin-sdk": "^0.1.
|
|
36
|
+
"@metasession.co/devaudit-plugin-sdk": "^0.1.30",
|
|
37
37
|
"commander": "^12.1.0",
|
|
38
38
|
"consola": "^3.2.3",
|
|
39
39
|
"env-paths": "^3.0.0",
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
# build / test / compliance / revert) for
|
|
27
27
|
# the release row. Unknown values are
|
|
28
28
|
# silently dropped server-side.
|
|
29
|
+
# --gate-status <status> `passed` / `failed` / `skipped`. Lets the
|
|
30
|
+
# portal distinguish a gate that ran-and-
|
|
31
|
+
# failed from one that never ran. Forwarded
|
|
32
|
+
# as `gateStatus`; unknown values are
|
|
33
|
+
# silently dropped server-side.
|
|
34
|
+
# DevAudit-Installer#96.
|
|
29
35
|
#
|
|
30
36
|
# Required environment variables:
|
|
31
37
|
# DEVAUDIT_BASE_URL e.g. https://meta-comply-production.up.railway.app
|
|
@@ -65,6 +71,7 @@ ENVIRONMENT=""
|
|
|
65
71
|
EVIDENCE_CATEGORY=""
|
|
66
72
|
RELEASE_TITLE=""
|
|
67
73
|
CHANGE_TYPE=""
|
|
74
|
+
GATE_STATUS=""
|
|
68
75
|
|
|
69
76
|
while [ "$#" -gt 0 ]; do
|
|
70
77
|
case "$1" in
|
|
@@ -80,6 +87,10 @@ while [ "$#" -gt 0 ]; do
|
|
|
80
87
|
# unknown change-type values are dropped server-side, not 400'd.
|
|
81
88
|
--release-title) RELEASE_TITLE="$2"; shift 2 ;;
|
|
82
89
|
--change-type) CHANGE_TYPE="$2"; shift 2 ;;
|
|
90
|
+
# passed/failed/skipped — surfaces failed gates on the portal so
|
|
91
|
+
# ran-and-failed != never-ran. Unknown values dropped server-side.
|
|
92
|
+
# DevAudit-Installer#96.
|
|
93
|
+
--gate-status) GATE_STATUS="$2"; shift 2 ;;
|
|
83
94
|
*) echo "Unknown option: $1"; exit 1 ;;
|
|
84
95
|
esac
|
|
85
96
|
done
|
|
@@ -181,6 +192,7 @@ for FILE in "${FILES[@]}"; do
|
|
|
181
192
|
[ -n "$EVIDENCE_CATEGORY" ] && CURL_ARGS+=(-F "evidenceCategory=${EVIDENCE_CATEGORY}")
|
|
182
193
|
[ -n "$RELEASE_TITLE" ] && CURL_ARGS+=(-F "releaseTitle=${RELEASE_TITLE}")
|
|
183
194
|
[ -n "$CHANGE_TYPE" ] && CURL_ARGS+=(-F "changeType=${CHANGE_TYPE}")
|
|
195
|
+
[ -n "$GATE_STATUS" ] && CURL_ARGS+=(-F "gateStatus=${GATE_STATUS}")
|
|
184
196
|
|
|
185
197
|
ATTEMPT=1
|
|
186
198
|
BACKOFF=$INITIAL_BACKOFF_SECONDS
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "AI Use Disclosure (deployer-facing)"
|
|
3
|
+
provider: "REPLACE — legal name of the AI system provider"
|
|
4
|
+
intended_purpose: "REPLACE — one-line description of intended use"
|
|
5
|
+
last_reviewed_at: "REPLACE — YYYY-MM-DD"
|
|
6
|
+
review_cadence_days: 180
|
|
7
|
+
risk_class: "REPLACE — minimal | limited | high | unacceptable"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
> ⚠️ **STARTER TEMPLATE — REPLACE BEFORE GOING TO PRODUCTION.**
|
|
11
|
+
> This file was auto-installed by `devaudit install` as a starting point.
|
|
12
|
+
> It does **not** describe your project's actual AI use. Edit and commit.
|
|
13
|
+
> Auditors will reject unedited stubs. See `docs/governance-templates.md` for guidance.
|
|
14
|
+
|
|
15
|
+
# AI Use Disclosure — Provision of information to deployers
|
|
16
|
+
|
|
17
|
+
**Framework coverage:** `EUAIA.Art-13` (Transparency and provision of information to deployers)
|
|
18
|
+
|
|
19
|
+
**Evidence type:** `ai_disclosure` · **Cadence:** refresh every 180 days, or whenever an AI tool / model / prompt-class is added or substantively changed.
|
|
20
|
+
|
|
21
|
+
> The EU AI Act requires providers to give deployers (the people who put the AI system into use in their professional activity) **clear, comprehensive, accurate and unambiguous** information about the system's capabilities, limitations, and intended use. This file is that disclosure for our project — both for AI we develop and for third-party AI we incorporate.
|
|
22
|
+
|
|
23
|
+
## 1. Intended purpose
|
|
24
|
+
|
|
25
|
+
- **What the AI system does:** REPLACE
|
|
26
|
+
- **Intended use cases:** REPLACE
|
|
27
|
+
- **Foreseeable misuse / out-of-scope use cases:** REPLACE
|
|
28
|
+
|
|
29
|
+
## 2. Risk classification
|
|
30
|
+
|
|
31
|
+
- **Annex III high-risk category match:** REPLACE — none / list applicable categories
|
|
32
|
+
- **Final risk class (per Title III):** REPLACE — minimal / limited / high / unacceptable
|
|
33
|
+
- **Reasoning:** REPLACE
|
|
34
|
+
|
|
35
|
+
## 3. AI tools and models in use
|
|
36
|
+
|
|
37
|
+
Add one row per AI tool / model / API. Delete this template row before your first audit.
|
|
38
|
+
|
|
39
|
+
| Tool / model | Vendor | Use case | Inputs (data classes) | Outputs | Risk class | Provider docs |
|
|
40
|
+
|---|---|---|---|---|---|---|
|
|
41
|
+
| REPLACE — e.g. GPT-4o | OpenAI | Code suggestion in IDE | Source code, no PII | Code suggestions | Limited | https://… |
|
|
42
|
+
| REPLACE | | | | | | |
|
|
43
|
+
|
|
44
|
+
## 4. Human oversight (Art. 14)
|
|
45
|
+
|
|
46
|
+
- **Where humans intervene in the AI loop:** REPLACE — e.g. "Every AI-suggested change goes through a four-eyes code review before merge"
|
|
47
|
+
- **Authority of the human reviewer:** REPLACE — can they reject / override / stop the system? Document the path
|
|
48
|
+
- **Cross-reference to four-eyes release approval:** all releases require an approved-by audit event in the portal (closes `EUAIA.Art-14`)
|
|
49
|
+
|
|
50
|
+
## 5. Capabilities and limitations
|
|
51
|
+
|
|
52
|
+
- **Known limitations:** REPLACE — failure modes, training data cut-off, hallucination risk
|
|
53
|
+
- **Accuracy / robustness metrics:** REPLACE — link to test reports / benchmark results
|
|
54
|
+
- **Conditions under which performance degrades:** REPLACE
|
|
55
|
+
|
|
56
|
+
## 6. Data, training, validation
|
|
57
|
+
|
|
58
|
+
- **Training data provenance (if we train):** REPLACE — sources, licensing, consent
|
|
59
|
+
- **Fine-tuning, RAG, prompt engineering used:** REPLACE
|
|
60
|
+
- **Data flowing to third-party AI providers:** REPLACE — list each provider + what's sent + DPA / SCC reference (cross-link to ROPA)
|
|
61
|
+
|
|
62
|
+
## 7. Logging and traceability (Art. 12)
|
|
63
|
+
|
|
64
|
+
- **What we log:** REPLACE — prompts, completions, user/agent identity, timestamp
|
|
65
|
+
- **Where logs live:** REPLACE — link to portal `audit_log` evidence pipeline
|
|
66
|
+
- **Retention:** REPLACE
|
|
67
|
+
- **Closes `EUAIA.Art-12` via the `audit_log` snapshot uploaded each release.**
|
|
68
|
+
|
|
69
|
+
## 8. Deployer obligations
|
|
70
|
+
|
|
71
|
+
- **What deployers must do to use the system safely:** REPLACE — link to operator runbook
|
|
72
|
+
- **Notification of substantial modifications:** REPLACE — process
|
|
73
|
+
|
|
74
|
+
## 9. Sign-off
|
|
75
|
+
|
|
76
|
+
| Role | Name | Date |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| Provider responsible | REPLACE | REPLACE |
|
|
79
|
+
| AI compliance reviewer | REPLACE | REPLACE |
|
|
80
|
+
|
|
81
|
+
## Sources
|
|
82
|
+
|
|
83
|
+
- [EU AI Act (Regulation 2024/1689)](https://eur-lex.europa.eu/eli/reg/2024/1689/oj) — especially Art. 9–15 (high-risk requirements) and Title IV (transparency)
|
|
84
|
+
- [NIST AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework)
|
|
85
|
+
- [Anthropic Responsible Scaling Policy](https://www.anthropic.com/news/anthropics-responsible-scaling-policy) (example provider disclosure)
|
|
86
|
+
|
|
87
|
+
## Review log
|
|
88
|
+
|
|
89
|
+
| Date | Reviewer | Changes |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| REPLACE — YYYY-MM-DD | REPLACE | Initial AI disclosure authored from starter template |
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Data Protection Impact Assessment (DPIA)"
|
|
3
|
+
processing_activity: "REPLACE — short name of the activity assessed"
|
|
4
|
+
controller: "REPLACE — legal name of the controller"
|
|
5
|
+
last_reviewed_at: "REPLACE — YYYY-MM-DD"
|
|
6
|
+
review_cadence_days: 365
|
|
7
|
+
risk_level: "REPLACE — low | medium | high"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
> ⚠️ **STARTER TEMPLATE — REPLACE BEFORE GOING TO PRODUCTION.**
|
|
11
|
+
> This file was auto-installed by `devaudit install` as a starting point.
|
|
12
|
+
> It does **not** describe your project's actual data protection risks. Edit and commit.
|
|
13
|
+
> Auditors will reject unedited stubs. See `docs/governance-templates.md` for guidance.
|
|
14
|
+
|
|
15
|
+
# Data Protection Impact Assessment
|
|
16
|
+
|
|
17
|
+
**Framework coverage:** `GDPR.Art-35` (Data protection impact assessment)
|
|
18
|
+
|
|
19
|
+
**Evidence type:** `dpia` · **Cadence:** refresh every 365 days, or whenever the processing materially changes.
|
|
20
|
+
|
|
21
|
+
> A DPIA is **mandatory** for processing likely to result in high risk to data subjects: large-scale special-category data, systematic monitoring, automated decision-making with legal effect, etc. See Art. 35(3) and your supervisory authority's "blacklist" guidance.
|
|
22
|
+
|
|
23
|
+
## 1. Description of the processing
|
|
24
|
+
|
|
25
|
+
- **Activity name:** REPLACE
|
|
26
|
+
- **Nature, scope, context, purposes:** REPLACE — what data is processed, how, why, for whom, at what scale
|
|
27
|
+
- **Data flow diagram or reference:** REPLACE — link to architecture doc / threat model
|
|
28
|
+
- **Cross-reference to ROPA:** `compliance/governance/ropa.md` activity REPLACE
|
|
29
|
+
|
|
30
|
+
## 2. Necessity and proportionality
|
|
31
|
+
|
|
32
|
+
- **Lawful basis (Art. 6):** REPLACE
|
|
33
|
+
- **Special-category basis (Art. 9), if applicable:** REPLACE
|
|
34
|
+
- **Less-intrusive alternatives considered:** REPLACE
|
|
35
|
+
- **Data minimisation:** REPLACE — what's not collected and why
|
|
36
|
+
- **Retention justification:** REPLACE
|
|
37
|
+
- **Data subject rights — how exercised:** REPLACE — link to SAR procedure, rectification, erasure, portability
|
|
38
|
+
|
|
39
|
+
## 3. Risks to rights and freedoms
|
|
40
|
+
|
|
41
|
+
For each risk, populate one row. Add or remove rows to fit your assessment.
|
|
42
|
+
|
|
43
|
+
| # | Risk | Likelihood (1–3) | Severity (1–3) | Inherent risk | Existing controls | Residual risk | Acceptable? |
|
|
44
|
+
|---|---|---|---|---|---|---|---|
|
|
45
|
+
| 1 | REPLACE — e.g. unauthorised access to user accounts | REPLACE | REPLACE | REPLACE | REPLACE — MFA, RBAC, encryption-at-rest | REPLACE | REPLACE Y/N |
|
|
46
|
+
| 2 | REPLACE | | | | | | |
|
|
47
|
+
|
|
48
|
+
## 4. Measures to address the risks
|
|
49
|
+
|
|
50
|
+
- **Technical measures:** REPLACE — encryption, pseudonymisation, access controls, logging
|
|
51
|
+
- **Organisational measures:** REPLACE — training, policies, contractual safeguards
|
|
52
|
+
- **Residual high risk?** REPLACE — if YES, you must consult the supervisory authority (Art. 36) **before** processing begins. Document the consultation outcome.
|
|
53
|
+
|
|
54
|
+
## 5. Consultation
|
|
55
|
+
|
|
56
|
+
- **DPO opinion:** REPLACE — name, date, conclusion
|
|
57
|
+
- **Data subjects / representatives consulted:** REPLACE — describe or document why not
|
|
58
|
+
- **Supervisory authority prior consultation:** REPLACE — required only when residual high risk remains
|
|
59
|
+
|
|
60
|
+
## 6. Sign-off
|
|
61
|
+
|
|
62
|
+
| Role | Name | Date | Decision |
|
|
63
|
+
|---|---|---|---|
|
|
64
|
+
| Controller | REPLACE | REPLACE | REPLACE — approved / rejected / conditional |
|
|
65
|
+
| DPO | REPLACE | REPLACE | REPLACE |
|
|
66
|
+
| Technical lead | REPLACE | REPLACE | REPLACE |
|
|
67
|
+
|
|
68
|
+
## Sources
|
|
69
|
+
|
|
70
|
+
- [EDPB DPIA guidelines (WP248 rev.01)](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/)
|
|
71
|
+
- [ICO DPIA template](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/accountability-and-governance/data-protection-impact-assessments-dpias/)
|
|
72
|
+
- [CNIL PIA software](https://www.cnil.fr/en/open-source-pia-software-helps-carry-out-data-protection-impact-assessment)
|
|
73
|
+
|
|
74
|
+
## Review log
|
|
75
|
+
|
|
76
|
+
| Date | Reviewer | Changes |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| REPLACE — YYYY-MM-DD | REPLACE | Initial DPIA authored from starter template |
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Incident Report"
|
|
3
|
+
incident_id: "REPLACE — e.g. INC-2026-001"
|
|
4
|
+
severity: "REPLACE — low | medium | high | critical"
|
|
5
|
+
detected_at: "REPLACE — ISO-8601 with timezone"
|
|
6
|
+
resolved_at: "REPLACE — ISO-8601 or 'ongoing'"
|
|
7
|
+
involves_personal_data: "REPLACE — true | false"
|
|
8
|
+
reported_to_supervisory_authority: "REPLACE — true | false | n/a"
|
|
9
|
+
notification_window_72h: "REPLACE — within | outside | n/a"
|
|
10
|
+
last_reviewed_at: "REPLACE — YYYY-MM-DD"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
> ⚠️ **STARTER TEMPLATE — REPLACE BEFORE GOING TO PRODUCTION.**
|
|
14
|
+
> This file was auto-installed by `devaudit install` as a starting point.
|
|
15
|
+
> If you reach for this file it's because something **happened** — replace this banner
|
|
16
|
+
> with the actual incident details. One incident per file (rename to
|
|
17
|
+
> `incident-report-<id>.md` if you keep multiple). Auditors will reject unedited stubs.
|
|
18
|
+
|
|
19
|
+
# Incident Report
|
|
20
|
+
|
|
21
|
+
**Framework coverage:**
|
|
22
|
+
|
|
23
|
+
- `ISO29119.3.5.4` (Test incident report)
|
|
24
|
+
- `SOC2.CC7.2` (System monitoring and incident response)
|
|
25
|
+
- `GDPR.Art-33` (Notification of a personal data breach to the supervisory authority — 72h)
|
|
26
|
+
- `GDPR.Art-34` (Communication of a personal data breach to the data subject)
|
|
27
|
+
|
|
28
|
+
**Evidence type:** `incident_report` · One artefact can satisfy multiple clauses depending on its scope (test defect, ops incident, personal-data breach).
|
|
29
|
+
|
|
30
|
+
## 1. Summary
|
|
31
|
+
|
|
32
|
+
- **Incident ID:** REPLACE
|
|
33
|
+
- **Severity:** REPLACE — low / medium / high / critical
|
|
34
|
+
- **One-line description:** REPLACE
|
|
35
|
+
- **Detected at:** REPLACE — when was it first noticed
|
|
36
|
+
- **Resolved at:** REPLACE — or "ongoing"
|
|
37
|
+
- **Duration:** REPLACE
|
|
38
|
+
|
|
39
|
+
## 2. Personal data scope (GDPR triage)
|
|
40
|
+
|
|
41
|
+
| Question | Answer |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Did the incident involve personal data? | REPLACE — Y / N |
|
|
44
|
+
| If Y: estimated number of data subjects affected | REPLACE |
|
|
45
|
+
| If Y: categories of personal data involved | REPLACE |
|
|
46
|
+
| If Y: likely consequences for data subjects | REPLACE |
|
|
47
|
+
| **Notify supervisory authority (Art. 33)?** | REPLACE — required if Y and risk to rights/freedoms |
|
|
48
|
+
| **Notify data subjects (Art. 34)?** | REPLACE — required if high risk to rights/freedoms |
|
|
49
|
+
| 72-hour notification window: | REPLACE — within / outside / n/a; if outside, explain delay |
|
|
50
|
+
|
|
51
|
+
## 3. Timeline
|
|
52
|
+
|
|
53
|
+
| Time (UTC) | Event |
|
|
54
|
+
|---|---|
|
|
55
|
+
| REPLACE — ISO-8601 | REPLACE — first signal observed |
|
|
56
|
+
| REPLACE | REPLACE — detection escalated to on-call |
|
|
57
|
+
| REPLACE | REPLACE — incident channel opened, IC assigned |
|
|
58
|
+
| REPLACE | REPLACE — mitigation deployed |
|
|
59
|
+
| REPLACE | REPLACE — incident declared resolved |
|
|
60
|
+
| REPLACE | REPLACE — supervisory authority notified (if applicable) |
|
|
61
|
+
| REPLACE | REPLACE — data subjects notified (if applicable) |
|
|
62
|
+
|
|
63
|
+
## 4. Root cause
|
|
64
|
+
|
|
65
|
+
- **What happened:** REPLACE — technical narrative
|
|
66
|
+
- **Why it happened:** REPLACE — 5-whys or equivalent
|
|
67
|
+
- **Why it wasn't caught earlier:** REPLACE — gap in monitoring / testing / review
|
|
68
|
+
|
|
69
|
+
## 5. Impact
|
|
70
|
+
|
|
71
|
+
- **Users affected:** REPLACE — count + segment
|
|
72
|
+
- **Data confidentiality / integrity / availability impact:** REPLACE
|
|
73
|
+
- **Financial / reputational:** REPLACE
|
|
74
|
+
- **Regulatory:** REPLACE
|
|
75
|
+
|
|
76
|
+
## 6. Containment, mitigation, and recovery
|
|
77
|
+
|
|
78
|
+
- **Containment actions:** REPLACE
|
|
79
|
+
- **Mitigation deployed (link PRs):** REPLACE
|
|
80
|
+
- **Recovery actions:** REPLACE
|
|
81
|
+
- **Verification that the incident is resolved:** REPLACE
|
|
82
|
+
|
|
83
|
+
## 7. Communications
|
|
84
|
+
|
|
85
|
+
- **Internal:** REPLACE — who was notified, when
|
|
86
|
+
- **Customer / data subjects:** REPLACE — channel, content (attach), timing
|
|
87
|
+
- **Supervisory authority:** REPLACE — body, reference number, content (attach)
|
|
88
|
+
- **Public statement:** REPLACE — link if any
|
|
89
|
+
|
|
90
|
+
## 8. Lessons learned and follow-ups
|
|
91
|
+
|
|
92
|
+
- **What worked well:** REPLACE
|
|
93
|
+
- **What didn't:** REPLACE
|
|
94
|
+
- **Follow-up actions (issue links, owners, due dates):** REPLACE — file GitHub issues; one row per action
|
|
95
|
+
- [ ] REPLACE — owner @REPLACE — due REPLACE
|
|
96
|
+
- [ ] REPLACE — owner @REPLACE — due REPLACE
|
|
97
|
+
|
|
98
|
+
## 9. Sign-off
|
|
99
|
+
|
|
100
|
+
| Role | Name | Date |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| Incident Commander | REPLACE | REPLACE |
|
|
103
|
+
| Engineering lead | REPLACE | REPLACE |
|
|
104
|
+
| DPO (if personal data involved) | REPLACE | REPLACE |
|
|
105
|
+
| Security lead | REPLACE | REPLACE |
|
|
106
|
+
|
|
107
|
+
## Sources
|
|
108
|
+
|
|
109
|
+
- [ICO breach reporting guidance](https://ico.org.uk/for-organisations/report-a-breach/personal-data-breach/) (UK)
|
|
110
|
+
- [EDPB Guidelines 9/2022 on personal data breach notification](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/)
|
|
111
|
+
- [SOC 2 Trust Services Criteria — CC7 (System Operations)](https://www.aicpa-cima.com/topic/audit-assurance/trust-services-criteria)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Periodic Review of Internal Controls"
|
|
3
|
+
period_start: "REPLACE — YYYY-MM-DD"
|
|
4
|
+
period_end: "REPLACE — YYYY-MM-DD"
|
|
5
|
+
reviewer: "REPLACE — name + role"
|
|
6
|
+
last_reviewed_at: "REPLACE — YYYY-MM-DD"
|
|
7
|
+
review_cadence_days: 90
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
> ⚠️ **STARTER TEMPLATE — REPLACE BEFORE GOING TO PRODUCTION.**
|
|
11
|
+
> This file was auto-installed by `devaudit install` as a starting point.
|
|
12
|
+
> Once Workstream 3 ships (`.github/workflows/periodic-review.yml`), this file will be
|
|
13
|
+
> auto-regenerated quarterly with portal metrics. Until then — and to add the human
|
|
14
|
+
> attestation the auto-generator can't produce — edit this file yourself. Auditors
|
|
15
|
+
> will reject unedited stubs. See `docs/governance-templates.md` for guidance.
|
|
16
|
+
|
|
17
|
+
# Periodic Review of Internal Controls
|
|
18
|
+
|
|
19
|
+
**Framework coverage:**
|
|
20
|
+
|
|
21
|
+
- `SOC2.CC4.1` (Monitoring of internal controls)
|
|
22
|
+
- `ISO27001.A.12.1` (Operational procedures and responsibilities)
|
|
23
|
+
|
|
24
|
+
**Evidence type:** `periodic_review` · **Cadence:** every 90 days (quarterly). The portal flags this evidence as `expired` after 365 days — but a 90-day cadence is the practical minimum.
|
|
25
|
+
|
|
26
|
+
## 1. Review period
|
|
27
|
+
|
|
28
|
+
- **From:** REPLACE — YYYY-MM-DD
|
|
29
|
+
- **To:** REPLACE — YYYY-MM-DD
|
|
30
|
+
- **Reviewer:** REPLACE — name + role
|
|
31
|
+
- **Approver (different person, if dual-actor required):** REPLACE
|
|
32
|
+
|
|
33
|
+
## 2. Activity summary (CI-derived, auto-fill when WS3 lands)
|
|
34
|
+
|
|
35
|
+
| Metric | Value | Notes |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| Releases shipped this period | REPLACE | Tracked + housekeeping combined |
|
|
38
|
+
| Tracked releases (REQ-XXX) | REPLACE | |
|
|
39
|
+
| Quality-gate pass rate | REPLACE — % | % of CI runs where every gate passed |
|
|
40
|
+
| SAST findings net change | REPLACE | +/- vs. previous period |
|
|
41
|
+
| Dependency-audit unaccepted high/critical | REPLACE | Current count |
|
|
42
|
+
| Audit-log entries | REPLACE | Total in period |
|
|
43
|
+
| Open SDLC issues at period end | REPLACE | From `gh issue list --label requirement --state open` |
|
|
44
|
+
|
|
45
|
+
## 3. Control-effectiveness review
|
|
46
|
+
|
|
47
|
+
For each control area, document evidence + reviewer judgement.
|
|
48
|
+
|
|
49
|
+
### 3a. Access control (ISO 27001 A.5.15)
|
|
50
|
+
|
|
51
|
+
- **Active access grants reviewed:** REPLACE — list or attach export
|
|
52
|
+
- **Grants revoked this period:** REPLACE — count + reason
|
|
53
|
+
- **Anomalies:** REPLACE — or "none"
|
|
54
|
+
- **Effective?** REPLACE — Y / N (if N, follow-up action below)
|
|
55
|
+
|
|
56
|
+
### 3b. Change management (ISO 27001 A.8.32 / SOC 2 CC8.1)
|
|
57
|
+
|
|
58
|
+
- **Releases approved via four-eyes flow:** REPLACE — N of M
|
|
59
|
+
- **Self-approval blocked on MEDIUM/HIGH risk?** REPLACE — confirm enforcement
|
|
60
|
+
- **Effective?** REPLACE
|
|
61
|
+
|
|
62
|
+
### 3c. Security testing (ISO 27001 A.8.29)
|
|
63
|
+
|
|
64
|
+
- **SAST gate pass rate:** REPLACE
|
|
65
|
+
- **Dependency-audit gate pass rate:** REPLACE
|
|
66
|
+
- **E2E gate pass rate:** REPLACE
|
|
67
|
+
- **Effective?** REPLACE
|
|
68
|
+
|
|
69
|
+
### 3d. Logging and monitoring (ISO 27001 A.8.16 / EUAIA Art. 12)
|
|
70
|
+
|
|
71
|
+
- **Audit-log entries reviewed:** REPLACE — sample size + method
|
|
72
|
+
- **Anomalies escalated:** REPLACE — count
|
|
73
|
+
- **Effective?** REPLACE
|
|
74
|
+
|
|
75
|
+
### 3e. Operational procedures (ISO 27001 A.12.1)
|
|
76
|
+
|
|
77
|
+
- **Procedures reviewed this period:** REPLACE — list (link `Periodic_Security_Review_Schedule.md` items completed)
|
|
78
|
+
- **Stale / out-of-date docs:** REPLACE
|
|
79
|
+
- **Effective?** REPLACE
|
|
80
|
+
|
|
81
|
+
## 4. Incidents this period
|
|
82
|
+
|
|
83
|
+
- **Total incidents:** REPLACE — link each `compliance/governance/incident-report-*.md`
|
|
84
|
+
- **Personal-data breaches:** REPLACE — count
|
|
85
|
+
- **Mean time to detection (MTTD):** REPLACE
|
|
86
|
+
- **Mean time to resolution (MTTR):** REPLACE
|
|
87
|
+
|
|
88
|
+
## 5. Findings and follow-up actions
|
|
89
|
+
|
|
90
|
+
| # | Finding | Severity | Owner | Due | Issue link |
|
|
91
|
+
|---|---|---|---|---|---|
|
|
92
|
+
| 1 | REPLACE | REPLACE | REPLACE | REPLACE | REPLACE |
|
|
93
|
+
| 2 | REPLACE | | | | |
|
|
94
|
+
|
|
95
|
+
## 6. Sign-off
|
|
96
|
+
|
|
97
|
+
| Role | Name | Date |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| Reviewer | REPLACE | REPLACE |
|
|
100
|
+
| Approver (dual-actor) | REPLACE | REPLACE |
|
|
101
|
+
| Decision | REPLACE — controls effective / partially effective / not effective |
|
|
102
|
+
|
|
103
|
+
## Sources
|
|
104
|
+
|
|
105
|
+
- [SOC 2 Trust Services Criteria — CC4 (Monitoring)](https://www.aicpa-cima.com/topic/audit-assurance/trust-services-criteria)
|
|
106
|
+
- [ISO/IEC 27001:2022 Annex A.12 — Operational security](https://www.iso.org/standard/82875.html)
|
|
107
|
+
- Your project's `Periodic_Security_Review_Schedule.md`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Records of Processing Activities (ROPA)"
|
|
3
|
+
controller: "REPLACE — legal name of the controller"
|
|
4
|
+
controller_contact: "REPLACE — DPO email or controller contact"
|
|
5
|
+
last_reviewed_at: "REPLACE — YYYY-MM-DD"
|
|
6
|
+
review_cadence_days: 365
|
|
7
|
+
processing_activities: []
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
> ⚠️ **STARTER TEMPLATE — REPLACE BEFORE GOING TO PRODUCTION.**
|
|
11
|
+
> This file was auto-installed by `devaudit install` as a starting point.
|
|
12
|
+
> It does **not** describe your project's actual processing activities. Edit and commit.
|
|
13
|
+
> Auditors will reject unedited stubs. See `docs/governance-templates.md` for guidance.
|
|
14
|
+
|
|
15
|
+
# Records of Processing Activities
|
|
16
|
+
|
|
17
|
+
**Framework coverage:** `GDPR.Art-30` (Records of processing activities)
|
|
18
|
+
|
|
19
|
+
**Evidence type:** `ropa` · **Cadence:** refresh every 365 days (portal flags as `expired` after)
|
|
20
|
+
|
|
21
|
+
## Controller
|
|
22
|
+
|
|
23
|
+
- **Legal name:** REPLACE
|
|
24
|
+
- **Address:** REPLACE
|
|
25
|
+
- **Contact / DPO:** REPLACE
|
|
26
|
+
- **Joint controllers / representatives:** REPLACE (or "none")
|
|
27
|
+
|
|
28
|
+
## Processing activities
|
|
29
|
+
|
|
30
|
+
For each distinct processing activity your project performs, add one section below. Delete this template row before your first audit.
|
|
31
|
+
|
|
32
|
+
### Activity 1 — REPLACE (e.g. "User authentication and session management")
|
|
33
|
+
|
|
34
|
+
| Field | Value |
|
|
35
|
+
|---|---|
|
|
36
|
+
| **Purpose(s) of processing** | REPLACE — why you process this data; lawful basis (Art. 6) |
|
|
37
|
+
| **Categories of data subjects** | REPLACE — e.g. customers, employees, prospects |
|
|
38
|
+
| **Categories of personal data** | REPLACE — e.g. name, email, IP address, hashed password |
|
|
39
|
+
| **Special categories (Art. 9)** | REPLACE — none / specify (health, biometric, etc.) |
|
|
40
|
+
| **Recipients / categories of recipients** | REPLACE — internal teams + named processors |
|
|
41
|
+
| **Third-country transfers** | REPLACE — none / list countries + safeguard (SCCs, adequacy) |
|
|
42
|
+
| **Retention period** | REPLACE — e.g. "duration of customer relationship + 7 years" |
|
|
43
|
+
| **Technical and organisational security measures** | REPLACE — link to ISO 27001 controls / Test_Policy.md / encryption details |
|
|
44
|
+
|
|
45
|
+
### Activity 2 — REPLACE
|
|
46
|
+
|
|
47
|
+
(repeat the table above)
|
|
48
|
+
|
|
49
|
+
## Sources
|
|
50
|
+
|
|
51
|
+
- [ICO ROPA template (UK)](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/accountability-and-governance/documentation/records-of-processing/)
|
|
52
|
+
- [EDPB Guidelines on Article 30](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/)
|
|
53
|
+
- Your privacy policy + DPIA (`compliance/governance/dpia.md`) should describe the same activities.
|
|
54
|
+
|
|
55
|
+
## Review log
|
|
56
|
+
|
|
57
|
+
| Date | Reviewer | Changes |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| REPLACE — YYYY-MM-DD | REPLACE | Initial ROPA authored from starter template |
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
# 4. Pending release ticket on disk: exactly one
|
|
14
14
|
# compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md
|
|
15
15
|
# -> REQ-XXX
|
|
16
|
+
# 4-bis. RTM.md IN PROGRESS row: exactly one tracked REQ marked
|
|
17
|
+
# IN PROGRESS in compliance/RTM.md
|
|
18
|
+
# -> REQ-XXX
|
|
16
19
|
# 5. Fallback: bare date -> v2026.05.17
|
|
17
20
|
#
|
|
18
21
|
# Step 4 (DevAudit-Installer#92) handles `chore:` / `docs:` / `ci:`
|
|
@@ -23,6 +26,12 @@
|
|
|
23
26
|
# bare date — when exactly one ticket is open, attribute to it.
|
|
24
27
|
# Multiple open tickets stays ambiguous → bare-date fallback.
|
|
25
28
|
#
|
|
29
|
+
# Step 4-bis (DevAudit-Installer#95) is the zero-ceremony equivalent:
|
|
30
|
+
# RTM.md is the file the operator already maintains as the source of
|
|
31
|
+
# truth for release state. When step 4 finds no ticket and exactly one
|
|
32
|
+
# RTM row is IN PROGRESS, attribute to it. RTM_PATH defaults to
|
|
33
|
+
# compliance/RTM.md and is overridable via env.
|
|
34
|
+
#
|
|
26
35
|
# The id is taken from a bracketed [REQ-XXX] tag (subject or body) or the
|
|
27
36
|
# `Ref:` line — NOT from unbracketed prose (e.g. "target close: REQ-002" must
|
|
28
37
|
# not win over "Ref: REQ-001"). Step 3 exists because a "Merge pull request"
|
|
@@ -83,5 +92,32 @@ if [ -d compliance/pending-releases ]; then
|
|
|
83
92
|
fi
|
|
84
93
|
fi
|
|
85
94
|
|
|
95
|
+
# 4-bis. RTM.md IN PROGRESS row: when exactly one REQ row in
|
|
96
|
+
# compliance/RTM.md (or $RTM_PATH) is marked IN PROGRESS, attribute the
|
|
97
|
+
# in-flight release to it. Reads the file the operator already
|
|
98
|
+
# maintains so chore/docs/ci sync commits don't need a manually-dropped
|
|
99
|
+
# pending-tickets file. Same exactly-one guard as step 4 — zero or
|
|
100
|
+
# multiple IN PROGRESS rows → ambiguous, fall through.
|
|
101
|
+
# DevAudit-Installer#95.
|
|
102
|
+
RTM_PATH="${RTM_PATH:-compliance/RTM.md}"
|
|
103
|
+
if [ -f "$RTM_PATH" ]; then
|
|
104
|
+
# Match REQ rows whose status column starts with `IN PROGRESS`.
|
|
105
|
+
# `\|[[:space:]]+IN PROGRESS` requires a pipe followed by whitespace,
|
|
106
|
+
# so legend rows (`| \`IN PROGRESS\``) and prose mentions don't match.
|
|
107
|
+
# Variable padding between REQ-ID and Status (Issue/Risk/Evidence
|
|
108
|
+
# columns) is fine — only the leading REQ-XXX and the status-cell
|
|
109
|
+
# marker matter.
|
|
110
|
+
IN_PROGRESS_REQS=$(grep -E '\|[[:space:]]+IN PROGRESS' "$RTM_PATH" 2>/dev/null \
|
|
111
|
+
| grep -oE '^\|[[:space:]]*REQ-[0-9]+' \
|
|
112
|
+
| grep -oE 'REQ-[0-9]+' | sort -u || true)
|
|
113
|
+
if [ -n "$IN_PROGRESS_REQS" ]; then
|
|
114
|
+
IN_PROGRESS_COUNT=$(echo "$IN_PROGRESS_REQS" | grep -c .)
|
|
115
|
+
if [ "$IN_PROGRESS_COUNT" = "1" ]; then
|
|
116
|
+
echo "$IN_PROGRESS_REQS"
|
|
117
|
+
exit 0
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
86
122
|
# 5. Fallback: bare date in UTC
|
|
87
123
|
echo "v$(date -u +%Y.%m.%d)"
|
|
@@ -154,6 +154,89 @@ cat > compliance/pending-releases/RELEASE-TICKET-REQ-051.md <<'TICKET'
|
|
|
154
154
|
TICKET
|
|
155
155
|
assert_eq "subject [REQ-099] beats pending REQ-051 -> REQ-099" "REQ-099" "$(run_helper)"
|
|
156
156
|
|
|
157
|
+
# Case 13 (DevAudit-Installer#95): step-4-bis. No subject/body tag,
|
|
158
|
+
# no pending ticket, but RTM.md has exactly one IN PROGRESS row.
|
|
159
|
+
# Attribute to that REQ. Tests the zero-ceremony fallback that
|
|
160
|
+
# survives chore/docs/ci sync commits when no operator state file
|
|
161
|
+
# has been dropped.
|
|
162
|
+
make_fixture "$WORK/c13" "chore: devaudit update to 0.1.29"
|
|
163
|
+
mkdir -p compliance
|
|
164
|
+
cat > compliance/RTM.md <<'RTM'
|
|
165
|
+
# RTM
|
|
166
|
+
| REQ-ID | Issue | Risk | Evidence | Status | Approver | Date |
|
|
167
|
+
| ------- | ----- | ---- | ---------------------------- | ------------------- | -------- | ---------- |
|
|
168
|
+
| REQ-100 | #10 | LOW | compliance/evidence/REQ-100/ | APPROVED - DEPLOYED | dev | 2026-05-30 |
|
|
169
|
+
| REQ-101 | #11 | MED | compliance/evidence/REQ-101/ | IN PROGRESS | dev | 2026-06-01 |
|
|
170
|
+
RTM
|
|
171
|
+
assert_eq "RTM single IN PROGRESS row -> REQ-101" "REQ-101" "$(run_helper)"
|
|
172
|
+
|
|
173
|
+
# Case 14: step-4-bis ambiguity guard. Two IN PROGRESS rows → falls
|
|
174
|
+
# through to the bare date rather than guessing.
|
|
175
|
+
make_fixture "$WORK/c14" "chore: devaudit update to 0.1.29"
|
|
176
|
+
mkdir -p compliance
|
|
177
|
+
cat > compliance/RTM.md <<'RTM'
|
|
178
|
+
| REQ-ID | Status |
|
|
179
|
+
| ------- | -------------- |
|
|
180
|
+
| REQ-101 | IN PROGRESS |
|
|
181
|
+
| REQ-102 | IN PROGRESS |
|
|
182
|
+
RTM
|
|
183
|
+
assert_eq "RTM two IN PROGRESS rows -> bare date $TODAY" "$TODAY" "$(run_helper)"
|
|
184
|
+
|
|
185
|
+
# Case 15: step-4-bis must ignore legend rows that mention IN PROGRESS
|
|
186
|
+
# inside backticks (the wawagardenbar-app RTM convention) and prose
|
|
187
|
+
# mentions in description columns.
|
|
188
|
+
make_fixture "$WORK/c15" "chore: devaudit update to 0.1.29"
|
|
189
|
+
mkdir -p compliance
|
|
190
|
+
cat > compliance/RTM.md <<'RTM'
|
|
191
|
+
# RTM
|
|
192
|
+
## Conventions
|
|
193
|
+
| Value | Meaning |
|
|
194
|
+
| ------------------ | ----------------------------- |
|
|
195
|
+
| `IN PROGRESS` | Active development underway |
|
|
196
|
+
|
|
197
|
+
| REQ-ID | Status |
|
|
198
|
+
| ------- | ----------------------------------------------------------------- |
|
|
199
|
+
| REQ-200 | RELEASED (was IN PROGRESS during Q3, then deployed) |
|
|
200
|
+
RTM
|
|
201
|
+
assert_eq "RTM legend + prose mentions -> bare date $TODAY" "$TODAY" "$(run_helper)"
|
|
202
|
+
|
|
203
|
+
# Case 16: step-4-bis with the real META-JOBS-shaped RTM row (long
|
|
204
|
+
# parenthetical commentary in the status cell). The status cell still
|
|
205
|
+
# starts with `IN PROGRESS` after the pipe.
|
|
206
|
+
make_fixture "$WORK/c16" "chore: devaudit update to 0.1.29"
|
|
207
|
+
mkdir -p compliance
|
|
208
|
+
cat > compliance/RTM.md <<'RTM'
|
|
209
|
+
| REQ-ID | Issue | Risk | Evidence | Status | Approver | Date |
|
|
210
|
+
| ------- | ----- | ----------- | ---------------------------- | --------------------------------------------------------------------- | ---------- | ---------- |
|
|
211
|
+
| REQ-056 | #117 | MEDIUM-HIGH | compliance/evidence/REQ-056/ | IN PROGRESS (WhatsApp inbound-message router; many details follow...) | ostendo-io | 2026-06-01 |
|
|
212
|
+
RTM
|
|
213
|
+
assert_eq "RTM long parenthetical status -> REQ-056" "REQ-056" "$(run_helper)"
|
|
214
|
+
|
|
215
|
+
# Case 17: step-4-bis must NOT win over a pending ticket on disk.
|
|
216
|
+
# Step 4 returns first.
|
|
217
|
+
make_fixture "$WORK/c17" "chore: devaudit update to 0.1.29"
|
|
218
|
+
mkdir -p compliance/pending-releases compliance
|
|
219
|
+
cat > compliance/pending-releases/RELEASE-TICKET-REQ-301.md <<'TICKET'
|
|
220
|
+
# Release Ticket: REQ-301
|
|
221
|
+
TICKET
|
|
222
|
+
cat > compliance/RTM.md <<'RTM'
|
|
223
|
+
| REQ-ID | Status |
|
|
224
|
+
| ------- | ----------- |
|
|
225
|
+
| REQ-302 | IN PROGRESS |
|
|
226
|
+
RTM
|
|
227
|
+
assert_eq "pending ticket REQ-301 beats RTM IN PROGRESS REQ-302" "REQ-301" "$(run_helper)"
|
|
228
|
+
|
|
229
|
+
# Case 18: step-4-bis respects RTM_PATH env override.
|
|
230
|
+
make_fixture "$WORK/c18" "chore: devaudit update to 0.1.29"
|
|
231
|
+
mkdir -p docs
|
|
232
|
+
cat > docs/custom-RTM.md <<'RTM'
|
|
233
|
+
| REQ-ID | Status |
|
|
234
|
+
| ------- | ----------- |
|
|
235
|
+
| REQ-400 | IN PROGRESS |
|
|
236
|
+
RTM
|
|
237
|
+
GOT=$(RTM_PATH=docs/custom-RTM.md run_helper)
|
|
238
|
+
assert_eq "RTM_PATH=docs/custom-RTM.md -> REQ-400" "REQ-400" "$GOT"
|
|
239
|
+
|
|
157
240
|
echo ""
|
|
158
241
|
echo "=== Summary: $PASS pass / $FAIL fail ==="
|
|
159
242
|
|
|
@@ -22,7 +22,10 @@ echo "Comparing: $BASE_BRANCH...HEAD"
|
|
|
22
22
|
echo ""
|
|
23
23
|
|
|
24
24
|
# Conventional Commit regex: type(optional-scope): description
|
|
25
|
-
|
|
25
|
+
# Scope accepts anything except `)` so multi-scope subjects like
|
|
26
|
+
# `feat(auth,profile):` and `fix(rewards/expiry):` validate. The closing-paren
|
|
27
|
+
# guard prevents pathological inputs. DevAudit-Installer#93.
|
|
28
|
+
CC_REGEX='^(feat|fix|docs|test|refactor|chore|compliance|security|perf|ci|build|revert)(\([^)]+\))?!?: .+'
|
|
26
29
|
|
|
27
30
|
COMMITS=$(git log "$BASE_BRANCH"..HEAD --format='%H' || true)
|
|
28
31
|
|