Skip to content

fix(db): refuse a negative item index on field corrections (#47) - #57

Merged
Fluory merged 3 commits into
mainfrom
claude/chore-correction-index-check-47
Sep 24, 2026
Merged

Fluory merged 3 commits into
mainfrom
claude/chore-correction-index-check-47

Conversation

@Fluory

@Fluory Fluory commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Warum

Fixes #47 · app.extracted_fields verbietet eine negative Positionsnummer per CHECK, app.field_corrections nicht. Die Prüfung in correctField verhindert es heute – die Datenbank als zweite Linie fehlte.

Arbeitsstand

  • Ziel: Dieselbe CHECK-Regel auf field_corrections.item_index.
  • Nicht-Ziele: Obergrenze (hängt vom Lauf ab, bleibt in correctField).
  • Erledigt: Test zuerst (rot bestätigt), Schema + Migration 0016 (generiert), data-model.md, CHANGELOG, verify grün, CI grün, frischer Review ohne Befund.
  • Offen: Review/Merge durch den Orchestrator (Migration → menschliche Freigabe).
  • Annahmen: In keiner Umgebung gibt es negative Werte (die App konnte sie nie schreiben) – sonst schlägt die Migration laut fehl statt still.
  • Nächster kleinster Schritt: Review und Merge durch den Orchestrator.

Was ist passiert (Klartext)

Korrekturen an Positionen merken sich, zu welcher Position (0, 1, 2 …) sie gehören. Bisher hat nur der Programmcode verhindert, dass dort eine negative Zahl landet. Jetzt lehnt auch die Datenbank so einen Eintrag ab – genauso, wie sie es für die erkannten Werte schon tut. Für Nutzer ändert sich nichts; es ist eine zusätzliche Sicherung gegen künftige Programmfehler.

Plan-Pflicht (SYSTEM.md §4)

  • Kein Auslöser – keine Modulgrenze, öffentliche API, Migration, Auth/Rechte, kein Zahlungs-/Daten-/Infrapfad, höchstens zwei Module, keine Architekturvarianten, umkehrbar
  • Auslöser zutreffend – Impact Manifest ausgefüllt (Plan vor Code)

Impact Manifest

  • Betroffene Module: db (Schema, Migration), Test in review.
  • Schnittstellen / Datenänderungen: Migration 0016_correction_item_index_check.sql: ADD CONSTRAINT field_corrections_item_index_check CHECK (item_index is null or item_index >= 0).
  • Akzeptanzkriterien: chore(db): CHECK constraint for field_corrections.item_index #47 – Insert mit item_index = -1 als app_rw scheitert mit 23514; null und ≥ 0 gehen weiter.
  • Testplan: tests/integration/review.test.ts (roh als app_rw im Tenant-Kontext), rls-guard unverändert grün.
  • Verifizierte Fakten: Die Constraint-Prüfung beim ALTER sieht alle Zeilen, auch die per Forced RLS verborgenen (lokal nachgestellt: eine Testzeile aus dem roten Lauf ließ die Migration scheitern – nach Entfernen lief sie durch). Einziger Schreiber ist correctField, der negative Werte schon ablehnt.
  • Offene Annahmen: –
  • Nicht-Ziele: siehe oben.
  • Risiken und Rollback: Kurzer Lock auf field_corrections beim ALTER (Pilot: kleine Tabelle). Rollback: DROP CONSTRAINT.

Geändert

  • src/db/schema/app.ts: check("field_corrections_item_index_check", …)
  • src/db/migrations/0016_correction_item_index_check.sql, meta/ (generiert)
  • tests/integration/review.test.ts: Negativ- und Positivfall
  • docs/technical/data-model.md, CHANGELOG.md

Nachweis (SYSTEM.md §11)

Doku-Entscheidung (genau eine)

  • Keine langlebige Doku betroffen – Begründung: –
  • Doku betroffen und im selben PR aktualisiert:
    • Produktdoku (P0: README): –
    • Technische Doku: docs/technical/data-model.md
    • Architekturkarte: –
    • ADR: –
    • CHANGELOG [Unreleased] (sichtbares Feature oder Verhalten – im selben PR, nie „später")

Entferntes oder Umbenanntes: docs/ + README gegrept, Treffer bereinigt: nichts entfernt

Dateigrößen und neue Bausteine (SYSTEM.md §7)

Dateien über 500 Zeilen im Diff (Ausnahmen: generierter Code, Lockfiles, Fixtures, Migrationen, Schemas, Ressourcen, Doku, Konfiguration):

  • keine
  • bewusst belassen – Begründung: –
  • im selben PR nach fachlicher Verantwortung geteilt
  • Folge-Issue –

Über 800 Zeilen mit neuer Fachlogik oder über 1000 Zeilen (P1/P2): nicht betroffen

Neue Shared-Komponente, Utility-Datei, Adapter oder fachlicher Service:

  • nein
  • ja – gesucht nach: –

Subagent-Einsätze

  • Frischer Review-Subagent (read-only, Sonnet) – nichts blockierend, ein nit (begründet belassen).

Risiken / offene Punkte

🤖 Generated with Claude Code

https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1

…ns (#47, test-first)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1
Migration 0016 adds the same check that extracted_fields already has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1

Fluory commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Frischer Review (read-only Subagent)

Nichts blockierend, keine should-Befunde. Bestätigt: Constraint-Name folgt extracted_fields_item_index_check; Snapshot-Kette und Journal (idx 16) konsistent; der Test läuft über den echten app_rw-Pool im Tenant-Kontext und war vor 0016 rot; die cause.code-Form entspricht der Fehlerbehandlung der App (process-request.ts); die Validierung beim ALTER sieht alle Zeilen, und der einzige Schreiber (correctField) lässt keine negativen Werte zu – die Migration kann beim Deploy nicht scheitern.

  • nit – Migration ohne abschließenden Zeilenumbruch: bleibt, entspricht der Generator-Ausgabe und 0015.

Generated by Claude Code

@Fluory
Fluory marked this pull request as ready for review September 24, 2026 11:19
…on-index-check-47

# Conflicts:
#	CHANGELOG.md
@Fluory
Fluory merged commit bb6579c into main Sep 24, 2026
2 checks passed
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.

chore(db): CHECK constraint for field_corrections.item_index

2 participants