Portal host contract
Overview
The portal host is the stable mounting boundary for product UI modules. A
module implements portal.Module; a module that needs canonical host URLs may
also implement portal.ContextModule; a GX-ready module can implement
portal.FrameworkModule or expose a lower-level portal.ModuleContract.
The host normalizes modules, publishes deterministic metadata at /v1/modules,
serves shared CSS assets, applies browser security headers, and dispatches
mounted routes under token-aware /modules/<id>/... URLs. Product modules use
the host contract instead of hard-coding standalone roots, asset paths, token
segments, or CSP additions.
Module Metadata
The public module metadata is derived from Go interfaces, not from an
operator-authored descriptor. Stable IDs use lowercase letters, digits, and
hyphens. Readiness is stable for normal opt-in modules or experimental for
modules that require explicit experimental enablement. The default-enabled flag
controls the module set mounted when the operator does not request a specific
module list.
| Go value | Metadata | Rule |
|---|---|---|
ID() |
id |
Stable route slug. Changing it changes mounted URLs. |
Title() |
title |
Public label for launchers and navigation. |
State() |
state |
stable or experimental; unsupported values normalize to stable. |
DefaultEnabled() |
default_enabled |
Included in the implicit module set when true. |
NavItems() |
nav_items |
Public labels and same-origin route paths. |
UIFramework() or ModuleContract()
|
render roots, WASM runtime, required browser effects, public runtime config, provider API origins, assets | Additive framework metadata derived from Go declarations. |
ValidateModuleContract and ValidateFrameworkContract enforce the mount-time
rules. A safe name is non-empty and may contain letters, digits, hyphens,
underscores, dots, and colons. Safe route paths start with /, do not start
with //, and do not contain backslashes, .., tabs, or newlines. Safe HTML
mount IDs use the safe-name character set but cannot start with a digit.
Render root entries use safe names, safe route paths, and safe HTML mount IDs.
WASM runtime asset paths and module asset paths are same-origin paths: they
cannot be empty, absolute URLs, host-qualified paths, query-only values,
fragment-only values, traversal paths, or paths with backslashes, tabs, or
newlines. Required browser effects use safe names for their name, kind,
optional event, optional action, and projected fields; target IDs use a safe
HTML mount ID when present. Public runtime config keys use safe names and must
not contain terms such as secret, token, password, credential,
private, or jwt. Provider API origins accept 'self' or HTTP(S) origins
without paths, queries, or fragments.
ModuleContractFor returns the deterministic live metadata snapshot. It sorts
valid entries and omits unsafe optional entries so /v1/modules remains stable
and browser-safe.
Invalid required module fields reject mounting: empty or unsafe module IDs,
empty titles, unsafe base routes, invalid mount IDs for declared render roots,
and unreadable framework contracts fail validation before the module is
published. State() is the only normalized required value; unsupported states
become stable so older modules stay visible. Unsafe optional framework
entries such as bad asset paths, rejected provider origins, unsafe runtime
config keys, or malformed browser-effect fields are omitted from the metadata
snapshot and reported through validation diagnostics, so missing routes,
assets, or runtime metadata can be traced to the rejected field.
Host Context
portal.HostContext is the request and render context passed by the host. It is
available through HandlerWithContext, through portal.HostContextFromRequest,
and through portal.UIRenderContext when a framework page is rendered in a
unit fixture.
| Go field | Semantics |
|---|---|
ModuleID |
Normalized module ID used by host routing and metadata. |
BasePath |
Canonical token-aware module path such as /tok/modules/notes/. |
ThemeAssetURL |
Host-served portal-theme.css URL. |
UIKitAssetURL |
Host-served uikit.css URL. |
PublicRuntimeConfig |
Public string configuration after secret-looking keys have been filtered. |
ProviderAPIOrigins |
Declared provider origins that extend the host connect-src policy. |
Modules build same-origin links with HostContext.ModuleURL(path) or with
typed Bus UI props that receive host context. Go WebAssembly receives only the
JSON-safe runtime subset published through metadata or injected by the host; it
does not receive server-only helpers or secret token values.
Consequence
Feature modules remain portable across local token URLs, hosted portal routes, and distribution-specific module sets. Provider APIs continue to enforce authentication, authorization, CSRF/session policy, account scope, and business rules; the portal host provides routing and browser delivery, not product authority.