brane 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/AGENTS.md +12 -7
  2. package/CHANGELOG.md +37 -4
  3. package/CONTRIBUTING.md +12 -2
  4. package/DESIGN.md +7 -4
  5. package/README.md +2 -2
  6. package/SECURITY.md +8 -0
  7. package/dist/commands/config.js +17 -0
  8. package/dist/commands/meld.js +38 -10
  9. package/dist/commands/spawn.js +11 -4
  10. package/dist/commands/token.js +2 -1
  11. package/dist/daemon/server.js +88 -84
  12. package/dist/db/schema.js +10 -0
  13. package/dist/db/tokens.js +43 -2
  14. package/dist/shared/app-origin.js +26 -0
  15. package/dist/shared/narrative-menu.js +8 -6
  16. package/dist/shared/view-url.js +39 -20
  17. package/dist/test/app-host-literal.test.js +53 -0
  18. package/dist/test/cors-preflight.test.js +28 -21
  19. package/dist/test/hook-config.test.js +38 -1
  20. package/dist/test/meld.test.js +59 -1
  21. package/dist/test/narrative-menu.test.js +13 -0
  22. package/dist/test/remote-meld.test.js +13 -0
  23. package/dist/test/terminal-size.test.js +36 -0
  24. package/dist/test/token-devices.test.js +59 -0
  25. package/dist/test/view-url.test.js +93 -47
  26. package/dist/test/wrangler-route.test.js +27 -0
  27. package/dist/tmux.js +11 -0
  28. package/docker-entrypoint.sh +15 -2
  29. package/docs/daemon-api.md +4 -4
  30. package/docs/releasing.md +59 -8
  31. package/docs/terminal-mirroring.md +32 -0
  32. package/docs/token-rotation.md +22 -4
  33. package/docs/view-urls.md +26 -6
  34. package/docs/web-app.md +1 -1
  35. package/expo/dist/_expo/static/js/web/{entry-e56efc1291dca7258ea00b8108b033a4.js → entry-e94247f119fdcd3b424a1764233a41d2.js} +47 -45
  36. package/expo/dist/index.html +1 -1
  37. package/expo/dist/sw.js +2 -2
  38. package/package.json +1 -1
  39. package/wiki/shared/index.md +5 -0
package/docs/view-urls.md CHANGED
@@ -3,7 +3,7 @@
3
3
  The query string of a narrative screen is not decoration — it is the only way
4
4
  a view travels. Active tab, pinned tabs, open file and line range are kept in
5
5
  `sessionStorage`, which is **origin-scoped**, and two menu items cross an
6
- origin: **Isolate** hops between `brane.organelle.dev` and a daemon's own
6
+ origin: **Isolate** hops between a shared app's origin and a daemon's own
7
7
  bundle, and **Meld** hands a URL to another device. Whatever is not in the URL
8
8
  does not arrive.
9
9
 
@@ -15,16 +15,36 @@ tab, pin subset, path and line spec):
15
15
  |---|---|
16
16
  | `viewParams()` | The view as params, `undefined` for anything at its default — which is how `router.setParams` clears one |
17
17
  | `parseActiveTab()`, `parsePinnedTabs()`, `parseLineSpec()` | Read them back. Writer and reader live together on purpose: a param whose two halves sit in different modules drifts |
18
+ | `isIsolated(pageHost, daemonHost)` | Whether this page is the daemon's own bundle: `location.host` against the connection's host, no constant in it |
18
19
  | `buildViewUrl(target, opts)` | The same narrative, same view, somewhere else |
19
- | `buildIsolateUrl()` / `buildMeldUrl()` | The same builder with one bit different — see below |
20
+ | `buildIsolateUrl()` / `buildMeldUrl()` | The same builder with one bit different — see below. Isolate is `null` from a daemon's bundle that reported no app host |
20
21
  | `withoutConnectionParams()`, `withoutConnectionHash()` | Strip `host`/`token` from the query string and from the fragment, and leave everything else |
