Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Korrekter rekursiver {{#if}}-Renderer (wie echtes Handlebars) zur Verifikation.
|
||||
import re, glob, json, os
|
||||
BASE=os.path.dirname(__file__)
|
||||
schema=json.load(open(os.path.join(BASE,"variables.schema.json")))
|
||||
allvars=set(schema["properties"].keys())
|
||||
|
||||
def make_ctx(inc, extra=None):
|
||||
c={k:(True if k.startswith("FLAG_") else k) for k in allvars}
|
||||
for k in ["FLAG_OT_USED","FLAG_DEV_INHOUSE","FLAG_CRYPTO_PKI","FLAG_CUSTOMER_SYSTEMS"]: c[k]=False
|
||||
c["FLAG_INCLUDE_SHOULD"]=inc
|
||||
c["ORG_NAME"]="Muster GmbH"; c["TOOL_NAME"]="ISMS-Portal"; c["REVIEW_CYCLE"]="jährlich"
|
||||
c["FLAG_FW_TISAX"]=True; c["FLAG_FW_ISO27001"]=False # dieses Skript prueft die TISAX-Sicht
|
||||
if extra: c.update(extra)
|
||||
return c
|
||||
|
||||
def render_if(t,c):
|
||||
# rekursiv innerste Bloecke zuerst
|
||||
pat=re.compile(r"\{\{#if (\w+)\}\}((?:(?!\{\{#if )(?!\{\{/if\}\}).)*?)\{\{/if\}\}",re.S)
|
||||
prev=None
|
||||
while prev!=t:
|
||||
prev=t
|
||||
t=pat.sub(lambda m:(m.group(2) if c.get(m.group(1)) else ""),t)
|
||||
return t
|
||||
|
||||
def render(t,c):
|
||||
t=render_if(t,c)
|
||||
t=re.sub(r"\{\{LINK:[^}]+\}\}","[LINK]",t)
|
||||
t=re.sub(r"\{\{(\w+)\}\}",lambda m:str(c[m.group(1)]) if m.group(1) in c else "«MISS:%s»"%m.group(1),t)
|
||||
return t
|
||||
|
||||
files=sorted(glob.glob(os.path.join(BASE,"richtlinien/*.md")))+[os.path.join(BASE,"Nachweisregister_zentral.md"),os.path.join(BASE,"ISA-Mapping-Matrix.md")]
|
||||
problems=0
|
||||
for inc in [True,False]:
|
||||
c=make_ctx(inc)
|
||||
for fp in files:
|
||||
r=render(open(fp,encoding="utf-8").read(),c)
|
||||
bad=re.findall(r"\{\{.*?\}\}",r); miss=sorted(set(re.findall(r"«MISS:\w+»",r)))
|
||||
if bad or miss:
|
||||
problems+=1; print("!",os.path.basename(fp),"inc=%s"%inc,"open:",bad[:4],"miss:",miss[:4])
|
||||
# Zwei Framework-Mappings teilen sich diese Bibliothek: die Anker des ISO-Mappings
|
||||
# werden hier ausgeblendet und von _verify_iso.py geprueft.
|
||||
iso_anchors=set()
|
||||
_iso=os.path.join(BASE,"mapping-iso.json")
|
||||
if os.path.exists(_iso):
|
||||
for a in json.load(open(_iso,encoding="utf-8"))["anforderungen"]:
|
||||
iso_anchors.add(a["req_anchor"]); iso_anchors.add(a["impl_anchor"])
|
||||
d=json.load(open(os.path.join(BASE,"mapping.json")))
|
||||
fa=set()
|
||||
for fp in glob.glob(os.path.join(BASE,"richtlinien/*.md")):
|
||||
for m in re.findall(r"<!-- (REQ|IMPL) ([0-9.\-A-Za-z]+) -->",open(fp,encoding="utf-8").read()): fa.add(m[0]+" "+m[1])
|
||||
ma=set()
|
||||
for a in d["anforderungen"]: ma.add(a["req_anchor"]); ma.add(a["impl_anchor"])
|
||||
fa-=(iso_anchors-ma) # nur ISO-exklusive Anker ausblenden; gemeinsam genutzte bleiben geprueft
|
||||
# F17: mapping.json enthaelt kein 'implementation'-Feld; der Umsetzungstext wird zur
|
||||
# Laufzeit ueber impl_anchor (Control-IMPL-Block) aus der jeweiligen .md aufgeloest.
|
||||
leftover_hb=any("{{" in a["requirement"] or "{{" in a.get("implementation","") for a in d["anforderungen"])
|
||||
print("Render-Probleme:",problems)
|
||||
print("mapping-Anker ohne Datei:",sorted(ma-fa))
|
||||
print("Datei-Anker ohne mapping:",sorted(fa-ma))
|
||||
print("Handlebars-Reste in mapping-Text:",leftover_hb)
|
||||
print("OK" if problems==0 and not (ma-fa) and not (fa-ma) and not leftover_hb else "PRUEFEN")
|
||||
Reference in New Issue
Block a user