Summary
Introduce a first-party transport interface for @omnicajs/vue-remote that is compatible with the current @remote-ui/rpc integration, but does not require all runtimes to depend on @remote-ui/rpc forever.
The goal is not to remove @remote-ui/rpc immediately.
The goal is to stop treating it as the only transport/runtime bridge story.
This should allow:
- existing extensions to continue using
@remote-ui/rpc unchanged;
- new integrations to adopt an alternative transport/runtime bridge if desired;
vue-remote itself to provide better diagnostics and controllable error handling around runtime transport failures.
Problem
@remote-ui/rpc is technically capable, but from a DX and debugging perspective it behaves too much like a black box.
When runtime failures happen, it is often hard to answer:
- which method was called;
- on which side it failed;
- whether the failure happened during transport, decode, invoke, or release;
- which function proxy was already released;
- whether the error is a real problem or just post-unmount noise.
Typical failure modes are especially painful around:
- retained/released function references;
- delayed messages after unmount;
- async teardown races;
- transport-level errors that surface after the UI session is already effectively over.
In these cases the current error often degenerates into an opaque UUID-based failure or a generic transport exception that is not actionable.
Desired outcome
We want a transport layer that preserves current behavior where needed, but gives us better control over:
- observability;
- diagnostics;
- lifecycle-aware error handling;
- optional transport replacement.
Goals
- Introduce a compatible transport abstraction that can sit above
@remote-ui/rpc.
- Allow multiple transport/runtime bridge implementations behind one
vue-remote-level contract.
- Keep backward compatibility for existing extensions using
@remote-ui/rpc.
- Make runtime transport activity observable.
- Enrich transport errors with structured context.
- Support conditional downgrading of selected transport errors from
error to warning when they happen after teardown or in explicitly tolerated lifecycle windows.
Non-Goals
- Remove
@remote-ui/rpc from the project immediately.
- Break the current integration story for existing users.
- Rewrite the full wire protocol in the first iteration.
- Hide real transport bugs by turning all errors into warnings.
Why this is needed
1. @remote-ui/rpc is too opaque during failures
Today, when something breaks, the transport layer often gives us too little context.
We need more than a generic RPC failure or a released-function id.
We need to know:
- attempted method name;
- call id / invoke id;
- target side;
- lifecycle phase;
- whether the target was already released;
- whether the failure happened after explicit teardown.
2. The current system cannot express lifecycle-aware severity well
A large class of transport errors happens after unmount / release.
Those errors are often technically true, but operationally uninteresting.
They create noise instead of signal.
We need a way to say, effectively:
- before teardown: transport failures are errors;
- after teardown: selected failures may be downgraded to warnings;
- in strict/debug mode: keep them as errors again.
This downgrade must be explicit and configurable, not silent.
3. We want gradual transport evolution, not a flag day rewrite
Old extensions should be able to stay on @remote-ui/rpc.
New integrations should be able to use a different implementation later.
That means the transition path should be additive and compatibility-oriented.
Proposed direction
A. Introduce a first-party transport contract
Define a vue-remote-level transport interface that captures what the runtime bridge actually needs from an RPC layer.
This contract should be designed around:
- request/call handling;
- method exposure;
- lifecycle control;
- event hooks for observability;
- optional memory-management integration.
The important point is that vue-remote should depend on this contract, not directly on a concrete RPC package.
B. Provide an adapter for @remote-ui/rpc
Ship a compatibility adapter that wraps @remote-ui/rpc.
This adapter becomes the default compatibility path for existing users.
That means:
- current extensions can keep using the old runtime bridge;
vue-remote gains a place to add diagnostics without forcing a rewrite;
- future alternative transports can target the same contract.
C. Make observability a first-class responsibility of the transport layer
The transport abstraction should expose hooks/events for:
- outgoing call attempts;
- incoming calls;
- results and rejections;
- release/retain lifecycle;
- termination;
- dropped/ignored messages.
This is the foundation for both debugger tooling and better runtime logs.
D. Add transport-aware error classification
Instead of treating every transport failure the same way, classify failures into categories such as:
- invoke target missing;
- released function reference;
- decode/encode failure;
- call after terminate;
- late message after teardown;
- unexpected result for unknown call id.
Each event should carry structured metadata so downstream handling can make decisions.
E. Support conditional error-to-warning downgrade
Introduce configurable policy-based severity mapping.
The intended behavior is not "swallow errors".
The intended behavior is:
- preserve hard errors for real runtime problems;
- downgrade known post-teardown noise where appropriate;
- allow strict mode to keep everything loud when investigating bugs.
Example policy dimensions:
- current lifecycle phase;
- event kind/category;
- whether session teardown was explicit;
- strict/debug mode enabled or not.
Migration strategy
Phase 1. Define the compatibility contract
- Identify the minimal bridge surface
vue-remote actually needs.
- Define a first-party transport interface around that surface.
- Keep the interface narrow and implementation-oriented.
Phase 2. Implement @remote-ui/rpc adapter
- Wrap
createEndpoint(...) and related lifecycle behavior.
- Preserve current behavior for existing integrations.
- Add instrumentation hooks and structured error context.
Phase 3. Route vue-remote integration guidance through the transport contract
- Keep
@remote-ui/rpc as the default compatibility path.
- Stop treating it as the only supported conceptual model.
- Make room for alternative implementations in docs/examples.
Phase 4. Add alternative transport implementation(s)
- Introduce one non-
@remote-ui/rpc implementation behind the same contract.
- Validate that old and new integrations can coexist without API breakage.
Compatibility requirements
- Existing extensions using
@remote-ui/rpc must continue to work.
- Existing lifecycle patterns like
run/release must remain valid.
- Existing retain/release semantics must either remain compatible or be clearly adapted behind the wrapper.
- The first iteration must not require a wire-protocol rewrite.
Suggested transport concerns to surface explicitly
The new contract or adapter layer should make the following visible:
- method name being called;
- call identifier;
- side / role (
host, remote, maybe bridge internally);
- release/retain state if relevant;
- lifecycle phase (
active, releasing, released, terminated);
- severity (
error, warning, maybe debug);
- root cause classification.
Example high-value cases
Released function reference
Current behavior is often effectively: "function already released", plus a UUID-like trail.
We need richer diagnostics, for example:
- method attempted;
- whether the proxy was released due to explicit teardown;
- which side initiated release;
- whether this happened after unmount.
Late post-unmount calls
These often should not look like catastrophic transport failures.
They are good candidates for downgrade to warnings if the session is already marked as ended.
Unknown result / orphaned response
These should stay loud and diagnosable.
They usually point to protocol or lifecycle mismatches worth investigating.
Acceptance criteria
vue-remote has a first-party transport contract or adapter layer.
@remote-ui/rpc remains usable through that layer without breaking existing integrations.
- Transport failures carry enough structured context to be actionable.
- Selected post-teardown transport failures can be downgraded to warnings through explicit policy.
- Strict/debug mode can keep those failures as errors.
- The new layer gives a clean place for debugger/instrumentation hooks.
Open questions
- Should retain/release compatibility stay hard-coupled to
@remote-ui/rpc symbols, or be abstracted behind the new layer from the start?
- How narrow can the first transport contract be while still being useful for alternative implementations?
- Should warning-downgrade policy live in the transport adapter, in
vue-remote, or in user-supplied hooks?
- Do we want compatibility at API shape level only, or eventual wire-protocol compatibility as well?
Recommended first step
Start with a compatibility adapter over @remote-ui/rpc, not with a rewrite.
That gives us the fastest path to:
- better diagnostics;
- better lifecycle-aware error handling;
- a migration path for future transport implementations;
- zero or minimal breakage for existing extensions.
Summary
Introduce a first-party transport interface for
@omnicajs/vue-remotethat is compatible with the current@remote-ui/rpcintegration, but does not require all runtimes to depend on@remote-ui/rpcforever.The goal is not to remove
@remote-ui/rpcimmediately.The goal is to stop treating it as the only transport/runtime bridge story.
This should allow:
@remote-ui/rpcunchanged;vue-remoteitself to provide better diagnostics and controllable error handling around runtime transport failures.Problem
@remote-ui/rpcis technically capable, but from a DX and debugging perspective it behaves too much like a black box.When runtime failures happen, it is often hard to answer:
Typical failure modes are especially painful around:
In these cases the current error often degenerates into an opaque UUID-based failure or a generic transport exception that is not actionable.
Desired outcome
We want a transport layer that preserves current behavior where needed, but gives us better control over:
Goals
@remote-ui/rpc.vue-remote-level contract.@remote-ui/rpc.errortowarningwhen they happen after teardown or in explicitly tolerated lifecycle windows.Non-Goals
@remote-ui/rpcfrom the project immediately.Why this is needed
1.
@remote-ui/rpcis too opaque during failuresToday, when something breaks, the transport layer often gives us too little context.
We need more than a generic RPC failure or a released-function id.
We need to know:
2. The current system cannot express lifecycle-aware severity well
A large class of transport errors happens after unmount / release.
Those errors are often technically true, but operationally uninteresting.
They create noise instead of signal.
We need a way to say, effectively:
This downgrade must be explicit and configurable, not silent.
3. We want gradual transport evolution, not a flag day rewrite
Old extensions should be able to stay on
@remote-ui/rpc.New integrations should be able to use a different implementation later.
That means the transition path should be additive and compatibility-oriented.
Proposed direction
A. Introduce a first-party transport contract
Define a
vue-remote-level transport interface that captures what the runtime bridge actually needs from an RPC layer.This contract should be designed around:
The important point is that
vue-remoteshould depend on this contract, not directly on a concrete RPC package.B. Provide an adapter for
@remote-ui/rpcShip a compatibility adapter that wraps
@remote-ui/rpc.This adapter becomes the default compatibility path for existing users.
That means:
vue-remotegains a place to add diagnostics without forcing a rewrite;C. Make observability a first-class responsibility of the transport layer
The transport abstraction should expose hooks/events for:
This is the foundation for both debugger tooling and better runtime logs.
D. Add transport-aware error classification
Instead of treating every transport failure the same way, classify failures into categories such as:
Each event should carry structured metadata so downstream handling can make decisions.
E. Support conditional error-to-warning downgrade
Introduce configurable policy-based severity mapping.
The intended behavior is not "swallow errors".
The intended behavior is:
Example policy dimensions:
Migration strategy
Phase 1. Define the compatibility contract
vue-remoteactually needs.Phase 2. Implement
@remote-ui/rpcadaptercreateEndpoint(...)and related lifecycle behavior.Phase 3. Route
vue-remoteintegration guidance through the transport contract@remote-ui/rpcas the default compatibility path.Phase 4. Add alternative transport implementation(s)
@remote-ui/rpcimplementation behind the same contract.Compatibility requirements
@remote-ui/rpcmust continue to work.run/releasemust remain valid.Suggested transport concerns to surface explicitly
The new contract or adapter layer should make the following visible:
host,remote, maybebridgeinternally);active,releasing,released,terminated);error,warning, maybedebug);Example high-value cases
Released function reference
Current behavior is often effectively: "function already released", plus a UUID-like trail.
We need richer diagnostics, for example:
Late post-unmount calls
These often should not look like catastrophic transport failures.
They are good candidates for downgrade to warnings if the session is already marked as ended.
Unknown result / orphaned response
These should stay loud and diagnosable.
They usually point to protocol or lifecycle mismatches worth investigating.
Acceptance criteria
vue-remotehas a first-party transport contract or adapter layer.@remote-ui/rpcremains usable through that layer without breaking existing integrations.Open questions
@remote-ui/rpcsymbols, or be abstracted behind the new layer from the start?vue-remote, or in user-supplied hooks?Recommended first step
Start with a compatibility adapter over
@remote-ui/rpc, not with a rewrite.That gives us the fastest path to: