002 Anrufinformation in Teams und aktive ConMeet-Instanz Entwurf

Definiert die Anrufinformation als Teams-App für den Proof of Concept – Anmeldung in Teams, Erkennen des Anrufers über seine Rufnummer in der aktiven ConMeet-Instanz und das Umschalten dieser Instanz durch die Person selbst. Stand 2026-10-30

0 offen von 63 · geprüft am 2026-10-30

Verglichen: die Spezifikation gegen sich selbst, gegen 001, gegen docs/requirements/ (userStories.md, Terminologie.md, Fragen.md, Releaseblocker.md, Quellen.md, SystemContext.md, Rollen.md, Sitzungen 2026-10-27 bis 2026-10-30), gegen docs/architecture.md, docs/backend-development.md, docs/frontend-development.md, docs/vds-suite/integration-plan.md und gegen AGENTS.md. Q4 (Prototyp) liegt nicht im Repository und ist nicht geprüft.

Punkte aus früheren Prüfungen, die inzwischen aufgelöst sind, tragen — behoben und bleiben stehen.

Unklarheiten in der Spezifikation

U1 Automatische Wahl der aktiven Instanz: wer löst sie aus? behoben

Ort: R22, R39, Abschnitt 8 (myCallContext, findCallerContacts) Problem: R22 speichert die einzige berechtigte Instanz, „sobald er die aktive Instanz der Person ermittelt“. R39 antwortet „ohne aktive Instanz“ mit NO_ACTIVE_INSTANCE. Offen ist, ob findCallerContacts R22 selbst anwendet oder bei noch nicht gespeicherter Wahl scheitert. Zudem schreibt dann eine Query (myCallContext) in die Datenbank. Erforderlich: Festlegen, welche Operation R22 ausführt, und ob eine Query schreiben darf oder eine Mutation nötig ist. Aufgelöst am 2026-10-30: R22 wendet nur die Mutation ensureMyActiveConMeetInstance an, die die Anrufinformation beim Laden aufruft; findCallerContacts nutzt nur die gespeicherte Wahl (R39); Entscheidung Martin Linkwitz.

U2 `RATE_LIMITED` ist Zustand oder Fehlercode? behoben

Ort: R45, R55, R65 Problem: R45 nennt für jeden Abbruch den Fehlercode CONMEET_REQUEST_FAILED mit Zustand nach 001-R63. R55 „bricht die Suche nach R45 mit RATE_LIMITED ab“ — lesbar als eigener Fehlercode, der in R65 fehlt. Die Anzeige aus 001-R63 („später erneut prüfen“) passt zudem auf die Prüfung, nicht auf die Suche. Erforderlich: Klarstellen, dass RATE_LIMITED der Zustand innerhalb von CONMEET_REQUEST_FAILED ist (oder ein eigener Code), und die Anzeige für die Suche festlegen. Aufgelöst am 2026-10-30: R55: RATE_LIMITED ist der Zustand innerhalb von CONMEET_REQUEST_FAILED, eigene Anzeige für die Suche; entschieden durch specification-fixer (folgt aus R45 und 001-R66).

U3 Begrenzung je Sekunde: Spitzen erlaubt? behoben

Ort: R53, Ziel 5, Beispiel Schritt 3 Problem: „höchstens 10 Aufrufe je Sekunde“ und „Token Bucket“ sagen nicht, wie groß der Eimer ist. Ein voller Eimer mit 10 Token plus Nachfüllung lässt in einer Sekunde mehr als 10 Aufrufe zu; Ziel 5 verlangt „nie überschreitet“. Die Dauer im Beispiel (gut 12 Sekunden) hängt davon ab. Erforderlich: Eimergröße und Nachfüllintervall festlegen, oder die Regel als gleitendes Fenster formulieren. Aufgelöst am 2026-10-30: R53: Token Bucket mit Kapazität 1, gleichmäßig verteilte Aufrufe, keine Spitzen; entschieden durch specification-fixer (folgt aus Ziel 5).

U4 Nicht auswertbare Nummer aus Teams zeigt „Keine Rufnummer verfügbar“ behoben

Ort: R41, R9 Problem: R41 zeigt bei einer nicht normalisierbaren Nummer aus Teams R9. Teams hat aber eine Nummer geliefert; der Text „Keine Rufnummer verfügbar“ trifft nicht zu, und die gelieferte Nummer erscheint nirgends. Erforderlich: Eigene Anzeige festlegen oder R9 so fassen, dass sie diesen Fall einschließt. Aufgelöst am 2026-10-30: R41: eigene Anzeige mit der gelieferten Nummer und dem Feld aus R77; entschieden durch specification-fixer.

U5 Hinweis bei fehlendem `READY` unbestimmt behoben

Ort: R19 Problem: „den Hinweis der jeweiligen Zustandsseite und einen Link, der sie im Browser öffnet“ — die Zustandsseiten enthalten mehrere Elemente (Portal- bzw. QuickAccess-Link, „Erneut prüfen“, Abmeldung). Welche davon die Anrufinformation zeigt und wohin der Link führt (Zustandsseite oder Portal), ist offen. Erforderlich: Text und Ziel des Links je Zustand nennen. Aufgelöst am 2026-10-30: R19: nur der Hinweistext der Zustandsseite und „Im Browser öffnen“ auf diese Seite (R80); entschieden durch specification-fixer.

U6 Vertikale nutzt eine andere fachliche Vertikale behoben

Ort: R38 Problem: CallInformation nutzt Instanz, Verknüpfung und Schlüssel aus ConMeetInstances. AGENTS.md regelt nur Feature → Querschnitt und verbietet Querschnitt → Feature; ob Feature → Feature erlaubt ist und über welche Schnittstelle (Contracts der Vertikale), steht nirgends. Erforderlich: Festlegen, über welchen Vertrag CallInformation auf ConMeetInstances zugreift, oder die Suche in ConMeetInstances ansiedeln. Aufgelöst am 2026-10-30: R38: Zugriff nur über die Contracts von ConMeetInstances; entschieden durch specification-fixer (Konvention der Vertikalen).

U7 Anmeldung in Teams setzt Teile von US-09 um, ohne es zu sagen behoben

Ort: Verhältnis zu anderen Dokumenten, Scope, Abschnitt 2 Problem: US-09 verlangt „Beim ersten Öffnen meldet sich die Person mit ihrem Suite-Benutzer an; danach bleibt sie angemeldet“. Abschnitt 2 erfüllt genau das; „Verhältnis“ nennt nur US-01, US-12 und US-03, „Nicht im Scope“ schließt US-09 als Ganzes aus. Erforderlich: In „Verhältnis“ und Scope nennen, welches Kriterium aus US-09 hier umgesetzt ist. Aufgelöst am 2026-10-30: „Verhältnis“ und Scope nennen die Anmeldung aus US-09; entschieden durch specification-fixer.

U8 Kleinere Unschärfen (gesammelt) behoben

Ort: R56, R58, R33 Problem:

  • R58 sortiert „nach Firma, dann nach Nachname“; Vergleichsregel (Groß-/Kleinschreibung, Umlaute) und Reihenfolge bei leerem Nachnamen fehlen.
  • R56 nimmt den Namen aus title, firstname, lastname; sind alle leer, ist offen, was als Name erscheint.
  • R33, Zeile 9 zeigt die gesuchte Rufnummer; ob in der normalisierten oder der gelieferten Schreibweise, steht nicht da. Erforderlich: Je Punkt eine Festlegung. Aufgelöst am 2026-10-30: R56 („Ohne Namen“), R58 (Sortierung de, ohne Groß-/Kleinschreibung, leere zuletzt), R33 Zeile 9 und R79 (gelieferte oder eingegebene Schreibweise); entschieden durch specification-fixer.
U9 Einzelentzug löscht die aktive Instanz auch bei gesetztem „Alle“ behoben

Ort: R28, R29 Problem: R29 löscht nur bei Personen, die „danach nicht mehr berechtigt“ sind; R28 löscht beim Entzug der Einzelberechtigung ohne Bedingung. Ist GrantedToAll gesetzt, bleibt die Person nach 001-R22 berechtigt (Einzelberechtigungen bleiben gespeichert, 001-R25), verliert nach R28 aber ihre Wahl. Erforderlich: R28 an die Bedingung aus R29 angleichen oder den Unterschied festlegen. Aufgelöst am 2026-10-30: R28 löscht nur, wenn die Person danach nicht mehr berechtigt ist; entschieden durch specification-fixer (folgt aus F-030 und R29).

U10 Zustandstabelle deckt nicht alle Antworten der Suche ab behoben

