@metasession.co/devaudit-cli 0.1.37 → 0.1.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metasession.co/devaudit-cli",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
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.37",
36
+ "@metasession.co/devaudit-plugin-sdk": "^0.1.39",
37
37
  "commander": "^12.1.0",
38
38
  "consola": "^3.2.3",
39
39
  "env-paths": "^3.0.0",
package/sdlc/SKILLS.md CHANGED
@@ -93,10 +93,11 @@ node scripts/validate-adapter.cjs sdlc/files/_common/skills/<name>/SKILL.md
93
93
 
94
94
  ## Skills currently shipped
95
95
 
96
- | Skill | Location | Triggers (paraphrased) | Additional emissions |
97
- | ------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
98
- | `e2e-test-engineer` | `_common/skills/` | "add e2e tests", "bootstrap an e2e suite", "update the test pack", "are any tests obsolete", "run e2e tests and file issues" | `e2e/helpers/evidence.ts` (node-stack consumers) |
99
- | `sdlc-implementer` | `_common/skills/` | "implement issue #N under the SDLC", "run the SDLC for issue #N", "automate REQ-XXX from issue to release", "resume REQ-XXX" | — (orchestrator; invokes `e2e-test-engineer`) |
96
+ | Skill | Location | Triggers (paraphrased) | Additional emissions |
97
+ | ----------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
98
+ | `e2e-test-engineer` | `_common/skills/` | "add e2e tests", "bootstrap an e2e suite", "update the test pack", "are any tests obsolete", "run e2e tests and file issues" | `e2e/helpers/evidence.ts` + `evidence-shot-core.ts` (node-stack consumers) |
99
+ | `sdlc-implementer` | `_common/skills/` | "implement issue #N under the SDLC", "run the SDLC for issue #N", "automate REQ-XXX from issue to release", "resume REQ-XXX" | — (orchestrator; invokes `e2e-test-engineer` + `governance-doc-author`) |
100
+ | `governance-doc-author` | `_common/skills/` | "create / refresh the RoPA", "write a DPIA", "update the AI disclosure", "set up the periodic review schedule", "GDPR.Art-30 is MISSING on the matrix" (v0.1.37+) | `references/incident-classification.md` (shared with `e2e-test-engineer`) |
100
101
 
101
102
  `sdlc-implementer` is the **default entry point for a tracked change** — an **orchestration skill** that drives Claude Code's native tools (`gh`, shell, `devaudit` CLI, portal API) through the full 5-stage flow against a single GitHub issue, pausing only at the UAT-review gate (and at the plan checkpoint for HIGH/CRITICAL risk). It is synced into every consumer (`.claude/skills/sdlc-implementer/`) by `devaudit update`. It replaces an earlier roadmap of five atomic skills (`risk-classifier`, `commit-message-author`, `compliance-evidence-author`, `sast-triager`, `release-ticket-author`) that were deprioritised — Claude Code's innate capabilities already cover what those atomic skills wrapped; the value-add is end-to-end orchestration with framework-compliant pauses, not five discoverable helpers a human still has to compose.
102
103
 
@@ -58,7 +58,7 @@ Read `SDLC/1-plan-requirement.md` for full details. Summary:
58
58
  2. Get next REQ ID: `grep -oP 'REQ-\d+' compliance/RTM.md | sort -t- -k2 -n | tail -1`
59
59
  3. Classify risk (use issue labels as input): LOW (internal, no auth) / MEDIUM (PII, user-facing, APIs) / HIGH (security, payments, RBAC). AI involvement raises risk by one level.
60
60
  4. Add to `compliance/RTM.md` Part B: `| REQ-XXX | #NNN | [RISK] | compliance/evidence/REQ-XXX/ | DRAFT | -- | -- |`
