Elonn Docs Platform Documentation

Runtime Contract

Status: Normative runtime contract source. Sections that explicitly describe current compatibility output record migration reality, not design authority for new runtime dataset work.

This document is the authoritative specification for what every Elonn runtime must implement. It is defined from the World Dataset Contract outward, not from any specific runtime. The fresh World Dataset Contract is documented in world-dataset-contract.md.

The contract goal is decision-complete runtime implementation: a competent runtime engineer must be able to build a new Elonn runtime for a new device from this document, the service contracts, examples, and conformance checks without reading existing runtime, World, or service implementation code to infer behavior.

Platform runtime pages describe implementation status and platform constraints. This document is the normative runtime contract.


What A Runtime Is

A runtime is a consumer of the canonical runtime dataset produced by World. It owns local state needed for rendering, input, projection, lifecycle, and recovery. It does not own identity, Social, Messages, Time, Maps, Find, Surface, workspace, permission, or business state.

The target architecture is:

Service object sources
  -> World canonical model
  -> Canonical runtime dataset
  -> Runtime adapter
  -> Platform renderer

The runtime dataset is transparent data. It contains objects, contexts, actions, workspace state, field state, findings, capabilities, and fallbacks. It does not contain service panel payloads, Surface records, stack records, right-rail records, dock definitions, renderer hints, HTML, embedded browser content, or platform-specific UI instructions.

Every runtime consumes the same logical dataset. Runtimes do not consume raw service payloads, current compatibility payloads, an implementation-private World model, or existing runtime implementation behavior.

Build Target

A new runtime is complete when a member can authenticate, request the canonical runtime dataset from World, build runtime state from that dataset, construct a platform-native scene, render objects and contexts, handle local interaction, dispatch World-published commands, receive an updated dataset, and update the scene without implementing service business logic.

Runtimes never render arbitrary HTML, execute resource JavaScript, call services directly, derive actions from URLs, infer permissions from missing fields, or hardcode service behavior.

Implement these responsibilities. Module names and language boundaries are adapter-specific:

Module Required responsibility
Runtime config Select World base URL, login URL, runtime id, version, and capability declaration without code changes
Auth client Obtain an Elonn credential, call World identity endpoints, and attach the credential to World requests
World client Fetch the canonical runtime dataset, resolve World-relative command URLs, post World commands, and receive refreshed datasets
Runtime state Validate the dataset, index objects/actions/contexts, track local UI-only state, and replace authoritative state from World updates
Scene construction Convert runtime state into platform-native structures such as DOM, SwiftUI, Compose, Unity scene graph, or future scene graphs
Renderer Draw the scene with platform capabilities without adding business logic
Interaction Convert platform input into World command dispatches or local presentation changes
Projection Convert dataset placement, field, and spatial data into platform coordinates
Fallback handling Render unavailable, unsupported, denied, empty, and degraded states exactly from the dataset

Do not build service clients for API, Social, Messages, Maps, Time, Surface, or Find. The only runtime-facing upstream is World.

Reference Runtime Baseline

The fresh world.elonn.local runtime harness is the current reference implementation baseline for new runtime architecture. It is not the product Web runtime, and its DOM scene is not normative for Android, iPad, XREAL, Unity, or future runtimes.

The baseline exists to prove component boundaries against the World Dataset Contract:

Runtime component Reference file Responsibility proven
World client world.elonn.local/public/assets/runtime-world-client.js Requests POST /world/session, sends World-owned profile/context, dispatches only World action endpoints, and receives refreshed datasets.
Runtime state world.elonn.local/public/assets/runtime-state.js Validates elonn.world.dataset, indexes objects/actions/collections/resources, tracks local selected object and action progress, and replaces state from returned datasets.
Scene construction world.elonn.local/public/assets/runtime-scene.js Converts runtime state into a platform scene without service logic. The current scene target is DOM; other runtimes use native scene graphs.
Renderer world.elonn.local/public/assets/runtime-renderer.js Applies scene output to the platform renderer without owning business state.
Interaction world.elonn.local/public/assets/runtime-interaction.js Converts platform input into local selection changes or World action dispatches.
Projection world.elonn.local/public/assets/runtime-projection.js Converts runtime objects and relationships into platform-specific display labels/coordinates without changing semantics.

The browser harness is acceptable reference material only for architecture and conformance. Future runtimes must preserve the same component responsibilities and World-only upstream boundary, but they must choose their own platform scene construction, renderer, interaction model, and projection.

Rendered acceptance is part of the baseline. The World service test world.elonn.local/tests/rendered-runtime-harness.mjs loads the harness in Chromium, verifies provider-backed collections, selected object details, resources, action controls, and action-response dataset replacement, and proves the browser runtime does not call Find or provider endpoints directly.

Transparent Runtime Dataset

The target canonical runtime dataset has this top-level shape:

Field Meaning
contract {name, version} identifying the runtime dataset contract
member Authenticated member context needed for presentation, never reusable credentials
capabilities Applied runtime capabilities and explicit unsupported capabilities
workspace Current working set, focus, order, placement, and continuity state
objects Runtime-presentable World objects with stable World ids and source authority references
contexts Navigation/control groups tied to objects, workspace, field, or findings
actions Runtime-dispatchable semantic command descriptors routed through World
field World-anchored field state, semantic field controls, and field-presentable objects
findings Discovered candidates from Find before or during promotion to objects
fallbacks Explicit degraded, unavailable, unsupported, empty, or denied states
sources Diagnostic source metadata, never service endpoints for runtime calls

