Lehnt Stripe die Kontoanlage ab, weil das Connect-Plattformprofil von WEBklar fehlt (oder Connect nicht aktiv ist),
bekommt der Kunde 503 'plattform_nicht_bereit' mit eigenem Du-Text, und das Log nennt die Ursache (ohne Stripe-Text).
Gefunden im Pilot 2026-10-06.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entwurf umbenannt (zeiten-datenschutz-6e-entwurf.md), Leistungsbeschreibung, Kanzlei-Fragen,
Livegang-Notiz und Test-Pins ziehen mit. N13: Rückgabe-Marker nach dem Löschen fehlt (vor on).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seit TP2 bleiben die Abo-Dokumente stehen (held), wenn das Löschen abhängiger Daten scheitert. Der Test für die
Aufbewahrungs-Löschung prüft jetzt auch für die Zeiten: held nennt den Kunden, das Abo-Dokument bleibt, der
nächste Lauf findet den Kunden wieder und erst nach dem Löschen der Zeiten gehen die Abo-Dokumente.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Wächter in zeitenRecht.test.js hat den Drift gefunden: Abschnitt 7 in public/datenschutz.html enthält seit TP2
den Satz zu Bestellungen ohne Abo. Das wörtliche Zitat im Entwurf ist nachgeführt, der Vorschlag ändert wie
bisher nur den Anfang des Satzes. Dazu ein Nachtrag im Entwurf: Abschnitt 6d ist seit dem Webshop-Livegang
vergeben, der Abschnitt der Öffnungszeiten muss beim Übernehmen als 6e eingebaut werden (Anker id="zeiten"
bleibt); die Umnummerierung entscheidet der Inhaber.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Öffnungszeiten stehen jetzt hinter dem Webshop (news, termine, shop, zeiten): Register, FEATURE_KEYS und
ticketFreischaltungKeys in zeitenRegister, die drei Listen in app.js (VIEW_HASHES, APP_PARENT, FEATURE_LABELS)
in zeitenBestellen und shopWiring (APP_PARENT endet mit webshop, zeiten). funktionenZeitenTile prüft die Importe
von funktionen.js gegen den Stand von main (fn-util.js und analyse-view.js); die Kachel der Öffnungszeiten
bringt weiterhin keinen neuen Import mit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zusammenführung von TP2-Abschluss und Webshop (origin/main cab9c33) mit Öffnungszeiten live. Beide
Funktionen bleiben vollständig: jeder Konflikt ist als Vereinigung gelöst, Reihenfolge der Funktionsschlüssel
überall news, termine, shop, zeiten.
Konfliktdateien (28): public/app.js, dashboard.html, funktionen.js, widerrufen.html; scripts/stripe-products.mjs;
server/config.js, index.js, middleware/kundenansichtGuard.js, routes/abo.js, routes/admin/funktionenAdmin.js,
routes/funktionen.js, services/customerAdmin.js, customerViewLog.js, featureRegistry.js, retention.js,
siteFeatures.js, stripeBilling.js; test/customerViewLog, featureFreischaltung, featureRegistry, funktionenRoutes,
funktionenTermine, kundenansichtGuard, mailTemplates, publicForms, siteFeatures, stripeProductsScript (je
.test.js) und test/support/schema.js.
Entscheidungen: Mailvorlagen G01–G15, K01–K30, T01–T21 lückenlos (K24–K26 Webshop, K27–K30 Öffnungszeiten);
Stripe-Katalog mit shopSetup und zeitenSetup; Widerruf kennt shop und zeiten; ABO_FUNKTIONEN bleibt analyse
und termine (kein zeiten); activate() schreibt die Zeiten-Felder nur über extra; kein Halter von
feature-activate:<id> ruft disable() auf; die Aufbewahrungs-Löschung löscht Zeiten-Daten vor dem Abschalten und
hält den Kunden bei einem Fehler (held); die Admin-Antwort trägt ersatzTicket und warnung; Hash-Routen webshop
und zeiten, Ansichten view-webshop und view-zeiten; assertOwnProject behält die Meldung von main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
K24–K26 sind seit dem Webshop-Livegang (main) vergeben; der Mail-Lader sucht die Vorlage über den
Dateianfang, doppelte Nummern hätten die falsche Mail geschickt. Das Feld ist noch nicht in der
Produktion angelegt (zeiten-setup.mjs lief noch nicht), daher jetzt ein sprechender Name.
Spec und Plan behalten die alten Nummern (Hinweis oben im Dokument).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seit 2c7cd26 kostet jede Art in VORRANG/NACHRANGIG ein notEqual in der Abfrage der Klasse normal; live stößt die URL
bei nginx an (414). G09–G15 laufen deshalb in der Klasse normal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Absatz "Die Website-Analyse und der Terminplaner gehören zum Wartungs-Abo und enden mit ihm."
stand bei jeder Kündigung eines Wartungs-Abos. Nach der Entscheidung vom 05.10.2026 steht er nur
noch, wenn der Kunde ein Funktionsdokument (portalFeatures, featureKey analyse oder termine) in
einem Zustand ausser off hat.
- abo.js: hatAboFunktionen(sub) liest über listCustomerFeatureDocs (wie die übrigen Funktions-
Abfragen) die Dokumente des Kunden des Abos; ein Lesefehler zählt als ja (eine Logzeile, die Mail
geht in jedem Fall raus). Der Block funktionen in K02 (Kündigung im Stripe-Kundenportal) und K03
(Kündigungsseite, weiterhin nur beim Abo) ist jetzt isWartung(sub) && hatAboFunktionen(sub);
beim Hosting-Abo wird gar nicht erst gelesen. Die Vorlagentexte bleiben unverändert.
- Tests: K02 und K03 ohne Dokument, mit aktiver Analyse, Terminplaner in setup/ordered/disabled,
nur off (und ohne Zustand), News oder Dokument eines anderen Kunden, Lesefehler (Hinweis bleibt,
Mail geht raus, eine Logzeile) und Hosting-Abo (kein Hinweis, kein Lesen).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Auf der echten Appwrite 1.8.1 lehnt notEqual mit Liste die Abfrage ab (HTTP 400
general_query_invalid, "NotEqual queries require exactly one value"). Die Klasse normal der
Mail-Warteschlange schickte immer eine Liste, jeder Lauf warf dort, und die nachrangige Klasse
(G05, K20, K21) kam nie dran.
- appwriteAdmin: Query.notEqual nimmt genau einen Wert (eine Liste wirft einen TypeError, der
keinerVon nennt); neu keinerVon(attribute, werte) = je Wert ein notEqual (Appwrite schneidet
sie); dokumenteUrl() baut die Listen-URL ohne Netz, mit derselben Serialisierung wie die Anfrage.
- outbox: klassenFilter liefert fuer jede Klasse eine Liste von Abfragen (normal = sechs notEqual
auf art), die Ausschlussliste ist keinerVon('featureId', ...). AUSSCHLUSS_MAX 90 -> 30 (der nginx
antwortet in dieser Abfrageform ab 46 Funktions-IDs mit 414); der Kommentar "100 Werte je Abfrage"
entfaellt.
- Nachbau (appwriteMock): notEqual mit Liste oder ohne Wert => 400 wie Appwrite; ein Dokument mit
Feld null oder ohne Feld passt nicht zu notEqual (SQL-Semantik).
- Tests: Query-Helfer, keinerVon, dokumenteUrl, Nachbau (400, null), ein Lauf bedient alle drei
Klassen, Ausschlussliste hoechstens 30 und URL unter 6000 Zeichen im schlimmsten Fall.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AVV, Leistungsbeschreibung, Datenschutzerklärung (6d), Datenschutz-Absatz und Kanzlei-Paket an das Verhalten
angepasst; HTML und PDF neu erzeugt (Fassung 2026-10-05 unverändert, nie ausgeliefert).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
schliesseAb und verwirf entfernen ipHash aus dem Bestell-JSON, sobald die Bestellung nicht mehr offen ist
(Begrenzung offener Bestellungen je IP bleibt). customer_details.phone wird nicht mehr in kaeufer.telefon
übernommen; Kundenansicht und Bestelldetail geben auch in alten Datensätzen keine Telefonnummer aus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AVV (Vorbemerkung Abs. 2, Nr. 2, 3, 8, 9, Anlage), Leistungsbeschreibung (Nr. 2, 5, 6, 10),
Datenschutzerklaerung Abschnitt 6d, Datenschutz-Absatz fuer Haendler und Kanzlei-Paket (F12, F14, F16, F18, F19,
Fundstellen) beschreiben jetzt genau, was gebaut ist: jede bestaetigte Fassung der Rechtstexte liegt im Archiv und wird
mit den Shop-Daten geloescht, G09 zeigt die archivierte Fassung zum Hash der Bestellung; Eingangsmail G15 bei SEPA; die
Stripe-Kasse fragt keine Telefonnummer ab; die Bestellung speichert einen gesalzenen IP-Hash (Missbrauchsschutz,
Pseudonym), der bei Loeschung oder Anonymisierung entfaellt; Freischaltung durch das Team nur mit Zustimmung in Textform
samt Nachweis. Fassung 2026-10-05 bleibt, HTML und PDFs neu erzeugt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"zzgl. Versand" steht jetzt unter dem Preis jeder Artikelkarte und im Detail, nur wenn der
Shop versendet. Unter dem Raster bleibt der Steuerhinweis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /:siteKey liefert dann die Widerrufsseite (nurWiderruf), POST /:siteKey/widerruf samt
Preflight geht durch, solange die Funktion active oder disabled ist. Bestellen, Pruefen, Status
und Bilder bleiben gesperrt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
I-6: Neue Collection shopRechtstexteArchiv (ID r + 35 Hex aus sha256(shopId + hash)); das
Bestaetigen legt die Fassung samt Versand-/Zahlungstext und Gewaehrleistungstext ab, G09 zeigt
die Fassung zum rechtstexteHash der Bestellung (Rueckfall mit Warnung auf die aktuell
bestaetigte), loescheShopDaten loescht das Archiv mit.
I-7: Grenzen AGB 20000, Belehrung 12000, Formular 3000 plus Pruefung der maskierten Laenge beim
Speichern; G09 ersetzt die AGB nie mehr durch einen Link, sondern scheitert (Marker bleibt
offen, wird wiederholt). Test mit Texten in Hoechstlaenge gegen die Grenzen der Warteschlange.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pruefeBestaetigbar listet die Probleme in Du-Form; POST /api/shop/rechtstexte/bestaetigen
antwortet 400 nicht_bestaetigbar mit der Liste, GET und PUT liefern sie als probleme mit.
Der Reiter Rechtliches zeigt die Punkte im Bestaetigungsblock und sperrt den Knopf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kleinunternehmer ist ab jetzt null (nicht gewaehlt), lieferzeit leer. istVollstaendig verlangt eine
bewusste Wahl (true oder false), der Shop kann sonst nicht geoeffnet werden. Im Reiter
Einstellungen gibt es zwei Pflicht-Radiobuttons ohne Vorauswahl; Preise, Artikel und Muster
rechnen bei null wie bei Regelbesteuerung. Tests und Fixtures angepasst.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die amtliche Gewaehrleistungsgrafik steht in hervorgehobenem Kasten mit Ueberschrift vor der
Zusammenfassung der Kasse (hoechstens 420 px breit, sofort geladen, Vergroessern oeffnet sie in
einem mit Esc und Knopf schliessbaren Dialog). Direkt ueber "Zahlungspflichtig bestellen" steht
"Es gelten unsere AGB. Informationen zu Ihrem Widerrufsrecht finden Sie in der
Widerrufsbelehrung." mit Links auf beide Texte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
§ 2 beschreibt Bestaetigungsseite, sofortige Bestellbestaetigung bei Karte/Klarna und
Eingangsmail mit spaeterem Vertragsschluss bei SEPA. § 9 nennt technische Schritte,
Berichtigung von Eingabefehlern, Speicherung, Sprache und Verhaltenskodizes. Markdown-Muster
und Test sind angeglichen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
G15 "Wir haben Ihre Bestellung erhalten" geht einmal raus, sobald Stripe die Sitzung
abgeschlossen, die Zahlung aber noch nicht gemeldet hat (meldeEingang, Marker mailsEingangAt,
aus dem Webhook und aus pruefeOffene). G09 sagt ausdruecklich, dass der Kaufvertrag mit der
Mail geschlossen ist, trennt Bestell- und Zahlungsdatum und nennt die Telefonnummer des
Anbieters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AVV Webshop, Vorbemerkung Abs. 2: Das Team darf den Webshop ohne Online-Bestellung
nur einschalten, wenn der Kunde vorher in Textform zugestimmt hat. Die Textform-Aktivierung
gilt jetzt wie beim Terminplaner auch fuer 'shop' (Modus on, Pilotadressen ausgenommen,
shopTextformNoetig): Nachweis in featureConsents mit Fassung (config.shop.fassung), Datum,
Weg, Mitarbeiter und dem Wortlaut der Erklaerungen der Bestelltexte, K16 mit
Leistungsbeschreibung und AVV als PDF. GET /api/team/funktionen/:kunde liefert zusaetzlich
shop { textformNoetig, avvVersion, links }.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
disable (und damit disableCustomerFeatures bei Kundenloeschung) leert fuer die Funktion shop den Kontext-Cache dieses siteKeys, per dynamischem Import und best effort.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ueber die gemeinsame Empfaenger-Kappe (darfEmpfaenger) geht an dieselbe Adresse hoechstens dreimal je Stunde ein G12. Darueber hinaus wird der Widerruf trotzdem gespeichert und mit eingang beantwortet, es wird aber keine weitere Mail eingereiht (bestaetigungAt bleibt leer).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Routen aktion, erstatten und widerrufe/erledigt akzeptieren jetzt auch den Zustand disabled; Einstellungen, Artikel und Oeffnen bleiben gesperrt. Die Oberflaeche laesst Bestellungen und Widerrufe bei abgeschaltetem Shop bearbeitbar (ctx.abwickeln), der Hinweis nennt es.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
berechne lehnt Gesamtbetraege unter 0,50 EUR mit dem Code mindestbetrag und einem Kaeufertext ab. legeBestellungAn schiebt expires_at um die seit Beginn vergangenen ganzen Sekunden (Warten auf Sperren) weiter und fuehrt ablaufAt auf denselben Wert nach, damit Stripes 30-Minuten-Minimum sicher bleibt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die IP wird nur als gesalzener Kurz-Hash (sha256, 16 Hex-Zeichen) im Bestell-JSON abgelegt; der Tagesjob entfernt ihn bei der Anonymisierung mit. Die Pruefung laeuft unter der Bestandssperre, Honigtopf und Fehlversuche legen nichts an und zaehlen nicht. Antwort 429 zu_viele_offen mit Retry-After 1800.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Editor sendet neben bestand den beim Laden gesehenen Wert (bestandGeladen, je Variantenwert mit id). speichereProdukt behaelt unter der Artikelsperre den aktuell gespeicherten Stand, wenn gesendet gleich geladen ist, und schreibt nur vom Haendler geaenderte Bestaende. bestandGeladen wird nie gespeichert; ohne den Wert (alter Browser) gilt der gesendete Bestand wie bisher.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der Bestandsabzug laeuft jetzt im selben Block unter shop-bestand und shop-produkte wie der Statuswechsel auf bezahlt, zieheBestandAb haelt keine eigene Sperre mehr. Im Bestell-JSON stehen bestandAbgezogenAt, mailsKaeuferAt und mailsHaendlerAt als Marker; schliesseAb (Webhook-Wiederholung, Statusabruf, Minutenjob) holt fehlende Schritte genau einmal nach, Mails hoechstens fuenfmal versucht. Bezahlte Bestellungen ohne Bestandsabzug zaehlen weiter als reserviert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Fragenliste F1 bis F18 ist ins Paket übernommen und um F19 bis F29 ergänzt; die alte Datei verweist nur noch auf das Paket.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nr. 1, 5, 9 Abs. 4 und Nr. 10 der Leistungsbeschreibung sowie AVV Nr. 2 und 9 nennen den Vertrag über den Betrieb der Website statt Hosting- oder Wartungs-Abo; HTML, PDF, Prüfsummen und Kanzlei-Frage F9 nachgezogen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 6d-Entwurf § 7: Stripe-Sitzung nur bei Bestellung, IP-Adresse und Browserkennung bei jeder Zustimmung
(auch Gratisweg); Offener Punkt 4 beantwortet
- Einbau-Anleitung: CSP braucht auch style-src, Portal mit docker compose up -d neu erstellen, Satz zu
Einzelseiten-Apps, data-api nur am Script-Tag
- Kanzlei-Fragen: ZQ11 (Team-Aktivierung ohne Zustimmung), ZQ12 (Pflichtinformationen als Haken und in K15);
ZQ3 und Schlussnotiz an den Stand von Wertersatz-Satz und Widerruf-Seite angepasst
- Livegang-Notiz: Zusammenführung über origin/main mit erwarteten Konflikten, genaue Push-Refs und
Webhook-Warnung, Sicherungen und Prüfungen vor der Compose-Änderung, Schema-Check nach dem Anlegen,
Runner-Neustart prüfen, setup-legal als ungetestet, Live-Checks und Rückweg, Handrezept für Testdaten,
Test-Anpassung bei bald:false, Checkliste nachgeführt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- shop/jobs.js: taeglicherJob (Käuferdaten bezahlter Bestellungen und Widerrufe 3 Jahre nach Ende des Bestelljahres anonymisieren, Grenze 1. Januar Berlin; unbezahlte/stornierte Bestellungen nach 30 Tagen löschen; Shops seit 90 Tagen disabled samt Artikeln, Bestellungen, Widerrufen, Bildern und shopConfig löschen, Funktionsdokument bleibt disabled mit Vermerk), seitenweise mit Deckel je Lauf, Schritte und Dokumente einzeln abgesichert; stuendlicherJob räumt nie beanspruchte Bilder auf
- shop/loeschen.js: gemeinsamer Baustein zum Löschen aller Daten eines Shops (Tagesjob und Löschfristen)
- shop/kundenLoeschung.js + customerAdmin.js: Kundenlöschung schaltet den Webshop ab (kunde_geloescht) und schließt die Shops
- retention.js: fällige Kunden verlieren auch ihre Shopdaten (vor den Abo-Dokumenten, bei Fehler held)
- server/index.js: Minuten- (75 s), Stunden- (130 s) und Tagesjob (200 s) registriert
- Tests: shopJobs.test.js, retention.test.js erweitert
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- JSON-LD wird ohne "<" geschrieben (<), ein </script> im Firmennamen bricht keinen Block mehr
- verschiebe(): ist die Hinweis-Leiste weggescrollt, bekommen feste Elemente ihren eigenen Inline-top zurück
(Köpfe, die per Klasse beim Scrollen wegfahren, funktionieren wieder)
- Späte Platzhalter (Einzelseiten-Apps): entprellter MutationObserver auf body zeichnet neue oder wieder
eingehängte Platzhalter nach
- sichererLink lehnt Zugangsdaten in der Adresse ab; die Adresse der Schnittstelle bestimmt nur das eigene
Script-Tag, kein Platzhalter mehr (der siteKey am Platzhalter bleibt laut Spec 4.2)
- Editor: die Bestätigung klebt unter der Kopfleiste und bleibt nach dem Speichern eines unteren Abschnitts sichtbar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eigene Helfer in shop-dom.js (inkl. euroEingabe, datumText), Anfrageformular und -karten
in shop-anfrage.js, Reiter als lazy geladene Platzhalter-Module für G3 bis G6.
Die Bestellseite zeigt den Hinweis zu „Ändern“ nur noch, wenn es Schritte gibt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- activate() schreibt die Zeiten-Felder (aboEndeAt, behaltenSessionId) nur noch über extra
(nur Abo-Rückkehr und Team-Aktivierung der Zeiten); News und Terminplaner laufen auch vor zeiten-setup.mjs
- Abo-Abgleich: K27 gilt als offen, solange der Marker vor disabledAt liegt (kein Zurücksetzen nach disable() nötig);
K27 geht erst nach dem Ersatz-Ticket raus (scheitert es, wiederholt der nächste Lauf beides);
Löschung setzt auch activatedAt zurück
- Zustimmung "beginn" (bezahlt) mit Wertersatz-Satz (§ 357a Abs. 2 BGB) wie bei News und Terminplaner, Fassung 2026-10-05
- Widerruf: Bestellung "zeiten" in ORDERS, FEATURE_OF_ORDER, orderLabel und widerrufen.html
- Team "Ticket nachlegen" der Zeiten ohne Kauf geht über holeZeitenNach statt über den Zahlungsweg
- Einschalten-Route nimmt nur { zustimmung }, nicht die Altform { consent: true }
- Team-Aktivierung behält kauf/unlockedByPurchase bei einem bisher gekauften Dokument
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
schliesseAb ist die einzige Stelle fuer den Status bezahlt: Sperre je Bestellung, Konto muss zum Shop passen,
idempotent, spaete Zahlung nach Ablauf wird angenommen, SEPA erst bei bezahlt, Bestandsabzug mit Ueberverkauft-Hinweis,
G09 an den Kaeufer und K25 an den Haendler (Mailfehler machen nichts rueckgaengig). pruefeOffene und jobs.js minutenJob
gleichen offene Bestellungen mit Stripe ab. fakeStripe: completeSession.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Käufermails laufen über die Warteschlange des Terminplaners (G09/G12 mit Vorrang),
G09 wird bei Überlänge um den AGB-Text gekürzt (Link statt Text). Der Mailteil des
Minutenjobs und die Aufräumschritte des Tagesjobs laufen auch bei TERMINE_ENABLED=off,
solange SHOP_ENABLED nicht off ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- routes/shop.js: gemeinsame Pruefung mitShop (Schalter, eigenes Projekt, Funktion setup|active, lesend auch disabled, shopConfig
bei Bedarf anlegen); GET /status erweitert (Bereitschaft, geoeffnet, Snippet, Vorschau, Stripe ohne Konto-ID, Zahlen);
Einstellungen, Artikel (mit Bild-Pruefung, Beanspruchen und Aufraeumen), Sortierung, Rechtstexte (Entwurf, Bestaetigen mit Hash),
Oeffnen/Schliessen, Bild-Upload (octet-stream, 8 MB) und Vorschau; Schreib-Limit 300 je Stunde und Kunde
- services/shop/bilder.js: Artikelbilder nach dem Muster von newsImages.js (1600/480 px WebP, Sidecar, 24-h-Aufraeumen, 40 Uploads/h)
- Kundenansicht: sieben Verwaltungs-Pfade erlaubt und als shop_aenderung protokolliert; Anfrage, Oeffnen, Bestaetigen, Stripe bleiben gesperrt
- Tests: shopRoutes, shopBilder; Erwartungen von kundenansichtGuard, customerViewLog und shopAnfrage angepasst
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Grafik aus dem Amtsblatt (ABl. L vom 2.10.2025, S. 5) ausgeschnitten; Text der Grafik wörtlich für Alternativtext
und Bestellbestätigung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Laden von shopConfig (Einstellungen, Rechtstexte als Entwurf/bestaetigt, Stripe-Status) mit sicherem Parsen,
30-s-Speicher je siteKey mit generation-Zaehler (active und disabled), bereitschaft() mit den fuenf Punkten,
istGeoeffnet() und oeffentlicheRechtstexte().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reine Funktion berechne(): Positionen zusammenfassen, Bestand und Reservierung,
Lieferart und Land, Mindestbestellwert, Versandkosten, enthaltene USt je Satz
(Versand anteilig) und Kleinunternehmer-Hinweis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Anfrage stellen, zurückziehen und Stand lesen (ensureShopConfig, normalisiereAnfrage,
stelleAnfrage, zieheZurueck, anfrageAnsicht), Router /api/shop mit Rate-Limit 20/h und
Sperre in der Kundenansicht, Vorlage T21 Neue Webshop-Anfrage mit Tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Widerrufsbelehrung nach Anlage 1 (Stand 2026, mit Hinweis auf die Widerrufsfunktion), Formular nach Anlage 2,
Muster-AGB ohne OS-Plattform, erzeugter Versand-/Zahlungstext, Gewaehrleistungshinweis (Wortlaut zu pruefen),
Muster-Markdown fuer die Kanzlei und Tests inkl. Abgleich Markdown/Code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registereintrag config.features.shop (Bestelltexte mit Fassung config.shop.fassung, Rechtsunterlagen-Getter,
Mailtexte, Ticket), STANDARD_HAKEN.shop (Schalter, Bestellpruefung ueber shop/anfrage.js, Unterlagen, Belehrung),
legalDocs-Satz shop, shopTicketDetails sowie Rumpf von anfrageOffenePunkte. Tests angepasst und um Shop-Faelle erweitert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reihenfolge nach Spec 13.6 mit allen LIVEGANG-Hinweisen, Probelauf, Rechtsrunde
und Checkliste der offenen Code-Punkte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Leistungsbeschreibung „Öffnungszeiten live“ als statische Seite unter
/vertragsunterlagen/zeiten-leistungsbeschreibung.html (Register-Adresse, nur HTML-Kommentar
ENTWURF), Entwürfe für Datenschutz § 6d mit Ergänzung § 6, den Block funktionen in K02/K03
und die Kanzlei-Fragen (⚖ AVV Funktionen, Behalten-Zustimmung), Absatz „Öffnungszeiten auf
dieser Website“ für Variante A und B, Einbau-Anleitung für das Team. Keine Codeänderung,
datenschutz.html und die Mailvorlagen bleiben unverändert. test/zeitenRecht.test.js.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Konflikte: funktionen.js folgt der Aufteilung aus main (fn-util.js, analyse.js); der Link
'Zu Verträge' der Analyse-Seite kommt jetzt auch in analyse.js aus vertraege-link.js.
Checkout und Team-Ansicht übernehmen assertOwnProject(..., { forNewOrder: true }) und
includeArchived aus main. Test-Pins der absoluten Importe nachgezogen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AVV Vorbemerkung (2): K16 der Textform-Aktivierung trägt nur Leistungsbeschreibung und AVV als PDF
- AVV Nr. 9 Abs. 6, Anlage (Löschung), LB Nr. 8 Abs. 3 und Datenschutz 6c: das Einrichtungs-Ticket bleibt mit einer Kurzfassung der Einstellungen als Arbeitsnachweis (keine Daten von Gästen)
- AVV Nr. 8 Abs. 2: "Gastdaten löschen" löscht nur wartende E-Mails; fehlgeschlagene behalten Adresse und Inhalt bis Nr. 9 Abs. 4
- Datenschutz § 7: Frist für Bestellungen ohne Abo (drei Jahre nach Ablauf des Jahres der Bestellung)
- News-Leistungsbeschreibung vom 30.09.2026 unverändert archiviert (SHA-256-Pin), die geltende Datei verweist darauf
- Kanzlei-Paket: Zitate, Q4/Q9/Q23, Livegang-Checkliste (Abschnitt 7.6/7.7), K23-Hinweis
- build-legal-html: Rückwärtsschrägstrich in Navigationsadressen abgelehnt; TP1-Spezifikation E2 (ohne USt)
- HTML, PDFs und Prüfsummen neu erzeugt (Terminplaner-Unterlagen und Datenschutzerklärung)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
„Ja, anlegen“ zeichnet nur noch die Hinweis-Liste neu (offene, ungespeicherte
Formulare und Zeilen bleiben), statt den ganzen Abschnitt zu ersetzen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hinweis-Leiste (Liste, „Hinweis-Leiste anlegen“, Art, Knopf, Zeitraum, Preis-Hinweis),
Kontakt-Leiste (Telefon, Adresse, WhatsApp mit Datenschutz-Haken, R12 in der Kundenansicht),
Google (Für Google kopieren, Profil-Link), Live-Vorschau mit Regler „Uhrzeit testen“
und UI-Prüfung test/ui/zeiten-portal.ui.mjs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PUT /fragebogen: ein Tab mit veralteter Branche bekommt 409 EINSTELLUNG_VERALTET (die Branche wechselt nur die Vorlage), bestaetigt wird mit
dem gespeicherten Stand vereinigt; die ungeprüften Vorlagenpreise können nicht mehr als geprüft gelten
- GET /einstellungen liefert in off aboHinweis (aboMeldung, auch bei nicht lesbarem Abo); die Hinweiskarte zeigt ihn immer und hat „Neu laden“
- Bestellseite und Statuskarte laden bei pageshow (persisted) neu, wenn der Browser sie nach der Zahlungsseite aus dem bfcache holt
- renderBestellen zeichnet „Ändern“ und „Zum Schritt“ nur mit zumSchritt; nach einem 409 bekommt die Meldung den Fokus
- Zusammenfassung nennt „Kleinunternehmer: ja/nein“
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- markOrdered speichert IP und Browser der Bestellung nicht mehr am Funktionsdokument (nur im Nachweis featureConsents, dort mit
Löschfrist); Altwerte werden bei einer neuen Bestellung geleert
- Aufbewahrungslauf (retention): consentIp, consentUserAgent, consentText, consentAt werden an allen Funktionsdokumenten eines fälligen
Kunden geleert, auch an abgeschalteten; Fehlschlag hält den Kunden wie die übrigen abhängigen Daten
- Einmal-Skript scripts/feature-consent-felder-leeren.mjs (Standard Probelauf, --apply leert nur, wo featureConsents die Angabe trägt)
- 30-Tage-Reset (jobs.js): auch eine bezahlte Einrichtung mit Grund abo_ende_vor_einrichtung und noch nicht gemeldetem T19 wird nicht
zurückgesetzt, solange zahlungMeldung nicht gemeldet ist (die Spur der Erstattung bleibt)
- K22: enddatum ist das Abo-Ende (lage.endedAt), sonst der Tag des Abschaltens; loeschdatum bleibt 30 Tage nach dem Abschalten
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Der Hinweis „Die N Ausnahmen, die nur für diesen Plan gelten, werden mit gelöscht“
wurde beim Bauen der Karte berechnet und war nach dem Speichern einer Ausnahme
veraltet. Er wird jetzt beim Öffnen der Rückfrage aus dem aktuellen Stand gelesen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- adoptPaidSession übernimmt ein erneut zugestelltes checkout.session.completed nicht mehr, wenn das Dokument nach 30 Tagen zurückgesetzt wurde
(off, purchaseStatus zurueckgesetzt, gleiche Sitzung): kein Setup, kein Ticket, keine K15/T16
- meldeFreigeschaltet liefert true/false; die Staff-Aktivierung in Textform vermerkt eine nicht gesendete K16 mit Unterlagen in adminNote und
antwortet mit warnung: true
- disable() nutzt die Sperre feature-activate:<id> statt feature-disable:<id> (Freischaltung und Abschalten überholen sich nicht)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Ungespeicherte Eingaben in anderen Formularen bleiben stehen: nach dem Speichern
wird nur die Plankarte, die Planliste (mit den Eingaben der übrigen Karten),
Feiertage oder Ausnahmen neu gezeichnet, „Nein, danke“ entfernt nur die Frage.
Während des Speicherns sind auch die Eingabefelder gesperrt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Speichern über PUT /api/zeiten (Version, 409, Feldfehler per ID-Pfad), Zeitpläne mit
Wochentagen, Hauptplan wechseln und Löschen (R10, R33), Feiertage je Bundesland,
Betriebsurlaub und Sondertage mit Hinweis-Leisten-Frage. Die Hülle behält den Editor
bei einem neuen Stand und zeichnet nur den Kopf neu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Genauere Aussagen: Widerrufsfrist je Bestellung mit spätestem Fristende für
"rechtzeitig", Textform beim Wiedereinschalten nur ohne Bestellung, Storno
und kein_widerruf in G02 getrennt beschrieben, keine Ablehnung nach dem
Klick außer aus den Gründen der Leistungsbeschreibung Nr. 4 Abs. 3, Preis
nur mit echten Wortlauten.
Zitate: Q4 mit dem früheren News-Haken und der früheren Leistungsbeschreibung
(Stand 3a0b008, per SHA-256 gepinnt und mit Git abgeglichen), Q8 mit
Leistungsbeschreibung Nr. 9 Abs. 2 und 3, Q19 mit Nr. 5 Abs. 2 und der Preiszeile
von K15, Q21 mit dem gespeicherten Nachweis und der Chat-Vorlage des
Ticketsystems. Begriffe (Betriebsart, Pilot, Kulanz) erklärt, interne
Entscheidungsnummern entfernt, Anlage C (gerenderte Mails K15 und K16) angekündigt.
Tests: Zitate unter 25 Zeichen zählen nicht mehr als geprüft (benannte Liste,
Belehrung und Knopftexte werden streng geprüft), schärfere Fundstellen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Behalten (30 €) gab es bei jedem inklusive false. nicht_aktiv und gekuendigt heißen aber,
dass das Wartungs-Abo läuft (Server: 409 Abo läuft wieder). Jetzt gilt an allen fünf Stellen
(Kachel, Karte, Behalten-Seite, Weg aus der Kachel, Abgeschaltet-Karte) dasselbe Prädikat:
inklusive false UND grund kein_abo; sonst „Abo läuft wieder“ ohne Bezahlknopf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Abschnitt 4 mit den 26 Fragen (Frage, Fundstelle im Text, unsere Annahme,
Alternative). Jede Kennung der früheren Listen "Für die Rechtsprüfung offen"
(H1 bis C8) steht in der Fundstelle genau einer Frage oder in Abschnitt 6
mit Begründung; die Hinweise aus den Reviews (Pilot/Kulanz, Rückkehr nur
nach Abo-Ende, Erstattung bei Ablehnung, Löschung auf Weisung, vereinbarte
Fassung in K15, G02 bei kostenlosen Buchungen) sind in den passenden Fragen.
Tests: Fragen lückenlos Q1 bis Q26 mit vier Teilen, jede Frage verwiesen,
Q4 nennt News, § 356 Abs. 3 und Altkunden, Abdeckung der entfernten Listen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Kachel „Öffnungszeiten live“ inline in funktionen.js (keine neuen Importe, keine Zusatzabfrage),
Ansicht #zeiten (zeiten.js, zeiten-bestellen.js, zeiten.css) mit Einschalten im Wartungs-Abo,
Bestellen für 30 € (Widerrufsbelehrung vor dem Knopf, Ruling R32), Behalten nach dem Abo-Ende,
Statuskarte je Zustand, Rückkehr von Stripe und Platz für den Editor (Aufgabe 29).
GET /api/funktionen liefert dafür zeiten.belehrung (Haken belehrung der Funktion).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>