Marktplatz für gebrauchte Fahrzeugteile · Meilensteine 1–7 stehen · vollständig in Betrieb · mit Treuhand-Kauf · Stand 18. September 2026
Die Beispielinserate sind weg. Die Datenbank enthält nur noch Stammdaten — 28 Fahrzeuge, 95 Kategorien, 8.298 Postleitzahlen. Was du auf der Seite siehst, ist ab jetzt echt.
Das Skript für Beispieldaten bleibt, weil die Live-Tests eine Vorrichtung brauchen: Sie legen sich ihre Inserate selbst an und räumen sie danach wieder weg.
Dein Konto emreevli270@gmail.com ist jetzt Administrator —
ohne das kämst du nicht ins Lager und nicht in die Moderation.
Fahrzeugtyp → Marke → Modell → Baujahr, auf jeder Seite ganz oben. Die Auswahl bleibt in der Sitzung. Probier Motorrad → Yamaha → MT-07 → 2018–2020.
„Passt zu deinem Fahrzeug“ (belegt), „Passt vermutlich“ (mit Prüfhinweis), „Weitere Treffer“ (Volltext, ohne Fahrzeugbezug). Kein Inserat steht in zwei Blöcken.
Auf der Inseratsseite steht „vom Verkäufer bestätigt“ oder „vermutet“ — nie eine Zusage, die kein Fitment-Eintrag deckt.
Registrierung mit E-Mail-Bestätigung, Anmeldung, Profil, eigene Inserate verwalten, Gespräche, Bewertungen, Meldefunktion.
Unleserliche Stellen bleiben als ? stehen und werden nie
ergänzt — siehe die Bremsscheibe mit 1WS-F581T-00 und den
Scheinwerfer mit B4C-84?00-00.
Airbagmodule, Gurtstraffer, pyrotechnische Batterietrenner und die Airbagweste lassen sich nicht einstellen. 27 der 95 Kategorien sind als sicherheitsrelevant markiert, 5 sind gesperrt.
| Baustein | Stand | Einzelheiten |
|---|---|---|
| Worker | läuft | ironparts auf der Subdomain ironparts.workers.dev, per API angelegt |
| Datenbank | läuft | PostgreSQL 17.6 bei Supabase, Region eu-west-1 — 16 Tabellen, 12 CHECK-Bedingungen, 4 Migrationen |
| Stammdaten | geladen | 28 Fahrzeuge, 95 Kategorien, 8.298 Postleitzahlen mit Koordinaten |
| Hyperdrive | läuft | Verbindungs-Pool vor dem Supabase-Pooler (Session-Modus, Port 5432) |
| Datenbankrolle | angelegt | ironparts_app mit eigenem Passwort — das postgres-Passwort blieb unangetastet |
| Geheimnisse | gesetzt | APP_GEHEIMNIS, S3_ZUGRIFFSSCHLUESSEL, S3_GEHEIMSCHLUESSEL |
| R2 (Bilder) | läuft | Bucket ironparts-bilder (WEUR), öffentlich über pub-…r2.dev, CORS für den Direktupload aus dem Browser gesetzt |
| E-Mail-Versand | läuft | Resend über die verifizierte Domain calestai.com, Absender noreply@calestai.com |
| KI — Käuferfragen | läuft | CALEST über calestai.com, Modell calest-auto |
| KI — Bilderkennung | aus | CALEST kann keine Bilder (gemessen). Braucht ein Vision-Modell — dafür fehlt ein Schlüssel. |
| Kauf mit Treuhand | läuft | Vollständiger Ablauf über Lager, mit Prüfpfad. Zahlung im Testmodus. |
| Zahlungsdienstleister | Testmodus | Stripe Connect angebunden, es fehlt nur der Schlüssel. Bis dahin fließt kein echtes Geld. |
52 Prüfungen laufen gegen die deployte Instanz grün.
22 davon fahren einen kompletten Treuhand-Kauf über drei Konten — Käufer, Verkäufer, Betrieb — von der Bestellung bis zur Auszahlung. Geprüft wird nicht nur, dass der gute Verlauf durchläuft, sondern auch, dass die Sperren halten: dass der Käufer sein eigenes Geld nicht freigeben kann, und dass die Freigabe ohne hinterlegtes Auszahlungskonto abprallt, und dass die Annahme ohne die Zustimmung nach § 356 Abs. 4 BGB gesperrt bleibt und diese Zustimmung danach in der Akte steht. Am Ende wird der Prüfpfad Schritt für Schritt gegen die erwartete Abfolge verglichen.
16 lesende (npm run test:live): Startseite, Fahrzeugleiste,
Anmeldung mit Demo-Konto, eigene Inserate, Inseratsseite mit Preis, Passung
und Teilenummer, Profil, alle vier Rechtstexte, keine Schlüssel im
ausgelieferten Browser-JavaScript, keine JavaScript-Laufzeitfehler.
14 schreibende (npm run test:live-schreibend) decken genau
das ab, was von den beiden externen Diensten abhängt: Registrierung mit
echtem Versand, der Bestätigungslink aus der tatsächlich zugestellten
Mail gelesen, Anmeldung, Bildupload direkt aus dem Browser nach R2 und
der öffentliche Abruf des hochgeladenen Bildes. Der Link kommt bewusst aus
der Mail und nicht aus der Datenbank: Dort liegt nur sein SHA-256-Hash, im
Klartext steht er nirgendwo sonst. Registriert wird auf
delivered@resend.dev, Resends Testadresse — echter Versandweg,
kein fremdes Postfach.
Die drei Suchblöcke wurden einzeln gegen die Live-Instanz nachgemessen: Bei gewählter MT-07 2018–2020 stehen Bremsscheibe und Scheinwerfer in Block 1, das Kettenkit in Block 2, und Spiegelpaar, Stahlflex-Leitung und Auspuff landen in Block 3 — ohne Überschneidung.
Die 214 Prüfungen der sieben Meilenstein-Suiten brauchen dagegen eine direkte Postgres-Verbindung, um sich ihre Testdaten selbst einzurichten. Die gibt es in dieser Umgebung nicht; gelaufen sind sie zuletzt in der Entwicklungsumgebung.
Der Ablauf, den du beschrieben hast, ist gebaut und läuft:
| Schritt | Wer |
|---|---|
| Bestellung anlegen | Käufer |
| Annehmen oder ablehnen | Verkäufer |
| Bezahlen — das Geld geht an den Zahlungsdienstleister | Käufer |
| Teil ans Lager schicken, Sendungsnummer eintragen | Verkäufer |
| Wareneingang buchen | Betrieb |
| Gegen das Inserat prüfen | Betrieb |
| An den Käufer verschicken | Betrieb |
| Erhalt bestätigen | Käufer |
| Geld an den Verkäufer freigeben | Betrieb |
Das Geld liegt nie auf einem Ironparts-Konto. Gehalten wird es beim lizenzierten Zahlungsdienstleister; Ironparts gibt nur frei. Würdet ihr es selbst entgegennehmen und weiterleiten, wäre das in Deutschland ein erlaubnispflichtiges Zahlungsgeschäft nach dem ZAG — mit BaFin-Erlaubnis oder gar nicht. So geht derselbe Ablauf, ohne in die Erlaubnispflicht zu laufen.
Gerade läuft der Testmodus. Alles ist durchklickbar, es fließt kein echtes Geld. Für echtes Geld fehlt nur ein Stripe-Schlüssel — die Anbindung steht.
Wer welchen Schritt auslösen darf, steht als eine Tabelle im Code statt verteilt in Abfragen. Zwei Entscheidungen daraus: Die Freigabe darf ausschließlich der Betrieb — der Schritt, bei dem das Geld die Treuhand verlässt, soll niemandem gehören, der davon profitiert. Und den Erhalt darf neben dem Käufer auch der Betrieb bestätigen, sonst hielte ein Käufer, der einfach nichts mehr tut, das Geld des Verkäufers auf ewig fest.
Jeder Schritt schreibt eine Zeile, die nie geändert wird. Bei einer Treuhand ist im Streitfall die Frage „wer hat wann was gemacht" die ganze Beweislage.
Die Bildfrage war zwischenzeitlich mit „nein" beantwortet — ein Testcall
mit Bildinhalt kam mit HTTP 400 zurück. Nach der Nachbesserung
am Schlüssel ist sie neu gemessen und lautet ja: CALEST
nimmt Bilder an und liest sie. Beides getrennt geprüft, weil ein
HTTP 200 für sich genommen nichts beweist — der Dienst könnte
den Bildteil stillschweigend verwerfen und trotzdem antworten.
npm run ki:bildtest schickt deshalb drei einfarbige Bilder
und verlangt drei verschiedene, jeweils richtige Farbantworten. Rotorange,
blau, grün — dreimal getroffen. Erst danach sind
KI_BILD_ANBIETER=calest und CALEST_BILDER=ja
gesetzt worden.
Der ganze Weg läuft: Prompt A liefert zu einem Foto schemagültiges JSON in 16,6 Sekunden — und weigert sich dabei korrekt, ein nichtssagendes Testbild zu bestimmen, statt etwas zu erfinden. Prompt B antwortet in 5,3 Sekunden aus der bestätigten Passung. Der Adapter besteht 45 von 45 Prüfungen.
Ein Fehler lag dabei bei uns, nicht bei CALEST: Der Prompt schreibt für
Unbekanntes null vor, unser Schema nahm aber nur ein fehlendes
Feld an — und war darin nicht einmal einheitlich. Wohlgeformte Antworten
fielen durch. Das Schema glättet null jetzt vor der Prüfung.
Impressum, Datenschutzerklärung, AGB und Widerrufsbelehrung sind keine
Gliederungen mehr, sondern vollständige Texte. Sie beschreiben den Ablauf,
den die Anwendung tatsächlich umsetzt, und nicht einen, den sie haben
könnte — die AGB folgen mit ihren 22 Paragraphen dem Zustandsautomaten
aus ablauf.ts: Vertragsschluss erst mit der Zahlung,
Gefahrübergang bei Ein- und Ausgang im Lager, was im Lager geprüft wird und
was ausdrücklich nicht, Fristen an einer Stelle gesammelt, Gebühr,
Streitfall, abgelehnte Teile.
Zwei Stellen sind dabei aufgefallen und behoben worden, weil der Text sie sonst hätte beschönigen müssen:
Anwaltlich geprüft sind die Texte nicht, und sie geben sich auch nicht so: Über jeder Rechtsseite steht, woran es noch fehlt. Fehlende Pflichtangaben nach § 5 DDG werden rot ausgewiesen, statt dass die Anwendung eine Anschrift erfindet.
Die Oberfläche sieht jetzt aus wie ein Marktplatz: helle Warenfläche, dunkles Kopf- und Fußband, Signalorange für alles, was zum Handeln auffordert. Der Inhalt trägt die Seite — Bild, Titel, Preis, Zustand, immer an derselben Stelle, damit sich Inserate vergleichen lassen.
Zwei Dinge sind dabei aufgefallen und mitrepariert worden. Die Suchleiste
schickte ihr Formular an die aktuelle Adresse, solange die Seite
noch nicht hydriert war — aus einem Klick auf der Anmeldeseite wurde
/anmelden?q= statt einer Suche; jetzt steht
action="/suche" daran, und die Suche funktioniert auch ganz ohne
JavaScript. Und die neuen Kategorielinks hätten still ins Leere gezeigt: Die
Suche kannte Kategorien nur als Id aus der Filterspalte, jetzt versteht sie
auch einen Slug.
Die zwei Dinge, die vorher am Konto hingen, sind erledigt — beide Wege laufen und sind nachgemessen.
http umgestellt, Absender auf die verifizierte Domain.workers.dev-Adresse. Sobald eine Domain da ist, kommt sie
als custom_domain in wrangler.jsonc, und
APP_URL zieht nach.