The dataset must be complete enough for a runtime adapter to render without reading Web, Android, iPad, Cardboard, World implementation code, service implementation code, or compatibility payload examples.

Dataset Rules

  • objects[] is the primary display set. Main and secondary display entities are objects with stable world_object_id, object_type, source, title, state, permissions, actions, relationships, placement, and focus metadata.
  • contexts[] is semantic navigation and control intent. A context is not a right rail, left rail, sidebar, sheet, menu, or panel. Runtimes may project a context into any of those forms.
  • workspace is semantic working-set state. It is not a stack, deck, dock, or window layout. Runtimes may project workspace order and focus into a stack, grid, spatial room, command list, or nonvisual sequence.
  • field is world-anchored state. It is not a map widget and not a marker list. Field controls are semantic selectors and toggle groups such as radius and place category filters. Runtimes choose marker, list, spatial anchor, audio, or other projection.
  • findings[] are candidates. A finding becomes a runtime-presentable object only when World composes or promotes it into objects[].
  • actions[] are semantic commands. Runtimes dispatch the declared command and must not reconstruct service or World URLs from ids, labels, object types, or source references.
  • fallbacks[] are required state, not optional text. If a capability, permission, service, object, field, or command is unavailable, the dataset must say so explicitly.
  • Unknown object types, context kinds, action types, fields, or capabilities are ignored or rendered generically according to explicit fallback data. Unknowns must not crash a runtime or cause service-specific inference.

Runtime Lifecycle

Every runtime follows this lifecycle:

Authenticate
  -> request canonical runtime dataset from World
  -> build runtime state
  -> construct platform scene
  -> render
  -> receive user interaction
  -> dispatch World command
  -> receive updated runtime dataset
  -> replace authoritative runtime state
  -> update platform scene

Persistent state changes always flow through World. A runtime may maintain local presentation state such as scroll position, focus ring, expanded local controls, cached textures, or retry timers only when that state does not contradict the latest World dataset.

Completion Standard

The contract is complete only when a runtime can implement these rules without reading an existing runtime or service implementation:

  • World response data is authoritative for objects, contexts, actions, workspace, field, findings, permissions, relationships, and fallbacks.
  • The runtime state layer validates the dataset, indexes by stable ids, replaces authoritative state from updates, and preserves only non-conflicting local presentation state.
  • The renderer adapts presentation to platform capability but does not create product structure, business rules, permissions, or service routes.
  • Interaction dispatches World-published commands and never mutates persistent business state directly.
  • Conformance fixtures prove that the same canonical runtime dataset can be projected by at least two runtime capability classes without changing object identity, action meaning, permissions, relationships, focus, field state, findings, or fallback semantics.

Compatibility Appendix

The sections below describe the current runtime v2 /world/session compatibility contract. They are retained only to explain existing migration state and tests. They are not the target runtime dataset, and no new runtime or service capability should use them as design authority.


1. Contract sources

Every runtime session begins by calling these endpoints. All relative paths resolve against world.elonn.com.

Endpoint When Purpose
GET /world/identity/me On load, after any 401 Authenticated member identity — World proxies to API
GET /world/session On load, after find query Full runtime contract: surfaces, stacks, commands, field objects, Social objects, Messages objects, member directory
GET /world/panels/{service} When focusing a surface with content_source.kind = runtime_panel Service payload for that durable surface: title, summary, sections, actions, and service-specific state. Canonical right rail content is delivered as right rail surfaces, not inferred by runtimes from panel payloads.
POST /world/find/query When member submits a find query Returns updated surface_runtime with finding surfaces

Runtimes never call api, social, messages, maps, time, surface, or find directly. World is the only upstream.

The full GET /world/session payload is specified in world-contract.md.

Request rules

  • Send Accept: application/json on every World JSON request.
  • Runtimes send JSON request bodies with Content-Type: application/json.
  • Browser form submissions may use application/x-www-form-urlencoded; World accepts both JSON and form-encoded bodies for runtime form and find writes.
  • Web runtimes send credentials with cookies. Native runtimes send Authorization: Bearer <elonn_api_token>.
  • Include X-Elonn-Runtime on GET /world/session; see Compatibility capability declaration.
  • Treat all 2xx responses as success and all non-2xx responses as failures. Do not infer success from response text.

2. Contract objects

From GET /world/session

surface_runtime.surfaces[]

Each surface is a durable record scoped to the authenticated member.

Field Type Notes
surface_id string Stable runtime identifier, e.g. surface_social
surface_type string Normalized type, e.g. conversation_surface, finding_surface, profile_surface
title string Display label
service_binding object {service_id, resource_type, resource_id} — empty object {} when absent
content_source object {kind, url}kind is runtime_panel or inline; empty {} when absent
runtime_state object {summary, details: [[key, val], ...]} — PHP serializes empty as []; accept both
permissions object {can_detach, can_pin, can_share, can_field_anchor} — empty {} when absent
rendering_hints object {preferred_size, interaction_mode} — non-authoritative; empty {} when absent
placement object {mode, metadata: {stack_id, x, y, width, height, z}}

Placement modes: stacked, docked, detached, shared, field_anchored.

The title field is required surface chrome data. The runtime renders it in a surface title bar with a show/hide content control for every surface. Content visibility is UI state unless World/Surface later returns a specific persisted surface state value; either way, toggling visibility never changes stack membership, placement, focus, Field objects, or finding surfaces.

