Skip to content

fix: pytest sammelt aus der Repo-Wurzel wieder, plus sieben Folgefixe - #151

Merged
b7n0de merged 8 commits into
mainfrom
fix/pytest-root-collection
Aug 20, 2026
Merged

fix: pytest sammelt aus der Repo-Wurzel wieder, plus sieben Folgefixe#151
b7n0de merged 8 commits into
mainfrom
fix/pytest-root-collection

Conversation

@b7n0de

@b7n0de b7n0de commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Ausfuehrung des Owner-GO vom 2026-08-20T01:10:23Z (Karte OA-1c8275d896, Option 1: GO fuer Push und PR).

Acht Commits, die seit Tagen lokal lagen und von keinem frueheren GO gedeckt waren:

  • fdfc4e6 pytest sammelt aus der Repo-Wurzel wieder — Bauartefakte raus, Abdeckung groesser statt kleiner
  • 5b22c9c cosign_*-Seite in den never-raise-Nenner, und der Nenner kann nicht mehr still altern
  • 3b7d6eb der Erwartungs-Pin wird selbst geprueft, statt nur verglichen
  • bda1d29 ein leerer Root baute eine signierte Note, die kein Verifizierer akzeptiert
  • a01b57a der Wurzelsammlungs-Riegel bekommt den Beleg, den er nie hatte
  • 55e98a6 save_signer bekommt den Typboden, den sein Nachbar seit zwei Tagen hat
  • 1a9c10e die Budget-Kappe laeuft vor der Arbeit, die sie begrenzt — an allen drei Stellen
  • cae1249 zwei untrusted-Verbraucher standen als Erzeuger ausserhalb des Nenners

Der Merge wartet auf gruene CI.

kraxo added 8 commits August 18, 2026 22:05
…raus, Abdeckung groesser statt kleiner