61
- 5. **MEDIUM/HIGH risk:** Create `compliance/evidence/REQ-XXX/implementation-plan.md` — document approach, files, architecture decisions. **WAIT CHECKPOINT:** Present the plan to the developer. Do NOT proceed until approved.
61
+ 5. **MEDIUM/HIGH risk:** Create `compliance/evidence/REQ-XXX/implementation-plan.md` from `SDLC/Implementation_Plan_TEMPLATE.md` (synced from the framework in v0.1.37+). The template's shape is load-bearing it carries the `## Framework attribution` section that closes **ISO 29119 §3.4** (test plan), **ISO 27001 A.8.25** (secure SDLC), **GDPR Art. 25** (data protection by design), and **EU AI Act Art. 11** (technical documentation). Don't delete sections — mark with `N/A — <reason>` if a clause genuinely doesn't apply. **WAIT CHECKPOINT:** Present the plan to the developer. Do NOT proceed until approved.
62
62
  6. Create `compliance/evidence/REQ-XXX/test-scope.md` with acceptance criteria (derived from the implementation plan for MEDIUM/HIGH).
63
63
  7. **WAIT CHECKPOINT:** Present the test scope to the developer. Do NOT proceed until confirmed.
64
64
  8. Create `compliance/evidence/REQ-XXX/test-plan.md` — map acceptance criteria to specific tests, list tests to add/update/remove. Distinguish unit tests (TDD, before implementation) from E2E tests (after implementation).
@@ -22,10 +22,10 @@ risk_class: "REPLACE — minimal | limited | high | unacceptable"
22
22
 
23
23
  ## Uploading this artefact
24
24
 
25
- - **File path:** `compliance/governance/ai-disclosure.md`
26
- - **Upload trigger:** automatic on every push to `develop` that touches `compliance/**`, `compliance-evidence.yml` uploads this file as `ai_disclosure` evidence.
27
- - **Verify after merge:** open `/projects/<slug>/compliance`. The **EU AI Act Art. 13** clause should flip MISSING → COVERED within ~2 minutes.
28
- - **Refresh cadence:** every 180 days, or whenever an AI tool / model / prompt-class is added or materially changed. Source data: git `Co-Authored-By: Claude` trailers + CI usage logs + per-REQ implementation-plan §5.
25
+ - **File path:** `compliance/governance/ai-disclosure.md` (kept in-repo for review; CI does NOT upload it).
26
+ - **Upload trigger:** manual via the portal Upload Evidence form at `/projects/<slug>/upload` select evidence type `ai_disclosure`. Tier-2 governance docs are operator-uploaded only since DevAudit-Installer v0.1.39 the previous CI auto-upload was treating placeholder content as canonical evidence. The matrix MISSING row for `EUAIA.Art-13` renders an `Upload ai-disclosure.md →` deep-link that pre-fills the form for you.
27
+ - **Verify after upload:** open `/projects/<slug>/compliance`. The **EU AI Act Art. 13** clause should flip MISSING → COVERED immediately.
28
+ - **Refresh cadence:** every 180 days, or whenever an AI tool / model / prompt-class is added or materially changed. The portal renders an inline `Expires YYYY-MM-DD` on the clause (amber within 30 days, red once stale). Source data for each refresh: git `Co-Authored-By: Claude` trailers + CI usage logs + per-REQ implementation-plan §5.
29
29
 
30
30
  ## Framework checklist — EU AI Act Art. 13
31
31
 
@@ -22,10 +22,10 @@ risk_level: "REPLACE — low | medium | high"
22
22
 
23
23
  ## Uploading this artefact
24
24
 