A finding surface is a surface with surface_type = "finding_surface" and placement.mode = "detached". Finding surfaces appear after a successful find query and carry runtime_state.finding. A translated finding also carries runtime_state.surface_object.

A Surface Object has surface_object_id, source_finding_id, object_type, title, summary, primary_url, branding, content, actions, and runtime_hints. primary_url is provenance, not a navigation instruction.

actions is always an ordered array of semantic descriptors with id, label, type, and optional targets. A runtime displays the supplied label. It must not derive labels or availability from object type, provider, route, or a string action name.

A place Surface Object may omit primary_url and instead carry content.location plus runtime_hints.map. The map contract contains a viewport, provider-neutral raster layer declarations, markers, and attribution. Render the declared layer with native runtime components. Do not parse provider search responses or use an embedded browser.

shell.dock.items[]

Dock items are ordered contract data. Render each item from its label, icon, and attached action. Do not hardcode service names, dock ordering, or service-specific handlers.

field_runtime.controls[]

Controls are generic selectors, toggle groups, and action items. Category ids such as coffee are opaque product data. A runtime renders labels and dispatches attached actions; it does not maintain a category registry.

services[]

Each service descriptor publishes its entry surface, content source, workspace, actions, and optional renderer hint. Resolve opening and navigation through this descriptor. Do not branch on service ids or recognize service URLs in the runtime router.

Renderer hints are optional optimizations. Unknown hints use the generic surface or panel renderer and remain usable from title, summary, sections, objects, and supported actions.

surface_runtime.stacks[]

Field Type Notes
stack_id string Stable placement target, e.g. carry_primary, left_context, right_context, finding_overlay
stack_type string e.g. carry_stack, context_stack
region string e.g. carry, context
display string e.g. full, rail
slot string Optional layout slot, e.g. left, right, center; may be empty
orientation string Stack navigation axis
focused_surface_id string|null Current focus
surface_order string[] Ordered surface ids for this stack
viewport_id string Viewport that presents this stack

Stack ids identify placement targets. Their role is described by stack fields such as region, display, slot, and orientation. Adapters must not infer product meaning from a specific id. A runtime renders every World-supplied stack whose display and region it supports; unsupported displays must degrade to a generic ordered list rather than being dropped silently. The canonical stacks currently published by Surface are:

Stack Meaning
carry_primary Center stack for dock-activated service panels and opened object surfaces
left_context Runtime and member context rail
right_context Service navigation or field controls rail
finding_overlay Detached current finding surfaces

The runtime must not remove any surface from a stack because of a service id, surface id, URL, title, or object type. If a runtime wants to hide a stack for a workspace mode, it keeps the stack in state and only changes presentation visibility.

surface_runtime.commands

focus_surface   — POST URL for writing focus: POST {url} with {surface_id}
reorder_stack   — POST URL for writing order: POST {url} with {surface_order: [...]}
update_placement — POST URL pattern for placement writes
translate_surface — POST URL pattern for translating a persisted resource finding
open_finding     — POST URL pattern for opening a place finding as a durable map surface

World may publish additional placement aliases such as detach_surface, dock_surface, field_anchor_surface, and share_surface. Those aliases resolve to World placement writes; the required minimum command set is focus_surface, reorder_stack, and update_placement.

translate_surface is required when translatable resource findings are present. Replace {surface_id} and send {}. Apply the returned surface_runtime.

open_finding is required when place findings are present. Replace {surface_id}, send {}, apply the returned surface_runtime, enter carry mode, and focus the returned map_surface. Reopening the same provider/source id must not create another durable surface. The original finding surface remains on finding_overlay until World replaces or clears that layer.

Command request bodies:

POST {commands.focus_surface}:

{"surface_id": "surface_social"}

POST {commands.reorder_stack}:

{"surface_order": ["surface_social", "surface_calendar", "surface_messages"]}

POST {commands.update_placement} after replacing {surface_id}:

{
  "placement_mode": "detached",
  "placement": {
    "stack_id": "carry_primary",
    "region": "carry",
    "display": "free",
    "x": 24,
    "y": 48,
    "width": 260,
    "height": 148,
    "z": 1
  }
}

field_runtime

Geographic objects composed server-side by world from the maps service. The runtime does not call maps directly.

Field data is requested through GET /world/session. When the runtime has a member/device location, include these query parameters:

Query parameter Type Default Notes
lat float none Member/device latitude
lon float none Member/device longitude
radius integer 1000 Meters
categories comma-separated string or repeated values all standard categories Field place categories

When lat and lon are omitted, field_runtime.objects is empty and field_runtime.origin is null. The runtime must still render the field shell and controls.

Top-level field runtime shape:

Field Type Notes
contract object {name: "elonn.field.runtime", version: 2}
origin object|null {latitude, longitude} for the returned object set
radius_meters integer Applied radius
field_width integer Logical panorama width for adapters that use it
controls Control[] Ordered selectors and toggle groups
objects Object[] Generic object envelopes with marker-capable presentation
source object Diagnostic source metadata; do not call it directly

field_runtime.objects[] fields:

Field Type
id string
type semantic object type
category opaque product data
title string
summary string
presentation card/marker preferences
location latitude, longitude, distance, bearing, and local offsets
actions ordered semantic action descriptors
attribution required provider attribution

Other session fields

  • services.social.objects{conversations, communities, events, presence} as integer counts
  • services.messages.objects{threads} for open one-to-one member message thread summaries
  • services.identity.members[] — member directory entries with {id, email, display_name}

From GET /world/panels/{service}

Panel payload shape:

