UIAP SDK API
UIAP SDK API v0.1
Abschnitt betitelt „UIAP SDK API v0.1“| Feld | Wert |
|---|---|
| Status | Draft |
| Version | 0.1 |
| Datum | 2026-03-27 |
| Abhängigkeiten | [UIAP-CORE], [UIAP-WEB] |
| Editoren | Patrick |
1. Zweck
Abschnitt betitelt „1. Zweck“UIAP SDK API v0.1 definiert die Einbau- und Laufzeit-API für Web-Anwendungen, die:
- einen
PageGraphpublizieren, - Actions registrieren,
- Policy lokal auswerten,
- Signale emittieren,
- Frame-Bridges betreiben,
- optionale Präsentation wie Overlay/Ghost Cursor rendern.
Das SDK ist der First-Party-Layer in der App. Genau dort gehört die Kontrolle hin, weil CSP externe Skripte begrenzen kann und die Same-Origin-Policy direkten DOM-Zugriff über Origins einschränkt. Für Cross-Origin-Kommunikation ist postMessage() der richtige Bridge-Mechanismus. ([MDN Web Docs][3])
Normative Begriffe
Abschnitt betitelt „Normative Begriffe“Die Schlüsselwörter MUSS, DARF NICHT, SOLLTE, KANN in diesem Dokument sind normativ gemäss RFC 2119 und BCP 14 zu interpretieren, wenn und nur wenn sie in GROSSBUCHSTABEN erscheinen.
2. Packaging und Installationsmodi
Abschnitt betitelt „2. Packaging und Installationsmodi“2.1 Empfohlene Pakete
Abschnitt betitelt „2.1 Empfohlene Pakete“package "@uiap/web-sdk"package "@uiap/web-sdk/overlay"package "@uiap/web-sdk/frame-bridge"2.2 Installationsmodi
Abschnitt betitelt „2.2 Installationsmodi“-
ESM / npm / first-party bundle Empfohlen für produktive Apps.
-
CDN script Nur wenn
script-srcdas erlaubt. -
Frame bridge Für kooperierende Child-/Parent-Kontexte via
postMessage(). -
External driver adapter Optional für Out-of-Process-Steuerung via WebDriver oder WebDriver BiDi. ([MDN Web Docs][3])
3. Top-Level API
Abschnitt betitelt „3. Top-Level API“interface UIAPConfig { app: { id: string; version: string; locale?: string; };
transport: UIAPTransport;
observe?: ObserveConfig; policy?: SDKPolicyConfig | false; overlay?: OverlayConfig | false; frames?: FrameConfig | false; annotations?: AnnotationConfig; debug?: boolean | "info" | "warn" | "error";}interface UIAPClient { start(): Promise<void>; stop(): Promise<void>; destroy(): Promise<void>;
getSnapshot(input?: SnapshotOptions): Promise<PageGraph>; publishSnapshot(input?: SnapshotOptions): Promise<PageGraph>; emitSignal(signal: WebSignal): void;
registerAction(descriptor: ActionDescriptor, handler: ActionHandler): Unsubscribe; unregisterAction(actionId: ActionId): void;
registerElementAdapter(adapter: UIAPElementAdapter): Unsubscribe; registerPolicyEvaluator(evaluator: SDKPolicyEvaluator): Unsubscribe;
bindElement(node: Element, binding: ElementBinding): Unsubscribe; bindScope(node: Element, binding: ScopeBinding): Unsubscribe;
setRouteProvider(provider: RouteProvider): void; createFrameBridge(options: FrameBridgeOptions): FrameBridge;
on<T = unknown>(event: SDKEventName, listener: (payload: T) => void): Unsubscribe;
overlay?: OverlayController;}type Unsubscribe = () => void;4. Transport API
Abschnitt betitelt „4. Transport API“interface UIAPTransport { send(message: UIAPEnvelope): Promise<void> | void; close?(): Promise<void> | void; onMessage(listener: (message: UIAPEnvelope) => void): Unsubscribe; onError?(listener: (error: unknown) => void): Unsubscribe;}- Das SDK MUSS transport-agnostisch bleiben.
- Ein Transport MUSS Nachrichten in UIAP-Core-Envelopes liefern.
- Das SDK DARF mehrere Transports adaptieren, solange genau einer pro aktiver Session write-primary ist.
5. State Collection API
Abschnitt betitelt „5. State Collection API“Das SDK SOLLTE Rollen, Namen, Beschreibungen und Zustände aus Web-Semantik ableiten, nicht aus bloßer Pixel-Magie. Browser erzeugen einen Accessibility Tree mit Name, Rolle, Beschreibung und Zustand; aria-label und aria-labelledby sind zentrale Quellen für Accessible Names. Für Laufzeitänderungen ist MutationObserver das native Werkzeug. ([MDN Web Docs][4])
interface ObserveConfig { root?: Document | ShadowRoot; includeHidden?: boolean; // default false includeNonInteractive?: boolean; // default false throttleMs?: number; // default 100 maxNodes?: number; // default implementation-defined signals?: WebSignalKind[]; // default supported set}interface SnapshotOptions { scopes?: ScopeId[]; documents?: DocumentId[]; includeHidden?: boolean; includeNonInteractive?: boolean;}- Das SDK MUSS mindestens einen Snapshot erzeugen können.
- Das SDK SOLLTE Deltas aus DOM-/State-Änderungen ableiten.
- Das SDK MUSS Bounding Boxes, Fokus und sichtbare Interaktionszustände aktualisieren können.
- Das SDK SOLLTE Route-, Dialog-, Toast- und Validierungssignale erkennen oder von der App entgegennehmen.
6. Annotation API
Abschnitt betitelt „6. Annotation API“interface ElementBinding { id: StableId; scopeId?: ScopeId; meaning?: string; name?: string; defaultAction?: ActionId; risk?: RiskLevel; sensitive?: boolean; success?: SuccessSignal[]; metadata?: Record<string, unknown>;}interface ScopeBinding { id: ScopeId; kind: ScopeKind; parentScopeId?: ScopeId; name?: string; metadata?: Record<string, unknown>;}bindElement()undbindScope()SOLLTEN die entsprechendendata-uiap-*-Metadaten spiegeln oder intern registrieren.- Explizite Bindings MÜSSEN Heuristiken schlagen.
- Ein SDK DARF Bindings sowohl über DOM-Attribute als auch über in-memory Registry führen.
Empfohlene HTML-Attribute
Abschnitt betitelt „Empfohlene HTML-Attribute“data-uiap-id="video.submit"data-uiap-scope="video.create.form"data-uiap-meaning="use_case"data-uiap-action="video.create"data-uiap-risk="confirm"data-uiap-sensitive="true"data-uiap-ignore="true"7. Action Registry API
Abschnitt betitelt „7. Action Registry API“interface ActionHandlerContext { actionHandle: string; action: ActionDescriptor; target?: ResolvedTarget; args: Record<string, unknown>; snapshot: PageGraph;
policy?: PolicyDecision;
emitSignal(signal: WebSignal): void; requestConfirmation(input: ActionConfirmationRequestPayload): Promise<"granted" | "denied">; waitForUser(note: string): Promise<void>;
overlay?: OverlayController;}type ActionHandlerResult = | { status: "succeeded"; returnValue?: Record<string, unknown>; sideEffectState?: "none" | "applied" | "unknown"; verification?: VerificationOutcome; } | { status: "failed"; error: RuntimeErrorDescriptor; sideEffectState?: "none" | "applied" | "unknown"; };type ActionHandler = (ctx: ActionHandlerContext) => Promise<ActionHandlerResult>;registerAction()MUSS Domain Actions und primitive Actions unterstützen.- Für registrierte Domain Actions SOLLTE
appActionbevorzugt werden. - Handler MÜSSEN
sideEffectStatekorrekt setzen. - Nicht-idempotente Handler SOLLTEN keine stillen Retries ausführen.
8. Policy Hook API
Abschnitt betitelt „8. Policy Hook API“interface SDKPolicyConfig { mode?: "local-only" | "delegated" | "hybrid"; // default hybrid document?: PolicyDocument;}type SDKPolicyEvaluator = (context: PolicyContext) => Promise<PolicyDecision> | PolicyDecision;local-only: Entscheidung ausschließlich im SDKdelegated: Entscheidung an externe Policy-Gegenstellehybrid: lokale Preflight-Regeln plus optionale Delegation
Durchsetzungsregeln
Abschnitt betitelt „Durchsetzungsregeln“- Das SDK MUSS vor jeder Action mindestens eine Policy-Entscheidung haben.
- Eine lokale
deny-Entscheidung MUSS final sein. confirmMUSS in den Runtime-Confirmation-Flow überführt werden.handoffMUSSwaitForUser()oder äquivalente UX auslösen.
Das SDK SOLLTE bei requireUserActivation den Browserzustand berücksichtigen. navigator.userActivation macht diesen Zustand abfragbar; genau deshalb gehört diese Prüfung lokal ins SDK und nicht erst in irgendein spätes Backend-Orakel. ([MDN Web Docs][2])
9. Element Adapter API
Abschnitt betitelt „9. Element Adapter API“Für komplexe Widgets, Design-System-Komponenten und freundliche Frontend-Exzesse, die visuell wie Controls aussehen, semantisch aber halbe Kunstinstallationen sind, braucht das SDK Adapter.
interface UIAPElementAdapter { id: string;
match(node: Element): boolean;
describe( node: Element, ctx: { route?: RouteContext; scopeId?: ScopeId; } ): Partial<UIElement> | null;
execute?( node: Element, request: ActionRequestPayload, ctx: ActionHandlerContext ): Promise<ActionHandlerResult | null>;}- Adapter SOLLTEN vor generischen Heuristiken laufen.
- Adapter DÜRFEN zusätzliche Semantik und Actions publizieren.
- Adapter SOLLTEN für Custom Components und Open Shadow Roots genutzt werden.
Open und closed Shadow Roots müssen unterschiedlich behandelt werden: offene Roots können vom Skript traversiert werden, geschlossene nicht. Für closed Shadow DOM braucht ihr deshalb entweder Host-seitige Bindings oder explizite Adapter auf dem Host, statt zu hoffen, dass JavaScript plötzlich Gedanken lesen lernt. ([MDN Web Docs][5])
10. Route Provider API
Abschnitt betitelt „10. Route Provider API“interface RouteProvider { getRoute(): RouteContext; subscribe?(listener: (route: RouteContext) => void): Unsubscribe;}- Das SDK SOLLTE einen App-spezifischen
routeIdbevorzugen. - Wenn kein Provider gesetzt ist, DARF das SDK URL-basierte Fallbacks nutzen.
11. Signal API
Abschnitt betitelt „11. Signal API“interface SignalEmitter { emitSignal(signal: WebSignal): void;}Empfohlene Signale
Abschnitt betitelt „Empfohlene Signale“route.changedtoast.shownstatus.changedvalidation.changeddialog.openeddialog.closedsubmission.startedsubmission.finished
App-interne DOM-Hooks
Abschnitt betitelt „App-interne DOM-Hooks“Das SDK SOLLTE zusätzlich DOM-seitige Integrationspunkte über CustomEvent anbieten, weil CustomEvent.detail App-Daten sauber mittransportieren kann. ([MDN Web Docs][6])
Empfohlene Events:
uiap:readyuiap:snapshotuiap:signaluiap:action-requestuiap:action-resultuiap:policy-decision
12. Frame Bridge API
Abschnitt betitelt „12. Frame Bridge API“Cross-Origin-DOM bleibt durch die Same-Origin-Policy begrenzt. Wenn Parent und Child zusammenarbeiten sollen, muss die Bridge deshalb auf Messaging beruhen, nicht auf direktem DOM-Zugriff. window.postMessage() ist dafür der native Mechanismus. ([MDN Web Docs][7])
interface FrameConfig { enabled?: boolean; channel?: string; // default "uiap"}interface FrameBridgeOptions { mode: "parent" | "child"; targetWindow: Window; targetOrigin: string; channel?: string;}interface FrameBridge { connect(): void; disconnect(): void; send(message: UIAPEnvelope): void;}targetOriginMUSS explizit gesetzt werden.- Eine Bridge MUSS eingehende
originundchannelprüfen. - Cross-Origin-Frames ohne Bridge MÜSSEN als
opaquebehandelt werden. - Bridged Frames SOLLTEN eine eigene
documentIdund optionalbridgeSessionIdpublizieren.
13. Overlay API
Abschnitt betitelt „13. Overlay API“interface OverlayConfig { ghostCursor?: boolean; highlightStyle?: "outline" | "spotlight" | "pulse"; narration?: boolean; zIndex?: number;}interface OverlayController { showCursor(target: ResolvedTarget, options?: { pace?: "instant" | "humanized" }): void; highlight(target: ResolvedTarget, options?: { style?: "outline" | "spotlight" | "pulse" }): void; announce(text: string): void; clear(): void;}- Overlay ist Präsentation, nicht Wahrheit.
- Overlay DARF nie Erfolg vortäuschen, wenn
action.resultfehlt. ghostCursorSOLLTE einen separaten visuellen Cursor verwenden.
14. Externe Driver
Abschnitt betitelt „14. Externe Driver“interface ExternalDriverAdapter { execute( request: ActionRequestPayload, target: ResolvedTarget | undefined ): Promise<ActionHandlerResult>;}Für Out-of-Process-Automation DARF das SDK einen Driver-Adapter verwenden, der auf WebDriver oder WebDriver BiDi aufsetzt. Wichtig ist nur, dass der UIAP-Lifecycle gleich bleibt: gleiche Policy, gleiche Verification, gleiche Fehlerklassen. ([W3C][8])
15. SDK-Events
Abschnitt betitelt „15. SDK-Events“type SDKEventName = | "ready" | "snapshot" | "signal" | "action:accepted" | "action:progress" | "action:result" | "policy:decision" | "error";16. Minimaler Konformitätsumfang
Abschnitt betitelt „16. Minimaler Konformitätsumfang“Ein konformes @uiap/web-sdk MUSS:
createUIAP()oder äquivalente Initialisierung anbieten,- Snapshots publizieren können,
- mindestens
registerAction,registerPolicyEvaluator,bindElement,bindScope,emitSignalunterstützen, - lokale Policy-Entscheidungen durchsetzen,
- offene/geschlossene Shadow-Boundaries korrekt behandeln,
- opaque Cross-Origin-Kontexte korrekt als unzugänglich markieren,
- Action- und Policy-Lifecycle-Events emittieren.
Ein konformes SDK SOLLTE:
- Deltas publizieren,
MutationObservernutzen,CustomEvent-Hooks anbieten,postMessage-Frame-Bridges unterstützen,- Overlay optional anbieten.
17. Referenz-Initialisierung
Abschnitt betitelt „17. Referenz-Initialisierung“import { createUIAP } from "@uiap/web-sdk";
const uiap = createUIAP({ app: { id: "videoland", version: "1.4.2", locale: "de-CH" },
transport: myTransport,
observe: { throttleMs: 120, includeHidden: false, includeNonInteractive: false },
policy: { mode: "hybrid", document: { modelVersion: "0.1", extension: "uiap.policy", defaults: { onSafeRisk: "allow", onConfirmRisk: "confirm", onBlockedRisk: "handoff", onUnknownAction: "deny", onSensitiveRead: "confirm", onSecretRead: "deny" }, rules: [] } },
overlay: { ghostCursor: true, highlightStyle: "spotlight", narration: true }});
uiap.bindScope(document.querySelector("[data-form='video-create']")!, { id: "video.create.form", kind: "form", name: "Video erstellen"});
uiap.bindElement(document.querySelector("#title")!, { id: "video.title", scopeId: "video.create.form", meaning: "title"});
uiap.bindElement(document.querySelector("#submit")!, { id: "video.submit", scopeId: "video.create.form", defaultAction: "video.create", risk: "confirm", success: [ { kind: "route.changed", pattern: "/videos/:id" }, { kind: "toast.contains", text: "erstellt" } ]});
uiap.registerAction( { id: "video.create", kind: "domain", targetKinds: ["scope"], executionModes: ["appAction", "semanticUi"], risk: { level: "confirm", tags: ["external_effect"] } }, async (ctx) => { const granted = await ctx.requestConfirmation({ actionHandle: ctx.actionHandle, actionId: "video.create", risk: { level: "confirm", tags: ["external_effect"] }, preview: { summary: "Video erstellen" } });
if (granted !== "granted") { return { status: "failed", sideEffectState: "none", error: { code: "confirmation_denied", message: "Aktion wurde nicht bestätigt" } }; }
// fachliche App-Aktion await app.actions.createVideo();
ctx.emitSignal({ signalId: "sig_1", kind: "toast.shown", level: "success", text: "Video erstellt" });
return { status: "succeeded", sideEffectState: "applied" }; });
uiap.registerPolicyEvaluator((context) => { if (context.dataClasses?.includes("credential")) { return { decision: "handoff", reasonCodes: ["credential_data", "human_actor_required"] }; }
if (context.risk?.level === "confirm") { return { decision: "confirm", reasonCodes: ["risk_confirm"] }; }
return { decision: "allow", reasonCodes: ["policy_default"] };});
await uiap.start();Normative Referenzen
Abschnitt betitelt „Normative Referenzen“- [UIAP-CORE] UIAP Core v0.1
- [UIAP-WEB] UIAP Web Profile v0.1
- [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
Security Considerations
Abschnitt betitelt „Security Considerations“- Das SDK MUSS im gleichen Origin-Kontext wie die Host-Anwendung laufen; externe Skript-Injection DARF NICHT ermöglicht werden.
- Transport-Credentials DÜRFEN NICHT im Client-seitigen Code hardcodiert werden.
targetOriginbei Frame-Bridges MUSS explizit gesetzt werden, niemals"*".- Policy-Evaluatoren MÜSSEN lokal ausgeführt werden, bevor Actions an den Transport übergeben werden.
- Overlay-Elemente DÜRFEN keine echten UI-Elemente der Host-Anwendung verdecken oder Klicks abfangen.
Changelog
Abschnitt betitelt „Changelog“| Version | Datum | Änderungen |
|---|---|---|
| 0.1 | 2026-03-27 | Initialer Entwurf |