25
- - **File path:** `compliance/governance/dpia.md` (or `dpia-<reqid>.md` for a per-REQ DPIA tied to a HIGH-risk requirement)
26
- - **Upload trigger:** automatic on every push to `develop` that touches `compliance/**`, `compliance-evidence.yml` uploads this file as `dpia` evidence.
27
- - **Verify after merge:** open `/projects/<slug>/compliance`. The **GDPR Art. 35** clause should flip MISSING → COVERED within ~2 minutes.
28
- - **Refresh cadence:** annually (365 days), or sooner whenever the assessed processing materially changes (new data category, new recipient, new automated-decision path).
25
+ - **File path:** `compliance/governance/dpia.md` (or `dpia-<reqid>.md` for a per-REQ DPIA tied to a HIGH-risk requirement). Kept in-repo for review; CI does NOT upload it.
26
+ - **Upload trigger:** manual via the portal Upload Evidence form at `/projects/<slug>/upload` select evidence type `dpia`. Tier-2 governance docs are operator-uploaded only since DevAudit-Installer v0.1.39 the previous CI auto-upload was treating placeholder content as canonical evidence. The matrix MISSING row for `GDPR.Art-35` renders an `Upload dpia.md →` deep-link that pre-fills the form for you.
27
+ - **Verify after upload:** open `/projects/<slug>/compliance`. The **GDPR Art. 35** clause should flip MISSING → COVERED immediately.
28
+ - **Refresh cadence:** annually (365 days), or sooner whenever the assessed processing materially changes (new data category, new recipient, new automated-decision path). The portal renders an inline `Expires YYYY-MM-DD` on the clause (amber within 30 days, red once stale).
29
29
 
30
30
  ## Framework checklist — GDPR Art. 35
31
31
 
@@ -20,10 +20,10 @@ processing_activities: []
20
20
 
21
21
  ## Uploading this artefact
22
22
 
23
- - **File path:** `compliance/governance/ropa.md`
24
- - **Upload trigger:** automatic on every push to `develop` that touches `compliance/**`, the `compliance-evidence.yml` workflow uploads this file as `ropa` evidence via the `upload_governance` helper.
25
- - **Verify after merge:** open `/projects/<slug>/compliance` on the DevAudit portal. The **GDPR Art. 30** clause should flip MISSING → COVERED within ~2 minutes.
26
- - **Refresh cadence:** annually (365 days). The portal flags the clause as `expired` once the most-recent ropa upload is older than that window.
23
+ - **File path:** `compliance/governance/ropa.md` (kept in-repo for review; CI does NOT upload it).
24
+ - **Upload trigger:** manual via the portal Upload Evidence form at `/projects/<slug>/upload` select evidence type `ropa`. Tier-2 governance docs are operator-uploaded only since DevAudit-Installer v0.1.39 — the previous CI auto-upload was treating placeholder content as canonical evidence. The matrix MISSING row for `GDPR.Art-30` renders an `Upload ropa.md →` deep-link that pre-fills the form for you.
25
+ - **Verify after upload:** open `/projects/<slug>/compliance` on the DevAudit portal. The **GDPR Art. 30** clause should flip MISSING → COVERED immediately.
26
+ - **Refresh cadence:** annually (365 days). The portal renders an inline `Expires YYYY-MM-DD` on the clause (amber within 30 days, red once stale).
27
27
 
28
28
  ## Framework checklist — GDPR Art. 30
29
29
 
@@ -7,13 +7,13 @@ description: Author or refresh one of the project's governance documents — RoP
7
7
 
8
8
  Author or refresh a single governance document so it correctly closes the framework clauses it's meant to satisfy. Five document classes covered:
9
9
 