Field Type Notes
kind string Service identifier, e.g. social, time, find
view string Active view within the panel
title string Display title for the containing panel
summary string One-line descriptive summary; presentation depends on region
nav array Legacy or in-panel navigation items; not the canonical right rail
sections array Panel body sections and their items
actions object Top-level action map
action_descriptors array Ordered semantic actions and producer-described form controls

The nav array is service-owned panel content for runtimes that need in-panel navigation. Each nav item has an id, a label, and an optional action URL. Items without an action are labels, not buttons. Runtimes may render nav inside the surface that loaded the panel, but nav does not define the canonical right rail. Canonical right rail content comes from right_context surfaces and their panel sections, item actions, and action_descriptors.

The sections array is service-owned content grouped for the panel body. Each section has a title and an items array. Each item has an id, title, optional summary, optional metadata, and optional actions.

Runtimes must treat panel payloads as transient service-owned content unless World also supplies a durable surface record for the same object. A panel payload does not by itself create a durable surface. A durable surface is authoritative only when it arrives through surface_runtime.surfaces[].

Panel payload state must be attached to the durable surface or modal panel that requested it. A single global "center payload" is not a valid model unless it is keyed to the currently focused durable surface and cleared when focus changes. A runtime must not replace a durable surface title, identity, placement, or stack membership with panel payload data.

If sections is empty or missing, full panel presentations must still render the title and summary plus an empty-state message. Compact rail presentations render the surface title as chrome and may omit summary/body text that is not actionable. If nav is empty, the surface must not invent navigation.

Additional service-specific keys are allowed and must be ignored when unknown.

When action_descriptors is present, render it instead of deriving behavior from action-map keys. A submit_form descriptor supplies its method, World URL, and ordered controls. Generic runtimes render text, textarea, and selector controls without knowing the product meaning of the action id.

Messages Route Reference

Messages is the reference vertical slice for service-owned panel content and World-owned runtime placement:

  • messages.elonn.local owns message threads, selected thread messages, recipient directory context, and producer action intent. Its /runtime/panel/messages?format=json payload publishes threads, selected_thread, messages, members, and action_descriptors; the start_thread descriptor uses a member-backed recipient selector when member options are available.
  • world.elonn.local is the runtime gateway. /world/panels/messages relays the Messages panel and normalizes thread objects. /world/panels/messages/rail publishes compact right rail content with a Threads row and Start thread submit_form descriptor.
  • surface.elonn.local owns durable placement. surface_messages lives in carry_primary and loads /world/panels/messages; surface_messages_rail lives in right_context, loads /world/panels/messages/rail, and declares placement.metadata.matches_surface_id: "surface_messages".
  • Runtimes load those World URLs from content_source, render the active matching right rail surface, and route open_panel/submit_form actions to the matched center surface. Runtimes must not invent Messages rail entries from service id, URL, or legacy panel nav.

From POST /world/find/query

Body:

{
  "query": "coffee",
  "scope": "nearby",
  "origin": {"latitude": 47.6062, "longitude": -122.3321},
  "radius_meters": 5000
}

The runtime chooses and visibly displays scope. Default to nearby when an existing runtime location is available. Otherwise default to everywhere and show that location was unavailable. Do not start a second permission flow for Find. Nearby without an origin returns location_required.

term near place is an explicit named-location override. Find resolves the place globally and applies its 5 km Nearby scope there. Find scope and radius are independent of Field state.

An ok response contains an updated surface_runtime with detached finding surfaces. Replace the returned surfaces and stacks. location_required and provider_error keep the previous finding overlay visible and provide a retryable status message.

If the response also includes a findings array, use it only for count/status text. The UI source of truth is still the returned surface_runtime.

The finding_overlay stack is the authoritative current query result layer. A successful query replaces its complete finding membership. Zero results produce an empty overlay without changing carry surfaces.

Finding surfaces are still durable surfaces. Render their title, summary, finding metadata, and action descriptors from surface_runtime. Do not treat a finding as a field marker unless World returns it through field_runtime. Resource findings use translate_surface; place findings use open_finding. Place finding opens create or focus a separate map_surface in carry_primary; the finding surface itself remains on finding_overlay.

From POST /world/surface/surfaces/{surface_id}/translate

Send {}. On success, replace local surface_runtime and render runtime_state.surface_object. Translation upgrades the same surface; its identity and placement do not change.


3. Required state machine

A runtime must maintain this state. Names are specification names; each runtime may use its own idiomatic names.

Lifecycle

State field Type Values
status enum idle / loading / ready / authRequired / unavailable
identity object|null {id, displayName, email} — null until authenticated

Initial values: status = idle, identity = null.

Workspace

State field Type Values
workspaceKind enum carry / field / find

Initial value: workspaceKind = carry.

Carry

State field Type
carrySurfaces Surface[] — from carry_primary stack order
leftContextSurfaces Surface[] — from left_context stack order
rightContextSurfaces Surface[] — from right_context stack order
activeRightRailSurfaceId string|null — focused right rail surface for the active center surface or workspace
stacksById Map\<string, StackRuntime> — every supported World-supplied stack
focusedCarrySurfaceId string
surfacePanelPayloads Map\<surface_id, PanelPayload> — loaded transient payloads keyed by durable surface
surfaceCommands object — write URLs from surface_runtime.commands

When carrySurfaces is empty (no items in carry_primary), focusedCarrySurfaceId is null. The runtime must not fall back to left_context or right_context surfaces to fill the carry area.

