OCP Embed profile — normative specification (v1.0-draft)
Extends Core. The widget: <script defer src=".../ocp.js" data-site="KEY">.
Topology
- Loader ≤15 kB; chat renders in an IFRAME (origin isolation). Host↔iframe via
postMessagewith strict origin checks in BOTH directions; iframe↔Hub via WSS. The host page NEVER sees Hub traffic; the iframe NEVER accepts messages from anything but its declared Hub origin. - The loader MUST be served with SRI hashes; the widget MUST be cookie-less at T0 (visitor continuity via localStorage, rotating id).
Host ↔ widget messages (contract: embed.ts)
Host → widget (hostToWidgetSchema):
ocp.setContext { context }— zero-config fields the loader captured (url, title, meta description, selection ≤8 KB) plus anything the host merges in.ocp.open/ocp.close— show/hide the panel.ocp.identify { visitorJws }— signed visitor identity (account-bound, T1+).
Widget → host (widgetToHostSchema):
ocp.ready— the iframe is mounted and listening; the host MUST queue any earlier host→widget messages and flush them on receipt (the loader core does this).ocp.state { phase }— idle | connecting | live | error.ocp.event { name, data? }— host analytics hook. Message CONTENT never leaves the iframe unless the host opts in.
A host→widget message MUST target the exact Hub origin; a widget→host message
MUST be dropped unless event.origin equals the Hub origin.
Host API (loader core: @schwaizer/ocp-embed)
ocp.setContext(…), ocp.open(), ocp.close(), ocp.identify(visitorJws),
ocp.on(listener). Zero-config context (URL, title, meta description, user
text selection) is captured with no host wiring (captureContext).
T0 protections
- Site-key + origin allowlist (
originAllowed: exact,*.suffix, or*for dev only); per-visitor/IP quotas; challenge before first session; tenant budgets with hard cutoffs.
Status
Loader core (context capture, origin-checked bridge, host API) is implemented
and unit-tested in @schwaizer/ocp-embed. The browser entry (real
document/window/iframe wiring, the ≤15 kB <script> payload, SRI, and the
in-iframe chat UI holding the WSS leg) is the remaining browser-verified work.