10
- | Document | File | Closes |
11
- |---|---|---|
12
- | **RoPA** | `compliance/governance/ropa.md` | `GDPR.Art-30` |
13
- | **DPIA** | `compliance/governance/dpia.md` (or `dpia-<reqid>.md`) | `GDPR.Art-35` |
14
- | **AI Use Disclosure** | `compliance/governance/ai-disclosure.md` | `EUAIA.Art-13` |
15
- | **Periodic Security Review Schedule** | `SDLC/Periodic_Security_Review_Schedule.md` *(Tier 2, uploaded as `compliance_document` via the portal Upload form)* | `ISO27001.A.12.1` (the schedule itself; the quarterly runs close `ISO27001.A.12.1` + `SOC2.CC4.1` via `periodic_review` evidence — see Phase 6) |
16
- | **Incident Report (project-level template)** | `compliance/governance/incident-report.md` | `ISO29119.3.5.4` baseline; conditionals via [[incident-classification]] |
10
+ | Document | Tier | File | Upload path | Closes |
11
+ |---|---|---|---|---|
12
+ | **RoPA** | 2 | `compliance/governance/ropa.md` | **Portal Upload form** (type `ropa`) — CI does NOT auto-upload since v0.1.39 | `GDPR.Art-30` |
13
+ | **DPIA** | 2 | `compliance/governance/dpia.md` (or `dpia-<reqid>.md`) | **Portal Upload form** (type `dpia`) — CI does NOT auto-upload since v0.1.39 | `GDPR.Art-35` |
14
+ | **AI Use Disclosure** | 2 | `compliance/governance/ai-disclosure.md` | **Portal Upload form** (type `ai_disclosure`) — CI does NOT auto-upload since v0.1.39 | `EUAIA.Art-13` |
15
+ | **Periodic Security Review Schedule** | 2 | `SDLC/Periodic_Security_Review_Schedule.md` | **Portal Upload form** (type `compliance_document`) | `ISO27001.A.12.1` schedule expectation (quarterly runs close it via `periodic_review` evidence — see Phase 6) |
16
+ | **Incident Report (project-level template)** | 3 | `compliance/governance/incident-report.md` | **CI auto-upload** via `compliance-evidence.yml` | `ISO29119.3.5.4` baseline; conditionals via [[incident-classification]] |
17
17
 
18
18
  Each doc has a starter template under `sdlc/files/_common/governance/*.md.template` (installed on demand via `devaudit bootstrap-governance` since v0.1.36). This skill does NOT regenerate the template — it walks the operator through *filling it in* against the project's actual state.
19
19
 
