Observability
draftStatus of this Document
This report was published by the User Journal Graph Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .
1. Overview
This second-level optional module defines a recognition contract for Surface nodes. It lets producers declare how a visible surface can be recognized by synthetic checks, browser collectors, native collectors, or other observation adapters without changing Graph traversal or Runtime ordering.
Observability depends on [UJG Surface] and [UJG Localization]. A binding points to a Surface
and uses localized message bundles when accessible names or descriptions are part of recognition.
Concrete runtime occurrence identity is derived by the collector when Runtime data is emitted. When a
binding has a SurfaceInstanceResolver, the resolver identifies the accessibility-exposed feature
used to derive the concrete instance key.
Observability has no direct dependency on Runtime. When Runtime data is present, a consumer can
correlate events to bindings by resolving RuntimeEvent.surfaceInstanceRef to a SurfaceInstance
and matching that instance's surfaceRef to ObservationBinding.observeSurfaceRef.
2. Normative Artifacts
This module is published through the following artifacts:
observability.ttl: ontology, published athttps://ujg.specs.openuji.org/ed/ns/observabilityobservability.context.jsonld: JSON-LD term mappings, published athttps://ujg.specs.openuji.org/ed/ns/observability.context.jsonldobservability.shape.ttl: SHACL validation rules, published athttps://ujg.specs.openuji.org/ed/ns/observability.shape
Examples in this page compose the shared baseline context https://ujg.specs.openuji.org/ed/ns/context.jsonld
with the Surface, Localization, and Observability contexts. Runtime appears only in the informative
correlation example.
3. Terminology
ObservationBinding: An addressable recognition contract for one
Surface.ObservationEvent: An addressable semantic event contract such as presence or activation.
AccessibleLocator: A locator that describes an accessible object using accessibility role, localized computed name or description references, state/property features, relations, and context.
AccessibleFeature: An accessibility state or property used by an accessible locator.
AccessibleRelation: A relationship between accessible objects used by an accessible locator.
CustomLocator: An opaque extension-backed locator for adapter-specific matching.
SurfaceInstanceResolver: A reusable resolver that identifies how an adapter derives a concrete
SurfaceInstancekey for repeated occurrences of the same stableSurface.Collector: A runtime observation component that evaluates
ObservationBindingnodes against an observed environment, resolves or creates the applicableSurfaceInstancewhen Runtime data is emitted, and records observed events without changing Graph, Surface, or Observability definitions.Synthetic Runner: A collector that drives or inspects a journey through automated execution, such as a Playwright-based browser test. A synthetic runner may activate accessible objects, match locators, and emit Runtime events, but its automation commands are not modeled as Graph traversal rules or Observability vocabulary.
4. Binding Model
The module introduces one canonical interoperable attachment:
observability:observeSurfaceReflinks anObservationBindingto oneSurface.
An ObservationBinding also identifies:
observationEventRef: the semantic event being observed.locatorRefs: one or more locator nodes that define how the surface evidence is recognized.surfaceInstanceResolverRef: an optional resolver for deriving a concreteSurfaceInstancewhen the same stable surface is repeated.
locatorRefs inside one binding are conjunctive: all referenced locators must match. Alternative
recognition strategies SHOULD be modeled as separate ObservationBinding nodes that reference the
same surface.
One ObservationBinding can describe behavior for many repeated SurfaceInstance occurrences of
the same Surface. SurfaceInstanceResolver does not reference concrete SurfaceInstance nodes and
MUST NOT require one binding per repeated occurrence.
Observability does not define touchpointRef, graphNodeRef, surfaceRef,
graphNodeInstanceRef, or surfaceInstanceRef. Those are Surface and Runtime terms. Observability
does not define Runtime properties.
5. Standard Observation Events
This draft defines two standard event IRIs:
https://ujg.specs.openuji.org/ed/ns/observability#presencehttps://ujg.specs.openuji.org/ed/ns/observability#activation
Presence means the referenced locators are currently perceivable or matched in the observed surface. It is typically used for state or composite-state surfaces.
Activation means a user or synthetic runner activates a user-operable accessible object represented by the observed surface. It is typically used for transition or outgoing-transition affordance surfaces.
Additional event IRIs can be defined later without changing the MVP vocabulary.
6. Locator Model
AccessibleLocator is the preferred interoperable locator for human-facing UI. It is based on the
accessibility object exposed through an accessibility API, not on DOM structure, CSS selectors,
Playwright expressions, or raw text content. WAI-ARIA defines an accessibility API as platform
interfaces that expose object and event information to assistive technologies [WAI-ARIA-1.2].
AccessibleLocator.accessibleNameRef and AccessibleLocator.accessibleDescriptionRef reference
localized MessageBundle nodes for the computed accessible-object name and description. For web DOM
environments, producers and consumers SHOULD compute accessible-object names and descriptions
according to [ACCNAME-1.2], then match the computed value against the locale-appropriate value of
the referenced message bundle.
Observability does not define standard raw string fallback properties for accessible names or
descriptions. Private adapter hints MAY appear in Core extensions, but such hints are not
normative Observability terms.
An AccessibleLocator SHOULD provide at least one of:
roleaccessibleNameRefaccessibleDescriptionRefaccessibleFeatureRefsaccessibleRelationRefscontextLocatorRefs
AccessibleFeature names SHOULD be accessibility-model oriented, such as selected, expanded,
disabled, checked, pressed, current, invalid, required, busy, or hidden. Producers
SHOULD NOT use raw web-only names such as aria-selected when a platform-neutral state/property name
is available.
AccessibleRelation names SHOULD also be accessibility-model oriented, such as controls,
labelled-by, described-by, owns, active-descendant, details, or error-message.
contextLocatorRefs scope a locator by another accessible object. Multiple context locators are
conjunctive.
CustomLocator is the escape hatch for stable semantic markers, CSS selectors, tool-specific
queries, native automation identifiers, CLI patterns, server-log queries, kiosk signals, or other
adapter-specific matching. A CustomLocator MUST define its semantics in Core extensions and is
opaque to consumers that do not understand that extension.
7. Runtime Correlation
Runtime correlation is derived, not modeled as an Observability-to-Runtime reference.
RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceRef = ObservationBinding.observeSurfaceRef RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceRef = ObservationBinding.observeSurfaceRef An observation adapter that emits Runtime data SHOULD:
match the binding's
locatorRefs;when
surfaceInstanceResolverRefis present, read the resolver'sinstanceKeyFeatureReffrom the matched accessible object or contextual accessible object;resolve or create the matching
SurfaceInstance;emit the required Runtime
surfaceInstanceRef.
If an instance key is not exposed through the accessibility API, adapters MUST use CustomLocator or
Core extensions for private resolver semantics. Runtime events MUST NOT be required to reference
an ObservationBinding.
8. Ontology
The normative Observability ontology is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/observability.
@prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/ed/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/ed/ns/observability#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
<https://ujg.specs.openuji.org/ed/ns/observability#> a owl:Ontology ;
rdfs:label "UJG Observability Editor's Draft Vocabulary"@en ;
dct:description "UJG Observability ontology declaration" .
### Classes
ujgobservability:ObservationBinding a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:ObservationEvent a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleLocator a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleFeature a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleRelation a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:CustomLocator a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:SurfaceInstanceResolver a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgobservability:observeSurfaceRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgsurface:Surface .
ujgobservability:observationEventRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgobservability:ObservationEvent .
ujgobservability:locatorRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range [
a owl:Class ;
owl:unionOf (
ujgobservability:AccessibleLocator
ujgobservability:CustomLocator
)
] .
ujgobservability:surfaceInstanceResolverRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgobservability:SurfaceInstanceResolver .
ujgobservability:instanceKeyFeatureRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:SurfaceInstanceResolver ;
rdfs:range ujgobservability:AccessibleFeature .
ujgobservability:role a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range xsd:string .
ujgobservability:accessibleNameRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgl10n:MessageBundle .
ujgobservability:accessibleDescriptionRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgl10n:MessageBundle .
ujgobservability:accessibleFeatureRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleFeature .
ujgobservability:accessibleRelationRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleRelation .
ujgobservability:contextLocatorRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleLocator .
ujgobservability:accessibleFeatureName a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleFeature ;
rdfs:range xsd:string .
ujgobservability:accessibleFeatureValue a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleFeature ;
rdfs:range xsd:string .
ujgobservability:accessibleRelationType a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleRelation ;
rdfs:range xsd:string .
ujgobservability:targetLocatorRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleRelation ;
rdfs:range ujgobservability:AccessibleLocator . @prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/ed/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/ed/ns/observability#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
<https://ujg.specs.openuji.org/ed/ns/observability#> a owl:Ontology ;
rdfs:label "UJG Observability Editor's Draft Vocabulary"@en ;
dct:description "UJG Observability ontology declaration" .
### Classes
ujgobservability:ObservationBinding a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:ObservationEvent a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleLocator a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleFeature a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:AccessibleRelation a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:CustomLocator a owl:Class ;
rdfs:subClassOf ujg:Node .
ujgobservability:SurfaceInstanceResolver a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgobservability:observeSurfaceRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgsurface:Surface .
ujgobservability:observationEventRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgobservability:ObservationEvent .
ujgobservability:locatorRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range [
a owl:Class ;
owl:unionOf (
ujgobservability:AccessibleLocator
ujgobservability:CustomLocator
)
] .
ujgobservability:surfaceInstanceResolverRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:ObservationBinding ;
rdfs:range ujgobservability:SurfaceInstanceResolver .
ujgobservability:instanceKeyFeatureRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:SurfaceInstanceResolver ;
rdfs:range ujgobservability:AccessibleFeature .
ujgobservability:role a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range xsd:string .
ujgobservability:accessibleNameRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgl10n:MessageBundle .
ujgobservability:accessibleDescriptionRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgl10n:MessageBundle .
ujgobservability:accessibleFeatureRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleFeature .
ujgobservability:accessibleRelationRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleRelation .
ujgobservability:contextLocatorRefs a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleLocator ;
rdfs:range ujgobservability:AccessibleLocator .
ujgobservability:accessibleFeatureName a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleFeature ;
rdfs:range xsd:string .
ujgobservability:accessibleFeatureValue a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleFeature ;
rdfs:range xsd:string .
ujgobservability:accessibleRelationType a owl:DatatypeProperty ;
rdfs:domain ujgobservability:AccessibleRelation ;
rdfs:range xsd:string .
ujgobservability:targetLocatorRef a owl:ObjectProperty ;
rdfs:domain ujgobservability:AccessibleRelation ;
rdfs:range ujgobservability:AccessibleLocator . 9. JSON-LD Context
The normative Observability JSON-LD context is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/observability.context.jsonld.
{
"@context": {
"@version": 1.1,
"ujgobservability": "https://ujg.specs.openuji.org/ed/ns/observability#",
"observability": "https://ujg.specs.openuji.org/ed/ns/observability#",
"ObservationBinding": "ujgobservability:ObservationBinding",
"ObservationEvent": "ujgobservability:ObservationEvent",
"AccessibleLocator": "ujgobservability:AccessibleLocator",
"AccessibleFeature": "ujgobservability:AccessibleFeature",
"AccessibleRelation": "ujgobservability:AccessibleRelation",
"CustomLocator": "ujgobservability:CustomLocator",
"SurfaceInstanceResolver": "ujgobservability:SurfaceInstanceResolver",
"observeSurfaceRef": {
"@id": "ujgobservability:observeSurfaceRef",
"@type": "@id"
},
"observationEventRef": {
"@id": "ujgobservability:observationEventRef",
"@type": "@id"
},
"locatorRefs": {
"@id": "ujgobservability:locatorRefs",
"@type": "@id"
},
"surfaceInstanceResolverRef": {
"@id": "ujgobservability:surfaceInstanceResolverRef",
"@type": "@id"
},
"instanceKeyFeatureRef": {
"@id": "ujgobservability:instanceKeyFeatureRef",
"@type": "@id"
},
"role": "ujgobservability:role",
"accessibleNameRef": {
"@id": "ujgobservability:accessibleNameRef",
"@type": "@id"
},
"accessibleDescriptionRef": {
"@id": "ujgobservability:accessibleDescriptionRef",
"@type": "@id"
},
"accessibleFeatureRefs": {
"@id": "ujgobservability:accessibleFeatureRefs",
"@type": "@id"
},
"accessibleRelationRefs": {
"@id": "ujgobservability:accessibleRelationRefs",
"@type": "@id"
},
"contextLocatorRefs": {
"@id": "ujgobservability:contextLocatorRefs",
"@type": "@id"
},
"accessibleFeatureName": "ujgobservability:accessibleFeatureName",
"accessibleFeatureValue": "ujgobservability:accessibleFeatureValue",
"accessibleRelationType": "ujgobservability:accessibleRelationType",
"targetLocatorRef": {
"@id": "ujgobservability:targetLocatorRef",
"@type": "@id"
}
}
} {
"@context": {
"@version": 1.1,
"ujgobservability": "https://ujg.specs.openuji.org/ed/ns/observability#",
"observability": "https://ujg.specs.openuji.org/ed/ns/observability#",
"ObservationBinding": "ujgobservability:ObservationBinding",
"ObservationEvent": "ujgobservability:ObservationEvent",
"AccessibleLocator": "ujgobservability:AccessibleLocator",
"AccessibleFeature": "ujgobservability:AccessibleFeature",
"AccessibleRelation": "ujgobservability:AccessibleRelation",
"CustomLocator": "ujgobservability:CustomLocator",
"SurfaceInstanceResolver": "ujgobservability:SurfaceInstanceResolver",
"observeSurfaceRef": {
"@id": "ujgobservability:observeSurfaceRef",
"@type": "@id"
},
"observationEventRef": {
"@id": "ujgobservability:observationEventRef",
"@type": "@id"
},
"locatorRefs": {
"@id": "ujgobservability:locatorRefs",
"@type": "@id"
},
"surfaceInstanceResolverRef": {
"@id": "ujgobservability:surfaceInstanceResolverRef",
"@type": "@id"
},
"instanceKeyFeatureRef": {
"@id": "ujgobservability:instanceKeyFeatureRef",
"@type": "@id"
},
"role": "ujgobservability:role",
"accessibleNameRef": {
"@id": "ujgobservability:accessibleNameRef",
"@type": "@id"
},
"accessibleDescriptionRef": {
"@id": "ujgobservability:accessibleDescriptionRef",
"@type": "@id"
},
"accessibleFeatureRefs": {
"@id": "ujgobservability:accessibleFeatureRefs",
"@type": "@id"
},
"accessibleRelationRefs": {
"@id": "ujgobservability:accessibleRelationRefs",
"@type": "@id"
},
"contextLocatorRefs": {
"@id": "ujgobservability:contextLocatorRefs",
"@type": "@id"
},
"accessibleFeatureName": "ujgobservability:accessibleFeatureName",
"accessibleFeatureValue": "ujgobservability:accessibleFeatureValue",
"accessibleRelationType": "ujgobservability:accessibleRelationType",
"targetLocatorRef": {
"@id": "ujgobservability:targetLocatorRef",
"@type": "@id"
}
}
} 10. Validation
The normative Observability SHACL shape is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/observability.shape.
@prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/ed/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/ed/ns/observability#> .
@prefix ujgobservabilityshape: <https://ujg.specs.openuji.org/ed/ns/observability.shape#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgobservabilityshape:LocatorShape a sh:NodeShape ;
sh:nodeKind sh:IRI ;
sh:or (
[ sh:class ujgobservability:AccessibleLocator ]
[ sh:class ujgobservability:CustomLocator ]
) .
ujgobservabilityshape:ObservationBindingShape a sh:NodeShape ;
sh:targetClass ujgobservability:ObservationBinding ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:observeSurfaceRef ;
sh:class ujgsurface:Surface ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:observationEventRef ;
sh:class ujgobservability:ObservationEvent ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:locatorRefs ;
sh:node ujgobservabilityshape:LocatorShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
] ;
sh:property [
sh:path ujgobservability:surfaceInstanceResolverRef ;
sh:class ujgobservability:SurfaceInstanceResolver ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:ObservationEventShape a sh:NodeShape ;
sh:targetClass ujgobservability:ObservationEvent ;
sh:nodeKind sh:IRI .
ujgobservabilityshape:SurfaceInstanceResolverShape a sh:NodeShape ;
sh:targetClass ujgobservability:SurfaceInstanceResolver ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:instanceKeyFeatureRef ;
sh:class ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:AccessibleLocatorShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
sh:or (
[ sh:property [ sh:path ujgobservability:role ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleNameRef ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleDescriptionRef ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleFeatureRefs ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleRelationRefs ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:contextLocatorRefs ; sh:minCount 1 ] ]
) ;
sh:property [
sh:path ujgobservability:role ;
sh:datatype xsd:string ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleNameRef ;
sh:class ujgl10n:MessageBundle ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleDescriptionRef ;
sh:class ujgl10n:MessageBundle ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleFeatureRefs ;
sh:class ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgobservability:accessibleRelationRefs ;
sh:class ujgobservability:AccessibleRelation ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgobservability:contextLocatorRefs ;
sh:class ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
] .
ujgobservabilityshape:AccessibleFeatureShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:accessibleFeatureName ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleFeatureValue ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:AccessibleRelationShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleRelation ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:accessibleRelationType ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:targetLocatorRef ;
sh:class ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:CustomLocatorShape a sh:NodeShape ;
sh:targetClass ujgobservability:CustomLocator ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujg:extensions ;
sh:datatype rdf:JSON ;
sh:minCount 1 ;
sh:maxCount 1 ;
] . @prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgl10n: <https://ujg.specs.openuji.org/ed/ns/l10n#> .
@prefix ujgobservability: <https://ujg.specs.openuji.org/ed/ns/observability#> .
@prefix ujgobservabilityshape: <https://ujg.specs.openuji.org/ed/ns/observability.shape#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgobservabilityshape:LocatorShape a sh:NodeShape ;
sh:nodeKind sh:IRI ;
sh:or (
[ sh:class ujgobservability:AccessibleLocator ]
[ sh:class ujgobservability:CustomLocator ]
) .
ujgobservabilityshape:ObservationBindingShape a sh:NodeShape ;
sh:targetClass ujgobservability:ObservationBinding ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:observeSurfaceRef ;
sh:class ujgsurface:Surface ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:observationEventRef ;
sh:class ujgobservability:ObservationEvent ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:locatorRefs ;
sh:node ujgobservabilityshape:LocatorShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
] ;
sh:property [
sh:path ujgobservability:surfaceInstanceResolverRef ;
sh:class ujgobservability:SurfaceInstanceResolver ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:ObservationEventShape a sh:NodeShape ;
sh:targetClass ujgobservability:ObservationEvent ;
sh:nodeKind sh:IRI .
ujgobservabilityshape:SurfaceInstanceResolverShape a sh:NodeShape ;
sh:targetClass ujgobservability:SurfaceInstanceResolver ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:instanceKeyFeatureRef ;
sh:class ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:AccessibleLocatorShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
sh:or (
[ sh:property [ sh:path ujgobservability:role ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleNameRef ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleDescriptionRef ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleFeatureRefs ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:accessibleRelationRefs ; sh:minCount 1 ] ]
[ sh:property [ sh:path ujgobservability:contextLocatorRefs ; sh:minCount 1 ] ]
) ;
sh:property [
sh:path ujgobservability:role ;
sh:datatype xsd:string ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleNameRef ;
sh:class ujgl10n:MessageBundle ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleDescriptionRef ;
sh:class ujgl10n:MessageBundle ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleFeatureRefs ;
sh:class ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgobservability:accessibleRelationRefs ;
sh:class ujgobservability:AccessibleRelation ;
sh:nodeKind sh:IRI ;
] ;
sh:property [
sh:path ujgobservability:contextLocatorRefs ;
sh:class ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
] .
ujgobservabilityshape:AccessibleFeatureShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleFeature ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:accessibleFeatureName ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:accessibleFeatureValue ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:AccessibleRelationShape a sh:NodeShape ;
sh:targetClass ujgobservability:AccessibleRelation ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgobservability:accessibleRelationType ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgobservability:targetLocatorRef ;
sh:class ujgobservability:AccessibleLocator ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
ujgobservabilityshape:CustomLocatorShape a sh:NodeShape ;
sh:targetClass ujgobservability:CustomLocator ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujg:extensions ;
sh:datatype rdf:JSON ;
sh:minCount 1 ;
sh:maxCount 1 ;
] . The rules below define the remaining module semantics beyond the structural constraints captured by the SHACL shape.
Surface first: An
ObservationBindingMUST identify exactly oneSurfaceusingobserveSurfaceRef.No graph traversal: Observability properties MUST NOT change Graph validity, graph traversal behavior, import resolution, or core node identity.
No Runtime dependency: Observability MUST NOT require Runtime data and MUST NOT define a Runtime property.
Derived Runtime correlation: Consumers MAY correlate Runtime events to bindings by matching
RuntimeEvent.surfaceInstanceRef -> SurfaceInstance.surfaceReftoObservationBinding.observeSurfaceRef.Conjunctive locators:
locatorRefsinside oneObservationBindingare conjunctive.Instance resolver:
SurfaceInstanceResolver.instanceKeyFeatureRefMUST identify oneAccessibleFeaturethat supplies the instance key source. A resolver MUST NOT reference concreteSurfaceInstancenodes.Accessible-object semantics:
AccessibleLocatoridentifies an accessible object, not an implementation node or selector expression.Localized name and description matching:
accessibleNameRefandaccessibleDescriptionRefMUST resolve toMessageBundlenodes. In web DOM environments, adapters SHOULD compute accessible names and descriptions according to [ACCNAME-1.2], then match the computed values against the locale-appropriate values of those message bundles.Accessibility API orientation: Role, feature, and relation names SHOULD describe accessibility API concepts rather than DOM or tool-specific implementation details [WAI-ARIA-1.2].
Opaque custom locators:
CustomLocatorsemantics live in Coreextensions; consumers that do not understand the extension MAY ignore the locator semantics.Graceful degradation: Consumers that do not implement Observability semantics MAY ignore Observability data, but SHOULD preserve recognized JSON-LD data during read-transform-write when possible.
11. Minimal Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/l10n.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/observability.context.jsonld"
],
"@id": "https://example.com/ujg/observability/share.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "Touchpoint",
"@id": "urn:touchpoint:nextcloud-web",
"label": "Nextcloud web client",
"channel": "web",
"origin": "https://cloud.example"
},
{
"@type": "State",
"@id": "urn:state:bob-pending-federated-share",
"label": "Bob pending federated share"
},
{
"@type": "Surface",
"@id": "urn:surface:bob-pending-share",
"graphNodeRef": "urn:state:bob-pending-federated-share",
"touchpointRef": "urn:touchpoint:nextcloud-web"
},
{
"@type": "ObservationEvent",
"@id": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"label": "Presence"
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:selected-true",
"label": "Selected true",
"accessibleFeatureName": "selected",
"accessibleFeatureValue": "true"
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:file-id",
"label": "File identifier",
"accessibleFeatureName": "file-id",
"accessibleFeatureValue": "*"
},
{
"@type": "MessageBundle",
"@id": "urn:message:files",
"messageKey": "files.heading",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Files"
}
}
},
{
"@type": "MessageBundle",
"@id": "urn:message:shared-with-you",
"messageKey": "files.sharedWithYou.tab",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Shared with you"
}
}
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:files-heading",
"label": "Files heading",
"role": "heading",
"accessibleNameRef": "urn:message:files"
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:shared-with-you-tab-selected",
"label": "Selected Shared with you tab",
"role": "tab",
"accessibleNameRef": "urn:message:shared-with-you",
"accessibleFeatureRefs": [
"urn:feature:selected-true"
]
},
{
"@type": "SurfaceInstanceResolver",
"@id": "urn:resolver:bob-pending-share-file-id",
"label": "Pending share file identifier resolver",
"instanceKeyFeatureRef": "urn:feature:file-id"
},
{
"@type": "ObservationBinding",
"@id": "urn:binding:bob-pending-share-present",
"label": "Bob sees pending federated share",
"observeSurfaceRef": "urn:surface:bob-pending-share",
"observationEventRef": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
"locatorRefs": [
"urn:locator:files-heading",
"urn:locator:shared-with-you-tab-selected"
]
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/l10n.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/observability.context.jsonld"
],
"@id": "https://example.com/ujg/observability/share.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "Touchpoint",
"@id": "urn:touchpoint:nextcloud-web",
"label": "Nextcloud web client",
"channel": "web",
"origin": "https://cloud.example"
},
{
"@type": "State",
"@id": "urn:state:bob-pending-federated-share",
"label": "Bob pending federated share"
},
{
"@type": "Surface",
"@id": "urn:surface:bob-pending-share",
"graphNodeRef": "urn:state:bob-pending-federated-share",
"touchpointRef": "urn:touchpoint:nextcloud-web"
},
{
"@type": "ObservationEvent",
"@id": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"label": "Presence"
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:selected-true",
"label": "Selected true",
"accessibleFeatureName": "selected",
"accessibleFeatureValue": "true"
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:file-id",
"label": "File identifier",
"accessibleFeatureName": "file-id",
"accessibleFeatureValue": "*"
},
{
"@type": "MessageBundle",
"@id": "urn:message:files",
"messageKey": "files.heading",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Files"
}
}
},
{
"@type": "MessageBundle",
"@id": "urn:message:shared-with-you",
"messageKey": "files.sharedWithYou.tab",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Shared with you"
}
}
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:files-heading",
"label": "Files heading",
"role": "heading",
"accessibleNameRef": "urn:message:files"
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:shared-with-you-tab-selected",
"label": "Selected Shared with you tab",
"role": "tab",
"accessibleNameRef": "urn:message:shared-with-you",
"accessibleFeatureRefs": [
"urn:feature:selected-true"
]
},
{
"@type": "SurfaceInstanceResolver",
"@id": "urn:resolver:bob-pending-share-file-id",
"label": "Pending share file identifier resolver",
"instanceKeyFeatureRef": "urn:feature:file-id"
},
{
"@type": "ObservationBinding",
"@id": "urn:binding:bob-pending-share-present",
"label": "Bob sees pending federated share",
"observeSurfaceRef": "urn:surface:bob-pending-share",
"observationEventRef": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
"locatorRefs": [
"urn:locator:files-heading",
"urn:locator:shared-with-you-tab-selected"
]
}
]
} 12. Runtime Correlation Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/l10n.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/runtime.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/observability.context.jsonld"
],
"@id": "https://example.com/ujg/observability/runtime-correlation.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "State",
"@id": "urn:state:bob-pending-federated-share",
"label": "Bob pending federated share"
},
{
"@type": "Surface",
"@id": "urn:surface:bob-pending-share",
"graphNodeRef": "urn:state:bob-pending-federated-share"
},
{
"@type": "SurfaceInstance",
"@id": "urn:surface-instance:bob-pending-share:shared-folder-42",
"surfaceRef": "urn:surface:bob-pending-share"
},
{
"@type": "ObservationEvent",
"@id": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"label": "Presence"
},
{
"@type": "MessageBundle",
"@id": "urn:message:files",
"messageKey": "files.heading",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Files"
}
}
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:shared-folder-42",
"accessibleFeatureName": "file-id",
"accessibleFeatureValue": "shared-folder-42"
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:files-heading",
"role": "heading",
"accessibleNameRef": "urn:message:files"
},
{
"@type": "SurfaceInstanceResolver",
"@id": "urn:resolver:bob-pending-share-file-id",
"instanceKeyFeatureRef": "urn:feature:shared-folder-42"
},
{
"@type": "ObservationBinding",
"@id": "urn:binding:bob-pending-share-present",
"observeSurfaceRef": "urn:surface:bob-pending-share",
"observationEventRef": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
"locatorRefs": [
"urn:locator:files-heading"
]
},
{
"@type": "JourneyExecution",
"@id": "urn:execution:fed-share-runtime-001"
},
{
"@type": "RuntimeEvent",
"@id": "urn:runtime-event:bob-pending-share-present-001",
"executionId": "urn:execution:fed-share-runtime-001",
"surfaceInstanceRef": "urn:surface-instance:bob-pending-share:shared-folder-42"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/l10n.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/runtime.context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/observability.context.jsonld"
],
"@id": "https://example.com/ujg/observability/runtime-correlation.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@type": "State",
"@id": "urn:state:bob-pending-federated-share",
"label": "Bob pending federated share"
},
{
"@type": "Surface",
"@id": "urn:surface:bob-pending-share",
"graphNodeRef": "urn:state:bob-pending-federated-share"
},
{
"@type": "SurfaceInstance",
"@id": "urn:surface-instance:bob-pending-share:shared-folder-42",
"surfaceRef": "urn:surface:bob-pending-share"
},
{
"@type": "ObservationEvent",
"@id": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"label": "Presence"
},
{
"@type": "MessageBundle",
"@id": "urn:message:files",
"messageKey": "files.heading",
"defaultLocale": "en",
"locales": {
"en": {
"value": "Files"
}
}
},
{
"@type": "AccessibleFeature",
"@id": "urn:feature:shared-folder-42",
"accessibleFeatureName": "file-id",
"accessibleFeatureValue": "shared-folder-42"
},
{
"@type": "AccessibleLocator",
"@id": "urn:locator:files-heading",
"role": "heading",
"accessibleNameRef": "urn:message:files"
},
{
"@type": "SurfaceInstanceResolver",
"@id": "urn:resolver:bob-pending-share-file-id",
"instanceKeyFeatureRef": "urn:feature:shared-folder-42"
},
{
"@type": "ObservationBinding",
"@id": "urn:binding:bob-pending-share-present",
"observeSurfaceRef": "urn:surface:bob-pending-share",
"observationEventRef": "https://ujg.specs.openuji.org/ed/ns/observability#presence",
"surfaceInstanceResolverRef": "urn:resolver:bob-pending-share-file-id",
"locatorRefs": [
"urn:locator:files-heading"
]
},
{
"@type": "JourneyExecution",
"@id": "urn:execution:fed-share-runtime-001"
},
{
"@type": "RuntimeEvent",
"@id": "urn:runtime-event:bob-pending-share-present-001",
"executionId": "urn:execution:fed-share-runtime-001",
"surfaceInstanceRef": "urn:surface-instance:bob-pending-share:shared-folder-42"
}
]
} The runtime event can be correlated to urn:binding:bob-pending-share-present because its referenced
surface instance points back to urn:surface:bob-pending-share. The event does not reference the
binding.