#!/usr/bin/env python3 # -*- coding: utf-8 -*- """R-593: the subdomain sentence describes a SUBDOMAIN field, never another one. papra's session-signing key (AUTH_SECRET) carried „Az alkalmazás aldomainje" — SUBDOMAIN's sentence, pasted one field too low — so a household read "the app's subdomain" under a key it must never regenerate, and SUBDOMAIN itself had no description. The copy gate could not see it: it freezes the Hungarian as it was, wrong sentence included. This test reads every `.felhom.yml` as TEXT (catalog CI has no PyYAML) and asserts, catalog-wide: * every field carrying the subdomain sentence (Hungarian or the English twin) is a SUBDOMAIN* field, and * every SUBDOMAIN field carries a description. Hungarian is matched by an ASCII-folded fragment (workspace rule), with a positive and a negative control. COMPANION RED-PROOF: with papra's pre-R-593 .felhom.yml restored this test fails naming `papra AUTH_SECRET` and `papra SUBDOMAIN`.""" import glob import io import os import re import unicodedata import unittest ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SENTENCES = ("az alkalmazas aldomainje", "the subdomain this app answers on") def fold(s): return "".join(c for c in unicodedata.normalize("NFD", s) if unicodedata.category(c) != "Mn").lower() def fields(text): """Yield (env_var, [description values]) for every `- env_var:` item, top-level and inside i18n blocks.""" cur, descs, ind = None, [], None for line in text.splitlines(): m = re.match(r"^(\s*)- env_var:\s*(\S+)", line) if m: if cur: yield cur, descs cur, descs, ind = m.group(2).strip("'\""), [], len(m.group(1)) continue if cur is None: continue stripped = line.strip() if not stripped or stripped.startswith("#"): continue lead = len(line) - len(line.lstrip()) if lead <= ind: # left the item (a sibling key, the next list, or a new top-level key) yield cur, descs cur, descs = None, [] continue d = re.match(r"^\s*description:\s*(.*)$", line) if d and lead == ind + 2: descs.append(d.group(1).strip().strip("'\"")) if cur: yield cur, descs def findings(app, text): out = [] for env, descs in fields(text): if any(fold(x) in SENTENCES for x in descs) and not env.startswith("SUBDOMAIN"): out.append("%s %s carries the subdomain sentence" % (app, env)) if env == "SUBDOMAIN" and not descs: out.append("%s SUBDOMAIN has no description" % app) return out class SubdomainSentence(unittest.TestCase): def test_controls(self): self.assertEqual(fold("Az alkalmazás aldomainje"), SENTENCES[0], "positive control: folding failed") self.assertNotIn(fold("A szerver domain neve"), SENTENCES, "negative control: a clean sentence matched") decoy = ("deploy_fields:\n - env_var: SUBDOMAIN\n label: \"Aldomain\"\n\n" " - env_var: AUTH_SECRET\n type: secret\n description: \"Az alkalmazás aldomainje\"\n") self.assertEqual(findings("x", decoy), ["x SUBDOMAIN has no description", "x AUTH_SECRET carries the subdomain sentence"]) def test_catalog(self): paths = sorted(glob.glob(os.path.join(ROOT, "templates", "*", ".felhom.yml"))) self.assertGreater(len(paths), 40, "the template glob found too few files — the test would pass empty") bad, seen = [], 0 for p in paths: with io.open(p, encoding="utf-8") as f: text = f.read() app = os.path.basename(os.path.dirname(p)) seen += sum(1 for env, d in fields(text) if env == "SUBDOMAIN" and d) bad += findings(app, text) self.assertGreater(seen, 40, "the parser found too few described SUBDOMAIN fields — it is not reading") self.assertEqual(bad, [], bad) if __name__ == "__main__": unittest.main()