UIAP Web Profile
UIAP Web Profile v0.1
Abschnitt betitelt „UIAP Web Profile v0.1“| Feld | Wert |
|---|---|
| Status | Draft |
| Version | 0.1 |
| Datum | 2026-03-27 |
| Abhängigkeiten | [UIAP-CORE], [UIAP-CAP] |
| Editoren | Patrick |
1. Zweck
Abschnitt betitelt „1. Zweck“UIAP Web Profile v0.1 definiert, wie eine Webanwendung ihren aktuellen, semantisch reduzierten UI-Zustand als PageGraph publiziert, damit ein UIAP-Agent oder eine Runtime:
- die sichtbare UI verstehen kann,
- steuerbare Ziele stabil adressieren kann,
- Laufzeitänderungen als Deltas erhält,
- Feedback-Signale strukturiert beobachten kann,
- Browsergrenzen wie Frames und Shadow DOM korrekt modelliert.
Dieses Profil setzt auf UIAP Core v0.1 und UIAP Capability Model v0.1 auf.
2. Profilkennung
Abschnitt betitelt „2. Profilkennung“Eine Implementierung, die dieses Profil unterstützt, MUSS [email protected] bei session.initialize.supportedProfiles bzw. session.initialized.selectedProfiles verhandeln.
3. Konformitätsklassen
Abschnitt betitelt „3. Konformitätsklassen“3.1 Web Publisher
Abschnitt betitelt „3.1 Web Publisher“Ein Web Publisher ist typischerweise das in der Anwendung laufende SDK oder die Bridge. Er MUSS:
- einen
PageGrapherzeugen können, - Snapshots und Deltas publizieren können,
- Frames und Shadow-DOM-Grenzen korrekt markieren,
- elementbezogene Semantik und Zustände bereitstellen,
- Web-Signale wie Route-Wechsel, Toasts, Validierungsfehler und Fokuswechsel emittieren können.
3.2 Web Consumer
Abschnitt betitelt „3.2 Web Consumer“Ein Web Consumer ist eine Agent-Runtime oder ein Planner. Er MUSS:
- Snapshots und Deltas verarbeiten,
- Revisionen korrekt nachhalten,
- Targets aus
stableId, Scope und Semantik auflösen können, - Opaque Boundaries respektieren.
3.3 Web Bridge
Abschnitt betitelt „3.3 Web Bridge“Eine Web Bridge ist optional. Sie verbindet Parent/Child-Dokumente oder mehrere Sessions, insbesondere bei eingebetteten UIs.
4. Grundprinzipien
Abschnitt betitelt „4. Grundprinzipien“- Das Web-Profil publiziert kein Vollabbild des DOM, sondern einen reduzierten semantischen Graphen.
- Standardmäßig SOLLTEN nur sichtbare und relevante UI-Objekte enthalten sein.
- Stabile App-IDs schlagen flüchtige DOM-Identitäten.
- Semantik schlägt CSS/XPath.
- Cross-Origin- und Closed-Shadow-Boundaries MÜSSEN als echte Grenzen behandelt werden.
- Snapshots MÜSSEN versions- und revisionsfähig sein.
- Deltas MÜSSEN auf eine bekannte Basisrevision verweisen.
5. Datenmodell
Abschnitt betitelt „5. Datenmodell“5.1 Basistypen
Abschnitt betitelt „5.1 Basistypen“type RevisionId = string;type DocumentId = string;type FrameId = string;type ScopeId = string;type ElementInstanceId = string;type StableId = string;type RelationId = string;type SignalId = string;interface DOMRectLike { x: number; y: number; width: number; height: number;}Koordinaten MÜSSEN in CSS-Pixeln relativ zum Top-Level-Viewport angegeben werden.
5.2 PageGraph
Abschnitt betitelt „5.2 PageGraph“interface PageGraph { modelVersion: "0.1";
revision: RevisionId; rootDocumentId: DocumentId;
route?: RouteContext; viewport: ViewportState;
documents: WebDocument[]; scopes: UIScope[]; elements: UIElement[]; relations?: ElementRelation[]; signals?: WebSignal[];
focus?: FocusState; selection?: SelectionState;
metadata?: Record<string, unknown>;}revisionMUSS innerhalb einer Session monoton fortschreiten.documents,scopesundelementsMÜSSEN vollständig für diese Revision gelten.- Ein Snapshot MUSS in sich konsistent sein.
5.3 ViewportState
Abschnitt betitelt „5.3 ViewportState“interface ViewportState { width: number; height: number; scrollX: number; scrollY: number; devicePixelRatio?: number;}5.4 RouteContext
Abschnitt betitelt „5.4 RouteContext“interface RouteContext { routeId?: string; // app-stabil url?: string; pathname?: string; title?: string; params?: Record<string, string>; query?: Record<string, string | string[]>; appState?: Record<string, unknown>;}routeIdSOLLTE vorhanden sein, wenn die App eine stabile Router-Semantik hat.urlDARF fehlen, wenn die Anwendung keine klassische URL-Navigation verwendet.
5.5 WebDocument
Abschnitt betitelt „5.5 WebDocument“type DocumentAccess = | "same-origin" | "bridged" | "opaque";interface WebDocument { documentId: DocumentId; frameId: FrameId; parentFrameId?: FrameId; parentDocumentId?: DocumentId;
access: DocumentAccess; origin?: string; url?: string; title?: string;
readyState?: "loading" | "interactive" | "complete"; bbox?: DOMRectLike; // Frame-Box im Top-Level-Viewport rootScopeId?: ScopeId;
bridgeSessionId?: string; // bei access="bridged" metadata?: Record<string, unknown>;}access="same-origin"bedeutet: Publisher kann den DOM-Inhalt direkt modellieren.access="opaque"bedeutet: nur die Frame-Grenze ist bekannt, der innere Inhalt nicht.access="bridged"bedeutet: der innere Inhalt wird durch eine kooperierende Gegenstelle publiziert.- Für
opaqueDokumente DÜRFEN keine inneren Elemente publiziert werden.
5.6 UIScope
Abschnitt betitelt „5.6 UIScope“Scopes gruppieren UI-Objekte logisch.
type ScopeKind = | "route" | "region" | "form" | "dialog" | "drawer" | "popover" | "menu" | "toolbar" | "tabset" | "tabpanel" | "collection" | "rowgroup" | "iframe-root" | "custom";interface UIScope { scopeId: ScopeId; kind: ScopeKind;
documentId: DocumentId; parentScopeId?: ScopeId;
stableId?: StableId; name?: string; description?: string;
state?: Partial<UIState>; bbox?: DOMRectLike;
metadata?: Record<string, unknown>;}- Jeder
UIScopeMUSS genau einemdocumentIdangehören. - Ein
dialog- oderdrawer-Scope SOLLTEstate.open=truepublizieren, wenn sichtbar. stableIdSOLLTE für wichtige Scopes gesetzt werden.
5.7 UIElement
Abschnitt betitelt „5.7 UIElement“interface UIElement { instanceId: ElementInstanceId; stableId?: StableId;
documentId: DocumentId; scopeId?: ScopeId;
role: UIRole; name?: string; description?: string;
state: UIState; affordances: UIAffordance[]; supportedActions: ActionId[];
bbox?: DOMRectLike; zIndexHint?: number;
textValue?: string; semanticValue?: string | number | boolean | null;
targetHints?: TargetHints; semantics?: WebSemantics; risk?: RiskDescriptor; success?: SuccessSignal[];
metadata?: Record<string, unknown>;}instanceIdMUSS innerhalb einer Revision eindeutig sein.stableIdSOLLTE vorhanden sein, wenn die App das Element absichtlich für Agent-Steuerung exponiert.role,state,affordancesundsupportedActionsMÜSSEN konsistent sein.bboxSOLLTE für sichtbare Elemente vorhanden sein.supportedActionsMUSS nur Actions enthalten, die für dieses Element tatsächlich zulässig sind.
5.8 TargetHints
Abschnitt betitelt „5.8 TargetHints“interface TargetHints { semantic?: { role?: UIRole; name?: string; scopeId?: ScopeId; ordinal?: number; };
annotations?: { meaning?: string; defaultAction?: ActionId; };
runtime?: { css?: string; // lokale Optimierung, nicht kanonisch xpath?: string; // lokale Optimierung, nicht kanonisch };}cssundxpathDÜRFEN nur als lokale Runtime-Hints verwendet werden.cssundxpathDÜRFEN NICHT als interoperable Kernidentität behandelt werden.
5.9 WebSemantics
Abschnitt betitelt „5.9 WebSemantics“type SemanticSource = | "native-html" | "aria" | "label-association" | "visible-text" | "agent-annotation" | "app-registry" | "inferred";interface WebSemantics { sources: SemanticSource[];
tagName?: string; inputType?: string; ariaRole?: string;
shadowHostId?: ElementInstanceId; framePath?: FrameId[];
interactable?: boolean; attached?: boolean; inViewport?: boolean; obscured?: boolean; stable?: boolean;
metadata?: Record<string, unknown>;}sourcesMUSS mindestens eine Quelle enthalten.- Wenn Heuristiken verwendet wurden, MUSS
sourcesden Wertinferredenthalten. attached,inViewport,obscured,stableSOLLTEN publiziert werden, wenn die Runtime später Actionability Checks ausführen soll.
5.10 ElementRelation
Abschnitt betitelt „5.10 ElementRelation“type RelationType = | "contains" | "labels" | "describes" | "controls" | "owns" | "opens" | "submits" | "invokes" | "error-for" | "next" | "previous";interface ElementRelation { relationId: RelationId; type: RelationType; from: ElementInstanceId | ScopeId; to: ElementInstanceId | ScopeId;}5.11 FocusState und SelectionState
Abschnitt betitelt „5.11 FocusState und SelectionState“interface FocusState { documentId: DocumentId; target?: ElementInstanceId;}interface SelectionState { anchorTarget?: ElementInstanceId; focusTarget?: ElementInstanceId; text?: string;}5.12 WebSignal
Abschnitt betitelt „5.12 WebSignal“type WebSignalKind = | "route.changed" | "toast.shown" | "status.changed" | "validation.changed" | "dialog.opened" | "dialog.closed" | "submission.started" | "submission.finished" | "custom";interface WebSignal { signalId: SignalId; kind: WebSignalKind;
documentId?: DocumentId; scopeId?: ScopeId; target?: TargetRef;
level?: "info" | "success" | "warning" | "error"; text?: string; detail?: Record<string, unknown>;}6. Ableitungsregeln für Semantik
Abschnitt betitelt „6. Ableitungsregeln für Semantik“6.1 Rolle
Abschnitt betitelt „6.1 Rolle“Ein Publisher MUSS role wie folgt ableiten:
- aus nativem HTML, wenn die Rolle eindeutig ist,
- aus ARIA, wenn die Anwendung gültige ARIA-Semantik bereitstellt,
- aus expliziter App-Annotierung,
- aus Heuristiken nur als letzter Fallback.
Ein Publisher DARF durch Annotation ergänzen, MUSS aber Widersprüche vermeiden. data-uiap-role="button" auf einem nicht aktivierbaren <div> ist genau die Sorte Lüge, die später in Meetings „Edge Case“ genannt wird.
6.2 Name
Abschnitt betitelt „6.2 Name“Ein Publisher SOLLTE name als zugänglichen Namen des Elements publizieren. Wenn kein belastbarer Accessible Name bestimmbar ist, DARF sichtbarer, benachbarter oder explizit annotierter Text genutzt werden.
6.3 Beschreibung
Abschnitt betitelt „6.3 Beschreibung“description SOLLTE die zugängliche Beschreibung oder eine explizite App-Beschreibung widerspiegeln.
6.4 Zustand
Abschnitt betitelt „6.4 Zustand“state SOLLTE aus nativen Kontrollzuständen, ARIA-States und Laufzeitbeobachtung abgeleitet werden.
6.5 Affordances
Abschnitt betitelt „6.5 Affordances“affordances SOLLTEN aus Rolle, Elementtyp, Zuständen und App-Annotierung abgeleitet werden.
7. Standard-Annotationen für Web-Apps
Abschnitt betitelt „7. Standard-Annotationen für Web-Apps“Das Profil REKOMMENDIERT folgende HTML-Datenattribute:
data-uiap-id="video.submit"data-uiap-scope="create-video-dialog"data-uiap-meaning="use_case"data-uiap-action="video.create"data-uiap-risk="confirm"data-uiap-sensitive="true"Semantik
Abschnitt betitelt „Semantik“data-uiap-id: stabile Ziel-IDdata-uiap-scope: logische Scope-Zuordnungdata-uiap-meaning: Domänenbedeutung eines Feldesdata-uiap-action: fachliche Default-Actiondata-uiap-risk:safe | confirm | blockeddata-uiap-sensitive: sensible Daten oder Controls
- Diese Attribute SIND NICHT verpflichtend.
- Wenn vorhanden, SOLLTEN sie Vorrang vor Heuristiken haben.
- Sie DÜRFEN native und ARIA-Semantik nicht grob widersprechen.
8. Sichtbarkeits- und Inklusionsregeln
Abschnitt betitelt „8. Sichtbarkeits- und Inklusionsregeln“Standardmäßig SOLLTE ein Snapshot enthalten:
- sichtbare interaktive Elemente,
- sichtbare Status- und Feedback-Elemente,
- relevante Container wie Dialoge, Forms, Popovers und Drawer,
- fokussierte Elemente, auch wenn sie gerade nicht sichtbar sind,
- invalidierte oder blockierte Elemente, wenn sie für den aktuellen Flow relevant sind.
Standardmäßig SOLLTE ein Snapshot NICHT enthalten:
- rein dekorative Elemente,
- redundante Textknoten ohne Steuerungsrelevanz,
- versteckte Alt-Zustände vergangener UI-Bäume,
- komplette, unstrukturierte HTML-Fragmente.
9. Frame- und Shadow-DOM-Regeln
Abschnitt betitelt „9. Frame- und Shadow-DOM-Regeln“Same-Origin-Policy beschränkt, wie ein Dokument oder Skript mit Ressourcen oder DOM anderer Origins interagieren kann; deshalb dürfen Cross-Origin-Frames ohne Kooperation nicht einfach ausgelesen werden. Shadow Roots haben einen mode von open oder closed; bei closed sind die internen Knoten von außen per JavaScript nicht zugänglich. UIAP muss diese Grenzen modellieren, statt sie wegzuphantasieren. ([MDN Web Docs][3])
9.1 Same-Origin Frames
Abschnitt betitelt „9.1 Same-Origin Frames“Ein Publisher DARF Inhalte gleichoriginärer Frames direkt als zusätzliche WebDocument-Einträge publizieren.
9.2 Opaque Cross-Origin Frames
Abschnitt betitelt „9.2 Opaque Cross-Origin Frames“Ein Publisher MUSS fremde, nicht kooperierende Frames als access="opaque" publizieren. Dabei DÜRFEN nur Frame-Metadaten und die äußere Bounding Box bekannt sein.
9.3 Bridged Cross-Origin Frames
Abschnitt betitelt „9.3 Bridged Cross-Origin Frames“Ein Publisher DARF einen kooperierenden Cross-Origin-Frame als access="bridged" modellieren. In diesem Fall SOLLTE bridgeSessionId gesetzt sein.
9.4 Open Shadow Roots
Abschnitt betitelt „9.4 Open Shadow Roots“Open Shadow Roots DÜRFEN traversiert werden. Elemente innerhalb eines offenen Shadow Roots SOLLTEN shadowHostId im WebSemantics-Block referenzieren.
9.5 Closed Shadow Roots
Abschnitt betitelt „9.5 Closed Shadow Roots“Closed Shadow Roots MÜSSEN als opaque behandelt werden. Nur der Host und explizit vom Host publizierte Agent-Metadaten DÜRFEN sichtbar sein.
10. Nachrichten des Web-Profils
Abschnitt betitelt „10. Nachrichten des Web-Profils“10.1 web.state.get
Abschnitt betitelt „10.1 web.state.get“Fordert einen Snapshot an.
Request
Abschnitt betitelt „Request“interface WebStateGetPayload { includeHidden?: boolean; // default false includeNonInteractive?: boolean; // default false scopes?: ScopeId[]; documents?: DocumentId[]; maxNodes?: number;}Response: web.state.snapshot
Abschnitt betitelt „Response: web.state.snapshot“interface WebStateSnapshotPayload { graph: PageGraph;}10.2 web.observe.start
Abschnitt betitelt „10.2 web.observe.start“Startet eine Beobachtung.
Request
Abschnitt betitelt „Request“interface WebObserveStartPayload { mode?: "snapshot+delta" | "delta-only"; // default snapshot+delta includeHidden?: boolean; includeNonInteractive?: boolean; throttleMs?: number; // default implementation-defined signals?: WebSignalKind[]; // default all supported}Response: web.observe.started
Abschnitt betitelt „Response: web.observe.started“interface WebObserveStartedPayload { subscriptionId: string; initialRevision?: RevisionId;}- Wenn
mode="snapshot+delta"gesetzt ist, MUSS zuerst einweb.state.snapshotfolgen. - Deltas MÜSSEN auf die zuletzt bekannte Revision referenzieren.
10.3 web.state.delta
Abschnitt betitelt „10.3 web.state.delta“interface WebStateDeltaPayload { subscriptionId: string; revision: RevisionId; baseRevision: RevisionId;
ops: WebDeltaOp[]; signals?: WebSignal[];}type WebDeltaOp = | { op: "upsertDocument"; document: WebDocument } | { op: "removeDocument"; documentId: DocumentId } | { op: "upsertScope"; scope: UIScope } | { op: "removeScope"; scopeId: ScopeId } | { op: "upsertElement"; element: UIElement } | { op: "removeElement"; instanceId: ElementInstanceId } | { op: "setRoute"; route: RouteContext } | { op: "setFocus"; focus?: FocusState } | { op: "setSelection"; selection?: SelectionState };baseRevisionMUSS auf die unmittelbar vorherige bekannte Revision verweisen.- Bei Revisionslücke MUSS der Consumer einen neuen Snapshot anfordern.
- Ein Delta DARF keine Operation enthalten, die auf unbekannte Dokumente oder Scopes verweist.
10.4 web.signal
Abschnitt betitelt „10.4 web.signal“interface WebSignalPayload { signal: WebSignal;}Diese Nachricht DARF zusätzlich zu Deltas verwendet werden, wenn Signale zeitkritisch sind.
10.5 web.observe.stop
Abschnitt betitelt „10.5 web.observe.stop“Request
Abschnitt betitelt „Request“interface WebObserveStopPayload { subscriptionId: string;}Response: web.observe.stopped
Abschnitt betitelt „Response: web.observe.stopped“interface WebObserveStoppedPayload { subscriptionId: string;}11. Web-spezifische Publisher-Regeln
Abschnitt betitelt „11. Web-spezifische Publisher-Regeln“Ein konformer Web Publisher MUSS:
- mindestens einen Snapshot publizieren können,
- Elemente mit
role,state,affordancesundsupportedActionspublizieren, documentId,scopeIdundinstanceIdsauber verwalten,- Revisionswechsel monoton publizieren,
- Opaque Boundaries korrekt markieren.
Ein Web Publisher SOLLTE:
- DOM-Änderungen in Deltas übersetzen,
- Route-Wechsel signalisieren,
- Fokus und Validierung publizieren,
- stabile
data-uiap-*-Annotationen unterstützen.
12. Minimalbeispiel web.state.snapshot
Abschnitt betitelt „12. Minimalbeispiel web.state.snapshot“{ "uiap": "0.1", "kind": "response", "type": "web.state.snapshot", "id": "msg_42", "correlationId": "msg_41", "sessionId": "sess_123", "ts": "2026-03-26T14:00:00.000Z", "source": { "role": "app", "id": "videoland-web-sdk" }, "payload": { "graph": { "modelVersion": "0.1", "revision": "rev_19", "rootDocumentId": "doc_root", "route": { "routeId": "videos.new", "url": "https://app.example.com/videos/new", "pathname": "/videos/new", "title": "Neues Video" }, "viewport": { "width": 1440, "height": 900, "scrollX": 0, "scrollY": 180 }, "documents": [ { "documentId": "doc_root", "frameId": "frame_root", "access": "same-origin", "url": "https://app.example.com/videos/new", "title": "Neues Video", "readyState": "complete", "rootScopeId": "scope_page" } ], "scopes": [ { "scopeId": "scope_page", "kind": "route", "documentId": "doc_root", "stableId": "videos.new", "name": "Neues Video" }, { "scopeId": "scope_form", "kind": "form", "documentId": "doc_root", "parentScopeId": "scope_page", "stableId": "video.create.form", "name": "Video erstellen" } ], "elements": [ { "instanceId": "el_title", "stableId": "video.title", "documentId": "doc_root", "scopeId": "scope_form", "role": "textbox", "name": "Titel", "state": { "visible": true, "enabled": true, "required": true }, "affordances": ["read", "focus", "edit"], "supportedActions": ["ui.focus", "ui.enterText", "ui.clearText"], "bbox": { "x": 120, "y": 220, "width": 480, "height": 40 }, "semantics": { "sources": ["native-html", "label-association"], "tagName": "input", "inputType": "text", "attached": true, "inViewport": true, "obscured": false, "stable": true } }, { "instanceId": "el_submit", "stableId": "video.submit", "documentId": "doc_root", "scopeId": "scope_form", "role": "button", "name": "Video erstellen", "state": { "visible": true, "enabled": true }, "affordances": ["read", "focus", "activate", "invoke"], "supportedActions": ["ui.focus", "ui.activate", "video.create"], "bbox": { "x": 120, "y": 420, "width": 180, "height": 40 }, "risk": { "level": "confirm", "tags": ["external_effect"] }, "success": [ { "kind": "route.changed", "pattern": "/videos/:id" }, { "kind": "toast.contains", "text": "erstellt" } ], "semantics": { "sources": ["native-html", "visible-text", "agent-annotation"], "tagName": "button", "attached": true, "inViewport": true, "obscured": false, "stable": true } } ] } }}Normative Referenzen
Abschnitt betitelt „Normative Referenzen“- [UIAP-CORE] UIAP Core v0.1
- [UIAP-CAP] UIAP Capability Model v0.1
- [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
Security Considerations
Abschnitt betitelt „Security Considerations“- PageGraph-Snapshots KÖNNEN sensitive Daten enthalten (Formularwerte, Benutzernamen). Implementierungen SOLLTEN PII vor der Übertragung redaktieren oder maskieren.
- Cross-Origin-Frames MÜSSEN als
opaquebehandelt werden, wenn keine explizite Bridge besteht. - Same-Origin-Policy und CSP-Regeln der Host-Anwendung MÜSSEN respektiert werden.
- Bounding-Box-Daten SOLLTEN nicht für Fingerprinting missbraucht werden.
Changelog
Abschnitt betitelt „Changelog“| Version | Datum | Änderungen |
|---|---|---|
| 0.1 | 2026-03-27 | Initialer Entwurf |