Elonn Docs Platform Documentation

Surface Contract

surface.elonn.local publishes the member-scoped runtime surface contract consumed by world.elonn.local.

World reads:

GET /runtime

World supplies trusted member context in X-Elonn-Member-Id when it reads Surface runtime state and embeds the returned surface_runtime object in /world/session.

Surface is the authority for durable surface state only: surface identity, stack membership, focus, placement, permissions, content binding, rendering hints, and surface session lifecycle. Service content remains owned by the service named in service_binding and loaded through content_source.

Surface also owns resource translation: converting external representations into runtime-safe Surface Objects. This does not transfer ownership of the source resource to Surface.

Runtime payload

{
  "contract": {
    "name": "elonn.surface.runtime",
    "version": 1
  },
  "surfaces": [],
  "stacks": [],
  "viewports": []
}

Surface object

Each entry in surfaces is a durable surface record.

Field Type Meaning
numeric_id integer Database id, internal to Surface
surface_id string Stable runtime id, for example surface_find
surface_type string Normalized surface type
title string Runtime display title
service_binding object Service/resource identity for the surface
content_source object Where the runtime gets body content
runtime_state object Runtime-safe state summary
permissions object Runtime affordance flags
rendering_hints object Non-authoritative presentation hints
placement object Current placement mode and metadata

content_source.kind is usually runtime_panel or inline. A runtime_panel URL points to a World panel endpoint such as /world/panels/social; the source service still owns the panel data. In the current runtime contract, runtime_panel is a content source, not a user-visible carry-panel product surface. Real workspaces render into durable center-stack surfaces, while transient notices may still use a short-lived panel bridge.

Object-valued fields are always JSON objects. Empty service_binding, content_source, runtime_state, permissions, rendering_hints, and placement.metadata values serialize as {}, not [].

Canonical durable workspace types: web_surface, document_surface, map_surface, calendar_surface, conversation_surface, community_surface, event_surface, finding_surface.

Canonical runtime/context types: profile_surface, dashboard_surface, service_nav_panel (transient service navigation or notice panel).

Web-extracted types produced by multi-surface translation:

Type Produced when
web_business_surface Schema.org LocalBusiness/Restaurant/Organization/FoodEstablishment found
web_hours_surface openingHours or openingHoursSpecification found on any schema object
web_menu_surface hasMenuSection/menuSection or @type: Menu/MenuSection found
web_events_surface One or more future @type: Event objects found
web_gallery_surface Two or more distinct ImageObject entries found
web_article_surface @type: Article, NewsArticle, BlogPosting, or Review found
web_contact_surface @type: ContactPage found

Surface Objects and translation

runtime_state.surface_object contains normalized content that any runtime can render without parsing the source format:

{
  "surface_object_id": "surface:...",
  "source_finding_id": "brave:...",
  "object_type": "resource",
  "title": "...",
  "summary": "...",
  "primary_url": "...",
  "branding": {},
  "content": {},
  "actions": [
    {"id": "save", "label": "Save", "type": "save_object"},
    {"id": "share", "label": "Share", "type": "share_object"}
  ],
  "runtime_hints": {}
}

primary_url is provenance, not a runtime navigation instruction. Surface Objects never contain arbitrary HTML, CSS, scripts, forms, tracking markup, advertisements, cookie prompts, or browser chrome.

Actions are ordered semantic descriptors. Surface owns their labels and types; runtimes do not infer actions from object_type or translate string names into UI.

An html_resource finding starts as a lightweight finding surface. A member action calls the World translation command, and Surface runs the multi-surface translator against the resource.

Multi-surface path (structured pages): When Schema.org JSON-LD is present, the translator runs type-specific extractors in priority order (Business → Article → Hours → Menu → Events → Gallery → Contact). Each extractor that finds sufficient data returns a typed surface object. Surface creates one new surface record per extracted object and replaces the original finding surface's slot in the finding_overlay stack with the new typed surfaces. The original finding surface is retained in the database (not deleted) with runtime_state.translation.status = "expanded" so the raw finding payload is available for audit or re-translation.

Fallback path (unstructured pages): If the multi-surface translator returns no surfaces (no JSON-LD or no recognized types), Surface falls back to the html_translator, which reads Schema.org JSON-LD, canonical and standard metadata, OpenGraph, Twitter card metadata, icons, theme color, publisher, title, description, and images. It produces a single generic resource or place object and upgrades the finding surface in place. Repeated translation on this path returns the persisted object unless an authorized refresh is requested.