Ort: R33, R36, R39, R41, Abschnitt 8 (setMyActiveConMeetInstance) Problem: R33 legt „die Zustände in dieser Reihenfolge“ fest, kennt aber keinen Zustand für INVALID_PHONE_NUMBER (R41) und keinen für NO_ACTIVE_INSTANCE und ACCOUNT_NOT_LINKED aus findCallerContacts (R39) — beide treten ein, wenn zwischen Laden und Suche entzogen, getrennt oder in einem anderen Fenster gelöst wird. Zeile 8 verweist für jeden Fehlschlag auf R36, R36 gilt aber nur, wenn „ein Aufruf der Suche an ConMeet“ scheitert. setMyActiveConMeetInstance liefert nur die „gespeicherte aktive Instanz“, nicht ob sie verknüpft ist; Zustand 5 nach dem Umschalten (Beispiel Schritt 7) ist so nicht ermittelbar. Erforderlich: Je Fehlercode der Suche Zustand und Anzeige festlegen (z. B. erneut ensureMyActiveConMeetInstance); Ergebnis von setMyActiveConMeetInstance um den Verknüpfungsstand ergänzen oder den Folgeaufruf nennen. Aufgelöst am 2026-10-30: R87 neu (Fehler der Suche führen zu erneutem Ermitteln des Zustands), R77 zeigt INVALID_PHONE_NUMBER am Feld, setMyActiveConMeetInstance liefert dasselbe wie ensureMyActiveConMeetInstance; Beispiel Schritt 7 angepasst; entschieden durch specification-fixer.

U11 „Nie in eine URL“ gegen Remote Function für eine Query behoben

Ort: R66, Abschnitt 8 (findCallerContacts als Query) Problem: Remote Functions der Art query übertragen ihr Argument per GET in der URL, command und form per POST. R66 verlangt Remote Functions und verbietet die Nummer in der URL, legt die Art aber nicht fest; die naheliegende Abbildung der GraphQL-Query auf query verletzt R66. Die Methode BFF → Dienst ist ebenfalls nicht genannt. Erforderlich: Art der Remote Function und HTTP-Methode zum Dienst für die Suche festlegen. Aufgelöst am 2026-10-30: R66: Remote Functions vom Typ command (POST), GraphQL vom BFF als POST; entschieden durch specification-fixer (folgt aus R66).

U12 „Normalisierbar“ ist nicht definiert behoben

Ort: R40, R41, R47 Problem: Ob eine Nummer als normalisierbar gilt, wenn libphonenumber sie parsen kann, wenn sie „möglich“ oder wenn sie gültig ist (IsValidNumber), steht nicht da. Davon hängt ab, wann eine Eingabe INVALID_PHONE_NUMBER ergibt und ob ungewöhnlich gepflegte Nummern in ConMeet still aus dem Vergleich fallen. Erforderlich: Kriterium festlegen. Aufgelöst am 2026-10-30: R40: normalisierbar heißt Parse gelingt und IsPossibleNumber; entschieden durch specification-fixer.

U13 Datenschutz: Gilt R67 für die gesuchte Rufnummer? behoben

Ort: R67, R66 Problem: R67 schützt „Rufnummern … aus der Suche“. Die Nummer des Anrufers ist Eingabe, nicht Ergebnis; als Argument von findCallerContacts steht sie in GraphQL-Variablen, Request-Logs und Traces von BFF und Dienst, ohne dass eine Regel sie ausschließt. Erforderlich: Klarstellen, ob R67 auch die gelieferte oder eingegebene Nummer umfasst, einschließlich GraphQL-Variablen und Traces in BFF und Dienst. Aufgelöst am 2026-10-30: R67 schließt die gesuchte Nummer, GraphQL-Variablen, Request-Bodies und Span-Attribute ein; entschieden durch specification-fixer.

U14 Beispiel passt nicht zum Stand aus 001 behoben

Ort: Beispiel, Einleitung und Schritte 5–7 Problem: „wie in 001“ — dort ist Ben mit „Staging“ als ben.mueller verknüpft (001-Beispiel Schritte 6–7), mit „Live“ nie (Schritt 5 scheitert), und Anna trennt „Staging“ am Ende (Schritt 8). Hier findet Ben in „Live“ einen Treffer (Schritt 6), was nach R34 eine Verknüpfung voraussetzt, und ist in „Staging“ nicht verknüpft (Schritt 7). Erforderlich: Ausgangszustand hier vollständig angeben (wer mit welcher Instanz verknüpft ist) statt „wie in 001“, oder die Schritte an 001 anpassen. Aufgelöst am 2026-10-30: Beispiel nennt seine Ausgangslage selbst (Verknüpfungen von Clara und Ben) statt „wie in 001“; entschieden durch specification-fixer.

U15 Außerhalb von Teams kein Anmeldeweg behoben

Ort: R9, R11, R12, R73, R80 Problem: R9 und R80 sehen den Aufruf außerhalb von Teams vor. Ohne Sitzung zeigt die Seite dort R11; „Anmelden“ nutzt authentication.authenticate() (R12), das außerhalb von Teams nicht funktioniert, und R73 schaltet die Weiterleitung zur Anmeldung für (teams) ab. Erforderlich: Anmeldeweg außerhalb von Teams festlegen oder den Aufruf außerhalb von Teams ausschließen (dann R9 und R80 anpassen). Aufgelöst am 2026-10-30: R94 neu: außerhalb von Teams führt „Anmelden“ das Fenster selbst zur Anmeldung; entschieden durch specification-fixer.

U16 App-Scope `personal` gegen chatbezogene RSC-Berechtigungen behoben

Ort: R2, R3 Problem: R2 deklariert nur den Scope personal; R3 fordert OnlineMeeting.ReadBasic.Chat und OnlineMeetingParticipant.Read.Chat, die Teams bei der Installation in einem Chat bzw. Besprechungschat gewährt. In welchem Scope die App im Anruf installiert ist und wer dort einwilligt, steht nicht da; Q4 ist nicht im Repository und nicht prüfbar. Erforderlich: Scope und Installationsweg gegen Q4 bestätigen und in R2 nennen; zusammen mit der offenen Frage zur Entra-App-Registrierung klären. Aufgelöst am 2026-10-30: R2 verweist auf das Manifest des Prototyps Q4, das die Nummer im 1:1-Anruf liefert; die Frage zur Einwilligung bleibt unter „Offene Fragen“; entschieden durch specification-fixer.

U17 Kleinere Unschärfen (gesammelt) behoben

Ort: R12, R24, R28, R29, R35, R45, R52, R53, R61, R64, R73, R77, R79, Ziel 2 Problem:

  • R24, R61, R77, R79: Auswahl der Instanz, Feld „Rufnummer“ und gesuchte Nummer stehen „oben“ bzw. „über der Liste“; die Reihenfolge ist offen.
  • R45 nennt nur „Antwort“; Netzwerk-, TLS-Fehler und Zeitüberschreitung eines Aufrufs (001-R63 UNREACHABLE) sind nicht ausdrücklich Abbruchgründe.
  • R52, R53: „je Instanz“ und „normalisierte BaseUrl“ fallen auseinander, wenn zwei Mandanten dieselbe Adresse verbinden (001-R2 gilt nur je Mandant) — gemeinsamer Eimer oder je Entität?
  • R64: „die angezeigten Nummern“ ohne Feldnamen.
  • R28, R29: anders als 001-R15 und 001-R87 keine Aussage zur Audit-Zeile beim physischen Löschen.
  • R12, R73: Was /teams/auth/start bei vorhandener Sitzung tut und wie es zu /teams/auth/done gelangt, steht nicht da.
  • R35: „Strg+V“ — Teams auf macOS nutzt Cmd+V.
  • Ziel 2 „bleibt angemeldet“ ohne Dauer; die Laufzeit von __Host-session (R15) steht in keinem Dokument. Erforderlich: Je Punkt eine Festlegung. Aufgelöst am 2026-10-30: R77 (Reihenfolge oben), R45 (Netzwerk-, TLS-Fehler, Zeitüberschreitung), R52 (Schlüssel BaseUrl, auch über Mandanten), R64 (Feldnamen), R29 (Audit-Zeilen), R12 (bestehende Sitzung), R35 (⌘+V), Ziel 2 (Laufzeit der Sitzung); entschieden durch specification-fixer.
U18 `/teams/auth/start` und `/teams/auth/done`: Weiterleitung zur Anmeldung ja oder nein? behoben

