Gemeinsamer App-Zugriffsvertrag
Vertrag ci-app-access-policy/v1, Referenzfassung 1.0.0. Kanonischer Einstieg: https://mcp-lab.christian-igel.tech/xp-contract/access/ . Dieser Vertrag ergänzt Programmregistrierung, Fensterrollen und Foundation-Fenstervertrag. WP-Lab bleibt Identitäts- und Kontoautorität. Eine veröffentlichte Referenz belegt noch keine Durchsetzung in einem Verbraucher; dessen Implementierung, Veröffentlichung, angemeldete Browserprüfung und MCP-Client-Abnahme sind getrennt nachzuweisen.
Begriffe und Berechnung
Rangfolge: guest < customer < developer < admin. Die Kontorolle ist eine Obergrenze der auswählbaren Rollen. Die Ansichtsrolle ist die bewusst verwendete Rolle. App- und Verbindungsgrenzen sind weitere Obergrenzen. Sie ersetzen die Ansichtsrolle nicht.
- Server prüft aktuelle Identität, Kontostatus und gültige Ansichtbindung.
- Basis ist die ausdrücklich gewählte Fensterrolle, sonst die aktuelle Desktop-Ansichtsrolle. Telegram verwendet seine eigene gespeicherte Channel-Ansichtsrolle.
- Wirksame Rolle ist das Minimum aus Basis, Konto-Maximum, optionalem App-Maximum, optionalem persönlichem App-Maximum und optionalem Verbindungsmaximum.
- Erst danach werden App-Mindestrolle, Nutzerliste, Gastfreigabe und sämtliche bestehenden Verbote, Eigentümer- und Verbindungsgrenzen geprüft.
Keine automatische Höherstufung. Eine ausdrückliche Fensterwahl darf über der Desktop-Ansicht liegen, bleibt aber durch die übrigen Maxima begrenzt. Sie verändert weder Desktop noch andere Fenster. Ein appweites Maximum stuft automatisch herab. Eine persönliche Obergrenze unterhalb des App-Minimums verweigert nur diesem Nutzer den Zugang.
| Beispiel | Ergebnis |
|---|---|
| Admin-Konto, Customer-Ansicht, keine Appgrenze | Customer |
| Admin-Ansicht, App-Maximum Customer | Customer |
| Customer-Ansicht, Minimum Developer | Verweigert |
| Desktop Customer, bewusste Fensterwahl Admin, alle Maxima Admin | Dieses Fenster Admin |
| Developer-Ansicht, persönliches Maximum Customer, Minimum Developer | Verweigert |
| Nutzerliste enthält Nutzer, bestehendes Programmverbot | Verweigert |
Gastzugriff ist eine zusätzliche ausdrückliche App-Fähigkeit im bestehenden Registrierungsvertrag. Er ist für anonyme Nutzung und jede effektive Guest-Ansicht erforderlich. Ein bekanntes gesperrtes Konto wird niemals zu einem anonymen Gast umgedeutet. Das Weglassen einer Nutzerliste veröffentlicht keine geschützte App.
Definition
Die maschinenlesbare Definition folgt policy.schema.json. Unbekannte Felder, Versionen und Rollen werden abgelehnt. revision ist eine positive, pro App steigende Ganzzahl bis 9007199254740991. Eine inhaltliche Änderung benötigt eine höhere Revision. Eine Revision mit anderem Inhalt wird niemals still übernommen.
| Feld | Bedeutung |
|---|---|
| schema | Genau ci-app-access-policy/v1 |
| app_id | Stabile registrierte App-ID ohne C0-/DEL-Steuerzeichen |
| revision | Positive steigende Ganzzahl |
| min_role | Optional; fehlend bedeutet kein zusätzliches Minimum |
| max_role | Optional; fehlend bedeutet keine zusätzliche Obergrenze |
| allowed_users | Optional; stabile bestätigte IdP-Subjects ohne C0-/DEL-Steuerzeichen, keine Namen/Telefonnummern |
| user_max_roles | Optional; Objekt Subject → maximale Rolle in dieser App |
Fehlende allowed_users bedeutet keine zusätzliche Nutzerfilterung; [] sperrt alle. Vorhandene Nutzerlisten verlangen einen exakten Subject-Treffer und überstimmen keine andere Prüfung. Ein einzelner Eintrag in user_max_roles ist keine Zulassung. Leere Objekte und Listen sind unterschiedlich; null ist kein Ersatz für ein weggelassenes optionales Feld.
Allgemeines min_role > max_role ist ungültig und verhindert Aktivierung. Rollenlisten aus Altverträgen bleiben exakt: [customer, admin] gestattet niemals automatisch Developer. Wird Admin auf Developer begrenzt, verweigert diese Altrollenliste den Zugang; sie sucht keine Ersatzrolle. Bestehende Einzelverbote bleiben bindend.
Beispiel mit rein synthetischem Subject:
{
"schema": "ci-app-access-policy/v1",
"app_id": "example-app",
"revision": 1,
"min_role": "customer",
"user_max_roles": {"example-subject": "customer"}
}
Export und Vertrauensgrenze
Lokale Programme registrieren das Objekt serverseitig als access_policy an der bestehenden Programmdefinition. MCP-Apps deklarieren an ihrer registrierten App-Ressource:
{
"_meta": {
"tech.christian-igel/app-access": {
"schema": "ci-app-access-policy/v1",
"app_id": "example-app",
"policy_resource": "app-access://example-app/policy"
}
}
}
policy_resource ist eine opaque MCP-Ressourcenkennung, keine vom Host frei zu ladende HTTP-Adresse. Der Host liest sie ausschließlich über dieselbe registrierte, authentifizierte App-Verbindung. Ressource mit MIME application/json; bei Ressourcenwechsel und ListChanged erneut prüfen. Die Metadaten sind ein Verweis und vergeben keine Rechte.
Der Host bindet Cache und Import an registrierte App-ID, konfigurierten Aussteller, exakte OAuth-Resource, Verbindung und Policyrevision. Ein Payload darf diese Bindung nicht selbst behaupten. Falsche App/Quelle, alte Revision, gleiche Revision mit anderem Inhalt, ungültiges Schema oder eine unzuverlässige Autorisierungsquelle verhindern Aktivierung. Ein erstmals ungültiger deklarierter Vertrag ist kein Anlass für einen Legacy-Fallback. Die Übernahme bleibt gespeichert: Verschwindende Metadaten, 404 oder entfernte Ressourcen einer bereits teilnehmenden App lösen niemals einen Legacy-Fallback aus. Eine gültige höhere Revision darf optionale Grenzen ändern; das Entfernen des Vertrags erfordert eine ausdrückliche vertrauenswürdige Deregistrierung und die Ungültigkeit aller alten Bindungen. Ein fehlerhaftes Update macht laufende Bindungen ungültig; der alte Stand darf keine Ersatzrechte erteilen. Betreiberregeln dürfen zusätzlich einschränken, nicht erweitern.
Vollständige Exporte einschließlich Nutzerlisten und persönlicher Caps erhalten nur berechtigte Administratoren oder ein ausdrücklich autorisierter Hostdienst. Die Exportberechtigung prüft der Server vor dem Lesen; ein MCP-Client ist nicht allein durch seine Verbindung ein Hostdienst. Normale Nutzer erhalten ausschließlich ihre eigene Entscheidung. Öffentliche Beispiele und Quelltests enthalten keine echten Nutzerzuordnungen.
App-HTML, CSS, URL-Parameter, Browserstorage und HostContext sind niemals Autorisierungsquellen. Der Browser sendet nur Fenster-/Appkennung, gewünschte Rolle und erwartete Revision. Identität, Kontostatus, Caps, Legacy-ACL und Verbindung löst der Server selbst auf. Fehlschlag oder fehlender Nachweis einer bestehenden Owner-/ACL-/Grant-Prüfung verweigert Zugriff; er darf nicht in ein weggelassenes optionales Kontextfeld mit erlaubendem Standard übersetzt werden. Direkte Werkzeug-/Backendaufrufe und Ressourcenlesen werden genauso geprüft wie das Öffnen der Oberfläche.
Referenzauswertung
reference.py und reference.php.txt sind reine Auswerter. Die PHP-Datei wird öffentlich absichtlich als Text ausgeliefert. Beide verwenden test-vectors.json. Eine Anwendung muss davor die Quellen authentifizieren und danach die Ausführungsbindung prüfen; ein Boolean binding_valid aus dem Browser darf diese Prüfung nicht ersetzen.
Der interne Kontext enthält subject, active, authenticated, view_role, account_max_role und binding_valid. Optional: window_role, connection_max_role, guest_access (Standard false), legacy_roles, legacy_denied (false) und owner_allowed (true). Fehlende Pflichtangaben und ungültige Typen verweigern Zugriff. window_role ist nur eine bereits serverseitig bestätigte Fensterwahl; Telegram reicht seine eigene gespeicherte Ansicht als view_role ein. Anonyme Kontexte haben subject=null, authenticated=false und ausschließlich Guest als Ansicht und Konto-Maximum. active bezeichnet den Kontostatus; bei einer echten anonymen Identität besteht kein Konto, deshalb wird dieses Pflichtfeld dort nicht als Kontosperre ausgewertet.
Die Entscheidung enthält allowed, effective_role, reason, policy_revision. Bei Verweigerung ist die Rolle null; diese Entscheidung ist keine Fähigkeit und kein wiederverwendbarer Zugriffstoken. Die Policyrevision ersetzt nicht die unten beschriebene Autorisierungsrevision.
reference_policy_store.py demonstriert den Import mit registrierter Quellenbindung und Revisionsprüfung. Die Anwendung muss Übernahmemarker, Revision und Digest dauerhaft speichern und die Quelle tatsächlich authentifizieren; die reine Referenz implementiert weder Datenbank noch OAuth. access-lifecycle.mjs demonstriert den bestätigungspflichtigen Fensterzustand. Seine Host-Hooks müssen Inhalte synchron sperren, Medien beenden und beim asynchronen Mount Abbruchsignal und aktuelle Generation beachten. Auch dieser Controller ersetzt weder den Backend-Wächter noch die XP-Integration.
Prüfen im heruntergeladenen Referenzordner: python -m unittest -v test_reference test_policy_store und node --test test-lifecycle.mjs. PHP im PATH und das Python-Paket jsonschema aktivieren die expliziten PHP-/Schema-Prüfgruppen; übersprungene Prüfungen gelten nicht als bestanden.
Lebenszyklus und Autorisierungsrevision
Zustände: active, confirmation_required, denied. Der Host führt je Fenster eine serverseitige Bindung aus Subject, Anmeldesitzung, App, Fensterinstanz, Verbindung, gewählter Rolle, Policyrevision und Autorisierungsrevision. Die Autorisierungsrevision deckt auch Konto-, Ansichts-, Grant-, Owner- und Betreiberänderungen ab, selbst wenn der Rollenname gleich bleibt. Der Client kann sie nur vergleichen, nicht ausstellen.
Öffnen → aktuelle Prüfung → active oder denied
active → Authentisierung/Ansicht/Policy/Grant ändert sich → confirmation_required
confirmation_required → bewusste Auswahl + frische Prüfung → active oder denied
abgelaufene/verlorene Bindung → confirmation_required (niemals alte höhere Rolle)
Bei Änderung sperrt der Host sofort die Inhaltsfläche und macht die alte Ausführungsbindung ungültig. Er erzeugt eine verständlich beschriftete Milchglasfläche, entzieht Tastatur-/Zeigerfokus und beendet den bisherigen iframe bzw. Appkontext. Milchglas ist kein bloßer Filter über einem weiterlaufenden privilegierten iframe. Audioaufnahme, Audiowiedergabe und interaktive Streams werden gestoppt; lokale Geräte-/Trackfreigaben und Medienleases werden freigegeben. Geschäftsjobs werden nicht pauschal abgebrochen; ihre weiteren Aktionen prüfen die aktuellen Rechte erneut.
Der Fensterrahmen erhält Schließen, Verschieben, Größe und Rollenwahl. Fachliche Appaktionen im Rahmen sind gesperrt. Fokus wird kontrolliert auf den Hinweis oder einen erlaubten Rahmenbutton gesetzt. Zustand und Grund müssen auch ohne visuelles Milchglas für assistive Technik erkennbar sein.
Der Host liefert über den vorhandenen Kontextänderungsweg einen Zusatz tech.christian-igel/app-access mit schema, state, effective_role, policy_revision, authorization_revision und reason. Grundlage ist weiterhin Foundation context-changed bzw. XP HostContext; kein paralleler unsignierter Berechtigungskanal. Zustellung erfolgt nach Sperren, vor kontrolliertem Teardown soweit erreichbar, ohne Warten auf ein App-ACK. Verlust der Appverbindung verhindert die Sperre nicht.
Erst eine ausdrückliche Aktion wie „Als Customer fortsetzen“ oder eine erlaubte Rollenwahl erzeugt unter Compare-and-Swap der aktuellen Autorisierungsrevision einen neuen geprüften Mount. Polling, Fokus, pageshow, Login-Rückkehr und App-Benachrichtigung lösen das nicht aus. Hat sich die Revision inzwischen geändert, bleibt das Fenster gesperrt. Früher höhere Fensterrollen werden nach Anmelde-/Desktopwechsel nicht automatisch wiederhergestellt.
Jeder Backendaufruf prüft die Bindung vor Ausführung, erneut vor privilegierten Seiteneffekten und vor Rückgabe geschützter Ergebnisse. Streams prüfen vor jedem nächsten geschützten Schritt; Widerruf unterbricht den laufenden Transport. Verspätete Antworten alter Mounts werden zusätzlich im Host anhand einer Mount-Generation verworfen. Bereits abgeschlossene Änderungen werden nicht rückwirkend zurückgenommen.
Telegram-Anwendung
Bestätigte numerische Telegram-IDs werden serverseitig mit WP-Lab-Subjects verbunden; Telefonnummern dienen höchstens der vorbereitenden Zuordnung. Eine Telegram-Nachricht kann keine Identität oder Rolle behaupten. Text, Sprachnachricht und nativer Telegram-Anruf verwenden dieselbe Entscheidung vor Medienverarbeitung/LLM sowie erneut vor Werkzeugaktionen.
Telegram führt einen eigenen dauerhaften Ansichtskontext. XP-Ansichtswechsel ändern ihn nicht; Kontoentzug und dauerhafte App-Caps gelten dennoch. Nach Channel-Kontextentzug wird eine aktive Unterhaltung/Audioverbindung suspendiert; sie restauriert keine alten Rechte. Unregistrierte Teilnehmer erhalten keine LLM-Verarbeitung. Optional ist eine feste Nichtverfügbarkeitsantwort zulässig. Eine spätere öffentliche Supportzulassung benötigt eine getrennte Admission-Policy; sie ist jetzt weder aktiviert noch durch einen Schalter vorweggenommen.
Admin darf systemweit beauftragte Änderungen ausführen. Developer darf ausschließlich in freigegebenen eigenen App-/Projektzielen entwickeln und veröffentlichen. Customer erhält Antworten ohne Systemänderungen. Diese Grenzen müssen Werkzeuge, Dateiziele und Laufzeit erzwingen; Prompttext allein reicht nicht. Ein nicht isolierter gemeinsamer Admin-Executor erfüllt den Vertrag nicht.
Prüfmatrix und Migration
Gemeinsame Testvektoren prüfen Rangmatrix, fehlende/leere Nutzerlisten, unbekannte Rollen/Versionen, persönliche Caps, Kontosperre, Guest und exakte Legacy-Rollen. PHP und Python müssen jedes Ergebnis identisch liefern. Zusätzlich notwendig: falsche App/Aussteller/Verbindung, Revision-Replay, gleichbleibender Rollenname mit Grantentzug, Rollenwechsel während Requests/Streams/Anrufen, zwei unabhängige Fenster, Ablauf und Verbindungsverlust, Browserrückkehr, Tastatur-/Fokussperre und bewusste Wiederfreigabe.
Die Einführung ist additiv: Apps ohne neue Definition behalten ihre bisherigen Beschränkungen. Neue Definitionen werden validiert und registriert; Altrollen, individuelle Verbote und Eigentümerbindungen bleiben zusätzliche Bedingungen. Verbraucher dürfen Konformität erst nach Durchsetzung an Öffnen, Ressourcen, Tools und Fachbackend erklären. Referenztests, Quellintegration, Release/HTTP-Prüfung, echte angemeldete Browserprüfung und MCP-Client-Abnahme werden getrennt protokolliert.
Veröffentlichung: manifest.json nennt Fassung, Dateien und SHA-256. Historische Release-URLs bleiben unverändert. Änderungen erfolgen im kanonischen Content-Git, als neuer geprüfter Release mit atomarem Pointerwechsel und geprüftem Rückweg. Quellbestand: contracts/xp-content/current/access/; die Veröffentlichung bindet diesen Bestand unter xp-contract/access/ ein. Kein direktes Editieren aktiver Releases.