Initial values: arrays are empty, stacksById = {}, focusedCarrySurfaceId = null, surfacePanelPayloads = {}, surfaceCommands = {}.

Find

State field Type
findQuery string
findStatus string|null — human-readable status after a query
findScope enum — nearby / everywhere
findScopeExplicit boolean — whether the member selected the current scope
findingSurfaces Surface[] — from the finding_overlay stack order
findingOverlayLimit integer — how many finding surfaces are visible (default 8, increments of 8)

Initial values: findQuery = "", findStatus = null, findScope = nearby when location exists and everywhere otherwise, findScopeExplicit = false, findingSurfaces = [], and findingOverlayLimit = 8.

Field

State field Type
geoObjects GeoObject[] — from field_runtime.objects
fieldPlacesRadius integer — tiers: 500 / 1000 / 5000 m
fieldPlaceCategories Set\<string> — 10 standard categories
deviceOrientation platform-specific — heading degrees, attitude matrix, or equivalent

Standard field place categories: coffee, food, gas, hotels, shopping, parks, transit, marinas, museums, landmarks.

Initial values: geoObjects = [], fieldPlacesRadius = 500, all standard field place categories selected.

Transient panel

State field Type
panelURL string|null
panelTitle string
panelOpen boolean
panelBodyVisible boolean

Initial values: panelURL = null, panelTitle = "", panelOpen = false, panelBodyVisible = true.


4. Required behaviors

These are the behaviors the runtime must expose to the user interface.

Behavior Trigger Effect
load() App launch or runtime session refresh GET /world/identity/me; GET /world/session; apply surfaces/stacks/commands/field objects; set status
focusSurface(surfaceId) User taps carry surface Update focusedCarrySurfaceId; load panel if content_source.kind == runtime_panel; write focus
openService(serviceId) open_service action Resolve the generic service descriptor and enter its declared workspace or entry surface
openWorkspace(workspace, surfaceId) open_workspace action Enter the declared workspace and focus the supplied right rail surface when present
enterFieldWorkspace() World dock/action opens Field workspaceKind = field; keep Field markers visible; focus the Field control surface in right_context
exitFieldWorkspace() World dock/action opens a non-Field surface/workspace Leave Field workspace without clearing Field markers
enterFindWorkspace() World dock/action opens Find workspaceKind = find; keep detached findings visible; focus the Find search/control surface in right_context
exitFindWorkspace() World dock/action opens a non-Find surface/workspace Leave Find workspace without clearing detached findings
setFindQuery(text) User types in find input Update findQuery
queryFind() User submits find query POST query plus visible scope; send origin only for Nearby; apply returned surfaces and applied-scope status
translateFinding(surfaceId) User opens or previews an html_resource finding POST the supplied translate_surface command; apply returned runtime; render surface_object
openPlaceFinding(surfaceId) User opens a place finding POST the supplied open_finding command; apply returned runtime; enter carry mode and focus the returned map_surface
clearFindings() User dispatches World-provided Find clear action Apply the returned surface_runtime or command result; detached findings are not cleared by hiding panels or switching views
showMoreFindings() User taps "show next" Increment findingOverlayLimit by 8
openSurfaceAction(action) User invokes a surface or rail action Dispatch the World-provided action without inferring service behavior
openPanel(url, title) Surface action or nav item with no inline target Open a transient loading or notice panel at URL
showPanelBody() User asks to show panel body Set panelBodyVisible = true
hidePanelBody() User asks to hide panel body Set panelBodyVisible = false
closePanel() User dismisses modal Clear modal panel state and remove it from view
openSurface(surfaceId) User requests a durable object surface Focus or open the durable carry surface for the object; keep it in surface_runtime
openAction(url) Any action URL Submit or navigate to the World action URL and refresh the affected surface or panel on success
submitForm(fields, url) User submits a form POST url with form fields; refresh panel or session on success
setFieldRadius(meters) User selects radius Update fieldPlacesRadius; re-fetch field session with new radius
dispatchAction(action) Any rendered action Execute a supported semantic action; disable unknown actions without crashing
writeFocus(surfaceId) After focusSurface POST {commands.focus_surface} with {surface_id}

State application rules

  • Apply surface_runtime by indexing surfaces by surface_id, then deriving each stack's surface list from surface_order.
  • Apply right_context as the canonical right rail stack. Its active surface matches the focused center surface or active workspace according to World and Surface focus/order data.
  • Render the active right_context surface as contextual rail content. Do not render every surface in right_context.surface_order as service buttons, tabs, or dock entries.
  • Resolve service content and navigation from services[], content_source, and actions. Never infer a renderer from a service id or URL.
  • Ignore unknown additive fields. Apply declared fallback behavior to unknown services, icons, surfaces, controls, objects, placement, and actions.
  • Normalize findings, Surface Objects, and panel section items into the common object envelope before rendering. Unknown object types use a generic title/summary/action card.
  • Render actions from ordered descriptors. A known but locally unavailable action is disabled; an unknown action follows its fallback policy.
  • Standard workspace/action types include open_surface, focus_surface, open_service, open_workspace, set_field_filter, set_radius, submit_query, translate_surface, open_finding, clear_findings, and placement command aliases published by World.
  • open_panel from a right rail item loads the supplied World URL into the matched center surface identified by placement.matches_surface_id.
  • submit_form from a right rail command opens the producer-described form in the matched center surface or active workspace. The runtime must not submit an empty form merely because the descriptor exists.
  • Preserve local UI-only state only when it does not contradict a fresh World response. World response data wins.
  • After a successful panel action or form submission, re-fetch the current panel URL and replace the panel payload. Do not patch service-owned lists from runtime assumptions.
  • A 409 or 422 form response is an inline form error. Keep the current panel payload and entered fields visible; do not mark the entire runtime unavailable.
  • After queryFind(), replace local surface_runtime with the returned surface_runtime, recompute stack lists, recompute findingSurfaces, reset findingOverlayLimit to 8, and leave the focused carry surface unchanged when it still exists.
  • clearFindings() must use a World-provided action or returned runtime state. It must not delete durable surfaces through unlisted service calls.
  • setFieldRadius() updates local filter state. If World exposes a radius-aware session endpoint later, use that World endpoint only; do not call Maps directly.
  • To refresh field objects after a field-control action, call GET /world/session again with the resulting location and filter inputs; apply the returned controls and objects.