Ort: R72, R73, R95, R12 Problem: R72 legt beide Routen in (teams). R73: „Für (teams) gilt die allgemeine Weiterleitung zur Anmeldung nicht“. R95: „/teams/auth/start und /teams/auth/done … leiten dafür im Anmeldefenster zur Anmeldung weiter“. Erforderlich: R73 auf /teams/call und /teams/auth/exchange beschränken oder R95 ausdrücklich als Ausnahme von R73 fassen. Aufgelöst am 2026-10-30: /teams/auth/start und /teams/auth/callback brauchen keine Sitzung mehr (R95); folgt aus der Entscheidung zu L17.

U19 Weg von `state` durch die Anmeldung nicht festgelegt behoben

Ort: R89, R12, R13, R14; vgl. U17 (Punkt R12, R73) und L8 Problem: „Der Wert reist durch die Anmeldung bis /teams/auth/done“ — wie, steht nicht da. Die bestehende Anmeldung trägt nur returnTo (docs/frontend-development.md); naheliegend ist returnTo=/teams/auth/done?state=…, dann steht state in URLs, Request-Logs und im Verlauf des Anmeldefensters. Offen auch, wie /teams/auth/start ohne Sitzung zu /teams/auth/done gelangt und was /teams/auth/done ohne oder mit ungültigem state tut. Erforderlich: Transport von state festlegen (Query in returnTo, Cookie, Zeile in frontend), ob state in URLs und Logs stehen darf, und das Verhalten von /teams/auth/done ohne gültiges state. Aufgelöst am 2026-10-30: R98 neu: /teams/auth/start legt den Hash von state mit eigenem OIDC-state in oauth_states ab, state steht in keiner weiteren URL, keine Query-Strings von /teams/auth/* in Logs; R99 neu: Verhalten ohne oder mit ungültigem state; entschieden durch specification-fixer.

U20 Verwaiste Wahl nach R93 blockiert R22 und lebt bei erneuter Berechtigung auf behoben

Ort: R92, R93, R22, R23, R25, R32; vgl. L10 Problem: Eine ActiveInstanceChoice ohne Berechtigung „gilt als nicht vorhanden“ (R93), bleibt aber als Zeile stehen; keine Regel löscht sie. (1) ensureMyActiveConMeetInstance legt nach R92 nur an, „wenn noch keine besteht“ (ON CONFLICT DO NOTHING) — die Zeile verhindert R22. Bei genau einer berechtigten Instanz zeigt R25 keine Auswahl und R23 greift nicht: die Person bleibt ohne aktive Instanz und ohne Ausweg. (2) Wird sie für die alte Instanz wieder berechtigt, gilt die Zeile wieder — gegen R32 („wird nach erneuter Berechtigung nicht von selbst wieder aktiv“). Erforderlich: Festlegen, dass ensureMyActiveConMeetInstance eine verwaiste Wahl löscht oder ersetzt (R92 anpassen), oder einen anderen Weg, der R22 und R32 auch in diesem Fall einhält. Aufgelöst am 2026-10-30: R106 neu: ensureMyActiveConMeetInstance löscht eine verwaiste Wahl und wendet R22/R23 an; Wiederaufleben nur nach Wettlauf, als Ausnahme von R32 hingenommen; entschieden durch specification-fixer.

U21 Feld „Rufnummer“ „immer“ gegen Zustände ohne Suche behoben

Ort: R77, R19, R33 (Zustände 1–5) Problem: R77: „steht immer das Feld ‚Rufnummer‘“. R19 zeigt bei nicht READY „nur den Hinweistext … und den Link“. In Zustand 1 (keine Sitzung), 3 (keine Instanz), 4 (Wahl ausstehend) und 5 (nicht verknüpft) ist keine Suche möglich; ob das Feld dort erscheint und was „Suchen“ tut, ist offen. Erforderlich: Zustände nennen, in denen das Feld erscheint (z. B. ab Zustand 6), oder das Verhalten von „Suchen“ in den Zuständen 1–5 festlegen. Aufgelöst am 2026-10-30: R77: Feld erst ab Zustand 6; entschieden durch specification-fixer.

U22 `BaseAddress` mit Pfad verliert den letzten Pfadabschnitt behoben

Ort: R84, R42, R43; 001-R2, 001-R75 Problem: R84 gibt dem Client „die BaseAddress der Instanz“; 001-R2 speichert sie ohne abschließenden Schrägstrich, 001-R75 erlaubt einen Pfad. Relative Adressen werden nach RFC 3986 aufgelöst: https://host/conmeet + api/public/v1/customers ergibt https://host/api/public/v1/customers. R42, R43 schreiben {BaseUrl}/api/… als Verkettung. Erforderlich: Festlegen, dass BaseAddress mit abschließendem Schrägstrich gesetzt wird und Aufrufe relative Pfade ohne führenden Schrägstrich nutzen, oder dass Aufrufe absolute Adressen aus BaseUrl bilden. Aufgelöst am 2026-10-30: R84: BaseAddress mit abschließendem /, relative Pfade ohne führendes /; entschieden durch specification-fixer.

U23 Abbruch der Suche im Browser mit `command` nicht umsetzbar beschrieben behoben

Ort: R75, R76, R66; vgl. L3 Problem: R75: Beim Umschalten und bei neuer Suche bricht die Anrufinformation die laufende Suche ab, „der BFF bricht seine Anfrage an den Dienst ab“. R66 legt Remote Functions vom Typ command fest; ein command bietet im Client nach heutigem Stand von SvelteKit keinen Abbruch (kein AbortSignal). Ohne Abbruch erfährt der BFF nichts, und die Suche belegt die Begrenzung bis zu 10 Sekunden weiter (gegen R76). Nur das Schließen beendet die Verbindung von selbst. Erforderlich: Weg des Abbruchs vom Browser zum BFF festlegen (z. B. eigener Abbruch-command mit Such-ID, oder eigener Endpunkt statt Remote Function) oder R75 auf das Schließen beschränken. Aufgelöst am 2026-10-30: Abbruch bei Umschalten und neuer Suche entfällt (R75); nur ein Verbindungsabbruch des Browsers bricht die Suche im Dienst ab (R76); Beispiel Schritt 9 angepasst; Entscheidung Martin Linkwitz.

U24 Woran der Server „Remote Functions der Anrufinformation“ erkennt behoben

Ort: R91, R74, R66 Problem: R91 lässt __Host-teams-session für (teams) und „die Remote Functions der Anrufinformation“ zählen. Remote Functions laufen über von SvelteKit vergebene Adressen außerhalb von /teams (/_app/remote/…); welche dazugehören und woran der Hook sie erkennt (Ablageort der .remote.ts, Liste, Namenspräfix), steht nicht da. Zählt das Cookie für alle Remote Functions, gilt es auch für die Verwaltung aus 001 — was R91 ausschließt. Erforderlich: Festlegen, welche Remote Functions dazugehören und woran der Server sie erkennt. Aufgelöst am 2026-10-30: R105 neu: getrennte locals.session/locals.teamsSession, Remote Functions der Anrufinformation unter src/lib/features/call-information/ lesen nur die Teams-Sitzung; entschieden durch specification-fixer.

U25 Kleinere Unschärfen (gesammelt) behoben

Ort: R16, R26, R41, R45, R46, R54, R65, R77, R84, R87, Ziel 2 Problem:

  • R41, R77: Bei nicht auswertbarer Nummer aus Teams zeigt R41 „Die Rufnummer lässt sich nicht auswerten.“, R77 die Meldung aus R65 am Feld — beides oder nur R41?
  • R26: „sucht die angezeigte Rufnummer erneut“ — Inhalt des Felds (auch ungesucht geändert) oder die zuletzt gesuchte Nummer (R79)?
  • R45, R46: Die Zeitüberschreitung je Aufruf (10 s, 001-R63) greift innerhalb der Gesamtgrenze von 10 s nie; ein hängendes ConMeet ergibt stets SEARCH_TIMEOUT, nie UNREACHABLE. Gewollt?
  • R84, R54: Dass die Begrenzung vor der Zeitüberschreitung je Aufruf in der Handler-Kette liegt, folgt nur aus R54; in R84 nennen.
  • R65, R87: Die Meldung zu NO_ACTIVE_INSTANCE erscheint nie, weil R87 stattdessen neu ermittelt.
  • R16, Ziel 2: Verlängert wird nur das erkennende Cookie. Wer nur im Browser arbeitet, verliert __Host-teams-session vor Ende der Sitzung; „solange die Sitzung des BFF gilt“ hält dann nicht. Erforderlich: Je Punkt eine Festlegung. Aufgelöst am 2026-10-30: R41/R77 (bei Nummer aus Teams nur R41), R26 (zuletzt gesuchte Nummer), R46 (SEARCH_TIMEOUT statt UNREACHABLE gewollt), R84 (Reihenfolge der Handler), R65 (NO_ACTIVE_INSTANCE nicht angezeigt); der Punkt R16/Ziel 2 entfällt mit R97 (eigene Teams-Sitzung mit eigener Verlängerung); entschieden durch specification-fixer.
U26 Wer welche Sitzung liest: R105 gegen R91, R95 und R74 behoben

Ort: R105, R91, R95, R74, R73; vgl. U24 Problem: R105: „aller übrige Code liest nur locals.session“; nur die Remote Functions unter src/lib/features/call-information/ lesen locals.teamsSession. Danach lesen auch die Routen von (teams) (/teams/call, /teams/auth/exchange) und der Layout-Load von (teams) mit me und WP4-Prüfung (R95; laut docs/frontend-development.md gemeinsamer Code in suite-access.ts) nur die Webseiten-Sitzung — gegen R91 („Routen der Gruppe (teams) … erkennen eine Sitzung nur an __Host-teams-session“) und R95. Offen auch, mit den Tokens welcher Sitzung GraphQL-Client und Token-Erneuerung arbeiten. Zudem nimmt R73 nur (teams) von der allgemeinen Weiterleitung aus; ruft /teams/call eine Remote Function ohne __Host-session auf, leitet der Hook weiter, sofern er Remote-Function-Anfragen nicht erkennt — gegen R74 und gegen „ohne dass der Hook Remote Functions unterscheiden muss“ (beruht auf eigener Kenntnis von SvelteKit: Remote-Function-Anfragen laufen unter eigener Adresse durch handle, nicht unter der Route der aufrufenden Seite). Erforderlich: R105 so fassen, dass Routen und Layout-Load von (teams) sowie die Remote Functions der Anrufinformation locals.teamsSession lesen und GraphQL-Aufrufe die Tokens der gelesenen Sitzung nutzen; festlegen, woran der Hook Remote-Function-Anfragen der Anrufinformation von der Weiterleitung ausnimmt. Aufgelöst am 2026-10-30: R105 definiert die Sitzung der Anrufinformation (Teams-Sitzung, außerhalb von Teams die Webseiten-Sitzung) für Routen und Layout-Load von (teams) inkl. me/WP4, die Remote Functions unter call-information/ sowie GraphQL und Token-Erneuerung; der Hook leitet Remote-Function-Anfragen nie weiter; R91 angepasst; entschieden durch specification-fixer.

U27 Anmeldung außerhalb von Teams führt im Kreis behoben

Ort: R94, R91, R105, R9, R80; vgl. U15 Problem: R94 führt außerhalb von Teams zu /auth/start?returnTo=/teams/call; das ergibt eine Sitzung des Clients web mit __Host-session. /teams/call erkennt nach R91 nur __Host-teams-session einer Teams-Sitzung, seine Remote Functions nach R105 nur locals.teamsSession. Die Person landet wieder bei R11. Die Auflösung von U15 hält nach der Umstellung aus L17 nicht mehr. Erforderlich: Anmeldeweg außerhalb von Teams neu festlegen (z. B. Code Flow des Teams-Clients im selben Fenster, der die Teams-Sitzung anlegt, oder /teams/call erkennt außerhalb von Teams die Webseiten-Sitzung) oder den Aufruf außerhalb von Teams ausschließen und R9, R80, R94 anpassen. Aufgelöst am 2026-10-30: Die Anrufinformation läuft auch im Browser und nutzt dort die Webseiten-Sitzung (R94, R105); Entscheidung Martin Linkwitz.

U28 Verknüpfen und Schlüssel ersetzen in Teams ohne passende Sitzung behoben

Ort: R34, R36, R105; 001-R61, 001-R62; Beispiel Schritt 7 Problem: R34 öffnet „das Verknüpfen aus 001-R62 in der Anrufinformation“, R36 bietet „Schlüssel ersetzen“ (001-R61) an. Nach R105 gilt die Teams-Sitzung nur für Remote Functions unter call-information/; die Remote Functions des Verknüpfens aus 001 lesen locals.session, die es im Teams-Fenster nicht gibt. Schritt 7 („Er verknüpft“) ist so nicht ausführbar. Erforderlich: Festlegen, dass die Anrufinformation für Verknüpfen und Ersetzen eigene Remote Functions unter call-information/ nutzt (aus 001 nur die Oberfläche), oder R105 um diese Operationen erweitern. Aufgelöst am 2026-10-30: R105: Die Anrufinformation hat eigene Remote Functions für Verknüpfen und Schlüssel ersetzen, die dieselben GraphQL-Operationen wie 001 aufrufen; entschieden durch specification-fixer.

U29 Ende der Teams-Sitzung: „Abmeldung an anderer Stelle“ gegen R97 behoben

Ort: R74, R97, Scope („Abmelden“), Ziel 2 Problem: R74 nennt als Ende der Sitzung „Abmeldung an anderer Stelle“; R97: „Abmelden … auf der einen Seite beendet die andere nicht“; Scope schließt Abmelden in der Anrufinformation aus („die Sitzung endet wie jede Sitzung des BFF“). Eine Teams-Sitzung endet damit nur durch Ablauf oder WP4; die Person kann sie nie selbst beenden (etwa an einem geteilten Rechner). Offen auch, was bei gescheiterter Erneuerung der Tokens der Teams-Sitzung gilt — nach eigener Kenntnis von Keycloak macht das Ende der Realm-Sitzung (Abmeldung der Webseite) auch die Refresh-Tokens des Teams-Clients ungültig, wenn beide Anmeldungen dieselbe SSO-Sitzung nutzen (Teams im Web, gleicher Browser). Erforderlich: R74 an R97 angleichen; festlegen, ob und wie eine Teams-Sitzung beendet werden kann und was bei gescheiterter Token-Erneuerung gilt (z. B. Sitzung beenden, R11). Aufgelöst am 2026-10-30: R107 neu: „Abmelden“ in der Anrufinformation beendet die Teams-Sitzung und widerruft ihr Refresh-Token; R74 nennt Abmelden, gescheiterte Erneuerung, Ablauf und WP4; Scope-Ausschluss entfernt, Ziel 2 und Beispiel Schritt 10 angepasst; Entscheidung Martin Linkwitz.

U30 Nach R75 läuft die Suche doch in zwei Instanzen gleichzeitig behoben

Ort: R70, R75, R26, R37 Problem: R70: „Die Suche läuft nie in mehreren Instanzen gleichzeitig“. Nach R26 sucht die Anrufinformation nach dem Umschalten sofort in der neuen Instanz; nach R75 läuft die Suche in der alten Instanz weiter. R37 verhindert nur die vermischte Anzeige. Erforderlich: R70 auf die Anzeige beschränken (Ergebnisse mehrerer Instanzen erscheinen nie zusammen) oder anders auflösen. Aufgelöst am 2026-10-30: R75: Während einer Suche sind „Suchen“, „Erneut suchen“ und die Instanzauswahl gesperrt; R70 hält; Entscheidung Martin Linkwitz.

U31 Kleinere Unschärfen (gesammelt) behoben

Ort: R14, R26, R52, R53, R64, R81, R89, R97, R98, R99, R101, R104, R106, Ziel 2, Scope Problem:

  • R89: „Der Wert reist durch die Anmeldung bis /teams/auth/callback“ — nach R98 steht state in keiner weiteren URL, nur sein Hash in oauth_states; Wortlaut angleichen.
  • R99: „state, der nicht aus 32 Bytes besteht“ — Kodierung im Parameter (base64url, hex) fehlt.
  • R106: „wendet danach R22 und R23 an“ — R23 ist eine Anzeigeregel der Oberfläche, keine Wirkung der Mutation.
  • R26: Bei der ersten Wahl aus Zustand 4 gibt es keine „zuletzt gesuchte Rufnummer“ (R23 sucht erst nach der Wahl); gemeint ist die Nummer aus Teams.
  • R104: Welcher Zustand nach 001-R63 (über R86) aus dem abgebrochenen Aufruf folgt, steht nicht da.
  • R53 „partitioniert nach Instanz“ gegen R52 „geschlüsselt nach der normalisierten BaseUrl“.
  • R64, R81: conMeetUrl braucht die BaseUrl; ConMeetInstanceContext enthält sie nicht, nur Http.BaseAddress (mit /). Quelle nennen.
  • R101: Welcher Aufruf das Ankommen des Cookies prüft und ob die Anzeige „Anmelden“ weiter anbietet.
  • R14, R97, R98: Tabelle der Einmalcodes unbenannt; frontend.oauth_states und die Spalte für den Client der Sitzung stehen in keinem anderen Dokument — neu oder aus der Referenz?
  • Ziel 2: „solange die Sitzung des BFF gilt“ — gemeint ist die Teams-Sitzung (R97).
  • Scope nennt die Einschränkung auf die Clients aus R101 nicht. Erforderlich: Je Punkt eine Festlegung. Aufgelöst am 2026-10-30: R89/R99 (Hash statt Wert, base64url mit 43 Zeichen), R106 (R22 in der Mutation, R23 in der Anzeige), R26 (Nummer aus Teams bei erster Wahl), R104 (UNEXPECTED ohne Statuscode), R53 (nach BaseUrl), R60 (aus Http.BaseAddress), R101 (Prüfung über invalidateAll, „Anmelden“ bleibt), R14 (frontend.teams_auth_codes; oauth_states und die Sitzungsspalte stehen jetzt in docs/frontend-development.md), Ziel 2 (Teams-Sitzung), Scope (andere Clients ausgeschlossen); entschieden durch specification-fixer.

Widersprüche zu anderen Dokumenten

C1 Aktive Instanz: verknüpft oder berechtigt? behoben

Diese Spezifikation (R21): „Aktiv sein kann nur eine Instanz, für die die Person berechtigt ist … Ob sie verknüpft ist, spielt für die Wahl keine Rolle.“ US-12 und Terminologie: „Die Person markiert eine ihrer verknüpften Instanzen als ‚aktiv‘“; Terminologie „Aktive ConMeet-Instanz: Die verknüpfte ConMeet-Instanz …“. US-12 nennt zugleich „Zur Auswahl stehen nur Instanzen, für die die Person berechtigt ist“; 001 (Nicht im Scope) folgt der Spezifikation. Widerspruch: Nach R21 kann eine unverknüpfte Instanz aktiv sein (Beispiel Schritt 7); nach US-12 und Terminologie nicht. Entscheidung erforderlich: Gilt „berechtigt“ (dann US-12 und Terminologie anpassen) oder „verknüpft“ (dann R21, R23–R25, R34 und Zustand 5 in R33 anpassen)? Aufgelöst am 2026-10-30: „berechtigt“ gilt; US-12 und Terminologie angepasst, 002 unverändert; Entscheidung Martin Linkwitz.

C2 Kunde und Zentrale im Proof of Concept behoben

Diese Spezifikation (R56, R57, R49): Jeder Treffer zeigt die Firma aus pretty_name des Kunden; ohne Kontakttreffer wird der Kunde über seine Zentralnummer Treffer, „ohne Namen einer Person“. US-01, US-17, Sitzung 2026-10-30: US-01 zeigt „den Kontakt … mit Namen und einigen Kontaktinformationen“; Sitzung: „je Kontakt nur Name, einige Kontaktinformationen und ‚in ConMeet öffnen‘; der Kunde noch nicht“; US-17: „Ist der Kontakt einem Kunden zugeordnet, ist auch der Kunde zu sehen … Nicht im Proof of Concept.“ Widerspruch: Die Spezifikation zeigt den Kunden schon im Proof of Concept und kennt Treffer, die kein Kontakt sind. Entscheidung erforderlich: Gehören Firma und Zentralnummer-Treffer in den Proof of Concept? Wenn ja, US-01 und US-17 nachziehen; wenn nein, R49, R56, R57 kürzen. Aufgelöst am 2026-10-30: Firma und Zentrale-Treffer gehören in den Proof of Concept; US-01 und US-17 angepasst; Entscheidung Martin Linkwitz.

C3 „Kontakt in ConMeet öffnen“ öffnet den Kunden behoben

Diese Spezifikation (R60): Der Link führt auf {BaseUrl}/home/master-data/customers/{Kunden-id}/dashboard. US-01 / US-03: US-01: „Die Person kann den Kontakt von dort in ConMeet öffnen“; US-03 (Proof of Concept): „Den Kontakt in ConMeet zu öffnen, gehört schon zum Proof of Concept“. Widerspruch: Der Link öffnet die Kundenseite, nicht den Kontakt. Entscheidung erforderlich: Genügt die Kundenseite (dann US-01 und US-03 anpassen), oder gibt es eine Adresse für den Kontakt (dann R60 anpassen)? Aufgelöst am 2026-10-30: Die Kundenseite genügt; R60 präzisiert, US-01 und US-03 angepasst; Entscheidung Martin Linkwitz.

C4 Architektur kennt nur ein Sitzungscookie und keine Einbettung behoben

Diese Spezifikation (R4, R5, R15, R16): Zweites Cookie __Host-teams-session mit SameSite=None und Partitioned; Einbettung unter /teams durch Teams-Hosts. docs/architecture.md (Vertrauensgrenzen): „Der Browser erhält nur das HttpOnly-Sitzungscookie“; Teams als Einbettender kommt im Ressourcengraphen und bei den Vertrauensgrenzen nicht vor. Widerspruch: Die Architektur beschreibt eine Vertrauensgrenze, die diese Spezifikation verschiebt. Entscheidung erforderlich: Architektur mit der Spezifikation nachziehen oder Abschnitt 2 anders lösen. AGENTS.md verlangt docs/architecture.md bei geänderten Vertrauensgrenzen. Aufgelöst am 2026-10-30: docs/architecture.md (Vertrauensgrenzen) nennt beide Cookies und die Einbettung unter /teams; nachgezogen durch specification-fixer.

C5 001 kennt die Erweiterungen aus 002 nicht behoben

Diese Spezifikation (R20, R28–R31, R52): Neue Entität ActiveInstanceChoice in der Vertikale ConMeetInstances, gelöscht beim Entzug, beim Trennen und über den Erweiterungspunkt aus 001-R87; Begrenzung der Aufrufe auch für die Prüfungen aus 001-R95. 001 (Abschnitt 1, R15, R87, R95, R18): „Die drei Entitäten bilden ein Aggregat“; R15 löscht Instanz „mit allen Berechtigungen und Kontoverknüpfungen“; R87 nennt nur InstanceGrant und AccountLink; R18 lässt jede Prüfung sofort starten. Widerspruch: Wer nur 001 umsetzt oder prüft, findet das vierte Element des Aggregats und die Wartezeit vor Prüfungen nicht. Entscheidung erforderlich: Die Regeln in 001 ergänzen (Aggregat, R15, R87, Wartezeit bei R18) oder in 001 auf 002 verweisen. Aufgelöst am 2026-10-30: 001 ergänzt: Vertikale enthält ActiveInstanceChoice (Abschnitt 1), R15, R26, R76 (Begrenzung) und R87 verweisen auf 002; durch specification-fixer.

C6 Vorabschnittstelle von Teams gegen „Nur stabile Releases“ behoben

Diese Spezifikation (R6): Die Rufnummer kommt aus meeting.getMeetingDetailsVerbose(). AGENTS.md / Q4: „Nur stabile Releases“ mit abschließender Liste genehmigter Ausnahmen; der Prototyp (Q4: README) nennt getMeetingDetailsVerbose „in der SDK als beta markiert“. Widerspruch: Die Spezifikation stützt sich auf eine Vorab-API, die nicht unter den Ausnahmen steht. Entscheidung erforderlich: Ausnahme in AGENTS.md genehmigen oder einen anderen Weg zur Rufnummer festlegen. Aufgelöst am 2026-10-30: Ausnahme genehmigt von Martin Linkwitz; in AGENTS.md (Projektentscheidungen) eingetragen, R6 verweist darauf.

C7 Frontend-Entwicklung kennt Abschnitt 2 nicht behoben

Diese Spezifikation (R6, R15, R16, R72–R74): zweites Sitzungscookie, Einlösen eines Einmalcodes, Routing-Gruppe (teams) ohne allgemeine Anmeldepflicht und ohne (authenticated)-Layout, Beta-API von Teams. docs/frontend-development.md: „Authentifizierung … unverändert aus validdata-frontend-features … Abweichung: keine“ (einzige genannte Abweichung: returnTo); „me im Layout-Load … genutzt von (authenticated) und (suite)“; „Fachseiten gehören nach (authenticated)“; „Experimentelle APIs (genehmigt)“ nennt nur SvelteKit und Svelte. Widerspruch: Abschnitt 2 ist eine Abweichung von der Referenz-Authentifizierung und eine Fachseite außerhalb von (authenticated); das Entwicklerdokument schließt beides aus. Entscheidung erforderlich: docs/frontend-development.md nachziehen (Abweichung, Gruppe (teams), Ausnahme getMeetingDetailsVerbose) oder Abschnitt 2 ändern. Aufgelöst am 2026-10-30: docs/frontend-development.md nennt die Beta-API, (teams) beim Layout-Load von me und die Ausnahme von der Regel für Fachseiten; nachgezogen durch specification-fixer.

C8 US-12 knüpft die Herkunftsanzeige weiter an „verknüpft“ behoben

Diese Spezifikation (R24, R61): Auswahl und Herkunft der Daten sind sichtbar, wenn die Person für mindestens zwei Instanzen berechtigt ist. US-12: „Ist die Person mit mehreren Instanzen verknüpft, ist sichtbar, aus welcher Instanz die angezeigten Daten stammen“. Widerspruch: Nach C1 gilt „berechtigt“; dieses Kriterium ist stehen geblieben. Berechtigt für zwei, verknüpft mit einer: nach R24 sichtbar, nach US-12 nicht verlangt. Entscheidung erforderlich: US-12 auf „berechtigt“ ändern oder R24 und R61 einschränken. Aufgelöst am 2026-10-30: US-12 sagt „berechtigt“; folgt aus der Entscheidung zu C1 (Martin Linkwitz).

C9 SQL-Upsert gegen Audit, Mandantenstempel und Indexregel behoben

Diese Spezifikation (R20, R92): ActiveInstanceChoice ist „mandanteneigen und auditiert wie die übrigen Entitäten“, UserId eindeutig; Anlegen per INSERT … ON CONFLICT DO NOTHING auf UserId, Umschalten per Upsert. docs/backend-development.md, AGENTS.md: Anlage-, Änderungs- und Audit-Felder sowie der Mandant entstehen über Interceptoren (TenantStampInterceptor, „Interceptoren (Anlage, Änderung, Soft Delete, Audit)“); „Rohes SQL auf mandanteneigene Tabellen trägt tenant_id ausdrücklich“; „eindeutige Indizes beginnen mit TenantId“, Eindeutigkeit mit Soft Delete über UniqueWithIsDeletedFilter(). Widerspruch: Rohes SQL umgeht die Interceptoren — Audit-Zeile, *_by/*_by_id und Mandantenprüfung entstehen nicht von selbst; ON CONFLICT auf UserId passt nicht zu einem Index (TenantId, UserId) mit Filter auf gelöschte Zeilen. Entscheidung erforderlich: Audit und Mandant für den SQL-Weg ausdrücklich regeln (wie 001-R15) und das Konfliktziel auf den tatsächlichen Index legen — oder Anlegen und Umschalten über EF mit Behandlung der Eindeutigkeitsverletzung. Aufgelöst am 2026-10-30: R92: Schreiben über EF Core mit Interceptoren, Index (TenantId, UserId) mit UniqueWithIsDeletedFilter(), Eindeutigkeitsverletzung wird behandelt; entschieden durch specification-fixer (folgt aus backend-development.md).

C10 Architektur nennt weder die Einschränkung auf `/teams/call` noch R91 behoben

Diese Spezifikation (R4, R5, R91): Nur /teams/call ist einbettbar, /teams/auth/* nicht; __Host-teams-session zählt nur für (teams) und die Remote Functions der Anrufinformation. docs/architecture.md (Vertrauensgrenzen): „Einbetten dürfen nur Teams-Hosts und nur Routen unter /teams“; zum Geltungsbereich von __Host-teams-session nichts. Widerspruch: Nach L8 und L9 nicht nachgezogen; L9 verlangte ausdrücklich, docs/architecture.md zu ergänzen. Die Vermerke zu C4 und L9 sind insoweit unvollständig. Entscheidung erforderlich: docs/architecture.md auf R4, R5 und R91 nachziehen. Aufgelöst am 2026-10-30: docs/architecture.md nennt beide Clients, die Trennung der Cookies und nur /teams/call als einbettbar; nachgezogen mit L17.

C11 Entwicklerdokumente kennen Teams-Client und getrennte Sitzung nur teilweise behoben

Diese Spezifikation (R14, R91, R96, R97, R105): (teams) erkennt nur __Host-teams-session; eigener Client vd-suite-conmeet-teams; jede Sitzung trägt ihren Client; Einmalcodes mit Tokens in frontend; locals.teamsSession für die Remote Functions unter call-information/. docs/frontend-development.md: „Authentifizierung … unverändert … Abweichungen stehen unten“ — unten nur returnTo/safeReturnTo; (teams) „nutzt zusätzlich das Cookie __Host-teams-session“. docs/architecture.md: „Jedes Cookie gilt nur für seinen Bereich ((teams) bzw. alle übrigen Routen)“. Widerspruch: „zusätzlich“ widerspricht „nur“ in R91; zweiter Client, Client der Sitzung, Tabelle der Einmalcodes und /teams/auth/* fehlen als Abweichung von der Referenz; die Architektur rechnet die Remote Functions der Anrufinformation keinem Bereich zu. Die Vermerke zu C7 und C10 sind insoweit überholt. Entscheidung erforderlich: Beide Dokumente auf R91, R96, R97, R105 nachziehen (nach U26). Aufgelöst am 2026-10-30: docs/frontend-development.md (Abweichungen von der Referenz: zweiter Client, /teams/auth/*, Einmalcodes, Client der Sitzung, locals) und docs/architecture.md (Bereich von __Host-teams-session) auf R91, R96, R97, R105 nachgezogen; durch specification-fixer.

C12 Secret des Teams-Clients fehlt bei den Parametern der entfernten Suite behoben

Diese Spezifikation (R96): Der Client wird für jede Suite-Umgebung angefragt; „sein Secret kommt wie das des Webseiten-Clients aus der Konfiguration“. integration-plan.md verlangt beide Secrets je Umgebung. AGENTS.md (Lokale oder entfernte Suite): einziger Parameter Parameters:suite-oidc-client-secret — „Secret des Clients vd-suite-conmeet-web in diesem Realm“. Widerspruch: Mit Suite:Environment = remote gibt es keinen Parameter für das Secret von vd-suite-conmeet-teams. Entscheidung erforderlich: Parameter benennen und in AGENTS.md aufnehmen (docs/vds-suite/deployment-handover.md nicht geprüft). Aufgelöst am 2026-10-30: AGENTS.md um Parameters:suite-oidc-teams-client-secret ergänzt, R96 verweist darauf; freigegeben von Martin Linkwitz.

C13 „Zuletzt gespeicherte gilt“ gegen Zeilenversion `xmin` behoben

Diese Spezifikation (R92): Schreiben „über EF Core wie jede Entität der Vertikale“; „bei gleichzeitigem Umschalten gilt die zuletzt gespeicherte“. AGENTS.md, 001-R73: Fachentitäten tragen die „Zeilenversion xmin“; 001-R73 lässt gleichzeitiges Ändern daran scheitern (INSTANCE_CHANGED). Widerspruch: Mit xmin scheitert die spätere von zwei gleichzeitigen Umschaltungen, statt zu gelten; R63 und R65 kennen dafür keinen Fehlercode. Entscheidung erforderlich: Für setMyActiveConMeetInstance den Konflikt ausdrücklich behandeln (z. B. erneut speichern) oder Fehlercode und Anzeige festlegen. Aufgelöst am 2026-10-30: R92: Bei Konflikt der Zeilenversion lädt setMyActiveConMeetInstance neu und speichert einmal erneut, danach liefert es den gespeicherten Stand ohne Fehler; entschieden durch specification-fixer.

Lücken

L1 Seite ohne Sitzung gegen die allgemeine Anmeldepflicht behoben

Problem: R11 zeigt ohne Sitzung eine eigene Anzeige im eingebetteten Fenster. Die Anwendung leitet heute jede Route außerhalb von (anonymous) zur Anmeldung weiter, und das (authenticated)-Layout leitet je Suite-Zustand auf Zustandsseiten um. Die Spezifikation sagt nicht, in welcher Routing-Gruppe /teams/call, /teams/auth/* und die Remote Functions der Seite liegen und wie sie diese Weiterleitungen umgehen. Ebenso offen: was das eingebettete Fenster zeigt, wenn die Sitzung während der Nutzung endet (Abmeldung anderswo, Ende nach WP4). Auswirkung: R11, R19 und R71 sind ohne diese Festlegung nicht umsetzbar, ohne die Anmeldepflicht anderer Routen zu berühren. Erforderlich: Routing-Gruppe und Verhalten bei fehlender oder beendeter Sitzung festlegen. Aufgelöst am 2026-10-30: Neu R72–R74: Routing-Gruppe (teams), keine allgemeine Weiterleitung, Verhalten bei fehlender oder beendeter Sitzung; entschieden durch specification-fixer (folgt aus R11, R71).

L2 Lange Suchen ohne Gesamtgrenze behoben

Problem: R46 begrenzt die Gesamtdauer nicht, R54 lässt Aufrufe beliebig warten. Bei vielen Kunden (z. B. 3000 → über 300 Sekunden bei 10 je Sekunde) greifen Zeitgrenzen zwischen Browser, BFF und Dienst. Was die Anrufinformation dann zeigt, steht nicht da. Erforderlich: Verhalten bei Abbruch durch eine Zeitgrenze festlegen, oder eine Gesamtgrenze mit Meldung. Aufgelöst am 2026-10-30: R46: Gesamtdauer höchstens 10 Sekunden, gemeinsames Cancellation Token, Fehlercode SEARCH_TIMEOUT; Beispiel auf 60 Kunden umgestellt; Entscheidung Martin Linkwitz.

L3 Verworfene Suchen belasten weiter die Begrenzung behoben

Problem: R37 verwirft veraltete Ergebnisse nur in der Anzeige. Ohne Abbruch im Dienst laufen die Aufrufe weiter, verbrauchen die Begrenzung aus R52 und verzögern Suchen anderer Personen und Prüfungen des Administrators. Erforderlich: Festlegen, ob Umschalten, neue Nummer oder Schließen der Seite die laufende Suche im Dienst abbricht. Aufgelöst am 2026-10-30: Neu R75, R76: Umschalten, neue Suche oder Schließen bricht die Suche bis in den Dienst ab; Entscheidung Martin Linkwitz (Abbruch per Cancellation Token).

L4 Öffnen von Links aus Teams nur teilweise geregelt behoben

Problem: R60 öffnet „im Browser, nicht im Teams-Fenster“, ohne den Weg zu nennen. Für den Link aus R19 und für die Anleitung aus 001-R62 (Seite zum Erzeugen des Schlüssels), die R34 in der Anrufinformation zeigt, fehlt die Regel ganz. Erforderlich: Eine Regel für alle externen Links der Anrufinformation. Aufgelöst am 2026-10-30: Neu R80: alle externen Links über app.openLink() bzw. neuen Tab; entschieden durch specification-fixer.

L5 Andere Nummer suchen, wenn Teams eine liefert behoben

Problem: Das Feld „Rufnummer“ gibt es nur nach R9. Ob die Person bei einer Nummer aus Teams eine andere suchen kann, und wo bei Treffern die gesuchte Nummer steht, ist nicht festgelegt. Erforderlich: Festlegen oder ausdrücklich ausschließen. Aufgelöst am 2026-10-30: Neu R77–R79: Feld immer sichtbar und vorbelegt, als eigenständiger, entfernbarer Baustein; Entscheidung Martin Linkwitz.

L6 Begrenzung bei mehreren Instanzen des Dienstes hinfällig

Problem: R52 gilt „über alle Personen und Anfragen des Dienstes hinweg“, umgesetzt im Prozess (R53). Laufen mehrere Instanzen des Dienstes, vervielfacht sich die Grenze. Erforderlich: Festlegen, dass der Proof of Concept mit einer Instanz des Dienstes läuft, oder eine gemeinsame Begrenzung verlangen (ggf. als Releaseblocker). Hinfällig am 2026-10-30: Im Proof of Concept läuft eine Instanz des Dienstes; danach ersetzt eine passende ConMeet-Schnittstelle den Vollabruf; Entscheidung Martin Linkwitz.

L7 `(teams)` lädt `me` nicht und prüft den Core-Benutzer der Sitzung nicht behoben

Problem: Zustand 2 in R33 und R19 brauchen den Zugangszustand; ensureMyActiveConMeetInstance verlangt READY (Standard-Policy) und scheitert vorher. me lädt laut docs/frontend-development.md nur das Layout von (authenticated) und (suite), das R73 für (teams) ausschließt. Damit fehlt in (teams) auch die Prüfung aus WP4 (sessions.suite_user_id, Sitzungsende bei anderem oder fehlendem Core-Benutzer), auf die R74 sich beruft. Auswirkung: Wer nur in Teams arbeitet, behält nach Entfernen oder Mandantenwechsel in Core seine Sitzung; R19 ist ohne me nicht umsetzbar. Erforderlich: Festlegen, dass (teams) me lädt und WP4 anwendet, ohne weiterzuleiten. Aufgelöst am 2026-10-30: R95 neu: (teams) lädt me wie (authenticated), ensureMyActiveConMeetInstance erst bei READY; entschieden durch specification-fixer.

L8 Einmalcode nicht an das anfragende Fenster gebunden behoben

Problem: R13–R15 binden den Code an die Sitzung, nicht an das eingebettete Fenster, das „Anmelden“ ausgelöst hat (kein state oder Nonce, der beim Einlösen geprüft wird). Ebenfalls offen: Herkunftsprüfung (Origin) für den POST an /teams/auth/exchange, Löschen abgelaufener und eingelöster Codes in frontend, und ob /teams/auth/start, /teams/auth/done und /teams/auth/exchange einbettbar sein müssen (R4 erlaubt es für alle Routen unter /teams, gebraucht wird es nur für /teams/call). Auswirkung: Ein abgefangener Code ist 60 Sekunden lang in jedem Browser einlösbar und ergibt die Sitzung seines Inhabers. Erforderlich: Bindung (z. B. Nonce des eingebetteten Fensters, in R12 übergeben, in R15 geprüft), Herkunftsprüfung, Aufräumen und Einbettbarkeit je Route festlegen. Aufgelöst am 2026-10-30: R89 neu (state bindet den Code an das Fenster), R14, R15, R17 angepasst, R90 neu (Origin-Prüfung, Aufräumen), R4/R5: nur /teams/call einbettbar; entschieden durch specification-fixer.

L9 `__Host-teams-session` gilt für jede Route behoben

Problem: R16 erkennt die Sitzung an __Host-teams-session auf jeder Route des BFF, nicht nur unter /teams und in den Remote Functions von /teams/call. Das Cookie ist SameSite=None; in der Partition des Teams-Hosts hängt der Browser es an jede Anfrage an den BFF, auch an solche, die andere in Teams eingebettete Apps auslösen. Mutationen, Formular-Actions und die Verwaltung aus 001 (ManageInstances) verlieren dort den Schutz von SameSite=Lax; welcher CSRF-Schutz stattdessen greift, steht nirgends. Erforderlich: Geltungsbereich des Cookies festlegen (nur /teams und die von dort genutzten Remote Functions) oder eine Herkunftsprüfung für jede zustandsändernde Anfrage verlangen; docs/architecture.md (Vertrauensgrenzen) entsprechend ergänzen. Aufgelöst am 2026-10-30: R91 neu: __Host-teams-session zählt nur für (teams) und die Remote Functions der Anrufinformation, Origin-Prüfung bleibt; entschieden durch specification-fixer.

L10 Gleichzeitiges Schreiben der aktiven Instanz behoben

Problem: ensureMyActiveConMeetInstance läuft bei jedem Laden (R22). Zwei Fenster oder Geräte ohne gespeicherte Wahl legen gleichzeitig je eine Zeile an und stoßen an „UserId eindeutig“ (R20). Ebenso offen: setMyActiveConMeetInstance von zwei Geräten zugleich (letzte Wahl gewinnt oder Fehler über xmin?) und ensure gleichzeitig mit dem Entzug aus R28, R29 (Wahl einer soeben entzogenen Instanz). Erforderlich: Ergebnis je Fall festlegen. Aufgelöst am 2026-10-30: R92 (Anlegen nur wenn leer, Upsert beim Umschalten) und R93 (Wahl ohne Berechtigung gilt als nicht vorhanden) neu; entschieden durch specification-fixer.

L11 Gleichzeitige Suchen in derselben Instanz behoben

Problem: Die Begrenzung (R52, R53) teilt die Aufrufe auf alle laufenden Suchen einer Instanz auf. Zwei Anrufe zugleich in einer Instanz mit 60 Kunden brauchen je rund 12 Sekunden und scheitern beide an R46; das Beispiel (Schritt 3) setzt voraus, dass „niemand sonst ‚Live‘ abfragt“. Weder eine Regel noch „Offene Fragen“ noch RB-001 nennen das; die Grenze von rund 95 Kunden gilt nur für eine einzelne Suche. Erforderlich: In Kauf nehmen und unter „Offene Fragen“ bzw. in RB-001 festhalten, oder eine Regel für gleichzeitige Suchen festlegen. Aufgelöst am 2026-10-30: Hingenommen; „Offene Fragen“ und RB-001 nennen gleichzeitige Suchen; Entscheidung Martin Linkwitz.

L12 `/teams/auth/done` außerhalb eines Teams-Anmeldefensters behoben

Problem: /teams/auth/start nimmt jedes state aus der URL an und geht bei bestehender Sitzung ohne Zutun zu /teams/auth/done (R12), das einen Code für diese Sitzung erzeugt (R13). Ein Link mit einem vom Angreifer gewählten state, im normalen Browser geöffnet, erzeugt so einen Code für die Sitzung des Opfers, dessen state der Angreifer kennt. Dass der Code nur über notifySuccess() an Teams geht und nie in URL, Seite oder Log steht, und was die Seite ohne Teams-Anmeldekontext zeigt, regelt keine Anforderung; ebenso nicht, ob der Code per GET mit Nebenwirkung entsteht. Erforderlich: Festlegen, dass der Code nur im Teams-Anmeldekontext entsteht (z. B. nach erfolgreichem app.initialize() per POST angefordert, sonst Hinweis ohne Code) und nie in eine URL gelangt. Aufgelöst am 2026-10-30: R100 neu: Code nur im Skript für notifySuccess(), nie in URL, Log oder Speicher; ohne Teams-Kontext verworfen; ohne Code nützt ein bekannter state nichts; entschieden durch specification-fixer.

L13 Browser speichert das partitionierte Cookie nicht behoben

Problem: Abschnitt 2 setzt voraus, dass der eingebettete Kontext ein Cookie mit SameSite=None; Partitioned speichert und sendet. WebKit (Safari, je nach Version auch der Teams-Client unter macOS, den R35 ausdrücklich nennt) und Browser mit gesperrten Drittanbieter-Cookies tun das nicht. Dann gelingt der Tausch (R15), die nächste Anfrage hat keine Sitzung, R74 zeigt wieder R11 — ohne Meldung, bei jedem Versuch. Erforderlich: Unterstützte Teams-Clients und Browser nennen und festlegen, was die Anrufinformation zeigt, wenn nach erfolgreichem Tausch keine Sitzung ankommt. Aufgelöst am 2026-10-30: R101 neu: unterstützte Clients (Teams für Windows, Teams im Web mit Edge oder Chrome), Prüfung nach dem Tausch und eigene Meldung; Entscheidung Martin Linkwitz.

L14 Domänen der Anmeldung fehlen im Manifest behoben

Problem: authentication.authenticate() verlangt, dass die Domänen des Anmeldeablaufs in validDomains des Manifests stehen. R2 nennt nur /teams/call als staticTab; Q4 hat keine Anmeldung. Weder die Domäne des BFF je Umgebung noch die von Keycloak (lokal localhost:8091, entfernt Parameters:suite-oidc-authority) stehen in einer Anforderung, auch nicht, was das Skript aus R2 dafür einsetzt. Erforderlich: validDomains und ihre Werte je Umgebung in R2 festlegen. Aufgelöst am 2026-10-30: R102 neu: validDomains mit Host des BFF und von Keycloak je Umgebung; entschieden durch specification-fixer.

L15 Nebenläufigkeit der Aufrufe innerhalb einer Suche behoben

Problem: R42, R43 sagen nicht, ob die Kontaktlisten nacheinander oder parallel abgerufen werden. Nacheinander bestimmt die Antwortzeit von ConMeet die Dauer, sobald ein Aufruf länger als 100 ms braucht — dann stimmen „gut 6 Sekunden“ (Beispiel Schritt 3), „rund 95 Kunden“ (Offene Fragen) und RB-001 nicht. Parallel fehlt eine Obergrenze gleichzeitig offener Aufrufe (vgl. 001-R76). Erforderlich: Nebenläufigkeit je Suche festlegen und Beispiel sowie Kundengrenze danach rechnen. Aufgelöst am 2026-10-30: R103 neu: Kundenseiten nacheinander, Kontaktlisten mit höchstens 4 offenen Aufrufen je Suche; Beispiel nennt die Annahme unter 400 ms; entschieden durch specification-fixer.

L16 Schlüssel geht an jede Adresse, die der Callback anspricht behoben

Problem: Der DelegatingHandler aus R83 setzt Authorization: Bearer … „beim Senden jeder Anfrage“. Der Client aus R81 steht dem Callback frei zur Verfügung; ein absoluter URI auf einen anderen Host (z. B. ein von ConMeet gelieferter Link oder eine fehlerhafte Verkettung, vgl. U22) schickt den persönlichen Schlüssel dorthin — im Ergebnis gegen R83 und 001-R52. Erforderlich: Festlegen, dass der Handler den Schlüssel nur für Anfragen unter BaseUrl setzt und andere Anfragen ablehnt. Aufgelöst am 2026-10-30: R104 neu: Schlüssel nur für Aufrufe unter der BaseAddress, andere werden nicht gesendet; entschieden durch specification-fixer.

L17 Woher das Sitzungstoken beim Einlösen kommt behoben

Problem: R14 speichert am Code nur einen Verweis auf die Sitzung; R15 setzt __Host-teams-session „mit dem Sitzungstoken derselben Sitzung“. Liegt das Token in frontend nur als Hash oder als daraus abgeleitete ID vor (übliches Muster; kein Dokument sagt es), kann der Server es beim Einlösen nicht zurückgewinnen. Erforderlich: Festlegen, wie das Token beim Einlösen verfügbar ist (z. B. verschlüsselt am Code) oder ob die Sitzung ein zweites Token erhält (dann R16 und das Sitzungsende nach WP4 für beide nennen). Aufgelöst am 2026-10-30: Eigener Keycloak-Client vd-suite-conmeet-teams (R96) und eigene Teams-Sitzung (R97): Der Code trägt die Tokens, erst /teams/auth/exchange legt die Sitzung an und setzt ein frisch erzeugtes Token (R14, R15); R16 entfällt, R91 trennt die Cookies; Entscheidung Martin Linkwitz.

L18 Fehler von `ensureMyActiveConMeetInstance` und `setMyActiveConMeetInstance` ohne Anzeige behoben

Problem: R33 behandelt nur Fehler der Suche (Zeile 8, R87). setMyActiveConMeetInstance antwortet nach R63 mit INSTANCE_NOT_GRANTED oder INSTANCE_NOT_FOUND (Entzug oder Trennen zwischen Laden und Wahl); ebenso kann ensureMyActiveConMeetInstance beim Laden scheitern (Dienst nicht erreichbar). Zustand und Anzeige dafür fehlen. Erforderlich: Je Fehler festlegen, z. B. wie R87 ensureMyActiveConMeetInstance erneut aufrufen; für den nicht erreichbaren Dienst eine Anzeige mit „Erneut versuchen“. Aufgelöst am 2026-10-30: R108 neu und Zustand 2a in R33: Anzeige bei gescheitertem ensureMyActiveConMeetInstance und bei INSTANCE_NOT_GRANTED/INSTANCE_NOT_FOUND aus setMyActiveConMeetInstance; entschieden durch specification-fixer.

L19 Folgesuchen derselben Person teilen sich die Begrenzung behoben

Problem: Nach R75 läuft jede alte Suche bis zu 10 Sekunden weiter; jede neue Suche, jedes Umschalten (R26) und jedes „Erneut suchen“ während einer laufenden Suche startet eine weitere, die sich die Begrenzung (R52, R53) mit den alten teilt. Keine Regel sperrt „Suchen“ oder begrenzt die Zahl laufender Suchen je Person. Beispiel Schritt 9 (60 Kunden): Sucht Ben kurz nach Beginn der ersten Suche erneut, teilen sich rund 120 Aufrufe 10 je Sekunde; die neue Suche endet voraussichtlich mit SEARCH_TIMEOUT (abgeleitet aus R46, R53, R103). Das Beispiel sagt nur „Die neue Suche beginnt“; „Offene Fragen“ und RB-001 nennen nur gleichzeitige Anrufe, nicht Folgesuchen einer Person. Erforderlich: Festlegen, ob „Suchen“ während einer laufenden Suche gesperrt ist oder Folgesuchen anders begrenzt werden, oder es hinnehmen; dann Schritt 9 mit Ergebnis, „Offene Fragen“ und RB-001 ergänzen. Aufgelöst am 2026-10-30: Mit der Sperre aus R75 läuft je Person höchstens eine Suche; Beispiel Schritt 9 angepasst; Entscheidung Martin Linkwitz.