ReDevPlugin is the reusable plugin platform intended to be consumed by host products through published Go modules, npm packages, Rust source crates, and machine-contract artifacts. ReDevPlugin publishes versioned source crates for the Rust runtime; host products build the runtime binary from exact published Rust source crates and own the resulting product artifact.
This repository owns the host-neutral plugin platform core. Host products own their product policy, UI shell integration, session adapters, and business capabilities.
- Platform version source:
VERSION - Go module:
github.com/floegence/redevplugin/v3 - TypeScript packages: the opt-in raw contract body package
@floegence/redevplugin-contractsand the sandbox/runtime SDK@floegence/redevplugin-ui - Rust workspace and publication set: exactly
redevplugin-runtimeandredevplugin-worker-sdk - Plugin author compatibility: manifest v9 with
plugin_api=1. Older manifests and parallel UI/WASM compatibility axes are rejected rather than normalized. - Host/runtime compatibility:
internal_wire=1, checked once by the exact Hello/HelloAck handshake. Ordinary frames carry no version field. - Canonical contracts use fixed paths, including
spec/openapi/plugin-platform.yamlandspec/internal/runtime-wire.schema.json. - Each release publishes one signed, staging-generated
PlatformReleaseManifestcontaining the exact hashes of the Go, npm, crate, and contract artifacts. The manifest is not checked into an artifact whose hash it contains. - The contracts npm package owns strict security-summary normalization and canonical SHA-256 APIs, generated from OpenAPI and verified against Go byte fixtures. Hosts and markets consume this complete evidence contract instead of maintaining summary field lists or hash payloads independently.
Start with a pure Web application; no Worker or runtime is required:
go install github.com/floegence/redevplugin/v3/cmd/redevplugin@v3.14.0
redevplugin init notes "Notes" notes
cd notes
npm install
redevplugin doctor .
redevplugin check .
redevplugin dev . --state ../notes-development --manualChoose --template data for persistent documents, files for streaming imports,
monitor for a configurable socket dashboard, or worker for WASM computation.
Save drafts before choosing Apply update. The preview provides explicit
permissions, connection review, action forms, task inspection, and data reset.
See the complete author workflow,
embedded author environments,
resource semantics, and
data upgrades.
Manifest v9 requires an author-owned presentation catalog. The default locale uses the manifest's plugin, publisher, surface, setting, and option labels; authors may add up to 15 complete localized records. Localizations are keyed by canonical BCP 47 tags and must cover every translatable field without missing, extra, or duplicate surface, setting, or option references.
ReDevPlugin validates author text as NFC-normalized Unicode plain text, includes the complete catalog in the canonical manifest boundary, and projects a normalized catalog plus its SHA-256 digest from verified inspection and installed inventory APIs. The Go and TypeScript resolvers use exact match, RFC 4647 parent lookup, then the author-declared default locale. They do not add an English fallback or mix locales within one resolved presentation.
redevplugin release inspectvalidates ordinary release packages and emits package identity, content hashes, presentation, and capability summaries.release extract-presentation-iconwrites only the validated package icon. Authors publish a package and.redevplugin/index.json, with independent stable tag namespaces for each plugin. No signing or registration is required.- All sources share the same inspection and durable installation Execution. Installed-source updates preserve user preferences, permissions and data.
- Host-neutral Go package boundaries for manifest validation, package IO, registry, host adapters, bridge, PluginData, runtime supervision, grants, capability adapters, HTTP routes, session context, and web security.
- Host capability contracts are exact artifacts registered by the Host. Package bindings resolve only against that closed local registry; no capability publisher, signing service or remote admission chain is required.
plugindata.FileStoreis the single data authority behind lifecycle, non-secret settings, files, KV, SQLite, retained bindings, and opaque export bundles. It resolves every request through the current registry binding, enforces quotas and filesystem boundaries, and publishes generation changes with semantic revision checks.- The settings package defines schema normalization and validation only. PluginData persists non-secret values with a values revision; the independent SecretStore contributes redacted binding metadata and never enters an export bundle.
- The Host-owned control database stores asynchronous work as one Execution and its ordered Events. Cursor reads are bounded by event and byte limits, waiters are notified without polling, and disable/uninstall transitions fence the same execution identity. Unknown or newer schemas fail closed.
- Observability stores include both in-memory and SQLite-backed implementations. Audit events are append-only through the host adapter contract. Owner-scoped diagnostic listing preserves filtering, defaults, newest-first ordering, retention limits, and generated event IDs across idempotent reopen.
- Secret binding stores include both in-memory and SQLite-backed implementations. They persist only plugin-instance, scope, secret-ref, bound state, and test/delete metadata, never secret plaintext, so hosts can keep the actual vault implementation product-owned while reusing common lifecycle state, filtering, cleanup, and durable current-schema storage.
- Confirmation intent stores include both in-memory and SQLite-backed implementations. They persist the server-held intent metadata and confirmation token id, request hash, plan hash, and expiry, but not the raw confirmation token; after a process restart, missing token-manager state makes any recovered intent fail closed instead of silently confirming.
- Host lifecycle APIs include idempotent
RecoverEnabled, which lets an embedding product restore enabled plugin runtime state after restart by replaying connectivity policy installation and surface publication from the durable registry without re-enabling plugins. The mountable HTTP adapter exposes the same behavior atPOST /_redevplugin/api/plugins/runtime/recover-enabled, so hosts can keep route mounting thin instead of reimplementing the refresh loop. - Updates preserve compatible PluginData shapes and support declared isolated WASM data conversions when the shape changes. Downgrades restore exact retained package-bound generations. See data upgrades for conversion, rollback, quota, and unknown-outcome rules.
- Package IO validates every entry and includes all package content in the canonical digest. Plugin signature files have no special semantics.
- Package validation accepts package-local HTML entries under a declared Web
root and rejects unsafe paths, reserved platform paths, missing entries, and
the removed worker-UI format. Ordinary modules, inline scripts, styles, and
framework DOM are application-owned. Runtime CSP and network admission
enforce the external boundary. Package-local raster icons remain separate
verified presentation evidence. The package validator also rejects
shell/shebang scripts, native executable or dynamic-library artifacts,
package-manager install lifecycle scripts, package-manager dependency fields,
Cargo
build.rs/ build scripts, proc-macro crates, native linker configuration, and Cargo dependency sections so third-party packages cannot smuggle a native backend beside the sandbox UI and WASM workers. Package IO also rejects file counts, entry sizes, package-local path lengths, compression ratios, and total uncompressed sizes beyond configured limits. Validation failures use stable platform error codes (PLUGIN_MANIFEST_INVALID,PLUGIN_PACKAGE_INVALID,PLUGIN_PACKAGE_TOO_LARGE, orPLUGIN_PACKAGE_PATH_FORBIDDEN) and expose structurederror_detailssuch asreason, packagepath, and manifest JSONpointerthrough the HTTP adapter. - Package admission resolves a selected HTTPS or GitHub source, validates the package and creates a session-bound inspection. One durable installation Execution commits the exact accepted bytes and exposes progress and outcome recovery. Signature and publisher trust systems are not enabled.
- An installed package starts enabled. Runtime permissions require separate grants. User-enabled updates resolve the original source and require a newer version without capability changes; changed sources require explicit review.
release inspectandrelease extract-presentation-iconprovide package summaries and validated images. Neither command requires signing inputs.- The public Go package pkg/testhost composes the real Host, HTTP adapter, isolated Web surfaces, durable package assets, and bounded events with explicit test adapters. It denies management and resources by default and is shared by author dev/test. See local author workflow for exact-session requests, verified runtime ownership, and persistence tests.
testdata/generated_plugins/minimal,networked,storage, andmethod-contractare positive generated-plugin fixtures that the platform gate validates and packages through the same CLI path.method-contractcovers dangerous confirmation, atomic confirmation rejection, risk preflight, asynchronous cancellation policy and delete-effect metadata.testdata/generated_plugins/malicious-build/*must fail packaging before any dependency install or build step can run.- Mountable HTTP routes call a host-provided
websecurity.Guardthrough the explicitAuthenticate,ValidateOrigin,ValidateCSRF, andAuthorizeRoutestages. Every platform route requires the closedtrusted_hostorigin policy, every unsafe method including asset and stream reads requires CSRF validation, and every route carries a closedRouteAction. The authenticated session and product-specific origin, CSRF, and authorization policy stay in the host product. - PluginPlatformClient.openSurfaceInSlot is the sole opening path. Each slot owns a fresh iframe and a separate application origin. The host registers SurfaceOriginAdapter and mounts NewWebSurfaceHandler; the platform owns single-use entry, browser network admission, resource cookies, exact package validation, source/origin/port binding, leases, and revocation. Ordinary HTML, CSS, DOM, modules, dynamic imports, Workers, Canvas, WebGL, and WASM run inside the app. Parent management credentials remain outside plugin JavaScript.
- Browser storage is a container-local cache. Durable data and privileged network/file/service operations use declared platform methods and brokers. Unsupported browser confinement fails before application execution. No VNode, dedicated JSX runtime, or legacy rendering path remains.
- A trusted parent that rejects a dangerous-method confirmation first calls the
surface-scoped rejection route. The Host validates the current gateway token,
session, bridge channel, active fingerprint, policy/management revisions, and
revoke epoch, then atomically removes the pending intent and records stable
audit/diagnostic evidence before the plugin receives
PLUGIN_CONFIRMATION_REJECTED. - Contract tests that keep the Go HTTP route set, OpenAPI paths, route fixture, Web surface contracts, TypeScript SDK route coverage, and package validator aligned.
- Manifest v9 requires every method to declare closed request and response object schemas. Package validation compiles those schemas without remote references; Host dispatch validates requests before adapters/runtime and validates canonical redacted responses before returning them to plugin code.
- Manifest v9 surface declarations use only host-neutral
view,command, orbackgroundkinds with optionalprimary,secondary, orutilityintent. Activity bars, workbench panes, settings pages, and modal placement remain host-product decisions. - Stable error-code contract tests keep the Go
pkg/securitycatalog, OpenAPI envelope enum, iframe bridge schema, TypeScript SDK exports, and Rust IPC runtime-origin error constants aligned. The catalog separates server platform codes, bridge response codes, TypeScript client-side transport codes, and Rust IPC codes so product shells can branch on stable values without scraping localized messages. - WASM author ABI schema tests keep
spec/plugin/wasm-abi.jsonaligned with the Go package validator, Rust worker export validation, runtime linked hostcall modules, and the canonical worker invocation schema.plugin_api=1is the only author-visible compatibility input. - Go package validation compiles the complete WASM module with Wazero before it
accepts memory and export metadata. The Rust ABI crate independently runs
wasmparser::Validator::validate_allbefore runtime execution, and the Wasmi store enforces the signed memory budget even when a worker callsmemory.grow. The manifest platform ceiling is 256 MiB per worker; a Host may reject a lower value through its resource policy. - Plugin backend authors use the published
redevplugin-worker-sdkcrate at the same platform version. The signed platform release manifest binds its registry coordinate and checksum; hosts and plugin authors do not copy a bundled crate or wire a sibling checkout. - Runtime wire tests keep startup
hello/hello_ackframes bound to the Host-issued connection nonce, exact platform version,internal_wire=1, and runtime artifact identity, while worker invocation leases remain bound tolease_noncefor runtime replay rejection, require structured heartbeat ACK results for control-channel liveness, and requirerevoke_epoch_ackresults to report the plugin instance, revoke epoch, and closed socket/stream/storage-handle counters. IPC golden fixtures undertestdata/contracts/ipc/are read by Go Host tests and Rust IPC crate tests. They cover the current handshake/response shape plus Host/Rust wire mismatch, missing required fields, replayed request IDs, unknown frame types, and runtime-generation mismatch fail-closed paths. - The current internal wire multiplexes invocations over one runtime process with one reader,
one serialized writer, and a pending map keyed by
request_id. Runtime-origin artifact and generic Hostcall frames carryparent_request_id, which the Go supervisor resolves back to the signed invocation audience before Host I/O.cancel_invokeremoves queued work or marks running work canceled without invalidating the runtime generation. No independently versioned IPC contract or semantic storage/network frame family remains. RuntimeLimitsis a Host-only Go configuration. Defaults derive 4-16 workers fromGOMAXPROCS, cap the queue at 64, cap each plugin at 2-8 concurrent workers, and allow 64 compiled modules or 128 MiB of source WASM. Go waits for capacity before consuming an execution lease; Rust independently enforces the same closed bounds, includingper_plugin_concurrency <= worker_count, with a fair per-plugin scheduler.- One Wasmi engine is shared by the runtime generation. Validated modules are single-flight compiled and retained in a deterministic content-addressed LRU keyed by artifact SHA-256 and ABI version. Each invocation still receives an independent Store, Linker, memory limiter, and fuel budget. Health reports active/queued counts, effective limits, and cache hit/miss/compile/entry/byte metrics.
- Runtime lease replay protection is generation-local and enforced before worker IPC. A fresh runtime generation receives a fresh signing identity; duplicate leases fail closed without a local trust ledger.
ProcessSupervisorgenerates a fresh ephemeral Ed25519 keypair for every supervisor instance, requires a non-empty public-key set in the startuphelloframe, binds every worker lease to the current runtime audience, and signs every invocation. Callers cannot provide, disable, or override the signature or public key. The canonical payload excludes onlysignatureand covers the display token ID, plugin metadata, active package fingerprint, issued timestamp, method, effect, execution mode, Host-owned execution id, audit correlation id, surface and owner context, descriptor hashes, quota limits, policy and management revisions, revoke epoch, expiry,lease_nonce,key_id, and runtime audience fields. The Go supervisor verifies that exact audience and signature before IPC. Rust independently rejects a missing keyring, invalid signature, expired lease, or any mismatch between the signed lease and the worker invocation's plugin, method/effect/execution, execution identity, audit, surface/session, or runtime binding before replay-cache consumption or artifact open. Worker-route dispatch emits aplugin.runtime.lease.issuedHost audit event with lease/token IDs, runtime IDs, revision bindings, descriptor hashes, and expiry metadata.- Rust runtime control-channel freshness is enforced inside the runtime as well as by the Go supervisor. After the heartbeat max-staleness window expires, the Rust runtime rejects new worker invocations before opening artifacts and rejects new storage/network broker hostcalls before dispatching Host IO.
- The Go runtime supervisor gives every runtime-origin hostcall a bounded
context before invoking host adapters. Storage and network calls that carry
timeout_msuse that value with a platform cap; artifact, handle-grant, storage file/KV, and network-grant calls use the default hostcall cap. The supervisor also sends default 2s heartbeat frames and invalidates the runtime when a heartbeat cannot be acknowledged within the 5s max-staleness window. - Bridge contract checks that keep sandbox iframe message names, source/port-bound MessageChannel messaging, UI protocol version, and parent-only token boundaries aligned with the TypeScript SDK.
- The TypeScript package includes sandbox iframe bridge helpers and a host-side
PluginPlatformClientfor package platform management routes: inspected install/update, downgrade, enable/disable/uninstall, surface open, runtime start/health/recover-enabled/retry/stop, settings schema/read/patch, execution list/get/cancel, data export/import, permission grant/revoke/list, secret bind/test/delete, host-mediated intent list/invoke, and owner-scoped diagnostic event list. Audit events remain an internal host adapter contract and are not exposed by the generic HTTP/TypeScript platform surface. The raw package import/update surface is intentionally separated intoPluginLocalImportClient, exported only from@floegence/redevplugin-ui/local-import, for explicit dev/admin local-import route sets. List helpers preserve the same data wrapper fields returned by the Go HTTP adapter, such asexecutions,permissions, anddiagnostic_events, so host products can consume the SDK and raw HTTP contract consistently. The browser harness uses the platform client from the host page to exercise settings management without exposing management credentials to the sandboxed iframe. Host pages can also usePluginSurfaceReloadLimiterto cap consecutive automatic iframe reloads after crashes or load failures before showing a host-owned error state. - Dispose uses a private quiesce/ack lifecycle. The SDK waits up to 1.5 seconds for async application lifecycle observers to flush state, then revokes the surface. Unknown close outcomes reconcile only the exact single surface.
- The npm boundary exposes trusted-parent management, the plugin-only bridge, explicit local-import tooling, and testing helpers. Application frameworks use their own DOM and JSX runtimes. Native input, selection, composition, canvas events, and accessibility remain application-owned.
- Appearance and locale flow through the bridge context. Templates and examples consume the published Floe standalone material and current surface roles. File export requires an explicit host decision on every request; click or interaction metadata never grants authority.
- Execution cancellation is a durable Host decision:
CancelExecutionrecordscancel_requested, emits audit evidence, and signals the live execution lease. The lease captures an optional route-local cancellation hook from the capability adapter, core action, or runtime supervisor when execution starts. An inactive persisted execution is never redispatched through a global registry lookup; its durable cancellation remains observable. - Every asynchronous method returns one Host-owned execution ID. Progress, output, and terminal state are ordered Events under that identity and cursor. Any internal byte-stream handle remains an implementation detail and cannot create a second public lifecycle. Generated business-error guards also bind the capability ID, capability version, and details-schema SHA-256.
- Event reads use a cursor to prevent lost wakeups, wait without holding plugin lifecycle locks, and revalidate registry and token audience after each wait. Terminal state and the final event commit atomically in the Host-owned control database, so restart cannot expose contradictory public identities.
- Dangerous method confirmation uses server-held one-time intents. When a method
declares a risk preflight method, the Host runs that read-only sync preflight
during confirmation preparation, returns the redacted plan plus
plan_hashto the trusted parent, and binds bothrequest_hashandplan_hashinto the parent-only confirmation token audience. The raw confirmation token is never returned to parent JavaScript, written to the confirmation intent store, or exposed to the sandboxed iframe. - Capability adapters can return
capability.RiskPlanfrom preflight methods to use the host-neutralredevplugin.capability.risk_plan.v1contract. The Host requires the current schema version, validates and normalizes the closed typed plan before hashing it, and rejects unknown or invalid risk fields fail-closed. The TypeScript SDK exports matchingPluginRiskPlan/PluginRiskFlagtypes plusisPluginRiskPlan()so trusted parent UI can render the typed plan without brittle ad hoc shape checks. - Capability, worker, and core-action method results pass through the Host-owned
capability.PrepareResponseDataboundary before they are returned to the plugin surface or HTTP adapter. The boundary budgets native Go structures before marshaling, converts their encoded representation to an independent, bounded JSON data tree, rejects ambiguous or non-JSON values, redacts sensitive keys plus container-shaped env, label, and mount secret values, and then revalidates the final tree against the same closed limits. Custom marshalers remain trusted host-adapter code: the platform bounds and validates their output but cannot isolate allocations or CPU used inside those methods. Response structs may use reflectiveomitzero, but customIsZeromethods are rejected because a second observation could change the wire shape. Business-error details use the same path and are exposed only after the Host attests them against the published capability contract. Adapter failures are likewise projected once into an immutable Host error: stable platform classifications and validated public details are preserved, while the original error graph and adapter-controlled error text are discarded before cleanup, diagnostics, or HTTP mapping. VERSIONis the only editable platform-version source. Release checks require exact equality across the/v3Go module, npm packages, Rust crates, OpenAPI, tag, and registry readback.scripts/generate_platform_release_manifest.mjsruns only after the package artifacts have been frozen. It emits deterministic canonical bytes into an external staging directory, with top-levelplatform_version,plugin_api,internal_wire, and sorted{name, sha256}artifacts. The signed release asset is the one release index; no checked-in contract registry, package set, compatibility matrix, runtime descriptor, or performance publication is a second source of truth.- The target-classifier fixtures remain executable security tests for public DNS, punycode hostnames, metadata hosts, RFC1918/ULA/link-local addresses, and IPv4-mapped IPv6 private addresses. They are security inputs, not independent compatibility axes.
- Connectivity brokers compile manifest-declared HTTP, WebSocket, TCP, and UDP connectors into grantable policies. The host-neutral network executor now consumes short-lived connection grants and performs bounded HTTP request/response calls, HTTP response streaming into the Host stream store, plus WebSocket, TCP, and UDP round trips with explicit timeout, cancellation, request-size, response-size, chunk-size, and stream-buffer limits. It revalidates grant expiry, transport, destination, and the target classifier at execution time so UI bridge calls and backend worker hostcalls can share the same fail-closed network boundary. Grants with an unknown target-classifier identity are rejected before any dial or broker dispatch. IPv4-mapped IPv6 literals and resolved addresses are unmapped before blocked-range checks so mapped loopback/private/link-local targets cannot bypass IPv4 CIDR policy. Long-lived WebSocket subscriptions remain tied to the streaming envelope contract instead of the one-shot round trip API.
- Host tests include black-box runtime subprocess paths that invoke workers
through the same
redevplugin.iocontract used by published plugins. They cover Host-owned storage namespaces plus bounded HTTP, WebSocket, TCP, and UDP resource operations without a second network-execute protocol. - The Rust runtime requests a bound WASM artifact only on a compiled-module cache
miss, validates the module through its private ABI module, executes it through
the shared Wasmi engine and fair worker scheduler, and returns the result over
multiplexed
invoke_worker_resultframes. Currentplugin_api=1workers may import only the six functions in theredevplugin.iomodule.rdp_call_v1carries one closed{plugin_api, operation, arguments}envelope;rdp_read_v1,rdp_write_v1,rdp_seek_v1,rdp_close_v1, andrdp_last_error_v1operate on opaque resources returned by that control call. The runtime sends one generic Hostcall frame keyed by the signed invocation identity. The Host resolves that identity to the already verified method, permissions, resource scope, management revision, revoke epoch, and broker access before dispatching plugin-data storage or resource I/O. Storage files, KV, and SQLite remain Host-owned namespace operations; HTTP, WebSocket, TCP, and UDP use the same resource control/read/write path. There are no separate WASM storage/network imports or storage/network semantic IPC frame families. Before each dispatch the runtime verifies control-channel freshness and fails closed withRUNTIME_CONTROL_CHANNEL_STALEwhen the Host heartbeat or revocation window is stale. Revoke ACKs report resources actually closed by the runtime; purely Host-owned resources are revoked by the Host broker. redevplugin inspect-data <state-root> [plugin-instance-id]reports catalog bindings, export objects, namespaces, and byte/file quota usage without dumping plugin file contents or scanning an unowned filesystem root.- Host data export/import uses one opaque
bundle_reffor the complete declared non-secret dataset. Import validates publisher/plugin ownership, the settings schema, namespace kind/scope/schema version, content hash, and target quotas before atomically swapping the active generation. Secret bindings remain in the host secret store and are never included in an exported bundle. redevplugin dev-install <state-root> <package>creates a persistent local development state root for Flower-generated plugins. The matchingdev-enable,dev-open <surface-id>,dev-disable,dev-secret-bind <secret-ref> [user|environment],dev-secret-test <secret-ref> [user|environment],dev-secret-delete <secret-ref> [user|environment],dev-permission-grant <permission-id>,dev-permission-revoke <permission-id> [reason],dev-permission-list [--active-only],dev-export-data,dev-import-data <bundle-ref>,dev-delete-export <bundle-ref>,dev-uninstall, anddev-statuscommands call the real Host lifecycle APIs. The state root containsregistry.sqlite,plugin-data/,secrets.sqlite, the installed package, and verified capability artifacts; it has no JSON mirrors of registry, authorization, settings, or secret state. Dev secret commands never store secret plaintext. Dev permission commands call the Host permission APIs, so policy revisions and revoke epochs move exactly as they do in an embedded host product. Dev data commands call the Host data lifecycle APIs and operate on cataloged opaque bundle refs. This gives generated plugins a local, auditable install -> enable -> open -> disable -> uninstall flow without importing any host-product internals. Dev uninstall always removes the copied package, plugin data, settings, secret bindings, and authorization records.redevplugin examples-server <state-root> <runtime-path>starts the user-facing Examples Showcase with Memos, Weather, and Sky Strike. Every example uses the Go Host, HTTP adapter, real Rust runtime, installable plugin package, and persisted plugin storage. Runtime identity is verified by the current Hello/HelloAck handshake; no public runtime descriptor is loaded. The examples server is a local conformance harness, not a production authentication or authorization implementation: it injects one synthetic session and accepts every valid platform action. An embedding product must provide its own authenticated session, origin, CSRF, and route-authorization guard. Memos is a complete private Markdown timeline: its always-available composer persists a safe draft before explicit publication, the feed renders identity-preserving native Markdown DOM without admitting raw HTML, images, or arbitrary navigation, and search invalidates stale requests. Tags, local-date calendar facets, pinning, and archives share one bounded query contract. Published memo edits use serialized autosave; failed persistence preserves the active edit and blocks navigation, surface quiesce flushes pending drafts and edits, and compact layouts use a full-height explorer drawer with modal deletion confirmation. The Showcase asksPluginPlatformClient.openSurfaceInSlot(...)to create and place a fresh isolated-origin iframe in the selected slot. The Go Host serves verified package resources through its dedicated Web handler; the trusted loader connects the application through a source/origin/port-bound bridge. The internal browser fixtures exercise native modules, Workers, browser storage, input, undo, drawing, independent containers, resource revocation, and browser admission. The real Rust/WASM Showcase retains draft recovery, Markdown tasks, autosave, search, pinning, archives, deletion recovery, Weather persistence, game input/animation, accessible status, and deterministic application disposal. Memos requests at most 10 complete memo records per page and its worker clamps every caller to that same limit; a compiled-WASM regression proves a 61-item pinned timeline returns bounded 10-item pages and a one-item tail without an unbounded response. Committed example workers are canonical Linux/amd64wasm32-unknown-unknownartifacts tied to the recursive local Cargo dependency source snapshot byexamples/plugins/worker-artifacts.lock.json;npm run examples:generateuses an immutable Rust Docker image digest on non-canonical hosts, whilenpm run examples:check:canonicalreproduces the exact canonical byte check. The CLI scaffold uses the same shared builder and records its backend worker inpkg/authoring/scaffold_assets/worker-artifacts.lock.json; usenpm run scaffold:generateandnpm run scaffold:check:canonicalfor that artifact. Linux native checks use the exact pinned Rust release, a clean target directory, isolated Cargo home, and an environment allowlist; external ancestor Cargo configuration is rejected. The local complete gate compares those bytes with the immutable Docker build and rejects source changes during compilation.- Host-mediated plugin intents are exposed end to end through the Go Host
library, HTTP adapter, OpenAPI route contract, and
PluginPlatformClient. Host products can list enabled runnable intents and invoke a chosen intent without iframe gateway tokens while still preserving local policy evaluation, permission grants, audit events, and dangerous-method fail-closed behavior.
ReDevPlugin intentionally does not import Redeven internals and does not provide a local sibling integration path for host products.
ReDevPlugin publishes redevplugin-runtime and redevplugin-worker-sdk source
crates together with a matching Go module, npm packages, generated contracts,
compatibility metadata, and package publication evidence. Host products build
the runtime binary from the exact published runtime crate after independently
verifying registry checksums, source identity, dependency metadata, and the
contract-set digest.
Tagged publication builds every package once in unprivileged jobs, publishes in dependency order, and reads the packages back from the Go proxy/sumdb, npm registry, and crates.io. Registry-only fake-host E2E then builds the runtime from the downloaded crate sources and exercises the Go Host, TypeScript SDK, IPC, WASM, brokers, streams, revocation, and shutdown without sibling wiring. A partial or mismatched registry publication is fail-closed and cannot be repaired by overwriting an existing version.
Only after registry readback and conformance succeed does the GitHub Release
contain exactly one attested platform-release-manifest.json asset. ReDevPlugin
GitHub Releases do not contain OS runtime binaries,
runtime archives, installers, or product signatures. They also do not attach npm
tarballs, .crate files, product checksums, or runtime signing bundles. Registry
integrity and provenance remain authoritative for package bytes; the release
manifest binds their readback SHA-256 values and canonical contract hashes to
the one platform version.
The host product owns the resulting binary, SBOM, provenance, signature, installer, and product archive. ReDevPlugin continues to own runtime admission, the Go supervisor, IPC, WASM execution, hostcalls, leases, quotas, revocation, and diagnostics contracts; building the product binary does not authorize a host-local supervisor or protocol fork.
Before pushing main, install the repository hook once:
git config core.hooksPath .githooksThe hook runs the authoritative complete local gate before main reaches the
remote. It only accepts a clean, fast-forward update from the checked-out main
branch whose HEAD exactly matches the pushed object. Feature-branch pushes do
not run the gate; attempts to push a feature ref to remote main are rejected.
The main-branch Quick CI is a separate bounded source-format and script-syntax
confirmation; it does not duplicate browser, runtime, package, performance, or
stress coverage. Run the complete gate directly when investigating a failure:
./scripts/check_redevplugin_pre_push.shGitHub-only release publication, tag identity, artifact upload/download, multi-runner runtime execution, npm/Go registry readback, Sigstore signing, and GitHub API checks remain in the release workflows because they require GitHub credentials or hosted runner infrastructure.
Rust checks require a local Rust toolchain:
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo deny checkcheck_redevplugin_runtime_contract.sh also runs connectivity and runtimeclient
Go tests plus the target-classifier fixture checks so grant validation, the Go
classifier, and the shared JSON cases cannot drift. Target classification has
no separately published Rust crate.
check_redevplugin_stress.sh always emits a JSON summary. The stress_evidence
field records structured counters from pkg/stress, including event
backpressure denials, execution cancellation, and inactive-execution
non-redispatch,
connectivity grant/classifier denials, runtime revoke ACK p95 latency,
redirect/DNS rebinding denials, HTTP proxy/CONNECT/header hardening, TCP mock
database round trips, TCP size denials, TCP cancelled reads, UDP source-pin
mismatch drops, UDP rate-limit denials, WebSocket round trips, WebSocket size
denials, WebSocket cancelled reads, KV byte quota pressure, file-count quota,
and SQLite sidecar/sparse bypass checks. The exact-main pre-push gate retains
that local summary as release evidence for host-neutral broker/backpressure,
execution cancellation, runtime-control, storage, and
sandbox telemetry behavior. Non-Linux hosts require Docker so the Linux-only
runtime revoke evidence is collected instead of skipped.