5. Render model

Every runtime must render the primitives supplied by World. Spatial layout and presentation technology are platform-specific; browser rails are one adapter choice, not a contract requirement.

Primitive Required behavior
Shell and dock Render ordered shell actions using platform-appropriate controls
Workspace Present the active workspace declared by a service or action
Stack and surface Preserve World order, focus, placement, title, content, and supported actions
Center carry stack Render carry_primary display: full surfaces as full panel surfaces in an ordered carousel; neighbor surfaces remain full panels, not cards or title-only previews
Panel Present transient content without treating it as a durable surface
Surface chrome Render a title bar and show/hide content control for every surface; hiding content keeps the title bar visible
Right rail Render the active right_context surface as compact contextual nav/controls; title is chrome, items/actions are the usable controls, summaries are not primary rail rows
Field and marker Project or list field objects behind panels according to device capabilities
Detached findings Render finding_overlay above field and behind carry/rail panels until changed by World-provided actions
Object and card Render a generic title/summary/action presentation when no specialization exists
Control Render known control primitives and disable unsupported controls safely
Attribution Display required provider attribution without provider-specific branching

When surface_calendar is open, Time must render native day, week, month, agenda, and task views from the World Time workspace payload. It must support appointment and task create/edit/delete actions, task completion, calendar assignment, description, location, all-day state, priority, status, timezone, recurrence, and reminder fields. It must also support calendar create, edit, and delete, preserve view/date/timezone across refreshes, and disable Social-owned mirror fields according to editable_fields. A generic list of calendars and events is not a conforming Time workspace.

Minimum UI states

  • If status = loading, show a loading state in the primary runtime surface.
  • If status = authRequired, show or open the login interface and provide a retry path after login.
  • If status = unavailable, show a retryable unavailable state. Do not render stale service data as fresh.
  • If carrySurfaces is empty, show an empty carry workspace. Do not synthesize default carry surfaces.
  • If a transient panel has no sections, show its title and summary and an empty notice state.
  • If any surface's content visibility is false, keep the title bar visible and hide only the content container.
  • If panelOpen = false, remove the panel entirely.
  • If a required command is absent, do not synthesize a route. Disable the corresponding action or leave optimistic local state non-persistent.
  • If there are no field objects after filtering, show an empty field state while keeping field controls usable.
  • If there are no finding surfaces after a successful query, show a zero-results find state and keep the previous non-finding carry surfaces.
  • If translation fails, keep the original finding visible and show a retryable inline error.
  • Render Surface Objects with native components. Never inject source HTML or execute source scripts.
  • If Find returns location_required, keep existing findings and ask the member to enable location or include a named place.
  • Field markers and detached findings remain visible behind panels. Hiding a panel's content reveals them; it does not clear or mutate them.
  • Background rendering of any service surface must not change workspaceKind; only explicit member navigation changes workspaces.

6. URL resolution

  • https:// or http:// URL → use as-is
  • Path starting with /https://world.elonn.com + path
  • Relative path → https://world.elonn.com/ + path

All panel and action URLs in the world contract are relative paths. The runtime constructs absolute URLs for requests only; it does not hard-code service hosts other than world.elonn.com.


7. Error handling

Error Response
HTTP 401 on any request Set status = authRequired; show auth panel
HTTP 403 on any request Show unavailable or inline permission error; do not retry as another member
HTTP 404 on a panel/action URL Show inline not-found error for that panel/action
HTTP 409/422 on write/form submit Show inline validation/conflict error and leave existing runtime state in place
Network/server error on load() Set status = unavailable with message
Panel load failure Show error text in panel region; do not crash or leave region blank without message
Find query failure Set findStatus to an error string; leave findingSurfaces unchanged
Find location required Keep findings unchanged; show a location-required status
Resource translation failure Keep the finding surface unchanged; show an inline retryable error
Form submit failure Show error inline; do not dismiss the form

Retries are user-initiated unless the platform provides a standard transient network retry. A retry must repeat the same World request with the same authenticated member credential.


8. Auth model

Runtimes authenticate through World. The identity endpoint GET /world/identity/me returns the authenticated member; World proxies to API internally. Runtimes do not call API directly.

The credential is the elonn_api_token value:

  • Web: Sent as a cookie automatically via credentials: 'include'. Login runs at elonn.com/account/login in the same browser session.
  • Native (Android, iPad, headset runtimes): Present the configured login URL in a WKWebView / WebView, complete the standard browser login, read the elonn_api_token cookie from that login session's cookie jar, and send it as Authorization: Bearer <token> on all requests to World. Native runtimes do not ask for a manual app token.

A 401 from any World endpoint means the credential is missing or expired. Set status = authRequired and show the login interface.


