einbauSnippet und esc wandern aus routes/termine.js nach services/termine/einbauanleitung.js
(Parameter statt ctx/config). Neu: Modus knopf mit data-knopf (nur bei gesetztem Text, hoechstens
40 Zeichen, Zeilenumbrueche zu Leerzeichen, maskiert; unbekannter Modus gilt als inline), WCAG-
Helfer luminanz/kontrast/textFarbeAuf 1:1 aus dem Widget und cssVorschlag(farbe) mit Warnung,
wenn der Akzent gegen Weiss unter 3 : 1 liegt. VORGABE_FARBE wird exportiert. Die Kundenansicht
bleibt unveraendert (Modus inline). Farbparitaet Widget/Server ueber alle 4096 Farben im
17er-Raster getestet.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
datenschutzAbsatz(einstellung, anrede) liefert den Absatz "Online-Terminbuchung" fuer die
Datenschutzerklaerung der Betriebs-Website als reinen Text (Sie- und Du-Fassung, fuenf bedingte
Saetze: Telefon-Feld, Nachricht/Zusatzfelder, Erinnerung, Widerruf ueber zeigtWiderruf, Telefon des
Betriebs). RECHTSTEXTE_ENTWURF = true. Test pinnt den Wortlaut gegen die Markdown-Quelle in allen
32 Bedingungskombinationen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reine Zeitlogik in Europe/Berlin: tagesbild (Sondertag > Urlaub > Feiertag > Wochenplan,
planbezogen vor global, später angelegt gewinnt), oeffnungsIntervalle (zusammengefügt,
Fenster über Mitternacht gehören zum Starttag), zuUtcOderDanach (März-Lücke auf 03:00).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neue Exporte feiertagName und feiertageImZeitraum (feiertagejs getHolidays je Jahr,
Namen per translate('de')). Heiligabend, Silvester, Mariä Himmelfahrt in BY und
Fronleichnam in SN/TH (Datum aus RP) sind 'pruefen'; istFeiertag bleibt unverändert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Funktion zeiten in config.features (30 €, aboInklusive, consentFrei, teilweiseLive),
freiweg() und Standard-Haken in featureRegistry.js, Stripe-Katalog zeitenSetup
(Metadaten zeiten-einrichtung) in stripeBilling.js und scripts/stripe-products.mjs,
vorläufige zeitenTicketDetails; Schlüssellisten-Pins um zeiten ergänzt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ZEITEN_ENABLED/ZEITEN_PILOT_EMAILS/ZEITEN_KEIN_NEUBAU als config.zeiten (neben config.termine),
zeitenSetup (30 € einmalig), Collection-IDs oeffnungszeiten und zeitenErinnerungen, Schema der beiden
Collections plus fünf neue portalFeatures-Felder, scripts/zeiten-setup.mjs (idempotent, --check),
schemaKeys kennt die neuen Collections und Felder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Ansicht #termine folgt dem Zustand aus GET /api/termine/einstellungen:
off mit laufendem Abo zeigt den Fragebogen samt Bestellseite, ohne Abo den
Hinweis des Servers (termine.hinweis, R111) und bei kein_abo den Link zu
Vertraege aus einer gemeinsamen Quelle (vertraege-link.js); ordered und setup
zeigen die Statuskarte und die Reiter Leistungen, Team & Plaetze und
Einstellungen nur zum Lesen (ohne Reiter Termine); active und disabled
bleiben wie bisher. Rueckkehr von Stripe: #termine?bestellt=1&projekt=<id>
und #termine?projekt=<id> waehlen das Projekt, "Danke!" nur mit bestellt=1,
die Adresse wird einmal gelesen und bereinigt.
R110: GET /einstellungen liefert bestellung und offen auch in ordered (ohne
Abo-Punkt, abo bleibt null); scheitert "Zahlung fortsetzen", zeichnet die
Huelle Liste und Daten neu (bei 409 zustimmung_fehlt mit dem
Bestellformular, sonst nach dem neuen Zustand, die Meldung bleibt am Knopf,
solange die Bestellung offen ist).
Dazu: "null" als Text im lesbaren Reiter Leistungen entfernt, Export und
Status der Einstellungen erst ab der Freischaltung.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET /api/funktionen liefert bei termine.verfuegbar ein fuenftes Feld hinweis
(aboMeldung mit dem Register des Terminplaners, null bei bestellbar true).
Die Kachel zeigt diesen Text maskiert an; die Browser-Kopie der Abo-Texte und
der Gleichheitstest entfallen. Der Link "Zu Verträge" ist eine gemeinsame
Konstante fuer Analyse und Terminplaner und erscheint bei kein_abo.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET /api/funktionen liefert bei termine.verfuegbar: true zusaetzlich bestellbar
(true | false | null bei Lesefehler im Abo), grund (kein_abo | gekuendigt |
nicht_aktiv | null), preis und einrichtung aus dem Register; nicht verfuegbar
bleibt exakt { verfuegbar: false }. Die Kachel zeigt je Zustand Pille und Knopf:
Aus mit Abo "Terminplaner einrichten · 149 €" bzw. "Fragebogen fortsetzen",
Aus ohne Abo keinen Knopf, sondern den Hinweis zum Abo, Zahlung offen und In
Einrichtung "Status ansehen", Aktiv "Termine oeffnen", Abgeschaltet "Termine
ansehen". Zielprojekt: aktiv, ordered/setup, abgeschaltet, Entwurf, erstes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Neu: server/services/termine/entwuerfe.js. Ein Terminplaner im Zustand off ist ein
Entwurf (Fragebogen, Einstellung). loescheEntwuerfe(now) im Tagesjob (nach den
abgeschalteten Funktionen, nur im vollen Lauf): letzte Aenderung = juengerer Zeitpunkt
aus $updatedAt des Funktionsdokuments und termineConfig.updatedAt, aelter als 90 Tage
=> Einstellung weg, das Funktionsdokument nur, wenn es nie in Betrieb oder bezahlt war
(sonst bleibt es wegen des siteKeys; ein von E8 zurueckgesetztes Dokument nie).
Vor jedem Loeschen unter feature-order, feature-admin und termine-cfg frisch lesen
(noch off, Frist, keine Buchung). Seiten zu 100 per cursorAfter, hoechstens 2000
geprueft und 100 geloescht je Lauf, der Rest folgt an Folgetagen; Einzelfehler zaehlen
in fehler. Tagesbericht: Segment "Entwuerfe n geloescht (m offen)".
loescheEntwuerfeVonKunde: Kundenloeschung entfernt alle off-Entwuerfe vollstaendig,
Fehler werden nur protokolliert.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
POST /api/termine/einstellungen/vorlage nimmt jetzt eine Branche (BRANCHEN), optionale
Betriebsfelder (nichtleere Werte ueberschreiben das Konto) und schreibt den Fragebogen mit
der Einstellung in einem Vorgang. Der Gesundheitsbereich ist ausgeschlossen (400
gesundheitsbereich, nichts wird angelegt). Eine bestehende Einstellung ersetzt nur
ersetzen:true mit passender version im Zustand off (neue IDs und Kalender-Token, Fragebogen
neu, Einbauwuensche bleiben). Die Route arbeitet im Entwurf (off, active, ordered/setup nur
in der Kundenansicht, disabled nie).
PUT /api/termine/fragebogen speichert nur den Fragebogen (Version der Einstellung bleibt),
ist in der Kundenansicht gesperrt (Waechter und Router), zaehlt gegen das Schreibbudget und
antwortet mit { fragebogen, offen }.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
PATCH /api/termine/einstellungen schreibt den Entwurf nach eigenen Regeln
(withTermine({ schreiben, entwurf }) in routes/termine.js): off und active
ja, ordered und setup nur in der Kundenansicht (sonst 409 gesperrt), disabled
409 abgeschaltet wie bisher. In off zusaetzlich laeuft(customerId): ohne
Wartungs-Abo 409 kein_abo (Text aus aboMeldung), bei Lesefehler 503
abo_pruefung; eine Kuendigung oder offene Zahlung sperrt nur die Bestellung,
nicht das Speichern des Entwurfs. Das Funktionsdokument legt erst der Handler
an (ensureFeatureDoc), nach der Eingabepruefung. PATCH normalisiert mit
entwurf: state !== 'active' und antwortet mit fehlt. Tests: Zustandsmatrix,
Mandanten, Pflichtangaben, Abo, und die Gegenprobe an der oeffentlichen
Schnittstelle (Entwurf und Einbauwuensche nie oeffentlich).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Ein kopiertes Repo (git clone + push, Vorlage) bringt die
.webklar-preview.json des Originals mit. Sein erster Push ueberschrieb
die Preview des Originals, danach scheiterte der Webhook mit 500
(Unique-Index auf subdomain). Fast passiert bei Olzinger -> HSK-Vorlage,
04.10.2026.
- foreignSubdomainOwner: Subdomain gehoert einem anderen Repo oder einem
Projekt ohne Repo; ein in Gitea umgezogenes Repo (Weiterleitung) zaehlt
nicht als fremd
- Webhook: fremde Subdomain -> kein Deploy, Projekt ohne Preview (neu:
synced, Repo-Name statt fremdem Anzeigenamen); eine schon vergebene
eigene Preview bleibt, WOMS zeigt den Grund als Preview-Fehler
- runDeploy prueft fuer alle anderen Wege (WOMS, Reaktivieren), vor dem
Runner, damit ein gesperrter Aufruf keinen laufenden Bau verwaist;
Appwrite-Fehler bei der Pruefung blockieren dort nicht (Webhook streng)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Wahl des Live-Hosts steht jetzt nur noch in liveHost() (kontext.js);
websiteUrl() und der Betriebsvorschlag des Fragebogens (routes/termine.js)
nutzen dieselbe Funktion.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
kontext.js: ctx.fragebogen (normalisiert; fehlt er oder ist er kaputt, der leere,
kaputt mit einer Logzeile und ohne Wurf), ladeEinstellung liefert zusaetzlich
fragebogen, neuer kontextFuerPortal(feature) fuer das Portal in jedem Zustand.
speichereFragebogen schreibt unter termine-cfg:<id> nur fragebogen, updatedAt und
updatedBy (ohne version; fehlt das Dokument: 409 keine_einstellung). Neue Option
fragebogen bei speichereEinstellung schreibt Einstellung und Fragebogen in
derselben Sperre. kontextPerSiteKey bleibt unveraendert (Entwurf nie oeffentlich),
Tests dazu fuer off, ordered, setup, disabled und nach activate. Der Test
ladeEntwurf in funktionenCheckout.test.js schaltet die neue Logzeile stumm.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
fragebogen.js ersetzt den Stub aus Block B: bestellpruefung (Kriterien (a) bis (h),
je Punkt ein Eintrag, nach Schrittfolge sortiert, Abo-Punkt nur bei mitAbo !== false),
SCHRITT_TITEL, gesundheitsWarnungen (Stichworte nur am Wortanfang, hoechstens 10
Meldungen) und bestellungAnsicht fuer die Bestellseite. einstellungen.js exportiert
sichtbareLeistungen und MELDUNG_PFLICHT. Testhelfer bestellbarerStand und entwurfDoc;
der Stub-Test entfaellt, die zwei B-Tests mit dem Stub laufen gegen das echte Gate.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
termineConfig bekommt das Attribut fragebogen (Text 20000, Inhalt bis
FRAGEBOGEN_MAX 16000). fragebogen.js: SCHRITTE, BRANCHEN (Vorlagen plus
Gesundheitsbereich), leerFragebogen und normalisiereFragebogen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET /api/termine/einstellungen liefert bei abgeschalteter Funktion
abgeschaltet { grund, seit, loeschungAm }. Die 409-Meldung bei
Schreibversuchen (Code abgeschaltet) und der Banner im Portal
unterscheiden Wartungs-Abo beendet, Abo vor der Einrichtung beendet und
die übrigen Gründe und nennen das Löschdatum, wenn es eines gibt.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
setzeFunktionZurueck setzt ein Funktionsdokument mit offenem Zahlungsfall
(zahlungMeldung nicht leer und nicht 'gemeldet') nicht auf off zurueck: Warnung
ohne Kennungen, +1 in lauf.fehler, kein Wurf. Das Dokument bleibt disabled mit
seinen Markern, der Abo-Abgleich holt T19 weiter nach, nach 'gemeldet' setzt der
naechste Lauf zurueck. Buchungen und Einstellung werden wie bisher geloescht.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Bei Grund abo_ende prüft die Löschung vor jedem unumkehrbaren Schritt frisch,
ob das Wartungs-Abo wieder läuft (Lesefehler: nichts löschen). Sind alle
Buchungen und die Einstellung weg, wird das Funktionsdokument unter
feature-admin und termine-cfg auf off zurückgesetzt (siteKey bleibt).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
taeglicherJob ruft gleicheAboAb(now) nach den Löschfristen und vor der Löschung
abgeschalteter Funktionen auf (Schritt „Abo-Abgleich“, ein Fehler dort stoppt weder
Löschung noch Rest; die Fehler des Abgleichs zählen in fehler). Das Ergebnis trägt
aboAbgleich, tagesbericht hängt „Abo-Abgleich N geprüft / N abgeschaltet / N wieder ein /
N Mails / N ausgenommen“ vor „N Fehler“ an.
fuehreAus nimmt trotzAus: Im Modus off läuft der Tagesjob nur, wenn es ein vom Kauf
freigeschaltetes Termine-Dokument gibt (eine Abfrage, limit 1; bei einem Lesefehler
Warnung und { aus: true }). Dann läuft ein eingeschränkter Lauf (eingeschraenkt: true,
gleiche Überlappungssperre): nur Abo-Abgleich und Löschung abgeschalteter Funktionen,
mit eigener Berichtszeile und den Feldern, die meldeTagesjob und die Statusroute lesen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Der taegliche Abo-Abgleich holt T19 fuer jedes bezahlte, abgeschaltete Dokument mit
Grund abo_ende_vor_einrichtung und zahlungMeldung ungleich gemeldet nach, auch wenn das
Wartungs-Abo wieder laeuft oder nicht lesbar ist (der Nachlauf liest das Abo nie).
Reihenfolge wie bisher: T19, dann K22 (nur wenn aboEndeMailAt leer), dann Marker.
meldeAboEnde sendet bei gesetztem K22-Marker und offener Erstattung nur T19.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- archiviertes Projekt bleibt unter Funktionen sichtbar, solange dort eine
Funktion bestellt/eingerichtet/aktiv ist (z. B. Terminbuchungen)
- auf archivierten Projekten nichts neu bestellen oder einschalten
- Projekttyp Vorlage nur fuer Admins; repo-readme nur fuer bekannte Projekte
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entscheidungen vom 04.10.2026:
- Projekt-Routen (website-projects, preview, gitea, services, analyse)
fuer jeden Mitarbeiter (Label mitarbeiter oder admin); Kunden-,
Mitarbeiter- und Finanz-Verwaltung bleiben nur fuer Admins
- Neue Repos aus der Vorlage werden privat angelegt
- Archivierte Projekte sieht der Kunde nicht mehr: Projektliste,
Projektdetails, Preview-Zugang, Funktionen (Mitarbeiter-Ansicht schon)
- Projektliste des Kunden mit Limit (Appwrite liefert sonst nur 25)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schritt 3 von gleicheAboAb: Ein abgeschaltetes Dokument mit Grund abo_ende,
dessen Wartungs-Abo wieder läuft, wird unter feature-admin:<projectId> nach
frischem Lesen von Dokument und Abo und mit vorhandener Einstellung über
activate wieder eingeschaltet (Daten und Einstellungen bleiben). K23 geht
nur, wenn K22 ging (aboEndeMailAt vor dem activate gelesen); scheitert K23,
bleibt die Reaktivierung bestehen. Nicht automatisch: off nach der Löschung,
abo_ende_vor_einrichtung, team, kunde_geloescht, Altbestand ohne Grund.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Terminplaner TP2 E5. Schritt 1b in gleicheAboAb: Dokumente im Zustand ordered
oder setup werden bei fehlendem Wartungs-Abo unter feature-admin:<projectId> nach
frischem Lesen von Dokument und Abo mit Grund abo_ende_vor_einrichtung abgeschaltet.
Die Meldelogik liegt in meldeAboEnde (auch für den Sofortpfad E9): bei bezahlter
Einrichtung zuerst T19 über meldeErstattung (außerhalb jeder feature-admin-Sperre),
dann K22 mit Block vor_einrichtung, dann der Marker aboEndeMailAt; scheitert T19,
folgen weder K22 noch Marker und der nächste Tag wiederholt beides. Ein unbezahltes
ordered-Dokument wird nur abgeschaltet. Schritt 2 holt auch abo_ende_vor_einrichtung
nach. Die Stripe-Sitzung und das Ticket bleiben unangetastet.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
gleicheAboAb(now) liest alle nicht abgeschalteten Terminplaner-Funktionen einmal,
bewertet je Kunde die Abo-Lage (aboMemo) und schaltet aktive, bezahlte Funktionen
ohne laufendes Wartungs-Abo ab (disabledReason abo_ende). Geschrieben wird nur
unter feature-admin:<projectId> nach frischem Lesen von Dokument und Abo; bei
Lesefehlern bleibt alles aktiv. Pilot- und Kulanz-Dokumente zaehlen als
ausgenommen. meldeAboEnde sendet K22 und setzt aboEndeMailAt erst nach Erfolg.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Terminplaner TP2 E3. K22 "Terminplaner beendet" (Blöcke abo_ende, hosting,
vor_einrichtung, daten) und K23 "Terminplaner läuft wieder" im Layout von K19,
Du-Form, Texte als Entwurf für die Mail-Überarbeitung. K02 und K03 bekommen den
Block funktionen (in K03 innerhalb von abo); routes/abo.js setzt ihn nur beim
Wartungs-Abo und nie bei der Speicher-Kündigung.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Ruling R105: featureView setzt loeschungAm nur für featureKey 'termine' (der
30-Tage-Löschlauf löscht nur Terminplaner-Daten); disabledReason und disabledAt
bleiben für alle Funktionen. Test: News ohne Löschdatum, Zeitfenster-Prüfung
entfernt, Teamroute-Ansicht pinnt loeschungAm für den Terminplaner.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
featureView liefert zusaetzlich disabledReason, disabledAt und loeschungAm (Berliner
Tag, 30 Tage nach disabledAt); alle drei nur im Zustand disabled, sonst null.
Neu termine/frist.js mit LOESCHFRIST_TAGE, loeschzeit und loeschTag (nur zeit.js/util.js).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
aboStatus.js (Kernversion aus B5 ausgebaut): ein privater Lader lage(customerId, { altbestand })
ueber getCurrentSubscription und listContractEvents, alle Praedikate bauen darauf. laeuft kennt
altbestand (Vorgabe true: productKey || 'wartung' plus Wechsel-Regel; false: die heutige Regel der
Analyse, keine Ereignisabfrage). Wechsel-Regel: sagt der Spiegel "Wartung laeuft" und ist das
juengste wechsel-Ereignis des Abos widerrufen, laeuft das Wartungs-Abo nicht (kein_abo beim
Bestell-Gate, Freischaltung bleibt in setup). Neu aboLage ({ laeuft, art, endedAt }) und
aboMemo().lage; der Memo merkt eine Ablehnung fuer den Lauf. analyse.js nutzt
laeuft(id, { altbestand: false }); Verhalten der Analyse unveraendert (+1 Pin-Test).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET /api/funktionen liefert features.news und features.termine (oeffentlicheAnsicht,
auch wenn der Terminplaner noch nicht freigegeben ist) und ustHinweis; setupEstimate und
consentText bleiben als News-Alias. Die News-Kachel und die Buchungsseite lesen Preis,
Knopftext und Zustimmungstext aus features.news und fallen ohne features auf die bisherigen
Werte zurueck. News sendet weiter consent: true an /api/funktionen/news/checkout.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Anlegen uebernimmt keinen alten Eintrag gleichen Namens mehr (Repo in
Gitea geloescht): Platzhalter werden entfernt, ein verknuepftes altes
Projekt blockiert den Namen mit klarer Meldung, bevor ein Repo entsteht;
neue Projekte starten mit archived=false
- archiveRepo aendert Gitea und Dokument unter der Repo-Sperre; der Import
liest den Archiv-Stand vor dem Spiegeln frisch aus Gitea
- Reaktivieren: Preview aus -> synced, Deploy-Fehler -> deploy_failed
statt dauerhaft 'pending'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
activateClosedTickets oeffnet jetzt alle Funktionen mit ticketFreischaltung im Register
(ticketFreischaltungKeys) statt fest news und fragt unter der Sperre feature-activate:<id>
nach dem frischen Lesen den Haken freischaltbar(doc). Der Standard fuer termine verlangt eine
gespeicherte Einstellung und ein laufendes Wartungs-Abo. false oder Fehler (z. B. Abo nicht
lesbar) lassen das Dokument in setup: Log und genau ein adminNote-Eintrag "Freischaltung
wartet: <Grund>", keine Mail. News bleibt unveraendert.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Beim Anlegen mit Kunde (ohne Ticket) loeste der Commit der
.webklar-preview.json durch webklar-system ein zusaetzliches Ticket
"Website <name>" aus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
onFeaturePaid wertet den Fall aus markPaid aus. Trifft die Zahlung eine Funktion, die
schon freigeschaltet, in Einrichtung oder abgeschaltet ist, geht nur eine Team-Meldung
raus (T16 Block bereits_aktiv, bei Abo-Ende vor der Einrichtung T19), kein Ticket und
keine K15. Beide Meldungen laufen genau einmal je Dokument: unter feature-meldung:<id>
frisch lesen, Marker zahlungMeldung gemeldet erst nach gesendeter Mail. Scheitert der
Versand, wirft onFeaturePaid (Webhook 500), Stripe wiederholt und der naechste Versuch
sendet genau einmal.
meldeErstattung ist die einzige Stelle fuer T19 (Zahlung nach dem Abo-Ende und spaeter
die Meldung des Abo-Abgleichs), wirft nie. Bei Funktionen mit Wartungs-Abo-Pflicht
zeigt T16 nach der Verbuchung den Block kein_abo, wenn das Abo nicht mehr laeuft; ein
Lesefehler laesst den Block aus und blockiert nichts. customerOf und projectName sind
exportiert.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Neues Projekt ohne Subdomain: subdomain null statt '' (Unique-Index
subdomain_unique, jedes weitere scheiterte mit "Document with the
requested ID already exists"); ebenso Typ "Internes Projekt"
- Anlegen unter derselben Repo-Sperre wie der Webhook repository/created;
upsertWebsiteProjectByRepo macht aus einem 409 ein Update
- Gitea-Beschreibung = Anzeigename; Art (kind) beim Anlegen aus dem Ticket
- Reaktivieren setzt status zurueck (vorher blieb 'archived' stehen)
- Import: archivierte Repos als archiviert, Archiv-Stand aus Gitea wird
gespiegelt, ein fehlerhaftes Repo bricht den Lauf nicht mehr ab
- Abgleich ueberschreibt Projektnamen nicht mehr
- CORS erlaubt PUT (Preview-Variablen speichern)
- Vorlage zieht beim Zuweisen nie in die Org um
- Erinnerungs-Lauf ueberspringt archivierte Projekte
- kaputte Umlaute (U+FFFD) in drei Fehlermeldungen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
markPaid liefert jetzt { doc, created, fall }. Trifft eine Zahlung ein Dokument, das nicht
mehr auf die Bezahlung wartet (active, disabled, setup mit Ticket), wird sie einmalig
verbucht (purchaseStatus paid, unlockedByPurchase, Rechnung, Notiz) und der noch zu
meldende Fall im eigenen Feld zahlungMeldung vermerkt (bereits_aktiv | abgeschaltet |
abo_ende), in einem einzigen Schreibzugriff. Ein Folgeereignis bucht nichts doppelt und
liefert den Fall erneut, bis zahlungMeldung auf gemeldet steht. ordered und fortsetzbares
setup laufen wie bisher, off bleibt unveraendert (Uebernahme ueber adoptPaidSession).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
T16 (Funktion bestellt) nennt die Funktion aus dem Register statt fest
"News-Pinnwand": neue Platzhalter funktion, zustand, anleitung_url und
gesundheit_text, neue Bloecke kein_abo, bereits_aktiv, anleitung (Knopf
"Im Ticketsystem oeffnen" zur Einbauanleitung) und gesundheit. teamNotice
und unmatchedNotice fuellen funktion aus featureConfig (ohne bekannten
Schluessel "Funktion"); die neuen Bloecke kein_abo, bereits_aktiv und
gesundheit bleiben aus, bis B10a und D4 sie fuellen. Die News-Mails
bleiben woertlich (HTML, Text und Betreff byte-gleich).
T19 (Erstattung faellig, Team-Hinweis) ist neu: volle Erstattung von
Hand in Stripe, Bloecke zahlung_nach_ende, ticket_offen und rechnung.
Gesendet wird sie spaeter ueber meldeErstattung (B10b).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
K15 (Bestellung eingegangen) und K16 (Funktion bereit) tragen den Wortlaut der
Funktion als Platzhalter (funktion, funktion_gen/akk/nom/pron/dein, preis_hinweis,
danach, bereit, knopf, portal_url) statt fest News-Pinnwand. siteFeatures baut die
Werte mit bestellMail/bereitMail aus dem Register-Eintrag (mails.*, setupEstimate,
returnHash) und dem Katalogpreis je feature.product. K15 geht ohne Anhaenge raus.
Die News-Mails bleiben Zeichen fuer Zeichen gleich (Test featureMails friert
Betreff und Text ein).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
markPaid holt Betreff und Details des Einrichtungs-Tickets aus dem Register (ticketTexte), createFeatureTicket
bleibt die einzige Stelle, die das Ticket anlegt. Betreff auf 128, Details auf 7000 Zeichen gekuerzt (surrogatsicher,
Schnitt an der Zeilengrenze, einheitliche Schlusszeile). Wirft die Details-Funktion oder liefert sie keinen Text,
gelten die Notfall-Details (Kopfzeilen und Verweis ins WOMS). Nach einem 400 bei langen Details gibt es genau einen
zweiten Versuch mit den Notfall-Details und derselben woid; 5xx, Netzfehler und kurze Details werden ohne
Wiederholung weitergereicht. Stub termine/ticketDetails.js bis Task D4.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Rest der Route POST /api/funktionen/:key/checkout unter der Sperre feature-order:<Kunde>:<Projekt>:
Zustand aus dem Register (setup/active, disabled, ordered mit offener Sitzung, "Zahlung fortsetzen"),
Stripe-Sitzung mit der Zeit des Klicks, Zustimmungsnachweis (Serverfassungen und -texte) vor markOrdered
und vor der URL. Standard-Haken belehrung mit BELEHRUNG_PLATZHALTER fuer den Terminplaner.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
POST /api/funktionen/:key/checkout ersetzt /news/checkout (der News-Pfad bleibt als
key = news erhalten). Stufen ohne Seiteneffekt: 1 Kundenansicht (403), 2 Schluessel
gegen das Register (404), 3 Zustimmung (400 zustimmung_fehlt, 409 fassung_veraltet mit
der Serverfassung; News weiter mit consent: true), 4 Projekt (400/403; bei fortsetzen
muss das Dokument ordered sein), 5 Schalter (409 nicht_verfuegbar), 5b Unterlagen
(503 unterlagen_fehlen), 6 Bestellpruefung (409 bestellung_offen mit offen), 7 Wartungs-Abo
(409 kein_abo | gekuendigt | nicht_aktiv, Lesefehler 500). fail() gibt err.body weiter.
featureOrder.js: pruefeZustimmung, istFortsetzen, aboMeldung (einzige Quelle der
Abo-Hinweistexte), ladeEntwurf, pruefeAbo, orderDeps. featureRegistry.js: featureSperre
und die Standard-Haken verfuegbar, bestellpruefung (mitAbo: false, ohne abo) und
unterlagenBereit des Terminplaners. Der Rest der Route (Sperre, Zustand, Sitzung,
Nachweis) bleibt bis Task B7 nur fuer News; andere Funktionen enden mit 503.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
aboStatus.js: laeuft(customerId) (Wartungs-Abo, productKey || 'wartung', Status in
ACTIVE_STATUSES), bestellbar(customerId) mit den Gruenden kein_abo, gekuendigt,
nicht_aktiv in dieser Pruefreihenfolge und aboMemo() (je Aufruf und Kunde nur eine
Lesung). Fail-closed: ein Lesefehler wirft, nie false oder ok:false.
termine/fragebogen.js: Platzhalter bestellpruefung() mit der endgueltigen Signatur,
liefert []; Block C ersetzt ihn.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>