name: sanitize
# PR gate: block personal data, secrets and tenant-internal references from
# entering the shared skill library. Every layer boundary is a gate.
# Deliberately PR-only: INSIDE a private tenant repo internal details are
# legitimate; the gate guards the boundary to the shared layers.
on:
  pull_request:

jobs:
  pii-scan:
    runs-on: windows
    steps:
      - uses: actions/checkout@v4
      - name: Scan for PII / secrets / internal URLs
        shell: python
        run: |
          import os, re, sys

          RULES = [
              ("e-mail address", re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")),
              ("phone number", re.compile(r"(?<![\w/.-])\+?\d[\d ()\-]{8,}\d(?![\w/])")),
              ("secret assignment", re.compile(r"(?i)(password|passwd|secret|api[_-]?key|token)\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{6,}")),
              ("internal URL/host", re.compile(r"(?i)(\bintranet\b|\.internal\b|\.local\b|\.corp\b|\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b|\b192\.168\.\d{1,3}\.\d{1,3}\b)")),
              ("person name marker", re.compile(r"(?i)\b(hiring manager|contact):\s*[A-Z][a-z]+ [A-Z][a-z]+")),
          ]
          ALLOW = re.compile(r"(?i)(esco\.ec\.europa\.eu|onetcenter\.org|data\.europa\.eu|creativecommons\.org)")

          findings = []
          for root, dirs, files in os.walk("."):
              dirs[:] = [d for d in dirs if d not in (".git", ".gitea")]
              for name in files:
                  path = os.path.join(root, name)
                  try:
                      text = open(path, encoding="utf-8", errors="ignore").read()
                  except OSError:
                      continue
                  for lineno, line in enumerate(text.splitlines(), 1):
                      if ALLOW.search(line):
                          continue
                      for label, rx in RULES:
                          m = rx.search(line)
                          if not m:
                              continue
                          # ISO-Datumsangaben (2026-07-06) sind keine Telefonnummern
                          if label == "phone number" and re.fullmatch(r"\d{4}-\d{2}-\d{2}", m.group(0)):
                              continue
                          findings.append(f"{path}:{lineno}: {label}: {line.strip()[:120]}")

          if findings:
              print("SANITIZE GATE FAILED — remove/anonymize before publishing:")
              print("\n".join(findings))
              sys.exit(1)
          print("sanitize: clean — no PII, secrets or internal references found.")