Befund PB-PYTEST-WURZEL-LAEUFT-NICHT-01. `pytest` aus der Wurzel brach mit 740 Sammelfehlern ab.
Gemessene Ursache, kein Testfehler: die entpackten sdist-Baeume unter `dist_pkgtest*/` tragen
dieselben Modul-Basenamen wie `tests/` ("import file mismatch: imported module 'test_signature'
has this __file__ attribute: dist_pkgtest/tree/tests/test_signature.py"). `build/` und `dist/`
sind pytest-Default, die `dist_*`-Varianten NICHT — der Default matcht `dist` exakt.

`norecursedirs` statt `testpaths`, und zwar als bewusst SCHMALERER Eingriff: ausgeschlossen wird,
was Bauartefakt ist, statt die Sammlung auf ein Verzeichnis zu verengen. Die naheliegende
Begruendung dagegen (scripts/test_manifest_gate.py wuerde verloren) ist GEMESSEN widerlegt — die
Datei sammelt null Tests, sie ist ein Gate-Skript mit test-artigem Namen; der Kommentar sagt das
so, statt eine schoenere Begruendung zu behaupten.

Wirkung beidseitig gemessen (Config von origin/main gegen diesen Zweig, gleicher Baum):
  vorher   2212 gesammelt + 740 Fehler, Abbruch
  nachher  2295 gesammelt, 0 Fehler
Die Sammelmenge WAECHST — es geht nichts still verloren.
…kann nicht mehr still altern

Befund PB-COSIGN-SIGN-SIDE-NEVER-RAISE-COVERAGE-01 (4. adversariale Linse des 4.0.0-Gates).

DIE INSTANZ: `_NAME_PATTERN` ist eine Allowlist von Namensfamilien, und die gesamte `cosign_*`-
Seite stand nie darin. Sie ist keine reine Erzeuger-Seite: `cosign_checkpoint` und
`cosign_checkpoint_mldsa` nehmen eine vom LOG gelieferte, also untrusted, Note entgegen — genau
die Eingabe, gegen die diese Eigenschaft schuetzt. Nenner gemessen 91 -> 97, alle sechs
`cosign_*` drin; die Eigenschaft haelt (die Code-Klasse hatten iter1-5 bereits geschlossen).

DIE KLASSE: der bestehende Bodentest wacht nur gegen KOLLAPS des Nenners (>= 65). Ein Nenner von
91 sieht gesund aus, auch wenn sechs Verbraucher-Surfaces danebenliegen — deshalb rutschten vier
Nachbarn derselben Klasse nacheinander durch. Neu ist deshalb die andere Richtung: jede
oeffentliche Funktion der gescannten Module muss ENTWEDER im Nenner stehen ODER namentlich als
ausserhalb gefuehrt sein (122 Namen, nach Familie begruendet: Erzeuger / beschreibend / Urteile
ueber bereits validierte Strukturen / Krypto-Primitive). Eine neue oeffentliche Funktion, die
keins von beidem ist, laesst den Test failen und erzwingt die Entscheidung.

EMPFINDLICHKEIT BEWIESEN, nicht behauptet: eine Klassifikation aus _OUT_OF_SCOPE entfernt -> Test
FAILT mit dem Namen; byte-genau zurueckgelegt -> 6 passed. Nachbarsuiten 52 passed, ruff clean.
… verglichen

BEFUND PB-EXPECTED-ORIGIN-ASCII-INKONSISTENZ-01. Die Log-Seite erzwingt fuer
`origin` seit dem Homoglyph-Fix druckbares ASCII (positive Regel, nicht
Kategorie-Aufzaehlung). Der vom Aufrufer gesetzte `--expected-origin` lief an
dieser Regel vorbei: ein Pin mit KELVIN SIGN oder unsichtbarem Zeichen wurde
stumm gegen die geprueften Werte gehalten und ergab ein "passt nicht", das wie
eine Aussage ueber die NOTE aussah, obwohl die ERWARTUNG kaputt war.

Bewusst BERICHTEND, nicht ablehnend: der Repo-eigene Test OriginVergleichIstExakt
pinnt, dass ein Beinah-Treffer ein Verdikt mit unberuehrtem `inclusion_ok` liefern
muss - ein hartes Nein waere dort ein Rueckschritt gewesen und wurde von genau
diesem Test widerlegt. Das neue Feld `expected_origin_wellformed` (True/False/None)
sagt es, ohne den Vergleich anzufassen.

Der fail-closed-Pfad traegt DIESELBE Form. Ohne das brach die CLI dort mit
KeyError ab und drei verschiedene Ursachen lieferten byte-identische Ausgabe;
der Test, der diese Unterscheidbarkeit sichert, hat es gefangen.

Sensitivitaet gemessen, nicht behauptet - drei eingepflanzte Defekte, jeder rot:
Praedikat immer True (12 rot) - Feld auf dem fail-closed-Pfad entfernt (2 rot) -
Praedikat wirft statt zu urteilen (never-raise-Familie rot). Die neue Funktion
steht deshalb ausdruecklich IM Nenner der never-raise-Familie, nicht daneben.

Volle Suite: 2292 passed, 7 skipped. ruff clean.
…Verifizierer akzeptiert

BEFUND PB-CHECKPOINT-CONSTRUCTOR-TYPEERROR-01 — nachgemessen statt geglaubt. Sein
eigener Kern (roher TypeError aus checkpoint_note/key_id/vkey/sign_checkpoint und
den vier cosign_*-Flaechen bei Nicht-bytes) ist durch das 4.0.0-Re-Gate iter5
LAENGST geschlossen: alle acht Flaechen werfen typisiert, gegen sieben Eingabearten
gemessen. Der Befund wird deshalb nicht "gefixt", sondern als erledigt belegt.

Dieselbe Messung legte einen NACHBARN derselben Klasse frei, den niemand gesucht
hatte: `checkpoint_note(root=b"")` kam durch, denn `b""` IST bytes. Die dritte
Notenzeile wurde damit leer, `sign_checkpoint` signierte das anstandslos, und
`verify_checkpoint` wie `_note_text_of` lehnten die frisch signierte Note danach
als "at least 3 non-empty lines" ab. Der Aufrufer haelt eine signierte Note in
der Hand, die KEIN Verifizierer akzeptiert, auch keiner ausserhalb dieser
Bibliothek. Der realistische Weg dorthin ist kein Tippfehler:
`root_bytes_from_b64("")` liefert `b""` und nicht `None`.

KLASSE STATT INSTANZ. Der Riss entsteht, weil Emit- und Verify-Regeln an zwei
Stellen gehalten werden; jede Regel, die nur die Pruefseite kennt, erzeugt ihn
erneut. tests/test_emitter_parser_rundlauf.py prueft deshalb generativ ueber ALLE
Emitter des Moduls: was ein Emitter ANNIMMT, darf sein eigener Parser nicht
malformed nennen. Der Sweep ueber sign_checkpoint (root/origin/tree_size),
cosign_checkpoint, vkey und cosign_vkey fand genau zwei auffaellige Faelle, beide
mit dieser einen Wurzel.

Anti-Tautologie ist Teil des Tests: eine Rundlauf-Eigenschaft ist ueber der leeren
Menge wahr. Jeder Emitter muss nachweisen, dass er ueberhaupt etwas angenommen hat.

Sensitivitaet gemessen, drei Proben, jede rot: Fix zurueckgenommen (5 rot) -
Emitter lehnt alles ab, Anti-Tautologie greift (4 rot) - Parser gelockert, sodass
der Rundlauf verstummt: der namentliche Pin haelt trotzdem (5 rot). Genau dafuer
steht er neben der generativen Eigenschaft.

EHRLICHE GRENZE, absichtlich nicht weiter zugezogen: ein nicht-leerer Root
falscher Laenge (5 Bytes) laeuft weiter durch, weil er den Rundlauf besteht - ein
Aufrufer-Fehler an den eigenen Wurzel-Bytes, kein angreifer-gelieferter Wert. Wo
das Format eine Laenge verlangt, steht sie schon (_mldsa_cosigned_message: 32).

Volle Suite: 2299 passed, 7 skipped. ruff clean.
…nie hatte

Befund PB-PYTEST-WURZEL-LAEUFT-NICHT-01 war mit fdfc4e6 gefixt, aber von KEINEM
Test gedeckt - der Fix lebte allein in pyproject.toml. Eine Konfigurationszeile
ohne Test faellt still zurueck: sie verschwindet bei einem Merge-Konflikt, einem
Werkzeugwechsel oder einer aufgeraeumten Liste, ohne dass etwas rot wird. Der
Abschluss-Vertrag der Befund-Queue verlangt aus demselben Grund zwei aufloesbare
Belege; ohne sie waere "geschlossen" ein Haken ohne Deckung gewesen.

Drei absichtlich verschieden gebaute Tests: die Wirkung (die real erstickenden
Verzeichnisse werden ausgeschlossen) - die Anti-Tautologie (ohne `dist_*` faellt
die Deckung, sonst maesse der erste Test nur den pytest-Default, in dem `dist`
EXAKT matcht und `dist_pkgtest` eben nicht) - die Gegenrichtung (ein zu breiter
Riegel versteckt echte Tests: sauber, aber blind).

DIE QUELLE IST PYTEST SELBST, und das ist eine Korrektur an meinem ersten Entwurf.
Der las pyproject.toml mit `tomllib` und uebersprang sich auf diesem Interpreter
(Python 3.10, tomllib ab 3.11) in DREI gruen aussehenden SKIPs - auch unter
eingepflanztem Defekt. Er mass nichts und sah wie eine Deckung aus; die
Sensitivitaetsprobe hat ihn gefangen, nicht der Lauf. `pytestconfig.getini` liest
den Wert, den pytest WIRKLICH benutzt, und ein fehlender Wert ist hier ein
Fehlschlag, nie ein Skip.

Sensitivitaet gemessen, drei Proben, jede rot: `dist_*` entfernt (2 rot) -
`tests` zusaetzlich ausgeschlossen (1 rot, die Gegenrichtung) - Liste geleert
(3 rot).
…ei Tagen hat

Befund PBNACHBAR-EMIT-TYPBODEN-01, am 2026-08-18 gegen den heutigen Stand
nachgemessen statt aus der alten Akte uebernommen. Ergebnis: HALB geschlossen.
`load_signer` hat den Boden am 16.08. bekommen, `save_signer` steht zwanzig Zeilen
darueber, nimmt denselben aufrufer-gelieferten Pfad und hatte ihn nicht -
`save_signer(echterSchluessel, 1)` warf einen rohen TypeError aus os.open.

DER URSPRUENGLICHE BELEG MASS DEN FALSCHEN GEGENSTAND: er rief
`save_signer(None, 1)` und schloss aus dem rohen Fehler auf den Pfad - der haette
ebenso vom None-Schluessel kommen koennen. Mit echtem Schluessel gemessen liegt er
wirklich am Pfad. Der Befund stimmte, seine Begruendung nicht ganz.

WARUM ES DURCHRUTSCHTE, und das ist die Klasse: die never-raise-Familieneigenschaft
entdeckt ueber Namensfamilien - `load_` steht darin, `save_` nicht. In der
begruendeten Ausschlussmenge liegt `save_signer` als ERZEUGER, "baut aus EIGENEN,
bereits geprueften Werten". Das trifft auf sein key-Argument zu und auf seinen PFAD
gerade nicht. Eine Begruendung, die fuer EIN Argument stimmt, deckt die Funktion
nicht. Die Ausschlussmenge bleibt deshalb richtig; der Beleg steht dort, wo der
Gegenstand liegt. Der Boden selbst ist jetzt EINE Funktion, die beide benutzen -
zwei Kopien waeren die naechste Drift.

MEIN EIGENER TEST WAR ZUERST BEINAHE TAUTOLOGISCH, und die Sensitivitaetsprobe hat
es gezeigt, nicht der Lauf: er zaehlte ein Zielverzeichnis vorher und nachher auf
und blieb gruen, als ich einen Schreibvorgang VOR die Schranke setzte - bei
`path=1` entsteht dort ohnehin nie eine Datei. Beobachtet wird jetzt der Gegenstand
selbst: ein Attrappen-Schluessel merkt sich, ob `private_bytes` gefragt wurde. Der
Seed darf gar nicht erst entstehen.

Sensitivitaet gemessen, beide Proben rot: Boden entfernt (6 rot) - Boden hinter den
Rohwert geschoben (1 rot, genau der neue Beobachter).

Volle Suite: 2305 passed, 7 skipped. ruff clean.
…llen drei Stellen

OWNER-ENTSCHEID 2026-08-18 zu PB-GLEICHE-KLASSE-BLEIBT-UMGEKEHRT-ENTSCHIEDEN-01,
Karte OA-43cbdbb292, Option 1: "vereinheitlichen auf Kappe-vor-Arbeit wie 2c52596,
das ist der dokumentierte Hausstandard des Budget-Moduls. Einzige Ausnahme, wenn
die Kappe an der Gegenstelle ohne die begrenzte Arbeit nicht berechenbar ist."

DIE AUSNAHME GREIFT AN KEINER DER DREI STELLEN, und das ist geprueft statt
angenommen: die Kappe zaehlt Elemente, `len(proof_list)` ist ohne das Dekodieren
berechenbar und exakt gleich `len(proof)`. Ein eigener Test haelt genau diese
Vorbedingung fest — faellt sie, ist dieser Fix der falsche und es muesste nach
Option 3 entschieden werden.

WIRKUNG GEMESSEN, nicht geschaetzt, und die Groesse ist bewusst die AUFRUFZAHL des
base64-Dekodierers statt der Laufzeit (eine Zeitmessung haengt an Last und Cache;
an einer Zeitmessung ist die erste Nachmessung dieses Befunds schon einmal
gescheitert):

  recompute_merkle_root_b64  195002 -> 2 Aufrufe, 365/942/5714 ms -> 35/36/37 ms
                             bei Proof-Elementen von 32/320/3200 Byte
  verify_bundle              195004 -> 4 Aufrufe, 410/5418 ms -> 32/35 ms
  verify_sample_opening      lehnt vor dem Dekodieren ab (0,06 ms), belegt daran,
                             dass ungueltiges base64 in der Liste nie beruehrt wird

Die Zeit skaliert danach NICHT mehr mit der Elementgroesse — das ist der Beleg,
dass die Liste nicht mehr durchlaufen wird, und nicht nur, dass es schneller ist.

VERDIKTE AENDERN SICH NICHT: ein Beweis ueber der Kappe konnte nie verifizieren.
EINE Fehlerklasse aendert sich: eine Eingabe, die GLEICHZEITIG ueber der Kappe
liegt UND kaputtes base64 traegt, ergab einen Format-Fehler (Exit 2) und ergibt
jetzt ein Verdikt (Exit 1). Genau diese Folge hat den ersten Anlauf (2c52596) vor
dem 4.0.0-Release zurueckgenommen; der Owner hat sie jetzt bewusst entschieden.
Sie steht im CHANGELOG unter [Unreleased], zusammen mit den beiden anderen
oeffentlichen Aenderungen dieses Zweigs (leerer checkpoint-Root, save_signer-
Typboden) und dem neuen expected_origin_wellformed-Feld — die fehlende
CHANGELOG-Disziplin war ein eigener Befund der Regressions-Linse.

Sensitivitaet gemessen, drei Proben, jede rot: Kappe wieder hinter die Arbeit
(2 rot) · Kappe auf 0, Anti-Tautologie (1 rot) · persample-Kappe zurueckgenommen
(1 rot). Der Anti-Tautologie-Test war im ersten Entwurf selbst vakuum-wahr — er
leitete seine Erwartung aus der geprueften Kappe ab und blieb bei Kappe 0 gruen;
die Probe hat das gezeigt, nicht der Lauf. Er nennt jetzt eine feste Zahl.

Volle Suite: 2311 passed, 7 skipped. ruff clean.
…alb des Nenners

Deep-Gate-Linse 2, Befund 1 (Lauf 2026-08-18, NORMAL 3L/3I). `split_key_binding`
und `holder_key_from_cnf` stehen beide in `kbjwt.__all__` und nahmen ihr
PRIMAERargument aus einer halter-gelieferten Praesentation — untrusted Eingabe.
Gemessen verliessen 7 von 7 bzw. 6 von 6 feindliche Formen sie als ROHER
AttributeError (`.endswith` / `.get`).

DER DEFEKT WAR BEKANNT UND AN DER FALSCHEN STELLE GESCHLOSSEN: `verify_key_binding`
traegt seit einem frueheren Durchgang einen aufrufer-seitigen Boden mit genau
diesem Kommentar ("never a raw AttributeError from split_key_binding's string
operations"). Der Aufrufer war gedeckt, die QUELLE nicht — und stand danach in der
Ausschlussmenge der never-raise-Eigenschaft unter ERZEUGER ("baut aus EIGENEN,
bereits geprueften Werten"). Diese Begruendung trifft auf ihr key-Argument zu und
auf ihre untrusted Primaereingabe gerade nicht. Dieselbe Form, die die Eigenschaft
selbst als Wurzel des cosign_*-Vorfalls dokumentiert: ein Verbraucher liegt
ausserhalb des Nenners, und nichts sagt es.

ZWEI VERSCHIEDENE ANTWORTEN, jede aus dem Vertrag der Funktion:
  split_key_binding   -> typisierter BundleFormatError (ein Parser, wie seine
                         Geschwister in dieser Datei)
  holder_key_from_cnf -> None, denn ihr Docstring sagt genau das ("Returns None if
                         there is no usable OKP/Ed25519 confirmation key") und sie
                         gibt schon fuer fehlendes cnf, Nicht-dict-jwk und falsches
                         kty None zurueck. Ein Wurf waere hier die INKONSISTENTE
                         Antwort.

Beide sind aus _OUT_OF_SCOPE heraus und im NENNER — ohne das haette der naechste
weggenommene Boden wieder niemanden gestoert.

Sensitivitaet, drei Proben: split-Boden weg (rot) · holder-Boden weg (rot) · beide
zurueck in _OUT_OF_SCOPE UND Boden weg (GRUEN, und das ist der Punkt: die Probe
stellt den urspruenglichen Blindfleck nach und zeigt, dass erst die Aufnahme in den
Nenner den Riegel beissen laesst).

Im selben Commit korrigiert (Linse 1, Befund 3): die Begruendung der
require_-Nenner-Oeffnung nannte einen Pruefer `require_wellformed_expected_origin`,
den es im Baum NICHT gibt — er war der erste Entwurf und wurde durch das
berichtende `expected_origin_wellformed` ersetzt. Gemessen bewirkt die Oeffnung
heute nichts (Nenner 91 -> 98, alle sieben Zugaenge cosign_*/expected_origin_
wellformed, kein einziges require_*). Sie bleibt als richtige Form stehen; was
nicht bleiben durfte, ist eine Begruendung, die auf etwas Nichtexistierendes zeigt.

Gueltige Eingaben unveraendert. Volle Suite: 2311 passed, 7 skipped.
@b7n0de
b7n0de merged commit c669d39 into main Aug 20, 2026
22 checks passed
@b7n0de
b7n0de deleted the fix/pytest-root-collection branch August 20, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant