Zum Inhalt springen

UIAP Agent Cognition

FeldWert
StatusDraft
Version0.1
Datum2026-03-29
AbhängigkeitenUIAP Core
EditorenPatrick

Diese Spezifikation erweitert UIAP um einen read-only Cognition Layer für Agenten.

UIAP Agent Cognition v0.1 definiert:

  • ein globales Entity-Schema als Datenmodell
  • einen Scope Context für aktuell sichtbare oder explizit freigegebene Datensätze
  • eine Navigation Map zur räumlichen Orientierung in der App
  • einen optionalen, begrenzten Scope Query-Mechanismus
  • eine standardisierte Entity-Referenz, die von Action-/Runtime-Spezifikationen weiterverwendet werden KANN

UIAP Agent Cognition v0.1 definiert nicht:

  • Mutationen auf Daten
  • direkte Datenbank- oder Backend-Zugriffe
  • freie, ungebundene Ad-hoc-Queries
  • relationale Joins über mehrere Entity-Typen
  • Action-Ausführungssemantik im Detail

Mutationen bleiben Sache von UI-Actions oder anderer dafür definierter Spezifikationen. Diese Erweiterung liefert nur zusätzlichen, kontrollierten Kontext.

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.

  1. Read-only by design. Agent Cognition liefert Kontext, keine Mutation.
  2. Schema global, Records restriktiv. Das Entity-Schema DARF session-weit bekannt sein; konkrete Datensätze SOLLTEN standardmässig nur im aktuellen Scope geliefert werden.
  3. Sicherer Default. Wenn nichts anderes deklariert ist, gilt für Datensätze recordAccess = "visible_only".
  4. UI-gebunden. Agent Cognition ergänzt das UI-Verständnis; es ersetzt keine App-API.
  5. App-kontrolliert. Die App entscheidet, welche Schemas, Felder, Counts und Datensätze verfügbar sind.
  6. Progressive Enhancement. Schema, Navigation, Context und Query KÖNNEN unabhängig voneinander bereitgestellt werden.
  7. Keine versteckte Voll-API. Scope Queries MÜSSEN begrenzt, read-only und an Scope oder Route gebunden bleiben.

Das Entity Schema beschreibt, welche Business-Objekte die App kennt und welche Felder diese Objekte haben.

Beispiele:

  • contact
  • deal
  • member
  • activity

Das Schema beschreibt Struktur, nicht notwendigerweise sichtbare Werte.

Der Scope Context beschreibt, welche Entitäten im aktuellen Scope relevant sind. Ein Scope KANN zum Beispiel sein:

  • eine Route wie /contacts
  • eine Liste wie contacts-list
  • ein eingebetteter Bereich wie dashboard-deals

Der Scope Context enthält standardmässig nur Datensätze, die im aktuellen Scope sichtbar oder explizit freigegeben sind.

Die Navigation Map beschreibt, wo in der App welche Entity-Typen typischerweise leben und wie ein Agent dorthin gelangt.

Sie ist eine Orientierungshilfe, keine Mutation.

Ein Scope Query ist ein optionaler, begrenzter Mechanismus, um innerhalb eines deklarierten Scopes oder einer Route weitere Datensätze lesen zu dürfen.

Ein Scope Query ist:

  • read-only
  • begrenzt
  • policy-kontrolliert
  • scope- oder route-gebunden

Ein Scope Query ist NICHT:

  • ein allgemeiner Datenbankzugriff
  • eine freie Query-Sprache
  • eine Join-Engine
type EntityType = string; // z. B. "contact" oder "deal"
type EntityId = string; // app-definiert, innerhalb des EntityType eindeutig
type FieldName = string; // z. B. "name", "company", "status"
type ScopeId = string; // z. B. "contacts-list"
type RouteId = string; // z. B. "contacts"
type Revision = string; // app-definiert für Change Detection
type CognitionSurface = "schema" | "navigation" | "context";
type RecordAccessMode =
| "visible_only" // nur aktuell sichtbare Datensätze
| "scope_window" // aktueller logischer Listenbereich / Fenster
| "queryable"; // begrenzte read-only Queries erlaubt
type FieldType =
| "string"
| "number"
| "boolean"
| "date"
| "datetime"
| "enum"
| "currency"
| "email"
| "phone"
| "url"
| "json";
type FieldExposure =
| "readable" // Werte DÜRFEN geliefert werden
| "redacted" // Werte KÖNNEN maskiert oder ausgelassen werden
| "declared_only"; // Feld ist Teil des Schemas, Werte DÜRFEN nicht geliefert werden
type RecordSource =
| "visible"
| "scope_window"
| "query";
type FilterOp =
| "eq"
| "neq"
| "in"
| "contains"
| "starts_with"
| "gt"
| "gte"
| "lt"
| "lte"
| "exists";
interface EntityRef {
type: EntityType;
id: EntityId;
stableId?: string; // optionaler UI-Bezug, falls vorhanden
primaryText?: string; // z. B. "Elena Rossi"
}
interface EntityFieldSchema {
type: FieldType;
label?: string;
description?: string;
enumValues?: string[];
exposure?: FieldExposure; // Default: "readable"
searchable?: boolean;
sortable?: boolean;
}
interface EntityRelation {
field: FieldName; // z. B. "contactId"
targetEntity: EntityType; // z. B. "contact"
kind: "belongs_to" | "has_one" | "has_many" | string;
}

relations sind in v0.1 primär semantische Deklarationen. Sie beschreiben, dass ein Feld auf eine andere Entity verweist, definieren aber keine eigene Traversal-Sprache.

interface EntitySchema {
label?: string;
primaryField?: FieldName;
recordAccess?: RecordAccessMode; // Default: "visible_only"
fields: Record<FieldName, EntityFieldSchema>;
relations?: EntityRelation[];
actions?: string[]; // semantische oder konkrete Action-IDs
}
interface EntitySchemaDocument {
revision?: Revision;
entities: Record<EntityType, EntitySchema>;
}
interface EntityRecord {
ref: EntityRef;
fields: Record<FieldName, unknown>;
redactions?: Record<FieldName, "masked" | "withheld" | "omitted">;
source: RecordSource;
actions?: string[];
}
interface SortSpec {
field: FieldName;
direction?: "asc" | "desc"; // Default: "asc"
}
interface FilterSpec {
field: FieldName;
op: FilterOp;
value?: string | number | boolean | Array<string | number | boolean>;
}
interface ScopeCollection {
entity: EntityType;
access: RecordAccessMode;
visibleCount: number; // Anzahl aktuell sichtbarer Datensätze im Scope
totalCount?: number; // optional; nur wenn die App dies freigibt
offset?: number; // bei virtuellen Listen/Fenstern
limit?: number; // bei virtuellen Listen/Fenstern
hasMore?: boolean;
filters?: FilterSpec[];
sort?: SortSpec[];
items: EntityRecord[];
}
interface ScopeContext {
revision?: Revision;
scopeId: ScopeId;
routeId?: RouteId;
routePath?: string;
routeLabel?: string;
collections: ScopeCollection[];
}
interface RouteActivation {
kind: "path" | "action" | "app_defined";
value: string; // z. B. "/contacts" oder "nav.contacts.open"
}
interface NavigationRoute {
id: RouteId;
path: string; // z. B. "/contacts" oder "/contacts/:id"
label?: string;
entities?: EntityType[];
capabilities?: string[];
activation?: RouteActivation;
}
interface NavigationMap {
revision?: Revision;
routes: NavigationRoute[];
}

Die Navigation Map ist deskriptiv. Sie definiert keinen eigenen Mutations- oder Navigationskanal.

Wenn ein Agent zu einer Route wechseln will, SOLLTE dies über die bestehende Action Runtime erfolgen.

Empfohlene Zuordnung:

  • activation.kind = "path" → der Consumer SOLLTE eine bestehende Navigations-Action ausführen, typischerweise nav.navigate, und dabei die Route über NavigationRoute.id, NavigationRoute.path oder eine app-definierte Runtime-Bindung adressieren.
  • activation.kind = "action" → der Consumer SOLLTE die in activation.value referenzierte deklarierte Action über action.request ausführen.
  • activation.kind = "app_defined" → die konkrete Ausführung ist app-spezifisch und DARF nur erfolgen, wenn eine passende deklarierte Capability oder Action vorhanden ist.

Agent Cognition definiert bewusst keinen separaten Nachrichtentyp wie uiap.cognition.navigate.

interface CognitionBootstrap {
revision?: Revision;
schema?: EntitySchemaDocument;
navigation?: NavigationMap;
context?: ScopeContext;
}

Agent Cognition unterscheidet klar zwischen:

  • Schema-Wissen: Welche Entitäten und Felder existieren?
  • Record-Wissen: Welche konkreten Datensätze und Feldwerte sind aktuell verfügbar?

Diese beiden Ebenen MÜSSEN getrennt betrachtet werden.

Wenn eine App nichts anderes deklariert, gilt:

  • Das Schema DARF vollständig geliefert werden.
  • Datensätze DÜRFEN nur im aktuellen Scope und nur sichtbar geliefert werden.
  • recordAccess ist implizit visible_only.
  • Nur aktuell sichtbare Datensätze DÜRFEN geliefert werden.
  • Querying ausserhalb des sichtbaren Bereichs DARF NICHT erfolgen.
  • Ein Agent SOLLTE in diesem Fall die Navigation Map nutzen, um zur relevanten Route oder Liste zu wechseln.
  • Die App DARF zusätzlich zum sichtbaren Viewport einen begrenzten logischen Listenbereich liefern.
  • Typische Fälle sind Virtualisierung, Paginierung oder Lazy Loading.
  • Filterung ausserhalb der bereits deklarierten Scope-Logik DARF NICHT frei erfolgen.
  • Die App DARF begrenzte read-only Queries erlauben.
  • Queries MÜSSEN an Scope oder Route gebunden sein.
  • Queries MÜSSEN Limits, Redaction und Policy-Regeln respektieren.

Diese Spezifikation verwendet die Extension-ID:

"uiap.cognition"

Extension-spezifische Handshake-Daten werden im Envelope-Feld ext transportiert.

interface CognitionInitializeExt {
bootstrapDelivery?: "inline" | "deferred" | "none";
requestedSurfaces?: CognitionSurface[]; // Default: ["schema", "navigation", "context"]
requestedQuery?: boolean; // Default: false
}
interface CognitionInitializedExt {
bootstrapDelivery: "inline" | "deferred" | "none";
enabledSurfaces: CognitionSurface[];
queryEnabled?: boolean;
maxQueryLimit?: number; // empfohlen: <= 50
bootstrap?: CognitionBootstrap; // nur bei bootstrapDelivery="inline"
}
  1. Wenn uiap.cognition nicht ausgehandelt wurde, DÜRFEN keine uiap.cognition.*-Nachrichten verarbeitet werden.
  2. Wenn bootstrapDelivery = "inline" gewählt wird, DARF bootstrap direkt in session.initialized.ext["uiap.cognition"] enthalten sein.
  3. Wenn bootstrapDelivery = "deferred" gewählt wird, SOLLTE der Agent uiap.cognition.bootstrap.get verwenden.
  4. requestedSurfaces SOLLTEN standardmässig ["schema", "navigation", "context"] bedeuten, wenn sie fehlen.
  5. queryEnabled MUSS explizit true sein, bevor uiap.cognition.query verwendet werden DARF.

Fordert Cognition-Daten nachgelagert an.

interface CognitionBootstrapGetPayload {
include?: CognitionSurface[]; // Default: alle aktivierten Surfaces
}
interface CognitionBootstrapPayload extends CognitionBootstrap {}
  • Wenn include fehlt, MÜSSEN alle aktivierten Surfaces geliefert werden.
  • Nicht aktivierte Surfaces DÜRFEN NICHT geliefert werden.
  • Wenn ausschliesslich nicht aktivierte Surfaces angefordert werden, MUSS error mit code="capability_unavailable" oder einem namespaced Cognition-Fehler zurückgegeben werden.

Meldet geänderte Cognition-Daten.

interface CognitionChangedPayload {
revision: Revision;
changed: CognitionSurface[];
reason?: "route_change" | "data_change" | "selection_change" | "configuration" | string;
bootstrap: CognitionBootstrap;
}
  • In v0.1 MUSS uiap.cognition.changed für jede in changed genannte Surface ein vollständiges Ersatzobjekt liefern.
  • Empfänger SOLLTEN die betroffenen Surfaces vollständig ersetzen.
  • uiap.cognition.changed ist für coarse-grained semantische Änderungen bestimmt, nicht für hochfrequente UI-Churn auf Elementebene.
  • Feingranulare UI-Änderungen SOLLTEN weiterhin primär über web.state.delta oder andere profilspezifische Delta-Mechanismen laufen.
  • Publisher SOLLTEN mehrere feingranulare Änderungen zusammenfassen und uiap.cognition.changed nur emittieren, wenn sich Schema, Navigation oder Scope Context semantisch relevant geändert haben.
  • Bei grossen Collections SOLLTEN context.collections[].items auf den aktuell sichtbaren oder deklarierten Fensterbereich begrenzt bleiben.
  • Query-Ergebnisse gelten in v0.1 als transiente Antwortdaten und MÜSSEN nicht automatisch über uiap.cognition.changed erneut publiziert werden.
  • Typische Auslöser sind Route-Wechsel, Filter-/Sortierwechsel, Collection-Mitgliedschaftsänderungen oder Konfigurationswechsel.

Hinweis: Delta-basierte Cognition-Updates KÖNNEN in einer späteren Version als separater Nachrichtentyp ergänzt werden.


Führt eine begrenzte read-only Query innerhalb eines Scopes oder einer Route aus.

interface CognitionQueryPayload {
entity: EntityType;
scopeId?: ScopeId; // Default: aktueller Scope
routeId?: RouteId; // optionaler Route-Bezug
filters?: FilterSpec[]; // implizites AND
sort?: SortSpec[];
offset?: number; // Default: 0
limit?: number; // Default: app-definiert
fields?: FieldName[]; // optionaler Feld-Subset
}
interface CognitionQueryResultPayload {
entity: EntityType;
scopeId?: ScopeId;
routeId?: RouteId;
offset: number;
limit: number;
returned: number;
totalCount?: number;
hasMore?: boolean;
items: EntityRecord[];
}
  1. uiap.cognition.query DARF nur verwendet werden, wenn queryEnabled = true.
  2. Queries MÜSSEN an einen aktiven Scope oder eine deklarierte Route gebunden bleiben.
  3. Queries DÜRFEN sich nur auf genau einen entity-Typ beziehen.
  4. Queries DÜRFEN keine Joins, keine transitive Relation-Auflösung und keine freien Skript-Ausdrücke enthalten.
  5. Wenn das recordAccess des betreffenden Entity-Typs oder Scope Collection nicht mindestens queryable ist, MUSS die Anfrage fehlschlagen.
  6. Die App MUSS einen effektiven Maximalwert für limit durchsetzen.
  7. Felder mit exposure = "declared_only" DÜRFEN in items.fields nicht erscheinen.
  8. Felder mit exposure = "redacted" KÖNNEN maskiert, ausgelassen oder in redactions als withheld markiert werden.
  9. Query-Ergebnisse MÜSSEN source = "query" verwenden.
  10. Eine Query DARF durch Filter auf einem deklarierten Relationsfeld auf direkt verknüpfte Datensätze eingeschränkt werden, z. B. deal.contactId = c1.
  11. Solche direkt relationsgebundenen Filter gelten nicht als Join oder transitive Relation-Auflösung.
  12. Multi-Hop-Traversal, reverse expansion, nested includes oder automatische Relation-Following-Semantik sind in v0.1 nicht definiert.
  13. Felder mit exposure = "declared_only" KÖNNEN filterbar sein, wenn die App dies erlaubt, MÜSSEN aber weiterhin aus items.fields weggelassen werden.

Diese Erweiterung KANN zusätzliche, namespaced Fehlercodes verwenden.

Empfohlene Fehlercodes:

type CognitionErrorCode =
| "uiap.cognition.unknown_entity"
| "uiap.cognition.unknown_scope"
| "uiap.cognition.query_not_allowed"
| "uiap.cognition.route_required"
| "uiap.cognition.ambiguous_entity";

Ein Agent SOLL Entities nicht nur lesen, sondern bei Bedarf eindeutig referenzieren können, damit Action-Spezifikationen präzisere Targets verwenden können.

interface CognitionTarget {
entityRef: EntityRef;
targetRef?: string; // optionaler UI-Target-Bezug
}
  1. Action-/Runtime-Spezifikationen KÖNNEN entityRef als zusätzliches oder alternatives Target unterstützen.
  2. Wenn entityRef und targetRef gemeinsam verwendet werden, MÜSSEN beide auf dieselbe zugrunde liegende Entität zeigen.
  3. Wenn die Auflösung einer entityRef mehrdeutig oder stale ist, MUSS die Action mit state_conflict, bad_request oder uiap.cognition.ambiguous_entity fehlschlagen.
  4. Die Unterstützung von entityRef erweitert nur die Zielpräzision; sie verleiht keine zusätzlichen Berechtigungen.
  5. Mutationen bleiben normativ in Action-/Runtime-Spezifikationen definiert.
  1. Secure Default. recordAccess SOLLTE standardmässig visible_only sein.
  2. Schema ist nicht gleich Datenfreigabe. Ein Feld DARF im Schema sichtbar sein, ohne dass seine Werte jemals geliefert werden.
  3. Field Exposure. declared_only und redacted SOLLTEN für sensible Felder wie email, phone oder interne IDs verwendet werden.
  4. Query Limits. Implementierungen SOLLTEN konservative Limits verwenden; 50 Datensätze pro Query sind eine sinnvolle obere Empfehlung für v0.1.
  5. Audit. Apps SOLLTEN dokumentieren können, welche Scope Queries und Cognition-Bootstrap-Daten an Agenten geliefert wurden.
  6. Least Surprise. Wenn der Agent einen Datensatz nicht sehen darf, SOLLTE dieser Datensatz weder implizit durch unerklärte Counts noch durch Nebenkanäle rekonstruiert werden.

Diese Spezifikation ist profil-neutral.

Ein Web-Profil KANN die sichtbaren Entity Records zum Beispiel aus DOM-Annotationen ableiten. Empfohlene Attributnamen sind:

  • data-uiap-entity
  • data-uiap-entity-id
  • data-uiap-field
  • data-uiap-collection
  • data-uiap-primary
  • data-uiap-redact

Die konkrete normative Definition dieser Attribute SOLLTE im jeweiligen Profil erfolgen, nicht im Core.

