Darstellung
Changelog
Alle relevanten Aenderungen an Work7 werden hier dokumentiert. Format: Keep a Changelog · Versionierung nach SemVer
[Unreleased]
Added
- Postman-Suite Public API v1 (Sept. 2026):
src/postman/work7-public-api.postman_collection.jsonmit Umgebungen Test und Prod (work7-public-api.<test|prod>.postman_environment.json) und Runnersrc/postman/run-public-api.mjs(newman pernpx, JUnit nachsrc/test-results/). 36 Requests:/me, Auth-Negativtests, Listen/Filter/Detail/404 für Projekte, Kontakte, Anfragen, Rapporte, Angebote, Rechnungen, Zeiten, Termine, Datenablage; Scope- und Modul-Erwartungen (403 insufficient_scope/module_disabled) werden aus/meabgeleitet, schreibende Requests nur mitallow_writes=true(Prod-Umgebung: aus). npm-Skripteapi:test,api:prod. Anleitung:src/postman/README.md, Runbookdocs/runbooks/runbook-public-api-tests.md. - Doku-Assistent (Sept. 2026): Schwebender Chat-Button „Frag die Doku" auf docs.work7.net. Nutzer stellen Fragen zur Dokumentation, der Assistent (gpt-5-mini) formuliert Suchanfragen und beantwortet sie ausschließlich aus den indexierten Inhalten (Handbuch, Public API, Features) mit Quellenangaben (Seite › Abschnitt, verlinkt). Lexikalische Suche über MiniSearch, kein Vector-DB. Rate-Limits pro IP (20/10 min) und global (3000/Tag). Nutzer-Daten werden nicht gespeichert (KI-Hinweis in der UI). Neue Node-Server
src/docs-site/server/index.mjsstatt nginx (Hono, SSE-Events), Index-Build bei jedem Docs-Build. Env:AZURE_OPENAI_*,DOCS_CHAT_*. Doku: 22-doku-assistent. - Datenablage (int.inbound, Sept. 2026): Endpunkte
POST /api/v1/inbound(Upload raw bytes beliebigen Content-Types mitsource, optionalfilename/batch/part, max. 2048 MB) undGET /api/v1/inbound(Aufzeichnung mit Pagination undsource-Filter). Scopesint.inbound:read,int.inbound:write. Speicherung mandantengetrennt in Azure Blob (Containerwork7-inbound), gestreamt ohne RAM-Buffering. Doku: datenablage. - Plattform-Admin (Migration 114, Sept. 2026): Flag
users.is_platform_adminfür das Betreiberkonto. Nur der Plattform-Admin wirkt über alle Betriebe (Admin-Dashboard, Kunden anlegen, Modul-Freischaltung). Siehe 01-auth-onboarding-rbac. - Admin-Dashboard – Kunden anlegen & Session-Wechsel (Sept. 2026): Plattform-Admin kann im Dashboard Betriebe anlegen (Name, Kürzel, Plan, Land, Admin-E-Mail/Name). Admin-Konto wird inaktiv angelegt (kein Passwort). „Betriebe"-Panel zeigt alle Betriebe mit Plan/Nutzerzahl; „Zugang senden" schickt Einladungs-E-Mail mit 7-Tage-gültigem Link (kopierbar falls Mail misslingt), „Einrichten" wechselt Plattform-Admin-Session in den fremden Betrieb zur Vorkonfiguration (Banner zeigt Betrieb an, Audit-Log beide Seiten, Rücksprung automatisch). Alte „Neuen Betrieb einladen"-Panel entfernt; Endpunkt
/api/admin/access-invitebleibt für Kompatibilität. - Ablage-Sync Phase 1 — Ordner-Register: Migration 115 ergänzt
storage_folders(Entität ↔ Ordner-ID beim Anbieter),storage_sync_logunddocument_storage_mappings.folder_id.putTenantObject(target: { entity, id, category })löst Zielordner über das Register auf (resolveUploadTarget/FolderResolver), übernimmt Altordner nach bisherigem Schema, legt fehlende mitfolderNameForan (Projekt{Nummer} {Name}, Kategorien deutsch, anbietertaugliche Namen, Kollisionen(2)). Anbieter-OperationenensureFolder/findChild/getFolder/renameFolder/moveFolder/listChildrenfür SharePoint, Google Drive, Dropbox, Nextcloud;fetchWithRetrybeachtet 429/503 mitRetry-After. Umgestellt: Anfrage-Dokumente, Mail-Anhänge (app + landing), Abnahme-Fotos, WhatsApp-Projektbilder, Materialimport. Projektanlage legt Projektordner samt Unterordnern best-effort an (In-Process-ListeneraddDomainEventListenerin App und Agent-Worker). Originaldateinamen mit Umlauten (Konflikt(2)), WhatsApp-Bilder alsWhatsApp {Datum Uhrzeit} {Absender}.jpg; WhatsApp-Zwischenablage liegt in Azure Blob statt im Firmenspeicher. Azure Blob nutzt ID-Pfade ohne Register. Skriptscripts/storage-folders-backfill.ts --company … [--dry-run], Runbookdocs/runbooks/runbook-ablage-backfill.md. - Ablage-Sync Phase 2 — ereignisgetriebener Sync: BullMQ-Queue
storage-sync(Job-ID{company}:{entity}:{id}, 3 s Verzögerung, 5 Versuche mit Backoff), eingereiht inpublishDomainEventübersetStorageSyncEnqueuer(App + Agent-Worker, nur Mandanten mit OAuth-Anbieter), Consumer im Agent-Worker; ohne Redis Rückfall auf Sync im Prozess. Reine PlanungplanFolderOpsfür alle Regeln aus Plan §5 (Umbenennen, Kundenwechsel, Archiv/Gelöscht/Reaktivieren,_Ohne Kunde, Anfrage angelegt/gelöscht/gewonnen mit Umzug der Dateien ins Projekt), ExecutorsyncEntityFoldermit Session-Advisory-Lock je Mandant und kurzer Transaktion je Operation (Wiederanlauf nach DB-Fehler ohne verwaiste Referenzen), Register-/Referenz-Umschreibung (Dropbox/Nextcloud inkl. Pfadspalten der Fachtabellen), nach letztem Versuchstate='error'. Übernommene Altordner werden beim ersten Lauf auf D1/D5 umbenannt.FolderOpsumdeleteFolderundmoveFolder(…, newName)ergänzt; In-Process-Listener aus Phase 1 entfernt.updateDocumentStorageMappingLocationfiltert jetzt nachcompany_id. - Ablage-Sync Phase 2, Nachbesserungen: D4-Wiederanlauf (Datei schon verschoben → nur Referenz nachziehen, verwaiste Referenzen vor dem Entfernen reparieren), idempotentes Entfernen, Einreihen erst nach COMMIT (
afterCommitinwithTransaction), kein verworfenes Event mehr (weiterer Nachlauf, Soll-Fingerabdruck am Laufende), Zeitbudget je Job undlock_timeout/statement_timeoutauf der Sync-Verbindung. - Ablage-Sync Phase 3 — Abgleich und Status: Cron
POST /api/cron/storage-reconcile?mode=light|deep(Kubernetes-CronJobs im Chart, abschaltbar übercronJobsin den Values, zusammen mitwebhook-out);planReconcile(Soll gegen Register über gespeicherten Soll-Fingerabdruck, Migration 116) und tiefer Abgleich über SharePointroot/deltabzw. Drivechanges.listmit Cursor, Dropbox/Nextcloud in Tranchen; externe Änderungen nach D6 (Name/Ort wiederherstellen, gelöschte Ordner neu anlegen, Dateien als „nicht auffindbar“ markieren:document_storage_mappings.missing_since).bootstrapTenantWorkspacelegt Grundordner über das Register an und startet den tiefen Abgleich;metadata.workspaceBootstrapentfällt. Status-Ansicht in Einstellungen › Integrationen › Dateispeicher (GET /api/settings/storage/status,POST /api/settings/storage/reconcile), Admin-Benachrichtigung bei Fehlerzustand > 24 h (höchstens täglich). D9: Aufbewahrung der WhatsApp-Zwischenablage (7 Tage zugeordnet, Rückfrage nach 23 Tagen, Löschung frühestens nach 30 Tagen und 7 Tage nach Rückfrage;agent_media.retention_notified_at/purged_at). - Ablage-Sync Phase 3, Nachbesserungen: D9 markiert Medien nur bei zugestellter Rückfrage (atomar, bei Versandfehler zurückgenommen; unbekannter Absender → Admins), löscht nie ohne zugestellte Rückfrage; Abgleich und Aufbewahrung laufen unter einer DB-Laufsperre (
acquireReconcileLease), die auch „Jetzt abgleichen“ nutzt (409 während des nächtlichen Laufs); Drive-Cursor bei ungültigem Token neu; Änderungsabfrage auf 20 Seiten je Lauf begrenzt. Status-Ansicht: Datum/Uhrzeit sauber formatiert, deutsche Namen der obersten Ordner (Kunden, Anfragen, Zwischenablage, Abwesenheiten, Import), Tabelle scrollt horizontal. - Ablage-Sync Phase 4 — Bestandsbereinigung: Skript
scripts/storage-cleanup.ts --company … [--apply] [--json](Standard Probelauf, ein Mandant, unter Mandanten-Sperre): Altordner aus früheren Umbenennungen werden nur bei eindeutiger Zuordnung (über Datei-Referenzen) in den registrierten Ordner zusammengeführt, Namenskonflikte mit „ (2)“, Referenzen/Mappings nachgezogen (Dropbox/Nextcloud über den Pfad); leereprojects/-Zwischenebenen und leere Altordner werden entfernt, fremde Dateien und Ordner nie. Bericht vorher/nachher, jede Aktion instorage_sync_log(manual). Runbook-Ablauf indocs/runbooks/runbook-ablage-backfill.md.
Changed
- SharePoint auf App-Berechtigungen umgestellt (Sept. 2026): Der Dateispeicher SharePoint nutzt statt delegiertem PKCE-OAuth jetzt Microsoft-Graph-Application-Permissions (
Sites.Selected, Client Credentials gegen{loginBaseUrl}/{tenantId}/oauth2/v2.0/token, Scope…/.default,MICROSOFT_CLIENT_ID/MICROSOFT_CLIENT_SECRETwie Mail/Kalender). Die Tenant-ID kommt aus der bestehenden Microsoft-365-Verbindung (sync_connections.token_state->>'microsoftTenantId'), kein Eingabefeld. Kein OAuth-Redirect mehr: neue RoutePOST /api/settings/storage/sharepoint/connect(Site-URL, optional Site-ID) löst die Site auf, prüft den Schreibzugriff und speichertsharepointSiteUrl/sharepointSiteId;connect/sharepoint/start|callbacklehnt mit klarem Fehler ab. Der OneDrive-Modus entfällt — eine Team-Site ist Pflicht. App-Token je Tenant im Speicher (Ablauf minus 120 s), keine SharePoint-Tokens mehr in der Datenbank (tenant_storage_oauth_credentialshält nur noch Site-URL/Site-ID; Spalte ist bereits nullable, keine Migration nötig). Unterscheidbare Fehler: Site nicht freigegeben (401/403), Site nicht gefunden (404), Microsoft 365 nicht verbunden. Die Oberfläche zeigt den fertigen PowerShell-Freigabe-Befehl (Connect-MgGraph+New-MgSitePermission) zum Kopieren,GET /api/settings/storage/setupliefert dafür die Client-ID (nie das Secret). Google Drive, Dropbox und Nextcloud bleiben unverändert beim delegierten PKCE-Flow. Anleitung: microsoft-365-einrichten (gemeinsame Seite für Postfach, Kalender und SharePoint inkl. Berechtigungen und PowerShell-Freigabe). - API-Schlüssel tragen die Umgebung (Sept. 2026): Neue Schlüssel heißen
w7_test_<prefix>_<secret>auf Test/Dev undw7_live_…auf Prod (vorher überallw7_live_). Die Marke liefertapiKeyEnvMarker()(packages/domain/src/modules/api-keys.ts) ausWORK7_ENV(je Umgebung in den Values gesetzt); fehlt sie, wird sie ausNEXT_PUBLIC_APP_URL/NEXTAUTH_URLabgeleitet.parseApiTokenvergleicht die Marke bewusst nicht — bestehende Schlüssel bleiben gültig, die Trennung leisten weiterhin die getrennten Datenbanken.GET /api/company/api-keysliefertkeyEnv, die Oberfläche zeigt damit das echte Präfix statt immerw7_live_. - Microsoft 365 verbinden (Einstellungen › Integrationen › Kalender & E-Mail): Nur noch ein Knopf „Bei Microsoft anmelden“ (Admin-Consent). Nach dem Rückruf läuft
POST /api/microsoft/connection-testautomatisch und legt die Verbindung an; Tenant-ID-Feld, Probe-User-Anzeige, „Provider speichern“ und „Verbindung testen“ entfallen. Bei aktiver Verbindung: Status „Mit Microsoft 365 verbunden“ und „Erneut anmelden“. - Admin-Dashboard je Betrieb: Administratoren (Rolle 1) sehen und verwalten nur Benutzer des eigenen Betriebs; die Regel „mindestens ein Admin“ gilt je Betrieb.
- Registrierung: Der erste Benutzer eines neu registrierten Betriebs ist Admin (Rolle 1) statt Manager. Registrierungseinladungen verfallen nach 14 Tagen.
Fixed
- Ablage-Sync Phase 0 (Plan
docs/plans/plan-ablage-sync.md): Abnahme-Fotos bei SharePoint/Google Drive/Dropbox/Nextcloud wieder ladbar (Vorschau und PDF) —acceptance_mediaspeichertstorage_provider/storage_external_id(Migration 115, Backfill ausdocument_storage_mappings), Download-Route und Report-Resolver (app + landing) laden überStorageRef/downloadStorageRef; Altzeilen ohne Anbieter werden überresolveStorageRefaufgelöst. Uploads nutzen für gleichnamige Kunden dieselben eindeutigen Ordner wie der Bootstrap (-2, id-Reihenfolge); WhatsApp-Bilder und Abnahme-Fotos zu Projekten ohne Kunden landen untercustomers/_Ohne Kunde/{projekt}statt im Wurzelordner.
Security
- Mandantentrennung in mehreren Verwaltungs-, Einstellungs- und Terminfunktionen verschärft; ein nicht mehr benötigter Diagnose-Endpunkt wurde entfernt.
[0.2.1] - 2026-09-12
Changed
- Agent-Effizienz (Plan
docs/plans/plan-agent-effizienz.md): System-Prompt cache-freundlich sortiert (statische Regeln zuerst, wechselnder Kontext unter „AKTUELLER KONTEXT:“ am Ende); Tool-Schemas ohne Validierungs-Ballast (compactSchemaForLlm, rund 12 % weniger Tool-Tokens);chart.renderverweist auf die Prompt-Regel statt sie zu wiederholen; jeder Modellaufruf loggtllm_usagemitcached_tokens. Verhalten unverändert, alle Agent-Tests grün.
[0.2.0] - 2026-09-12
Erste versionierte Ausgabe nach der Architektur-Konsolidierung. Enthält alles unten Gelistete (Modularisierung, Public API & Webhooks, Doku-Site docs.work7.net, Dashboard-Pins, WhatsApp-Menü-Rework, Freitext-Regeln).
Added
- Modularisierung (Phasen 0–3, Sept. 2026): Modul-Entitlements-Schicht mit zentralem Manifest (
packages/domain/src/modules/manifest.ts). Module sind nun Runtime-Freischaltungen (nicht Package-Split): jeder Mandant hat aktive Module (Fachmodule, Kanäle, Integrationen). Guards in Domain (requireModule), Middleware, Agent-Registry und Cron-Jobs erzwingen zentrale Kontrolle. Migrationen 111 (company_modules) + 112 (api_keys/webhooks); Entitlements-Cache mit Redis+PubSub (≤ 60 s Propagierung). CLIscripts/set-company-modules.ts+ Admin-UI/admin/modulezum Freischalten. Siehe Plan und Runbook. - Public API & Webhooks (Phase 0): API-Keys mit HMAC-Validierung, ausgehende Webhooks pro Modul (Abrechnung Phase 4 folgt). Endpunkte
/api/v1/{me,projects,kontakte,rapports,invoices,offers,time-entries,appointments,anfragen}. Doku: api-public-v1. - Agent-Module-Filter: Agent-Registry filtert Tools nach Rolle ∧ Modul; Prompt-Blöcke je freigeschaltetem Modul. Test
packages/agent/test/registry-modules.test.tsprüft Tool-Manifest-Zuordnung. Siehe Pflegeregel. - Zwei-Container-Deployment:
work7-landing(Marketing) undwork7-app(SaaS + API) mit host-basiertem Ingress-Routing. WORK7_SURFACE-Runtime (landing|app) und Middleware-Guards insrc/lib/site-surface.ts.- App-Login unter Root
/aufapp.work7.net(Legacy/auth/signinredirectet).
Changed
- Primaere Domain auf
work7.net: Landingwork7.net/www.work7.net, Appapp.work7.net(Test:test.work7.net,app.test.work7.net). - Helm Chart: Dual-Deployment/Services, Ingress pro Host + Component; CI baut/pusht beide Images.
- Env/Callbacks (
NEXTAUTH_URL,CORS_ORIGIN,DOCUSIGN_REDIRECT_URI) auf App-Subdomain. - Domain-Regeltests fuer
site-surface.ts. - Modul-Guard-Verhalten (Phase 1): Gesperrtes Modul → API 403
module_disabled, Agent zeigt klare Ablehnung, Web-Links/Sidebar gefiltert. Keine Daten-Löschen beim Abschalten (Reaktivierung stellt alles her).
Fixed
- Microsoft-Calendar-/Mail-Routen nutzen einen dedizierten Microsoft-Session-Helper statt des Google-Helpers.
calendar/sync/[provider]/webhookvertrautcompany_idnicht mehr ohne verifizierte Signatur.- Agent-Mail-Absender: Worker sendet jetzt über Firmen-Postfach statt no-reply (Microsoft-Pfad in domain-Paket, Fallback auf System). Gmail-Worker-Versand bleibt offen (fehlender Service-Account).
Releases
- 0.2.1 (2026-09-12): Agent-Effizienz (Prompt-Cache, kompakte Tool-Schemas), Tag
v0.2.1. - 0.2.0 (2026-09-12): erste versionierte Ausgabe, Tag
v0.2.0.