Plugin Runtime and Security

Execution Location

Operational plugin code, credentials, processes and accessed files stay on the selected Desktop / Runner; declared UI modules may run in the current Web, Desktop or native mobile client. Web, mobile, and the service request work; Runner executes it. Start authoring with the Quickstart.

ComponentResponsibility
Web / mobileInstallation, setup, permissions, approval and platform UI modules; no operational credentials
APICatalog, installations, permissions, device validation, signed request routing
WorkerChat tool preparation, device dispatch, incomplete-operation recovery
Electron MainIsolated configuration prompts and OS-backed credential storage
RunnerRequest validation, package verification, processes, incoming-message journals
ProviderApproved business calls through the common stdio MCP contract

The service never starts providers or substitutes another device when the selected one is offline. See the capability types for general MCP and client-loading limitations.

Device Connectivity

Enrollment stores a long-lived public-key identity. A lease is an expiring online proof. Desktop reconnects reuse enrollment and renew the lease. Revocation changes device generation and rejects old connections and requests.

Interactive configuration uses a short-lived user-gesture ticket. The Runner control channel uses a WSS ticket at /liyanlabs/ws/v1/runner/device.

The Redis device bridge routes to the API instance holding that exact connection. Requests expire rather than waiting for offline devices. Offline or revoked devices, missing verified runtimes, and failed incoming-message persistence make capabilities unavailable.

Release Channels and Trust

Dev, Beta/Test, RC/UAT, and Stable/Prod each use separate trust resources. Desktop checks channel, service origin, exact WSS path, public-key validity, and signing key id. Another channel’s key cannot replace missing configuration.

Distinguish lease, trust-resource, signer, network, and protocol errors. See device connection failures.

Runtime Packages

Downloadable first-party runtimes are pinned to the Desktop build and fetched on demand. They are not bundled into the installer or executed in API / Worker containers.

Runner downloads the platform archive, checks the manifest, sizes, SHA-256 digests, and file roles, then atomically publishes a private channel-cache entry. Later execution rechecks evidence. Download, platform, or verification failures make the capability unavailable.

Distinguish the portable capability manifest from the Runner native archive manifest; see tool protocols and runtime artifacts. Developer imports use the common /2 runtime index, verified on Runner from directories/archives. The server stores declarations and the declared public icon, without programs or Skill bytes. Public generic download publication remains unfinished.

Client Modules

clientModules declares separate web/native entries, files and injected dependencies. The client acquires the current installation graph, verifies digests, loads factories and calls apply(ctx, config). Dependencies must be declared. This directly executes in the client JavaScript realm, without an isolation sandbox; users must trust the author.

ctx.resources shares address-based subscriptions and cancels I/O on last release; ctx.connections.list exposes public connection state; ctx.tools.call invokes only currently authorized read-only tools for this installation. Business and file requests still target the exact online Runner. Modules receive neither operational credentials nor device executable paths. Disablement, revocation, offline state and version changes withdraw old modules and service authority.

Implementations: service/pkg/core/plugin/clientmodule/, frontend/shared/src/core/pluginClientModules/ and platform module runtimes.

Credential Configuration

A plugin_device_action binds owner, installation, capability, release, configuration schema, device generation and profile label, without operational credentials. The package declares its fields and optional registration entrypoint. The user configures the bound Desktop in a native prompt. Electron Main encrypts credentials with safeStorage in the current channel’s private directory.

Feishu defaults to scan registration, with manual existing-app setup. GitHub uses a device-local token. The service receives profile labels, opaque identities, devices, and credential versions. Feishu/GitHub credential_id stays null; operational credentials do not enter plugin_secret.

Even an empty field schema requires a real profile saved natively. A packaged setup Skill guides status reads, permission questions, native confirmation and completion queries. A prepared request establishes neither a visible window nor saved configuration.

Provider startup receives one-shot credential bootstrap over a private device channel. Keep credentials out of chat, manifests, ordinary Web / Mobile forms, logs, and public DTOs. Existing OAuth schema and routes do not establish a working server-side provider login solution.

Checks on Every Call

Calls resolve current installation, release, connection, and permissions before dispatch to the selected Runner. The service signs the request. Runner checks generation, state revisions, content digests, deadlines, and request identity, rejecting stale or modified requests.

plugin-provider/1 is the device bridge. Programs use stdio MCP and private inherited-handle plugin-provider-bootstrap/2. Runner initializes and matches the complete catalog. Sessions bind exact installation/capability/release/configuration/device generation; cancellation and revocation clean up the process tree. See protocol examples and basic concepts.

Implementing checks live in service/pkg/core/plugin/localprovider/, devicebridge/, and runner/crates/liyanlabs-runner/src/plugins/provider/.

External Writes

Sending messages or modifying issues uses host approval. plugin_effect_intent records approved actions, arguments, destinations, and release, permission, and device evidence. Changed conditions prevent reusing old approval for another operation.

OutcomeMeaningAuthor response
failed_before_dispatchNo external call boundary crossedRetry under host policy
uncertainThe platform may have accepted the writeQuery or reconcile before resending
reconciled_succeeded / reconciled_failedPlatform evidence resolved the resultSettle using the confirmed outcome

The plugin permission field external_writes accepts prompt / deny. Reuse host approval and receipts instead of implementing independent resend logic.

Incoming Messages and Webhooks

Feishu messages reach Runner through a local long connection. Runner journals them before sending to the service. The service validates, deduplicates, and persists product events before acknowledging. This path requires the selected device online.

GitHub webhook uses controlled public ingress:

  1. Bind account, installation, connection, release, and device generation.
  2. Verify signatures, event types, and delivery id; bound size and rate.
  3. Immediately relay to the exact online Runner.
  4. Runner persists the message and returns a body-digest-bound ACK.
  5. Return success to GitHub only after that ACK.

Offline devices, timeout, or failed local persistence return retryable failure, without storing payload work until reconnection. The service stores only verifier material and deduplication receipts, not GitHub API tokens.

Trace service/pkg/core/plugin/feishuchannel/, github/webhook_relay.go, and Runner inbound handling before changing these paths.