Cache behaviour: A finding surface already in the expanded state (has runtime_state.translated_surface_ids) returns the current runtime immediately without re-fetching unless refresh=true is supplied in the translate request.

A place finding opens as a durable map_surface in carry_primary. Surface converts the finding into a place Surface Object and requests a provider-neutral map presentation from Maps. The original finding remains a finding; opening it does not move the finding surface into the center stack. Repeated opens of the same provider/source id focus the same map surface.

The place Surface Object includes content.location, runtime_hints.presentation_status, and runtime_hints.map. The map value uses the elonn.map.runtime contract and contains a viewport, declared layers, markers, and attribution. A runtime renders those declared assets natively; it does not receive OSM response formats or embedded browser content.

Stack object

Each entry in stacks is a member-scoped ordered collection of surfaces.

Field Type Meaning
numeric_id integer Database id, internal to Surface
stack_id string Stable stack id, for example carry_primary
stack_type string Stack role, for example carry_stack
region string Runtime region, for example carry or context
display string Runtime display mode, for example full or rail
slot string Optional contextual slot
orientation string Stack navigation orientation
focused_surface_id string Current focused surface id
surface_order array Ordered list of surface ids
viewport_id string Viewport that presents the stack

Canonical stack ids:

Stack Role
carry_primary Center workspace
left_context Runtime and user context rail
right_context Service navigation or field controls rail

Viewport object

Each entry in viewports describes a runtime presentation region.

Field Type Meaning
viewport_id string Stable viewport id
viewport_type string Viewport behavior, stack
region string Runtime region
slot string Optional contextual slot
display string Display mode
neighbor_visibility number Adjacent surface visibility hint

Runtime writes

Runtimes write through World. World derives trusted member context and relays the write to Surface.

Place findings use:

POST /world/surface/surfaces/{surface_id}/open

The successful response contains the opened surface and the complete updated surface_runtime. The runtime applies that state, enters carry mode, and focuses the returned map surface.

POST /world/surface/stacks/{stack_key}/focus
POST /world/surface/stacks/{stack_key}/reorder
POST /world/surface/surfaces/{surface_id}/placement
POST /world/surface/surfaces/{surface_id}/translate

focus body:

{
  "surface_id": "surface_social"
}

reorder body:

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

placement body:

{
  "placement_mode": "stacked",
  "placement": {
    "stack_id": "carry_primary",
    "region": "carry",
    "display": "full"
  }
}

Allowed placement modes: stacked, docked, detached, shared, field_anchored.

Translation has no runtime-supplied URL. Surface reads the persisted finding from the member-owned surface, validates and fetches its public HTTP(S) source, and returns the updated surface_runtime.

Surface's internal service endpoints still require trusted member context; runtime clients do not send it.

Member scoping

Trusted member context is part of the Surface runtime contract. Reads and writes for one member must not alter another member's stack rows, focus, order, or placement.

Runtime reads without member context are rejected. The database enforces one stack row per (member_id, stack_key) and does not retain global member_id = NULL stack rows.

Persistence behavior

Runtime reads are additive. When a member runtime asks for surface_runtime, Surface may create missing canonical stacks, append missing default surfaces, and create missing placement rows. It must not clear stack items, reorder an existing stack, overwrite valid focus, or reset an existing placement during a read.

Definition changes are additive:

  • a newly introduced default surface is appended to the member's stack
  • an existing user order is preserved
  • an existing valid focused_surface_id is preserved
  • an existing placement is preserved
  • a removed or renamed default surface is not automatically deleted from a member stack

focused_surface_id is member-level persisted focus. It is not a realtime cross-runtime synchronization rule. Per-runtime or per-device session focus should be modeled separately from durable member stack membership and order.

Verification

The contract is covered by smoke tests in the producing services:

bash surface.elonn.local/test.sh
bash world.elonn.local/test.sh

Surface verifies trusted member context, normalized payload fields, object-valued JSON shape, focus/order persistence, and cross-member focus isolation.

World verifies that /world/session preserves the normalized surface_runtime object and publishes World relay command URLs without exposing member_id or direct Surface service URLs to runtimes.