@@ -23,7 +23,7 @@ Each doc has a starter template under `sdlc/files/_common/governance/*.md.templa
23
23
  - Authoring or refreshing one (or more) of the five governance docs above.
24
24
  - Gathering source data from the codebase / CI runs / git history.
25
25
  - Confirming framework attribution before commit.
26
- - Driving the commit + push → CI auto-upload → portal verification loop.
26
+ - Driving the commit + push → portal upload (manual for Tier 1/2, CI auto for Tier 3) → portal verification loop.
27
27
 
28
28
  **Out of scope**
29
29
  - Incident response itself — that path is the `e2e-test-engineer` skill's defect-filing flow plus `incident-export.yml` on issue close.
@@ -104,10 +104,15 @@ If any required section is still stub, **do not commit**. Surface the gap in the
104
104
 
105
105
  ### Phase 5 — Commit + verify
106
106
 
107
+ Tier 1/2 docs (RoPA, DPIA, AI Disclosure, Periodic Security Review Schedule) and Tier 3 per-event docs (Incident Report template) take different upload paths since DevAudit-Installer v0.1.39. The skill must drive the right one based on which doc Phase 0 routed to.
108
+
107
109
  1. Show the operator the diff. Confirm before committing (per the **Confirm before destructive or public actions** principle).
108
110
  2. Commit with a conventional-commit message: `compliance(governance): refresh <doc> for <reason>` — e.g. `compliance(governance): refresh ropa.md — annual review 2026-Q2`.
109
- 3. Push to the current working branch. Surface the path: "next `git push` to `develop` → `compliance-evidence.yml` auto-uploads as `<evidence_type>`, closing `<framework_clause>` within ~2 minutes."
110
- 4. Suggest the operator open `/projects/<slug>/compliance` on the portal post-merge to verify the clause flipped MISSING → COVERED.
111
+ 3. Push to the current working branch.
112
+ 4. Drive upload based on doc class:
113
+ - **Tier 1/2 (RoPA, DPIA, AI Disclosure, Periodic Security Review Schedule)** — CI does NOT upload these. Direct the operator to the portal Upload Evidence form at `/projects/<slug>/upload`. Surface the exact evidence type to select (`ropa` / `dpia` / `ai_disclosure` / `compliance_document` respectively) and remind them: "the matrix MISSING row for the corresponding clause renders an `Upload <filename> →` deep-link that pre-fills the form."
114
+ - **Tier 3 (Incident Report template, plus per-event `periodic-review.md` and `incident-report-<n>.md`)** — CI auto-uploads via `compliance-evidence.yml`. Surface: "next `git push` to `develop` → `compliance-evidence.yml` auto-uploads as `<evidence_type>`, closing `<framework_clause>` within ~2 minutes."
115
+ 5. Suggest the operator open `/projects/<slug>/compliance` on the portal post-upload to verify the clause flipped MISSING → COVERED. For docs with freshness windows (365d for RoPA / DPIA / Test_Policy / Test_Strategy / AGENT / INSTRUCTIONS; 180d for AI Disclosure) the matrix renders an inline `Expires YYYY-MM-DD` label — confirm it reads the expected date for the upload.
111
116
 
112
117
  ### Phase 6 — Special case: the Periodic Review Schedule vs the quarterly review itself
113
118
 
@@ -156,13 +156,17 @@ jobs:
156
156
  || echo "Warning: Failed to upload test-summary-report.md"
157
157
  fi
158
158
 
159
- # Project-level governance docs (devaudit#370 Phase 3a). When the
160
- # operator commits any of these markdown files, upload with the
161
- # precise evidence_type so the portal's framework-coverage matrix
162
- # auto-closes the matching clauses (GDPR.Art-30 for ropa, GDPR.Art-35
163
- # for dpia, EUAIA.Art-13 for ai_disclosure, SOC2.CC4.1 + ISO27001.A.12.1
164
- # for periodic_review, etc.). Each path is optional — skipped silently
165
- # when the file is absent.
159
+ # Tier 3 per-event governance docs (devaudit#370 Phase 3a, narrowed
160
+ # in v0.1.39). Only periodic-review and incident-report are CI-uploaded
161
+ # both are auto-generated by other workflows (periodic-review by the
162
+ # quarterly cron, incident-report by the incident-export workflow).
163
+ #
164
+ # Tier 1/2 governance docs (Test_Policy, AGENT, INSTRUCTIONS,
165
+ # Test_Strategy, Test_Architecture, Periodic_Security_Review_Schedule,
166
+ # ROPA, DPIA, AI Disclosure) are operator-uploaded via the portal
167
+ # Upload Evidence form. CI auto-upload was removed because placeholder
168
+ # starter content was landing as canonical evidence; the portal form
169
+ # ensures the operator reviews each refresh before it counts.
166
170
  upload_governance() {
167
171
  local FILE="$1" TYPE="$2"
168
172
  if [ ! -f "$FILE" ]; then return 0; fi
@@ -175,12 +179,6 @@ jobs:
175
179
  }
176
180
  # Recognise governance docs at top-level OR under compliance/governance/
177
181
  # (operator's choice — both layouts are common).
178
- upload_governance compliance/ropa.md ropa
179
- upload_governance compliance/governance/ropa.md ropa
180
- upload_governance compliance/dpia.md dpia
181
- upload_governance compliance/governance/dpia.md dpia
182
- upload_governance compliance/ai-disclosure.md ai_disclosure
183
- upload_governance compliance/governance/ai-disclosure.md ai_disclosure
184
182
  upload_governance compliance/periodic-review.md periodic_review
185
183
  upload_governance compliance/governance/periodic-review.md periodic_review
186
184
  upload_governance compliance/incident-report.md incident_report
@@ -218,54 +218,62 @@ jobs:
218
218
  # consumer's portal base URL — fall back to the SDLC docs when
219
219
  # DEVAUDIT_BASE_URL isn't set in the workflow env.
220
220
  BASE="${DEVAUDIT_BASE_URL:-https://github.com/metasession-dev/DevAudit-Installer/blob/main/docs/governance-templates.md}"
221
- PR_BODY=$(cat <<PRBODY
222
- Auto-generated quarterly periodic-review for **${REVIEW_ID}** by the \`Periodic Review\` workflow.
223
-
224
- ## What auto-filled (~40%)
225
-
226
- - Review-period metrics: releases shipped, gate pass rate, SAST + dependency findings, audit-log volume, open issues
227
- - Frontmatter (\`review_id\`, period dates, generated_at)
228
- - Section 2 control-area headers wired to the right framework clauses
229
-
230
- ## What still needs the operator (~60%)
231
-
232
- Each item below corresponds to a section of the doc. **Tick the box once the section is non-stub** leaving REPLACE markers in place will fail audit review and the merge bar.
233
-
234
- ### §3 Review notes
235
- - [ ] Qualitative observations on the review period (≥2 sentences; no \`REPLACE\` text remaining)
236
- - [ ] Cross-reference any incidents from this period (\`compliance/governance/incident-report-*.md\`)
237
-
238
- ### §4 Control-effectiveness judgement
239
- *Closes \`SOC2.CC4.1\` + \`ISO27001.A.12.1\` only when ALL control areas have a non-stub judgement.*
240
-
241
- - [ ] Access control (ISO 27001 A.5.15) — effective / partially / not + 1-line evidence
242
- - [ ] Secure SDLC (ISO 27001 A.8.25) — judgement + evidence
243
- - [ ] Secure coding (ISO 27001 A.8.28) judgement + evidence (SAST + dep-audit pass rate)
244
- - [ ] Security testing (ISO 27001 A.8.29) judgement + evidence (E2E pass rate)
245
- - [ ] Change management (ISO 27001 A.8.32 + SOC 2 CC8.1) — judgement + evidence (four-eyes approvals count)
246
- - [ ] Monitoring activities (ISO 27001 A.8.16 + EU AI Act Art. 12) — judgement + evidence (audit-log volume / coverage)
247
-
248
- ### §5 Follow-up actions
249
- - [ ] Each material finding owner due date (or "none for this period" stated explicitly)
250
- - [ ] Carry-over actions from last quarter's review status updated
251
-
252
- ### §6 Sign-off
253
- - [ ] Reviewer name + date (must be different from the actor who made code changes that the review is judging)
254
- - [ ] Approver name + date (when \`risk_tier\` is medium or higherdual-actor required)
255
-
256
- ## Closes once merged
257
-
258
- - \`SOC2.CC4.1\` (Monitoring of internal controls)
259
- - \`ISO27001.A.12.1\` (Operational procedures and responsibilities)
260
-
261
- Verify at \`${BASE}/projects/<slug>/compliance\` after the PR-merge push lands on develop both clauses should flip MISSING COVERED within ~2 minutes. Stays COVERED for 365 days (portal's \`freshnessDays\`), then flips to EXPIRED until the next quarterly review.
262
-
263
- See [\`docs/governance-templates.md\`](https://github.com/metasession-dev/DevAudit-Installer/blob/main/docs/governance-templates.md#soc-2--trust-services-criteria) for full guidance.
264
- PRBODY
265
- )
221
+ # Assemble the PR body via printf to a temp file. We avoided
222
+ # a heredoc here because <<PRBODY preserves leading whitespace
223
+ # literally — and any body line at YAML column 1 breaks the
224
+ # surrounding `run: |` block scalar (prettier-yaml fails with
225
+ # "collection cannot be both a mapping and a sequence").
226
+ # printf '%s\n' …list of lines… keeps every line inside the
227
+ # block scalar's indentation discipline.
228
+ PR_BODY_FILE=$(mktemp)
229
+ printf '%s\n' \
230
+ "Auto-generated quarterly periodic-review for **${REVIEW_ID}** by the \`Periodic Review\` workflow." \
231
+ "" \
232
+ "## What auto-filled (~40%)" \
233
+ "" \
234
+ "- Review-period metrics: releases shipped, gate pass rate, SAST + dependency findings, audit-log volume, open issues" \
235
+ "- Frontmatter (\`review_id\`, period dates, generated_at)" \
236
+ "- Section 2 control-area headers wired to the right framework clauses" \
237
+ "" \
238
+ "## What still needs the operator (~60%)" \
239
+ "" \
240
+ "Each item below corresponds to a section of the doc. **Tick the box once the section is non-stub** — leaving REPLACE markers in place will fail audit review and the merge bar." \
241
+ "" \
242
+ "### §3 Review notes" \
243
+ "- [ ] Qualitative observations on the review period (≥2 sentences; no \`REPLACE\` text remaining)" \
244
+ "- [ ] Cross-reference any incidents from this period (\`compliance/governance/incident-report-*.md\`)" \
245
+ "" \
246
+ "### §4 Control-effectiveness judgement" \
247
+ "*Closes \`SOC2.CC4.1\` + \`ISO27001.A.12.1\` only when ALL control areas have a non-stub judgement.*" \
248
+ "" \
249
+ "- [ ] Access control (ISO 27001 A.5.15) effective / partially / not + 1-line evidence" \
250
+ "- [ ] Secure SDLC (ISO 27001 A.8.25) judgement + evidence" \
251
+ "- [ ] Secure coding (ISO 27001 A.8.28) — judgement + evidence (SAST + dep-audit pass rate)" \
252
+ "- [ ] Security testing (ISO 27001 A.8.29) — judgement + evidence (E2E pass rate)" \
253
+ "- [ ] Change management (ISO 27001 A.8.32 + SOC 2 CC8.1) judgement + evidence (four-eyes approvals count)" \
254
+ "- [ ] Monitoring activities (ISO 27001 A.8.16 + EU AI Act Art. 12) judgement + evidence (audit-log volume / coverage)" \
255
+ "" \
256
+ "### §5 Follow-up actions" \
257
+ "- [ ] Each material finding → owner → due date (or \"none for this period\" stated explicitly)" \
258
+ "- [ ] Carry-over actions from last quarter's review → status updated" \
259
+ "" \
260
+ "### §6 Sign-off" \
261
+ "- [ ] Reviewer name + date (must be different from the actor who made code changes that the review is judging)" \
262
+ "- [ ] Approver name + date (when \`risk_tier\` is medium or higher — dual-actor required)" \
263
+ "" \
264
+ "## Closes once merged" \
265
+ "" \
266
+ "- \`SOC2.CC4.1\` (Monitoring of internal controls)" \
267
+ "- \`ISO27001.A.12.1\` (Operational procedures and responsibilities)" \
268
+ "" \
269
+ "Verify at \`${BASE}/projects/<slug>/compliance\` after the PR-merge push lands on develop — both clauses should flip MISSING → COVERED within ~2 minutes. Stays COVERED for 365 days (portal's \`freshnessDays\`), then flips to EXPIRED until the next quarterly review." \
270
+ "" \
271
+ "See [\`docs/governance-templates.md\`](https://github.com/metasession-dev/DevAudit-Installer/blob/main/docs/governance-templates.md#soc-2--trust-services-criteria) for full guidance." \
272
+ > "$PR_BODY_FILE"
266
273
  gh pr create --base develop --head "${BRANCH}" \
267
274
  --title "chore(compliance): periodic review ${REVIEW_ID}" \
268
- --body "$PR_BODY"
275
+ --body-file "$PR_BODY_FILE"
276
+ rm -f "$PR_BODY_FILE"
269
277
  else
270
278
  echo "PR #${EXISTING} already open for this period — branch updated in place."
271
279
  fi