{
"uiap": "0.1",
"kind": "request",
"type": "session.initialize",
"id": "msg_1",
"ts": "2026-03-29T09:00:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"payload": {
"supportedVersions": ["0.1"],
"supportedProfiles": ["[email protected]"],
"supportedExtensions": [
{ "id": "uiap.cognition", "versions": ["0.1"], "required": false }
],
"capabilityDelivery": "deferred",
"peer": {
"role": "agent",
"name": "cascade-agent",
"version": "0.1.0",
"locale": "de-CH",
"timezone": "Europe/Zurich"
}
},
"ext": {
"uiap.cognition": {
"bootstrapDelivery": "inline",
"requestedSurfaces": ["schema", "navigation", "context"],
"requestedQuery": false
}
}
}
{
"uiap": "0.1",
"kind": "response",
"type": "session.initialized",
"id": "msg_2",
"correlationId": "msg_1",
"sessionId": "sess_123",
"ts": "2026-03-29T09:00:00.040Z",
"source": { "role": "app", "id": "cascade-crm" },
"payload": {
"sessionId": "sess_123",
"selectedVersion": "0.1",
"selectedProfiles": ["[email protected]"],
"selectedExtensions": [
{ "id": "uiap.cognition", "version": "0.1" }
],
"capabilityDelivery": "deferred",
"heartbeatMs": 15000
},
"ext": {
"uiap.cognition": {
"bootstrapDelivery": "inline",
"enabledSurfaces": ["schema", "navigation", "context"],
"queryEnabled": false,
"bootstrap": {
"schema": {
"revision": "schema_1",
"entities": {
"contact": {
"label": "Kontakt",
"primaryField": "name",
"recordAccess": "visible_only",
"fields": {
"name": { "type": "string", "searchable": true, "sortable": true },
"company": { "type": "string", "searchable": true },
"status": { "type": "enum", "enumValues": ["active", "inactive", "prospect"] },
"email": { "type": "email", "exposure": "declared_only" }
}
}
}
},
"navigation": {
"revision": "nav_1",
"routes": [
{
"id": "contacts",
"path": "/contacts",
"label": "Kontakte",
"entities": ["contact"],
"capabilities": ["list", "search", "create"],
"activation": { "kind": "path", "value": "/contacts" }
}
]
},
"context": {
"revision": "ctx_7",
"scopeId": "contacts-list",
"routeId": "contacts",
"routePath": "/contacts",
"routeLabel": "Kontakte",
"collections": [
{
"entity": "contact",
"access": "visible_only",
"visibleCount": 2,
"items": [
{
"ref": { "type": "contact", "id": "c1", "stableId": "uiap-contact-c1", "primaryText": "Elena Rossi" },
"fields": { "name": "Elena Rossi", "company": "TechNova AG", "status": "active" },
"source": "visible"
},
{
"ref": { "type": "contact", "id": "c2", "stableId": "uiap-contact-c2", "primaryText": "Daniel Meier" },
"fields": { "name": "Daniel Meier", "company": "Nordstern GmbH", "status": "inactive" },
"source": "visible"
}
]
}
]
}
}
}
}
}
{
"uiap": "0.1",
"kind": "request",
"type": "uiap.cognition.query",
"id": "msg_41",
"sessionId": "sess_123",
"ts": "2026-03-29T09:05:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "contact",
"scopeId": "contacts-list",
"filters": [
{ "field": "status", "op": "eq", "value": "inactive" }
],
"sort": [
{ "field": "name", "direction": "asc" }
],
"offset": 0,
"limit": 20
}
}
{
"uiap": "0.1",
"kind": "response",
"type": "uiap.cognition.query.result",
"id": "msg_42",
"correlationId": "msg_41",
"sessionId": "sess_123",
"ts": "2026-03-29T09:05:00.015Z",
"source": { "role": "app", "id": "cascade-crm" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "contact",
"scopeId": "contacts-list",
"offset": 0,
"limit": 20,
"returned": 2,
"totalCount": 2,
"hasMore": false,
"items": [
{
"ref": { "type": "contact", "id": "c2", "primaryText": "Daniel Meier" },
"fields": { "name": "Daniel Meier", "company": "Nordstern GmbH", "status": "inactive" },
"source": "query"
},
{
"ref": { "type": "contact", "id": "c8", "primaryText": "Priya Shah" },
"fields": { "name": "Priya Shah", "company": "Aster Labs", "status": "inactive" },
"source": "query"
}
]
}
}

Beispielhafter Wechsel zur Contacts-Route über die bestehende Runtime:

{
"uiap": "0.1",
"kind": "request",
"type": "action.request",
"id": "msg_51",
"sessionId": "sess_123",
"ts": "2026-03-29T09:06:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"payload": {
"actionId": "nav.navigate",
"target": {
"ref": { "by": "route", "value": "contacts" }
}
}
}

Beispiel: Lade alle Deals, deren contactId auf den Contact c1 zeigt.

{
"uiap": "0.1",
"kind": "request",
"type": "uiap.cognition.query",
"id": "msg_61",
"sessionId": "sess_123",
"ts": "2026-03-29T09:07:00.000Z",
"source": { "role": "agent", "id": "agent-runtime" },
"requires": ["uiap.cognition"],
"payload": {
"entity": "deal",
"routeId": "deals",
"filters": [
{ "field": "contactId", "op": "eq", "value": "c1" }
],
"limit": 20
}
}

Dies ist in v0.1 ein direkter Filter auf einem deklarierten Relationsfeld, aber kein allgemeines Relation-Traversal.

Eine UIAP Agent Cognition v0.1-konforme Implementierung MUSS, sofern sie diese Erweiterung anbietet:

  • die Extension sauber aushandeln
  • CognitionBootstrap in inline oder deferred Form liefern können
  • recordAccess respektieren
  • FieldExposure respektieren
  • uiap.cognition.changed als Full-Replacement für geänderte Surfaces senden
  • bei aktiviertem Query-Modus uiap.cognition.query read-only und begrenzt verarbeiten

Eine Implementierung MUSS nicht alle Surfaces oder Querying unterstützen, um konform zu sein.

  • [RFC2119] Key words for use in RFCs to Indicate Requirement Levels, BCP 14
VersionDatumÄnderungen
0.12026-03-29Initialer Entwurf