9. Runtime projection capability classes

Runtime capabilities describe how a runtime can project the canonical runtime dataset. They do not describe service behavior and do not create a runtime-specific dataset.

World may use a runtime capability declaration to include fallback state, degraded availability, or optional data that is already part of the canonical runtime dataset. World must not branch on runtime product name, and runtimes must not ask services for alternate runtime-specific contracts.

The current target capability classes are:

Capability class Typical capabilities Runtime projection responsibility
flat_viewport viewport_rendering, pointer_input Project workspace objects and contexts into a flat visual scene. Field objects may be listed when field projection is unsupported.
camera_overlay camera_background, heading_sensor, field_projection, touch_input Project field objects relative to camera heading and render contexts in native controls.
spatial_room spatial_anchors, field_projection, hand_tracking, volumetric_media Project objects into anchored or volumetric platform-native scene nodes.
nonvisual audio_output, voice_input, linear_navigation Project workspace, context, field, and finding state into ordered prompts and command choices.

The following dataset semantics are invariant across all projection classes:

  • object ids, object types, source references, permissions, action references, relationships, placement anchors, and focus metadata;
  • context ids, context items, action references, and targets;
  • action ids, action types, World command URLs, controls, availability, and fallback policy;
  • workspace item ids, focus order, active object, active context, and continuity state;
  • field id, field object ids, world object references, locations, attribution, and fallback state;
  • finding ids, source references, object types, titles, and action references.

A runtime may change scene construction, renderer-native layout, coordinate projection, input mapping, local focus presentation, and media realization. It must not change business meaning, infer permissions, create service routes, translate source references into direct service calls, or add Calendar, Social, Find, Maps, Messages, or other service business rules.

Unsupported capabilities are represented by fallbacks[] and action fallback metadata. A runtime renders that explicit fallback data. It does not invent a service-specific substitute. Unknown capabilities are ignored by older runtimes and older World versions; unknown object, context, action, or field properties are rendered generically or ignored according to fallback data.

The canonical projection class fixture is projection-capability-classes.json.

10. Compatibility field projection model

Each runtime projects field objects onto its display surface using bearing_degrees and distance_meters from the contract.

Web (panorama):

projectedX   = ((bearing + 180) % 360) / 360 × fieldWidth
projectedY   = clamp(120 + distance × 0.28, 84, 520)

Android / iPad (camera overlay):

relativeBearing = (bearing − deviceHeading + 360) % 360, folded to [−180, 180]
cull if |relativeBearing| > hFOV / 2
projectedX = (relativeBearing / hFOV + 0.5) × viewportWidth
projectedY = clamp(120 + distance × 0.28, 84, 520)

Category ids and control choices are contract data. A runtime never assumes a fixed category set.

The canonical examples and expected projection outputs are in Runtime Contract v2 Conformance Corpus.

The corpus also defines behavioral state transitions and exact World command requests for focus, order, placement, panels, authentication, and unavailable states. Runtime implementations must pass those scenarios without relying on Web code.


11. Compatibility surface stack gesture model

The gesture model is defined here as the platform standard. All runtimes implement these parameters using their platform's native rendering system.

  • Drag threshold: 0.18 × viewport height to advance to the next surface
  • Velocity threshold: ±650 pt/s (or platform-equivalent units) to trigger advance on release
  • Tap detection: drag travel < 4% of viewport height with no qualifying velocity → focus that surface directly

Carry stack visual parameters:

  • Offset per position step: 82 logical units
  • Scale reduction per step: 0.10 per offset unit
  • Minimum opacity: 0.34

Rail stack visual parameters:

  • Offset per position step: 48 logical units
  • Scale reduction per step: 0.06 per offset unit
  • Minimum opacity: 0.42

The specific rendering mechanism (CSS transforms, Android Compose modifiers, SwiftUI geometry, etc.) is the runtime's responsibility. Only the numeric parameters are specified here.


12. Compatibility capability declaration

Every runtime must declare its capabilities when initiating a session. Capabilities are sent as a JSON-encoded X-Elonn-Runtime header on GET /world/session.

{
  "runtime": "cardboard",
  "version": "0.1.0",
  "capabilities": {
    "dock": true,
    "surface_stacks": true,
    "camera_background": true,
    "field_markers": true,
    "stereo_rendering": true,
    "headset_mode": true
  }
}

World may use declared capabilities to tailor the session response — for example, omitting field projection data for a runtime that declares no field support, or including richer spatial data for a runtime that declares geospatial anchors.

Runtime behavior must be capability-driven, not platform-name-driven. World must never branch on runtime name. If a behavior difference is needed, it must be expressed through a capability.

In the target architecture, the capability declaration informs World fallback state and lets runtimes decide how to project the canonical runtime dataset. The dataset itself must not become docks, stacks, rails, sheets, panels, markers, anchors, volumes, command groups, nonvisual prompts, or other renderer instructions.

Capabilities are open-ended. New hardware will introduce capabilities not listed here. Declare all supported capabilities; omit unsupported ones. Unknown capabilities are ignored by older World versions.

Current standard capabilities:

