|
| 1 | +# PC2 → ElastOS Runtime Convergence Plan |
| 2 | + |
| 3 | +> Working plan. Not a release commitment. Direction here must pass the Planning |
| 4 | +> Review Gate in [ROADMAP.md](../ROADMAP.md#planning-review-gate) before |
| 5 | +> implementation. Volatile facts and proof transcripts belong in |
| 6 | +> [state.md](../state.md), not here. |
| 7 | +
|
| 8 | +For why this work exists, see [pc2.net's ELASTOS_VISION.md](https://github.com/Elacity/pc2.net/blob/main/ELASTOS_VISION.md) |
| 9 | +and this repo's [PRINCIPLES.md](../PRINCIPLES.md) and [ROADMAP.md](../ROADMAP.md). |
| 10 | + |
| 11 | +## Why |
| 12 | + |
| 13 | +[pc2.net](https://github.com/Elacity/pc2.net) is the current shipping |
| 14 | +"Internet OS" product. It is a Puter-derived Node.js stack with wallet |
| 15 | +auth, IPFS storage, SQLite, WASM execution, and a browser desktop. It |
| 16 | +runs on macOS, Linux, Windows, Pi, Docker today. It is wrapped by |
| 17 | +[elastos-launcher](https://github.com/Elacity/elastos-launcher) into a |
| 18 | +one-click .dmg/.deb/.exe. |
| 19 | + |
| 20 | +`elastos-runtime` is the target architecture: a minimal Rust trusted |
| 21 | +core that gives every capsule its own isolation domain, capability |
| 22 | +tokens, content-addressed identity, DID-anchored principals, and a |
| 23 | +single namespace contract. Per [PRINCIPLES.md](../PRINCIPLES.md), it |
| 24 | +delivers what pc2.net cannot retrofit: |
| 25 | + |
| 26 | +- **No Ambient Authority** — capsules see capability-scoped operations, |
| 27 | + not raw filesystems or networks. |
| 28 | +- **Small Trusted Core** — only isolation, signatures, capabilities, and |
| 29 | + `elastos://` live in the runtime; everything else is a capsule or |
| 30 | + provider. |
| 31 | +- **Stable Identity Over Transport** — `localhost://...` and |
| 32 | + `elastos://...` are the real nouns; HTTP is edge transport. |
| 33 | +- **One Canonical Path Per Operation** — no soft fallbacks; fail closed. |
| 34 | + |
| 35 | +Convergence means: existing pc2.net features become capsules and |
| 36 | +providers running on this runtime. The launcher wraps the runtime |
| 37 | +instead of pc2-node. The Puter-derived desktop is progressively replaced |
| 38 | +by the runtime-owned `home`/`system`/`library`/`documents`/`inbox` |
| 39 | +surfaces under one capability model. |
| 40 | + |
| 41 | +## Non-Goals |
| 42 | + |
| 43 | +- This doc does **not** propose deprecating pc2.net before its features |
| 44 | + have working capsule equivalents. |
| 45 | +- It does **not** propose folding pc2.net's ambient-authority Node |
| 46 | + process into the runtime. The trusted core stays small; pc2.net |
| 47 | + features arrive as capsules under the same capability checks every |
| 48 | + other capsule gets. |
| 49 | +- It does **not** propose committing to a specific calendar. |
| 50 | + Sequencing is intent; gates are real. |
| 51 | + |
| 52 | +## Convergence Direction (Already in This Repo's Docs) |
| 53 | + |
| 54 | +This plan is the assembly of commitments that are already in the repo: |
| 55 | + |
| 56 | +- `state.md` — *"The default Home path must remain a KVM-independent |
| 57 | + browser-hosted adapter so macOS and Windows stay in scope without |
| 58 | + pretending to offer Linux parity."* And: *"Linux is the truthful |
| 59 | + full-runtime baseline. macOS is not yet a truthful full runtime |
| 60 | + target on this branch."* |
| 61 | +- `ROADMAP.md / Later` — *"Decide how much Puter-derived UI remains |
| 62 | + after the runtime-owned Home/System contract is stable."* |
| 63 | +- `ROADMAP.md / Later — Cross-platform runtime and host adapters` — |
| 64 | + Server / Desktop / Mobile / Kiosk host adapter modes share one |
| 65 | + capsule contract; *"Capsules don't know which host adapter they're |
| 66 | + on."* |
| 67 | +- `TASKS.md / Now / 1` — *"Keep the default Home path compatible with |
| 68 | + macOS and Windows by avoiding KVM-only assumptions. Remove remaining |
| 69 | + donor/KVM-only assumptions from scripts and runtime special cases."* |
| 70 | + |
| 71 | +What this doc adds is sequencing, gates, and pc2.net-specific mapping. |
| 72 | + |
| 73 | +## Capsule Inventory (Current Branch) |
| 74 | + |
| 75 | +For Planning Review Gate "Boundary clarity". Every capsule.json in |
| 76 | +this repo: |
| 77 | + |
| 78 | +| Substrate | Capsule | Role | Cross-platform today? | |
| 79 | +|---|---|---|---| |
| 80 | +| `wasm` | `home` | shell | yes | |
| 81 | +| `wasm` | `home-cli` | shell | yes | |
| 82 | +| `wasm` | `system` | app | yes | |
| 83 | +| `wasm` | `chat-room` | app | yes | |
| 84 | +| `wasm` | `chat-wasm` | app | yes | |
| 85 | +| `data` | `inbox` | app | yes | |
| 86 | +| `data` | `library` | app | yes | |
| 87 | +| `data` | `documents` | viewer | yes | |
| 88 | +| `data` | `gba-emulator` | viewer | yes | |
| 89 | +| `data` | `gba-ucity` | content | yes | |
| 90 | +| `microvm` | `shell` | shell | Linux/KVM only | |
| 91 | +| `microvm` | `localhost-provider` | provider | Linux/KVM only | |
| 92 | +| `microvm` | `did-provider` | provider | Linux/KVM only | |
| 93 | +| `microvm` | `webspace-provider` | provider | Linux/KVM only | |
| 94 | +| `microvm` | `ipfs-provider` | provider | Linux/KVM only | |
| 95 | +| `microvm` | `tunnel-provider` | provider | Linux/KVM only | |
| 96 | +| `microvm` | `ai-provider` | provider | Linux/KVM only | |
| 97 | +| `microvm` | `llama-provider` | provider | Linux/KVM only | |
| 98 | +| `microvm` | `agent` | app | Linux/KVM only | |
| 99 | +| `microvm` | `chat` | app | Linux/KVM only | |
| 100 | +| `microvm` | `notepad` | app | Linux/KVM only | |
| 101 | + |
| 102 | +The user-visible Home product (Home, System, Inbox, Library, Documents, |
| 103 | +Chat Room, GBA, chat-wasm) is already either `wasm` or `data`. What |
| 104 | +keeps the runtime Linux-only is **critical provider capsules** being |
| 105 | +`microvm`-substrate, in particular `localhost-provider` (filesystem) and |
| 106 | +`shell` (orchestrator). |
| 107 | + |
| 108 | +## pc2.net Feature → Runtime Counterpart |
| 109 | + |
| 110 | +Mapping at the *user-visible* level, with the substrate the runtime |
| 111 | +currently uses. |
| 112 | + |
| 113 | +| pc2.net feature | Runtime counterpart today | Gap to converge | |
| 114 | +|---|---|---| |
| 115 | +| Desktop UI (Puter fork) | `home` (wasm) + `system` (wasm) + browser-hosted `/apps/home/` | Home contract still maturing; Library/Documents/Inbox slices landing | |
| 116 | +| Wallet authentication | `did-provider` + `elastos://did/` + capability tokens | Wallet/WebConnect step in [ROADMAP.md § Four-quadrant runtime balance](../ROADMAP.md#near-term-direction); DID and capability machinery are in the runtime; WebConnect-style wallet pairing flow is open work | |
| 117 | +| File storage / file manager | `localhost://Users/self/...` via `localhost-provider`; `library` capsule for browsing | `localhost-provider` substrate (see §macOS Host Adapter) | |
| 118 | +| IPFS storage | `elastos://...` + `ipfs-provider` (microvm) | `ipfs-provider` substrate; pin/CID semantics already match the trust model | |
| 119 | +| Real-time sync | Carrier P2P (`elastos://peer/`) | Carrier carries presence, gossip, room sync today; richer object/sync model is open work | |
| 120 | +| WASM execution | `elastos-compute` (Wasmtime) + capsule `type: wasm` | Already first-class; capsule contract is the substrate-agnostic boundary | |
| 121 | +| AI chat | `ai-provider` + `llama-provider` (microvm) + `agent` capsule | Substrates; the runtime-side capability contract is already there | |
| 122 | +| DApp store | `webspace-provider` (microvm) + `localhost://WebSpaces/Marketplace` (intended) | Substrate + Marketplace WebSpace is open work (see ROADMAP "marketplace is a WebSpace") | |
| 123 | +| Tunneling (`.ela.city`) | `tunnel-provider` (microvm) — wraps cloudflared/sing-box paths | Substrate; the runtime needs the tunnel as a provider, not as a built-in protocol | |
| 124 | +| Backup / restore | localhost-provider + content-addressed `elastos://...` | Out of scope for the runtime-as-trusted-core; sits as a capsule using the same provider plane | |
| 125 | +| Auto-update | `elastos update` + trusted-source / signed-release pipeline | Already first-class in the runtime; the launcher's update flow can defer to it | |
| 126 | +| Access control (wallet-based perms) | Capability tokens + browser-session principals + Inbox approval | Already first-class architecturally; UX coverage of every flow is open work | |
| 127 | + |
| 128 | +The pattern: **the runtime contract is largely in place**. What is |
| 129 | +not in place on every platform is the *substrate* that lets providers |
| 130 | +run with isolation. That is the heart of the macOS work below. |
| 131 | + |
| 132 | +## macOS Host Adapter — Sequenced Slices |
| 133 | + |
| 134 | +The runtime should reach macOS as a first-class host adapter without |
| 135 | +faking Linux/KVM parity. Per `ROADMAP.md` host-adapter direction, the |
| 136 | +contract is identical across adapters; only how capsules are presented |
| 137 | +changes. |
| 138 | + |
| 139 | +### Slice A — Workspace builds on non-Linux (Layer 1) |
| 140 | + |
| 141 | +**Status:** complete on this branch in [commit 1dc27b4](https://github.com/Elacity/elastos-runtime/commit/1dc27b4). |
| 142 | + |
| 143 | +- `elastos-crosvm/src/network_stub.rs` mirrors the public surface of |
| 144 | + `network.rs` on non-Linux and fails closed in `setup()` with an |
| 145 | + explicit "requires Linux" error. |
| 146 | +- `lib.rs` cfg-gates `mod network` to Linux vs. stub. |
| 147 | +- Pre-existing `rootfs.rs` data-disk test cfg-gated to Linux only |
| 148 | + (shells out to `mkfs.ext4`). |
| 149 | +- One `null()` → `null_mut()` fix in an `elastos-guest` test for macOS |
| 150 | + `openpty` signature. |
| 151 | + |
| 152 | +**Verified on Apple Silicon M5 Pro / macOS 26.4.1:** |
| 153 | + |
| 154 | +- `cargo build -p elastos-server --release` succeeds. |
| 155 | +- `cargo check --workspace --all-targets` succeeds. |
| 156 | +- `cargo test -p elastos-crosvm` → 18/18 pass. |
| 157 | +- `cargo fmt --check` + `cargo clippy --all-targets -- -D warnings` |
| 158 | + clean on the touched crates. |
| 159 | +- `./elastos --version`, `--help`, `setup --list`, `identity show`, |
| 160 | + `config show`, `source list`, `source --help`, `serve --help` all run. |
| 161 | +- `elastos serve` initializes data dir, capability signing key, CA cert, |
| 162 | + TLS leaf cert, IP detection, TLS enable, `documents-provider` |
| 163 | + registration; then fails closed with `Error: localhost-provider not |
| 164 | + installed`. |
| 165 | +- `elastos setup` (default `home` profile) correctly emits `[skip] |
| 166 | + shell — not available for unknown-arm64`, `[skip] localhost-provider |
| 167 | + — not available …`, `[skip] did-provider …`, `[skip] |
| 168 | + webspace-provider …`. Setup logic already knows what is unavailable |
| 169 | + on this platform. |
| 170 | + |
| 171 | +**Linux behavior is bit-identical:** the real `network.rs` is |
| 172 | +unchanged. |
| 173 | + |
| 174 | +### Slice B — Critical providers available on non-Linux (Layer 2) |
| 175 | + |
| 176 | +**Status:** scope concretized; implementation open. |
| 177 | + |
| 178 | +**Smallest shippable slice:** make `localhost-provider` available as an |
| 179 | +**in-process provider** on non-Linux. The runtime already registers |
| 180 | +`documents-provider` in-process during `elastos serve` startup; the |
| 181 | +mechanism exists. `localhost-provider` is a pure-Rust crate (no |
| 182 | +Linux-only deps in `Cargo.toml`) so it links cleanly. |
| 183 | + |
| 184 | +**Boundary clarity:** |
| 185 | + |
| 186 | +- This must not weaken the trusted-core contract. An in-process |
| 187 | + provider on the macOS host still runs *under* the same capability |
| 188 | + token validation, audit, and provider-registry routing every other |
| 189 | + provider gets. The change is *isolation substrate*, not *authority |
| 190 | + model*. |
| 191 | +- On Linux, the microVM-backed `localhost-provider` capsule remains the |
| 192 | + default. Substrate selection is host-adapter policy, not capsule |
| 193 | + policy. |
| 194 | + |
| 195 | +**Affected quadrants:** |
| 196 | + |
| 197 | +| Quadrant | Change | |
| 198 | +|---|---| |
| 199 | +| PC2/Home | none in this slice — Home reaches `localhost-provider` through the same provider registry call regardless of where the provider runs | |
| 200 | +| Runtime | substrate-selection policy: when `elastos_crosvm::is_supported()` returns false, fall back to the in-process provider variant for capsules tagged as such | |
| 201 | +| Carrier | none in this slice | |
| 202 | +| Blockchain | none in this slice | |
| 203 | + |
| 204 | +**Proof path (must pass before declaring Slice B done):** |
| 205 | + |
| 206 | +1. `elastos serve` binds `127.0.0.1:3000` on macOS without `Error: |
| 207 | + localhost-provider not installed`. |
| 208 | +2. A browser request to `/apps/home/` returns the Home surface assets. |
| 209 | +3. A Home `/api/provider/localhost/*` call returns a typed object from |
| 210 | + `~/Library/Application Support/elastos/...`. |
| 211 | +4. Existing source-line tests (`cargo test -p elastos-server home --lib` |
| 212 | + etc.) still pass on Linux. The in-process variant must not regress |
| 213 | + the microVM-backed path. |
| 214 | +5. On Linux, microVM-backed `localhost-provider` remains the default |
| 215 | + and `setup --list` does not change behavior. |
| 216 | + |
| 217 | +**Entropy risk avoided:** do not introduce a third substrate name or a |
| 218 | +parallel capsule manifest schema. The capsule continues to declare |
| 219 | +itself once; substrate selection is a runtime-policy detail bound to |
| 220 | +`is_supported()` on the chosen provider. |
| 221 | + |
| 222 | +**Not in this slice:** |
| 223 | + |
| 224 | +- `did-provider`, `webspace-provider`, `ipfs-provider`, |
| 225 | + `tunnel-provider`, `ai-provider`, `llama-provider`. Each of these |
| 226 | + should follow the same pattern after Slice B proves it on |
| 227 | + `localhost-provider`. Doing one at a time keeps regressions |
| 228 | + attributable. |
| 229 | +- A WASM substrate variant of these providers. Possibly correct |
| 230 | + long-term, but bigger than Layer 2. Layer 2 should not block on it. |
| 231 | +- An Apple Hypervisor.framework substrate. Out of scope here; tracked |
| 232 | + separately. |
| 233 | + |
| 234 | +### Slice C — Platform identity on macOS |
| 235 | + |
| 236 | +**Smallest shippable slice:** the runtime currently reports the macOS |
| 237 | +platform as `unknown-arm64` (observable in `elastos setup --list` |
| 238 | +output and `elastos setup` skip lines). The setup logic does the right |
| 239 | +thing despite the unknown label, but the public surface should be |
| 240 | +honest: `aarch64-apple-darwin` (and the Intel equivalent if/when |
| 241 | +relevant). |
| 242 | + |
| 243 | +**Proof path:** `elastos setup --list` reports `aarch64-apple-darwin` |
| 244 | +on macOS; existing Linux platform IDs unchanged. |
| 245 | + |
| 246 | +### Slice D — Source-line proof script for the macOS path |
| 247 | + |
| 248 | +The repo has Linux smokes (`local-carrier-setup-smoke`, |
| 249 | +`home-frontdoor-smoke`, etc.). Add a macOS-aware variant or extend the |
| 250 | +existing scripts to detect `aarch64-apple-darwin` and run the subset |
| 251 | +that has provider availability under Slice B. |
| 252 | + |
| 253 | +**Not yet in scope** — this slice waits on Slice B + C to define what |
| 254 | +"works on macOS" means as a proof contract. |
| 255 | + |
| 256 | +## Launcher Convergence — Sequenced Slices |
| 257 | + |
| 258 | +[elastos-launcher](https://github.com/Elacity/elastos-launcher) today |
| 259 | +downloads pc2.net + Node 20 + WireGuard + AmneziaWG + sing-box, runs |
| 260 | +`pc2-node`, and exposes a Power On / Power Off + Update UI. |
| 261 | + |
| 262 | +### Launcher Slice 1 — `--backend elastos-runtime` opt-in |
| 263 | + |
| 264 | +**Smallest shippable slice:** add a runtime backend choice to |
| 265 | +elastos-launcher. Default stays `pc2-node`. Users can opt into |
| 266 | +`elastos-runtime` after Slice B above lands. The launcher's start/stop |
| 267 | +logic in `src/main/pc2Manager.ts` gains a sibling `elastosManager.ts` |
| 268 | +that supervises `elastos serve` under the same lifecycle: install via |
| 269 | +trusted source, start under PM2 or equivalent, status check, log view, |
| 270 | +update via `elastos update`. |
| 271 | + |
| 272 | +**Boundary clarity:** the launcher does not learn capsule semantics or |
| 273 | +become a second policy plane. It runs a daemon and forwards UI to |
| 274 | +`http://127.0.0.1:3000/apps/home/`. That keeps PRINCIPLES "HTTP Is Edge |
| 275 | +Transport, Not Product Truth" honest. |
| 276 | + |
| 277 | +**Affected quadrants:** |
| 278 | + |
| 279 | +- PC2/Home: launcher gains a runtime-backend switch and learns to open |
| 280 | + `/apps/home/` instead of `:4200` |
| 281 | +- Runtime: nothing changes; the launcher consumes the existing serve + |
| 282 | + trusted-source + update contracts |
| 283 | +- Carrier: nothing changes |
| 284 | +- Blockchain: nothing changes |
| 285 | + |
| 286 | +**Proof path:** on macOS, launcher with `--backend elastos-runtime` |
| 287 | +opens Home in the bundled browser/webview. Power On installs the |
| 288 | +runtime via trusted source if missing, runs `elastos serve`, surfaces |
| 289 | +status. Power Off stops the daemon cleanly. Switching back to |
| 290 | +`pc2-node` is a one-click toggle. |
| 291 | + |
| 292 | +### Launcher Slice 2 — install-parity check for the runtime backend |
| 293 | + |
| 294 | +The launcher's existing "Install Parity Rule" (CONTRIBUTING.md) says |
| 295 | +the GUI must install the same tool set as the terminal scripts. For |
| 296 | +the runtime backend, the analogous rule is: the GUI must always run |
| 297 | +the same `elastos setup --profile <p>` the terminal install would run, |
| 298 | +with no GUI-only side-effects. Codify this as a unit test in the |
| 299 | +launcher repo. |
| 300 | + |
| 301 | +### Launcher Slice 3 — UX convergence |
| 302 | + |
| 303 | +Once both backends ship features that map cleanly, the launcher's |
| 304 | +"Open Cloud" button can target the runtime's Home surface by default |
| 305 | +and keep pc2.net as a fallback during deprecation. The actual |
| 306 | +decommissioning of pc2.net is `ROADMAP.md / Later` territory and is |
| 307 | +out of scope for the launcher slice. |
| 308 | + |
| 309 | +## Sequencing Summary |
| 310 | + |
| 311 | +The order below is intent. Each step ends on a proof gate; no step |
| 312 | +ships until its gate passes. |
| 313 | + |
| 314 | +1. **Slice A** — workspace builds on non-Linux ✅ done |
| 315 | +2. **Slice B** — in-process `localhost-provider` on non-Linux → |
| 316 | + `elastos serve` reaches a functional Home on macOS |
| 317 | +3. **Slice C** — honest macOS platform identity in setup output |
| 318 | +4. **Slice D** — macOS source-line smoke script reflecting the realised |
| 319 | + provider matrix |
| 320 | +5. **Wallet-backed identity + WebConnect** ([ROADMAP.md § Near-term § |
| 321 | + Four-quadrant runtime balance](../ROADMAP.md)) — first cross-quadrant |
| 322 | + move. Independent of macOS work; both can proceed in parallel. |
| 323 | +6. **Other microvm providers** (`did-`, `webspace-`, `ipfs-`, |
| 324 | + `tunnel-`, `ai-`, `llama-`) repeat the Slice B pattern one at a |
| 325 | + time |
| 326 | +7. **Launcher Slice 1** — `--backend elastos-runtime` opt-in, lit once |
| 327 | + Slice B + C are real on macOS |
| 328 | +8. **Spaces / network drives** ([ROADMAP.md § Near-term § Four-quadrant |
| 329 | + runtime balance](../ROADMAP.md)) |
| 330 | +9. **Capsule publish/install registry** ([ROADMAP.md § Near-term § |
| 331 | + Four-quadrant runtime balance](../ROADMAP.md)) |
| 332 | +10. **Launcher Slice 2 + 3** as the underlying capsule and registry |
| 333 | + contracts harden |
| 334 | + |
| 335 | +Apple Hypervisor.framework substrate, dedicated browser capsule, and |
| 336 | +deeper Puter-derived UI deprecation are explicitly later. They should |
| 337 | +not distort the immediate sequence above. |
| 338 | + |
| 339 | +## Decision Log Stub |
| 340 | + |
| 341 | +Track decisions here when they pin down a previously open choice. |
| 342 | + |
| 343 | +- **2026-05-21** — macOS port chosen over Linux-VM-only workflow. |
| 344 | + Driver: contributors on macOS, runtime's own commitment in `state.md` |
| 345 | + that the default Home path stays KVM-independent. |
| 346 | +- **2026-05-21** — Slice B "smallest shippable" is in-process |
| 347 | + `localhost-provider` only, not WASM-substrate provider rework. |
| 348 | + Driver: matches existing `documents-provider` in-process mechanism, |
| 349 | + fewer new concepts. |
0 commit comments