Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/security-methodology-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ jobs:

- name: Run methodology structure check
run: bash scripts/check-security-methodology.sh

- name: Run requirement traceability check
run: bash scripts/check-requirement-traceability.sh
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Secure-AI-Flow separates the AI delivery process into four roles.
verify-methodology.sh
```

## Automated Methodology Checks

The repository includes automated checks for:

- Structure validation with `scripts/check-security-methodology.sh`.
- Methodology verification with `scripts/verify-methodology.sh`.
- Requirement traceability validation with `scripts/check-requirement-traceability.sh`.

## How to Use This Methodology

### Step 1: Fill Governance First
Expand Down
58 changes: 58 additions & 0 deletions scripts/check-requirement-traceability.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re
import sys

requirements_path = Path("context/06-security-requirements.md")
specs_dir = Path("specs")
valid_id_pattern = re.compile(r"^[A-Z][A-Z0-9]+-[0-9]{3}$")
source_id_pattern = re.compile(r"\b[A-Z][A-Z0-9]+-\d{3}\b")

valid_ids = set(source_id_pattern.findall(requirements_path.read_text(encoding="utf-8")))

errors = []
for spec_path in sorted(specs_dir.glob("*.md")):
lines = spec_path.read_text(encoding="utf-8").splitlines()
in_security_requirements = False

for line_number, line in enumerate(lines, start=1):
if line.startswith("## "):
in_security_requirements = line.strip() == "## Security Requirements"
continue

if not in_security_requirements:
continue

stripped = line.strip()
if not stripped or not stripped.startswith("-"):
continue

bullet = stripped[1:].strip()
if bullet == "":
continue

first_token = bullet.split()[0]
if not valid_id_pattern.fullmatch(first_token):
issue = "malformed ID" if ("-" in first_token or any(c.isdigit() for c in first_token)) else "missing ID"
value = first_token if issue == "malformed ID" else bullet
errors.append((spec_path, line_number, value, issue))
continue

if first_token not in valid_ids:
errors.append((spec_path, line_number, first_token, "unknown ID"))

if errors:
for spec_path, line_number, value, issue in errors:
print("Invalid security requirement ID reference:", file=sys.stderr)
print(f" file: {spec_path}", file=sys.stderr)
print(f" line: {line_number}", file=sys.stderr)
print(f" issue: {issue}", file=sys.stderr)
print(f" value: {value}", file=sys.stderr)
print(f" valid IDs source: {requirements_path}", file=sys.stderr)
sys.exit(1)

print("Requirement traceability check passed.")
PY
1 change: 1 addition & 0 deletions scripts/check-security-methodology.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ required_files=(
"specs/001-secure-file-upload.md"
"ci/security-gates.md"
".github/pull_request_template.md"
"scripts/check-requirement-traceability.sh"
)

missing=0
Expand Down
3 changes: 3 additions & 0 deletions scripts/verify-methodology.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ required=(
"context/15-security-stress-test-matrix.md"
"ci/security-gates.md"
"references/official-source-map.md"
"scripts/check-requirement-traceability.sh"
)

missing=0
Expand All @@ -45,4 +46,6 @@ grep -q "Data" context/02-data-classification-and-privacy.md
grep -q "Threat" context/04-threat-model.md
grep -q "Reviewer" context/13-reviewer-playbook.md

bash scripts/check-requirement-traceability.sh

echo "Secure-AI-Flow methodology structure verified."
Loading