Basis: Certvia dev@a48c5fb als Fundament für Craftvia
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s

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:
2026-09-14 11:05:39 +02:00
co-authored by Claude Opus 5
commit c8e6f30a27
720 changed files with 140143 additions and 0 deletions
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
"""
Regressionsschutz: Rendert alle Richtlinien in einer Framework-Sicht und vergleicht das
Ergebnis mit einem Git-Stand. Erwartung fuer TISAX: 0 Abweichungen.
python3 _render_diff.py <git-revision> [--framework TISAX|ISO|BEIDE]
Beispiele:
python3 _render_diff.py a9649b3 # TISAX-Sicht gegen den Stand vor dem ISO-Umbau
python3 _render_diff.py dev --framework ISO # ISO-Sicht gegen dev
Verglichen wird der gerenderte Text ohne Leerzeilen und ohne Kommentar-Anker — also das,
was ein Mandant tatsaechlich zu sehen bekommt.
"""
import difflib, glob, json, os, re, subprocess, sys
BASE = os.path.dirname(os.path.abspath(__file__))
REPO = subprocess.run(["git", "rev-parse", "--show-toplevel"], cwd=BASE,
capture_output=True, text=True).stdout.strip()
if len(sys.argv) < 2:
print(__doc__); sys.exit(2)
REV = sys.argv[1]
FW = "TISAX"
if "--framework" in sys.argv:
FW = sys.argv[sys.argv.index("--framework") + 1].upper()
schema = json.load(open(os.path.join(BASE, "variables.schema.json"), encoding="utf-8"))
def ctx():
c = {k: (True if k.startswith("FLAG_") else "{%s}" % k) for k in schema["properties"]}
for k in ["FLAG_OT_USED", "FLAG_DEV_INHOUSE", "FLAG_CRYPTO_PKI", "FLAG_CUSTOMER_SYSTEMS"]:
c[k] = False
c["FLAG_FW_TISAX"] = FW in ("TISAX", "BEIDE")
c["FLAG_FW_ISO27001"] = FW in ("ISO", "BEIDE")
return c
def render(txt, c):
pat = re.compile(r"\{\{#if (\w+)\}\}((?:(?!\{\{#if )(?!\{\{/if\}\}).)*?)\{\{/if\}\}", re.S)
prev = None
while prev != txt:
prev = txt
txt = pat.sub(lambda m: (m.group(2) if c.get(m.group(1)) else ""), txt)
txt = re.sub(r"<!--.*?-->", "", txt, flags=re.S)
txt = re.sub(r"\{\{LINK:([^}]+)\}\}", r"[\1]", txt)
txt = re.sub(r"\{\{(\w+)\}\}", lambda m: str(c.get(m.group(1), "?")), txt)
return [l.rstrip() for l in txt.split("\n") if l.strip()]
def at_rev(relpath):
r = subprocess.run(["git", "show", "%s:%s" % (REV, relpath)], cwd=REPO,
capture_output=True, text=True)
return r.stdout if r.returncode == 0 else None
c = ctx()
drift, missing, checked = 0, 0, 0
for path in sorted(glob.glob(os.path.join(BASE, "richtlinien", "*.md"))):
rel = os.path.relpath(path, REPO)
old_raw = at_rev(rel)
if old_raw is None:
missing += 1
print(" neu in dieser Fassung:", os.path.basename(path))
continue
checked += 1
old, new = render(old_raw, c), render(open(path, encoding="utf-8").read(), c)
if old != new:
drift += 1
print("ABWEICHUNG:", os.path.basename(path))
for line in list(difflib.unified_diff(old, new, lineterm="", n=0))[:10]:
print(" ", line[:140])
print()
print("Sicht: %s · Vergleichsstand: %s" % (FW, REV))
print("geprueft: %d Richtlinien, neu: %d, abweichend: %d" % (checked, missing, drift))
print("OK" if drift == 0 else "PRUEFEN")
sys.exit(0 if drift == 0 else 1)