21
22
  | `connectionFragment()` | `#host=…&token=…` for the shared app, `#token=…` for a daemon's own bundle — the one place the connection is written into a URL, used by `buildViewUrl` and by `brane meld` |
22
23
 
23
24
  **Isolate flips the origin kind; Meld stays on it.** Isolate exists to change
24
- which app serves you. Meld aims at another *device* — hand a phone a shared-SPA
25
+ which app serves you. Meld aims at another *device* — hand a phone a shared-app
25
26
  link while the operator is reaching the daemon directly, and the phone loads an
26
27
  app that has never heard of that daemon.
27
28
 
29
+ **The app knows no host.** There is no constant naming `brane.organelle.dev`
30
+ in the bundle, and `src/test/app-host-literal.test.ts` keeps it that way.
31
+ "Isolated" means *this page is served by the daemon it is connected to*:
32
+ `window.location.host` equal to the connection's host, which a daemon's own
33
+ bundle fills from the same `location.host`. Everything else is a shared app,
34
+ whichever host serves it: the hosted shell, a staging hostname, a fork's
35
+ deployment, a dev server on `localhost`. From a shared app, Meld stays on
36
+ *that* origin and Isolate hops in to the daemon; neither needs to be told a
37
+ host. From a daemon's bundle, Isolate hops *out* to whatever the daemon
38
+ reports as its `app_domain` in `GET /api/status` (`useAppHost`,
39
+ `expo/lib/appHost.ts`, fetched before the tap, since a `window.open` after an
40
+ await is a popup the browser blocks). A daemon that reports none, or cannot
41
+ be reached for it, has no way out, and the menu leaves Isolate out rather
42
+ than hand you a link to a host the app made up. `brane meld` reads the same
43
+ config, so a fork changes `CONFIG_DEFAULTS.app_domain` and both its CLI and
44
+ its daemons name its own shell. None of this is trust: the daemon accepts any
45
+ origin (`SECURITY.md`, Authentication); the host only decides which copy of
46
+ the app a browser loads.
47
+
28
48
  **Back undoes a jump, never a view change.** A jump pushes a history entry: to
29
49
  a different narrative (from the list, an `@nid` link, the switcher, Revive or
30
50
  Twin), and to a message by `nid:seq`, *including one in the narrative you are
@@ -86,9 +106,9 @@ by resetting to the bare pathname, which would throw away the view that just
86
106
  arrived.
87
107
 
88
108
  **The connection rides in the fragment; the view rides in the query string.**
89
- A query string is part of the HTTP request. On a `brane.organelle.dev` link
90
- that meant the daemon's bearer token and tailnet hostname reached Cloudflare's
91
- edge with every meld; on an Isolate hop it landed in the daemon's own request
109
+ A query string is part of the HTTP request. On a shared-app link that meant
110
+ the daemon's bearer token and tailnet hostname reached the shell host's edge
111
+ with every meld; on an Isolate hop it landed in the daemon's own request
92
112
  log; and a meld URL pasted into iMessage or Slack handed it to the link
93
113
  unfurler. A fragment is never sent to any server, so `#host=…&token=…` is what
94
114
  every link carries now (`connectionFragment`), and `?token=` is read only for
package/docs/web-app.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Web App (Expo)
2
2
 
3
- The Expo app runs as a web PWA served by the daemon (and optionally via Cloudflare Workers at `brane.organelle.dev`). It provides:
3
+ The Expo app runs as a web PWA served by the daemon (and optionally via Cloudflare Workers at `brane.organelle.dev`, which serves the app of the `latest` npm release and is deployed only by a release — see [The app ships with the release](releasing.md#the-app-ships-with-the-release)). It provides:
4
4
 
5
5
  - **Narrative list** — shows all narratives with summary, status, and MCP connection indicator
6
6
  - **Spawn button** — header button that opens fold picker modal (or spawns directly with 1 fold)