Supported baseline: LG webOS TV 22+ or webOS OSE 2.7+. The Luna service bundle targets ES2019 CommonJS and Node.js 12.14.1 or newer. The SDK is pure JavaScript and does not load the desktop Node native library.
Install the onboarding tarball
Section titled “Install the onboarding tarball”Place the supplied package in the Luna service project, then install it without optional native accelerators:
npm install --save-exact --omit=optional \ ./artifacts/p2psdk-webos-2.0.0.tgzThe webOS package has its own version, 2.0.0, within the P2PSDK 1.0.0 onboarding release. It is not available from the public npm registry. Keep the tarball in an access-controlled artifact store and do not copy the API key or consent configuration into the browser app bundle.
Split the app and service
Section titled “Split the app and service”Use separate application and Luna service IDs. The service ID must begin with the application ID:
com.example.productcom.example.product.p2psdkThe browser app owns presentation, remote-control focus, the hosted consent frame, and sanitized status. The Luna service owns the API key, persistent identity, receipt verification, bootstrap, WebSocket, TCP, and UDP traffic.
Register the Luna service
Section titled “Register the Luna service”Create the service from the @p2psdk/webos/service entry point:
import path from 'node:path';
import { createWebOsSdkService } from '@p2psdk/webos/service';
const controller = createWebOsSdkService({ application: { appId: 'com.example.product', serviceId: 'com.example.product.p2psdk', storagePath: path.join( process.env.HOME ?? '/tmp', 'p2psdk-state.json', ), }, credentials: { apiKey: process.env.P2PSDK_API_KEY!, }, endpoints: { bootstrapUrl: process.env.P2PSDK_BOOTSTRAP_URL!, consentUrl: process.env.P2PSDK_CONSENT_URL!, revokeUrl: process.env.P2PSDK_CONSENT_REVOKE_URL!, }, consent: { version: process.env.P2PSDK_CONSENT_VERSION!, publicKeyPem: process.env.P2PSDK_CONSENT_PUBLIC_KEY!, }, transport: { maxConcurrentStreams: 1024, maxBufferedReceiveBytes: 16 * 1024 * 1024, maxBufferedSendBytes: 16 * 1024 * 1024, },});
controller.register();Use HTTPS bootstrap, consent, and revoke endpoints. WSS is required for the peer connection. Development-only insecure transport and private-target overrides must not ship in production.
The service persists a random install seed and accepted receipt atomically at storagePath. Keep this file in persistent service storage and do not share it between devices or application IDs.
Call the service from the app
Section titled “Call the service from the app”Subscribe to luna://com.example.product.p2psdk/state and treat data.connection.online as the authoritative online signal. connect only starts the supervised connection; it does not mean the peer is online yet.
The registered methods are:
statewith{ subscribe: true }returns current state and future transitions.connectstarts only after verified consent is persisted.disconnectstops transport and preserves consent.submitConsentaccepts{ decision, version, nonce, receipt }, then verifies and commits the decision.revokeConsentrevokes remotely before deleting local consent.dismissErrorclears the presentation error.diagnosticsreturns sanitized state and SMUX counters.
Only the configured application ID may call the service. Treat a Luna response as successful only when its returnValue is true, then read the typed result from data.
Validate hosted consent
Section titled “Validate hosted consent”Load the onboarding consent URL in an iframe or hosted web view. Before forwarding a result to submitConsent, verify all of the following in the app:
event.sourceis the exact consent frame window.event.originequals the configured HTTPS origin.- The message type, decision, consent version, and nonce match the active request.
- An accepted decision contains a compact receipt.
The Luna service independently verifies the RS256 signature and binds the receipt to the decision, consent version, nonce, API key, device identity, and expiry before persisting it. The private receipt-signing key must never ship in the app, service, configuration, or test fixture.
Package the IPK
Section titled “Package the IPK”Build the browser app and ES2019 CommonJS service, then package both directories together:
ares-package path/to/app path/to/service -o path/to/outputThe combined package is target-neutral. Use the same app/service output for supported TV and OSE versions, but validate every generation in the product support matrix. Keep secret-bearing generated service configuration out of the browser bundle and write it with owner-only permissions.
Lifecycle and background behavior
Section titled “Lifecycle and background behavior”ActivityManager keep-alive is best effort. webOS may suspend the service even while a connection is desired. On resume, the SDK follows the bootstrap-provided reconnect policy.
disconnectcloses transport resources but keeps consent for a later connection.- Successful
revokeConsentcloses the runtime and removes the accepted receipt. - Failed revocation preserves consent and the active state so the user can retry safely.
- Final service shutdown must stop or dispose the controller before service-owned resources are released.
Do not promise uninterrupted background operation or reward traffic that has not been confirmed by the online state.
webOS verification
Section titled “webOS verification”- Install and launch the combined IPK on physical TV and OSE devices.
- Test consent accept, decline, invalid/expired receipt, restart, and revoke failure/retry.
- Suspend and resume the app and service, interrupt the network, and confirm supervised reconnection.
- Exercise TCP, UDP, DNS, and private/reserved-target rejection.
- Validate Back and arrow-key focus behavior without exposing credentials to the browser app.
- Inspect
diagnosticsand packaged files to confirm that API keys, receipts, tokens, and consent URLs are not logged or included in the app bundle.