Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

202 lines
8.2 KiB
Python

#!/usr/bin/env python3
"""Agent for assessing ISO 27001:2022 ISMS compliance."""
import json
import argparse
from datetime import datetime
from collections import Counter
ANNEX_A_CATEGORIES = {
"A.5": {"name": "Organizational controls", "count": 37},
"A.6": {"name": "People controls", "count": 8},
"A.7": {"name": "Physical controls", "count": 14},
"A.8": {"name": "Technological controls", "count": 34},
}
REQUIRED_DOCUMENTS = [
"ISMS Scope (4.3)", "Information Security Policy (5.2)",
"Risk Assessment Methodology (6.1.2)", "Risk Treatment Plan (6.1.3)",
"Statement of Applicability (6.1.3d)", "Information Security Objectives (6.2)",
"Evidence of Competence (7.2)", "Documented Operating Procedures (8.1)",
"Risk Assessment Results (8.2)", "Risk Treatment Results (8.3)",
"Monitoring and Measurement Results (9.1)", "Internal Audit Program (9.2)",
"Management Review Results (9.3)", "Nonconformities and Corrective Actions (10.1)",
]
def assess_soa_completeness(soa_path):
"""Assess Statement of Applicability completeness."""
with open(soa_path) as f:
soa = json.load(f)
controls = soa if isinstance(soa, list) else soa.get("controls", [])
total = len(controls)
implemented = sum(1 for c in controls if c.get("status", "").lower() == "implemented")
partially = sum(1 for c in controls if c.get("status", "").lower() == "partial")
not_implemented = sum(1 for c in controls if c.get("status", "").lower() == "not_implemented")
excluded = sum(1 for c in controls if c.get("status", "").lower() == "excluded")
missing_justification = [c for c in controls
if c.get("status", "").lower() == "excluded"
and not c.get("justification")]
findings = []
if missing_justification:
findings.append({
"issue": f"{len(missing_justification)} excluded controls without justification",
"severity": "HIGH",
"controls": [c.get("id", "") for c in missing_justification],
})
no_evidence = [c for c in controls
if c.get("status", "").lower() == "implemented"
and not c.get("evidence")]
if no_evidence:
findings.append({
"issue": f"{len(no_evidence)} implemented controls without evidence",
"severity": "MEDIUM",
})
return {
"total_controls": total,
"implemented": implemented,
"partial": partially,
"not_implemented": not_implemented,
"excluded": excluded,
"implementation_rate": round(implemented / total * 100, 1) if total else 0,
"findings": findings,
}
def assess_documentation(docs_inventory_path):
"""Check required ISMS documentation against inventory."""
with open(docs_inventory_path) as f:
inventory = json.load(f)
docs = inventory if isinstance(inventory, list) else inventory.get("documents", [])
doc_names = [d.get("name", d.get("title", "")).lower() for d in docs]
missing = []
for req in REQUIRED_DOCUMENTS:
found = any(req.lower().split("(")[0].strip() in name for name in doc_names)
if not found:
missing.append(req)
outdated = [d for d in docs
if d.get("last_review") and
(datetime.utcnow() - datetime.fromisoformat(
d["last_review"].replace("Z", ""))).days > 365]
return {
"required": len(REQUIRED_DOCUMENTS),
"present": len(REQUIRED_DOCUMENTS) - len(missing),
"missing": missing,
"outdated_documents": len(outdated),
"compliance_rate": round(
(len(REQUIRED_DOCUMENTS) - len(missing)) / len(REQUIRED_DOCUMENTS) * 100, 1),
}
def assess_risk_register(risk_register_path):
"""Assess risk register for completeness and currency."""
with open(risk_register_path) as f:
register = json.load(f)
risks = register if isinstance(register, list) else register.get("risks", [])
findings = []
by_level = Counter()
for risk in risks:
level = risk.get("risk_level", risk.get("rating", "unknown")).lower()
by_level[level] += 1
if not risk.get("treatment", risk.get("mitigation")):
findings.append({
"risk": risk.get("id", risk.get("name", "")),
"issue": "No treatment plan defined",
"severity": "HIGH",
})
if not risk.get("owner"):
findings.append({
"risk": risk.get("id", ""),
"issue": "No risk owner assigned",
"severity": "MEDIUM",
})
if risk.get("treatment", "").lower() == "accept" and not risk.get("acceptance_authority"):
findings.append({
"risk": risk.get("id", ""),
"issue": "Risk accepted without management approval",
"severity": "HIGH",
})
return {
"total_risks": len(risks),
"by_level": dict(by_level),
"findings": findings,
"untreated": sum(1 for r in risks if not r.get("treatment")),
}
def generate_gap_analysis(current_state):
"""Generate ISO 27001 gap analysis from current state assessment."""
clauses = {
"4_context": ["scope_defined", "interested_parties", "isms_scope_document"],
"5_leadership": ["security_policy", "roles_responsibilities", "management_commitment"],
"6_planning": ["risk_methodology", "risk_assessment", "soa", "security_objectives"],
"7_support": ["resources", "competence", "awareness", "communication", "documented_info"],
"8_operation": ["operational_planning", "risk_assessment_results", "risk_treatment"],
"9_evaluation": ["monitoring", "internal_audit", "management_review"],
"10_improvement": ["nonconformity_handling", "corrective_actions", "continual_improvement"],
}
gaps = {}
for clause, requirements in clauses.items():
clause_state = current_state.get(clause, {})
met = sum(1 for r in requirements if clause_state.get(r, False))
gaps[clause] = {
"total": len(requirements),
"met": met,
"gaps": [r for r in requirements if not clause_state.get(r, False)],
"compliance": round(met / len(requirements) * 100, 1),
}
return gaps
def main():
parser = argparse.ArgumentParser(description="ISO 27001 ISMS Compliance Agent")
parser.add_argument("--soa", help="Statement of Applicability JSON")
parser.add_argument("--docs", help="Documentation inventory JSON")
parser.add_argument("--risks", help="Risk register JSON")
parser.add_argument("--state", help="Current state assessment JSON for gap analysis")
parser.add_argument("--action", choices=["soa", "docs", "risks", "gaps", "full"],
default="full")
parser.add_argument("--output", default="iso27001_report.json")
args = parser.parse_args()
report = {"generated_at": datetime.utcnow().isoformat(), "results": {}}
if args.action in ("soa", "full") and args.soa:
result = assess_soa_completeness(args.soa)
report["results"]["soa"] = result
print(f"[+] SoA: {result['implementation_rate']}% implemented")
if args.action in ("docs", "full") and args.docs:
result = assess_documentation(args.docs)
report["results"]["documentation"] = result
print(f"[+] Documentation: {result['compliance_rate']}%, {len(result['missing'])} missing")
if args.action in ("risks", "full") and args.risks:
result = assess_risk_register(args.risks)
report["results"]["risks"] = result
print(f"[+] Risk register: {result['total_risks']} risks, {result['untreated']} untreated")
if args.action in ("gaps", "full") and args.state:
with open(args.state) as f:
state = json.load(f)
gaps = generate_gap_analysis(state)
report["results"]["gap_analysis"] = gaps
avg = sum(g["compliance"] for g in gaps.values()) / len(gaps)
print(f"[+] Gap analysis: {avg:.1f}% average compliance")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()