Capability Meaning
dock Runtime renders ordered shell dock items
surface_stacks Runtime renders ordered, focused surface stacks
camera_background Runtime can render the field layer over a live camera feed
field_markers Runtime renders field geo objects
compass Runtime has access to a compass or equivalent heading source
earth_anchors Runtime supports world-anchored object placement
native_share Runtime exposes a platform-native share action
offline_cache Runtime supports offline operation with cached data
stereo_rendering Runtime renders split-screen stereoscopic output (e.g. VR headset)
headset_mode Runtime is used inside a head-mounted display; touch interaction is unavailable or secondary
gaze_input Runtime supports head-gaze as a pointing input — the heading vector is the cursor
trigger_input Runtime has a single hardware confirm input (e.g. Cardboard magnetic trigger, controller trigger)
pointer_input Runtime has a continuous pointer device (Bluetooth mouse or controller stick used as raycast cursor)

13. Development environment

Every runtime must support configurable World and login endpoints. Production endpoints must be replaceable with alternate deployment endpoints at build or launch time without code changes.

This allows a runtime to be developed and tested against the deployment target used by the project without code changes. The deployment environment provides real data structures, real auth, and real service behavior — no fake datasets.

A runtime is not considered buildable until it can authenticate and load a session against the configured deployment target.


13. Compatibility implementation checklist

Build in this order:

  1. Runtime config: environment-selectable World base URL, login URL, runtime id, version, and capabilities.
  2. Auth: obtain elonn_api_token, call GET /world/identity/me, handle 401 by showing login.
  3. Session load: call GET /world/session with X-Elonn-Runtime, decode surface_runtime, field_runtime, and services.
  4. Stack derivation: index surfaces by surface_id, preserve every supported stack, and derive stack frames from each stack's surface_order and focused_surface_id.
  5. Carry render: render focused carry surface, neighbor surfaces, left rail, right rail, top dock, and bottom dock without dropping surfaces by service id or URL.
  6. Focus writes: on carry focus, update local focus and POST {surface_id} to surface_runtime.commands.focus_surface.
  7. Panel loading: when focused surface has content_source.kind = runtime_panel, fetch content_source.url, render nav, sections, and actions, and keep the panel transient unless World also supplies a durable surface record.
  8. Workspace switching: implement carry, field, and find modes without changing service state.
  9. Field render: render field_runtime.controls[], dispatch attached actions, refresh through World, and project returned field_runtime.objects[].
  10. Find: submit POST /world/find/query, replace local surface_runtime with the returned one, render finding_overlay above field and behind panels, show count/status, and clear only through World-provided actions.
  11. Translation: open an html_resource through translate_surface, replace runtime state, and render its Surface Object without browser behavior.
  12. Place open: open a place finding through open_finding, render the returned map_surface in the center stack with marker and attribution, and preserve place details if map assets fail.
  13. Placement writes: for movable/detachable surfaces, post placement changes to the URL from update_placement after replacing {surface_id}.
  14. Error states: implement the error handling table exactly enough that no failed request leaves a blank or crashed region.
  15. Local verification: submit web and place queries, translate a web result, open a place result, refresh, and confirm the durable surfaces reload from World.

14. Compatibility acceptance criteria

A runtime passes runtime contract acceptance when all of these are true:

  • It can run against local and production World endpoints by configuration only.
  • It can be implemented from the Runtime Contract and contract examples without reading existing runtime or service code for hidden behavior.
  • It consumes the shared Runtime Dataset v1 conformance corpus as first-class test input and passes every fixture/scenario relevant to its declared capabilities. Existing runtimes may also use Runtime Contract v2 fixtures as migration tests.
  • It never calls API, Social, Messages, Maps, Time, Surface, Find, or provider services directly after token acquisition.
  • It sends X-Elonn-Runtime on GET /world/session.
  • It renders exactly the surfaces supplied by surface_runtime; it does not synthesize carry surfaces when a stack is empty.
  • It preserves every supported World-supplied stack, including finding_overlay, and keeps carry focus independent of left/right context surfaces.
  • It derives stack focus from surface_runtime.stacks[].focused_surface_id, not from whether a panel payload happened to load.
  • It renders dock items only from shell.dock.items[] and does not hardcode dock membership, labels, icons, or order.
  • It renders canonical right rail content from the active right_context surface, not from runtime-inferred service panel nav, and does not expose right_context.surface_order as service switching UI.
  • It renders a title bar and show/hide content control for every surface, and hiding content keeps the title bar visible.
  • It keeps Field markers and detached findings behind panels and does not clear them when panels are hidden or workspaces change.
  • It loads panels only from World URLs supplied by content_source.url and keeps panel chrome separate from durable surfaces.
  • It keys panel payloads to the durable surface or modal that requested them and never uses panel payload data as durable surface identity.
  • It renders full panel payloads with title, summary, nav, sections, and actions, including empty and error states. Compact rail presentation uses the right rail contract above: surface title as chrome, panel items and action descriptors as controls, and summary only where the runtime has a non-primary presentation affordance such as a tooltip or detail view.
  • It refreshes the current panel after successful panel actions and form submissions, while preserving the current panel on inline validation errors.
  • It submits find queries only to /world/find/query and renders returned finding_surface objects from surface_runtime.
  • It translates web resources only through the supplied World command and renders normalized Surface Objects.
  • It opens place findings only through the supplied World command and renders the resulting durable center-stack map surface with visible attribution.
  • It never renders arbitrary source HTML, executes source JavaScript, or navigates to source URLs.
  • It projects field objects from field_runtime.objects[] without calling Maps.
  • It routes focus, reorder, and placement writes through surface_runtime.commands.
  • It handles 401, failed load, failed panel load, failed find query, and failed form submit without crashing or showing a blank primary region.
  • It preserves member scoping by never sending or storing another member id in runtime requests.
  • It has a documented runtime id, version, capability set, local endpoint configuration, and manual test path.