|
|
|
@@ -1,28 +1,27 @@
|
|
|
|
|
# dsh-trustworthy
|
|
|
|
|
|
|
|
|
|
**Removes the untrusted-origin restriction from DeepSeek Harness without
|
|
|
|
|
removing its authentication.** Every browser window is treated as if it were
|
|
|
|
|
running on the harness machine itself: no declared trusted host and no
|
|
|
|
|
per-plugin origin fence, because one interceptor answers every request with the
|
|
|
|
|
loopback authority. The harness's own browser-session check stays in place —
|
|
|
|
|
open the one-time launch URL from the process log once, and the 30-day cookie it
|
|
|
|
|
exchanges covers the rewritten requests too.
|
|
|
|
|
**Removes the untrusted-origin restriction from DeepSeek Harness, and the
|
|
|
|
|
launch-token prompt with it.** Every browser window is treated as if it were
|
|
|
|
|
running on the harness machine itself: no declared trusted host, no per-plugin
|
|
|
|
|
origin fence, and no process token to paste into a phone — one interceptor
|
|
|
|
|
answers every request with the loopback authority, and the session check is off
|
|
|
|
|
by default.
|
|
|
|
|
|
|
|
|
|
A window that reaches the harness by a LAN address, a DNS name, or a tunnel
|
|
|
|
|
authenticates normally and then fails every mutating request with
|
|
|
|
|
`403 {"error":"untrusted origin"}`. Cards render, but Install, Update, toggle,
|
|
|
|
|
and "Update all" do nothing that the user can see. This plugin removes the
|
|
|
|
|
distinction between a local window and a remote one — with no declared trusted
|
|
|
|
|
host, no `--trusted-host`, and no per-plugin configuration. Removing the session
|
|
|
|
|
check as well (`disableAuth: true`) is available, but it is now opt-in.
|
|
|
|
|
host, no `--trusted-host`, and no per-plugin configuration. The launch-token
|
|
|
|
|
check is removed as well; `disableAuth: false` puts it back.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ⚠️ Read this before enabling it
|
|
|
|
|
|
|
|
|
|
**This plugin is a deliberate and total removal of the harness's request-identity
|
|
|
|
|
fence. It is not a bug fix and it is not a workaround for one specific plugin.**
|
|
|
|
|
The session check is a separate matter: it stays unless you ask for it to go.
|
|
|
|
|
fence, and by default of its browser-session check too. It is not a bug fix and
|
|
|
|
|
it is not a workaround for one specific plugin.**
|
|
|
|
|
|
|
|
|
|
The harness fences requests by their `Host` and `Origin` headers for one
|
|
|
|
|
reason: those are the only headers a page on another origin cannot forge, so
|
|
|
|
@@ -30,47 +29,36 @@ they are what stops a web page you happen to visit from driving your agent API
|
|
|
|
|
while the harness is reachable. With this plugin enabled:
|
|
|
|
|
|
|
|
|
|
- **DNS rebinding** against the harness API is no longer defended.
|
|
|
|
|
- **A page on any other origin** that carries a session cookie can issue
|
|
|
|
|
mutating requests to the API.
|
|
|
|
|
- **A page on any other origin** can issue mutating requests to the API.
|
|
|
|
|
- Those requests can **run commands on your machine** through the agent.
|
|
|
|
|
|
|
|
|
|
The default posture keeps the browser-session check, so the additional exposure
|
|
|
|
|
is limited to a page holding a live session cookie. Set `disableAuth: true` and
|
|
|
|
|
there is no check either: **anyone who can reach the port has full control of
|
|
|
|
|
the agent, including code execution.** Reachability becomes the only access
|
|
|
|
|
control.
|
|
|
|
|
And with the default `disableAuth: true` there is no session check either:
|
|
|
|
|
**anyone who can reach the port has full control of the agent, including code
|
|
|
|
|
execution.** Reachability is the only access control.
|
|
|
|
|
|
|
|
|
|
That second posture is reasonable when the port is behind something that
|
|
|
|
|
authenticates on your behalf, or when it is bound to a network you fully
|
|
|
|
|
control. It is a poor posture for a `0.0.0.0` bind fronted by a public tunnel
|
|
|
|
|
with no authentication of its own. Decide accordingly, and re-read this section
|
|
|
|
|
if you change how the port is exposed.
|
|
|
|
|
That posture is reasonable when the port is behind something that authenticates
|
|
|
|
|
on your behalf, or when it is bound to a network you fully control. It is a poor
|
|
|
|
|
posture for a `0.0.0.0` bind fronted by a public tunnel with no authentication of
|
|
|
|
|
its own. Decide accordingly, and re-read this section if you change how the port
|
|
|
|
|
is exposed. Set `disableAuth: false` to restore the launch token as a second
|
|
|
|
|
line of defence.
|
|
|
|
|
|
|
|
|
|
### The launch token, and why the default changed
|
|
|
|
|
### The launch token, and the `disableAuth` switch
|
|
|
|
|
|
|
|
|
|
The Web UI prints a one-time launch token in the process log —
|
|
|
|
|
`dsh web: http://…/?token=…` — and from `0.2.1-alpha.4` the container entrypoint
|
|
|
|
|
writes that line into the Docker log as well. The token rotates on every
|
|
|
|
|
restart. Open the URL once on each origin you use, and the harness exchanges it
|
|
|
|
|
for a **30-day cookie** bound to the authority it was minted under; until then
|
|
|
|
|
every page answers `401`.
|
|
|
|
|
restart. With the check enabled, every new device or origin must open that URL
|
|
|
|
|
once; the harness exchanges the token for a **30-day cookie** bound to the
|
|
|
|
|
authority it was minted under, and until then every page answers `401`.
|
|
|
|
|
|
|
|
|
|
The exchange, the cookie, and the authority check are all present in
|
|
|
|
|
`0.2.1-alpha.2` and later; what changed is that the bypass (0.3.0 and the
|
|
|
|
|
`disableAuth: true` default it shipped) discarded all three. The default now
|
|
|
|
|
keeps them.
|
|
|
|
|
`0.4.0` made that check the default, on the argument that one exchange covers
|
|
|
|
|
every domain because the plugin rewrites `Host` to the same loopback authority
|
|
|
|
|
the cookie is bound to. In practice it still means producing a token on each new
|
|
|
|
|
device, which is the friction this plugin exists to remove — `0.5.0` therefore
|
|
|
|
|
restores `disableAuth: true` as the default. Set `disableAuth: false` to get the
|
|
|
|
|
check, and the cookie, back.
|
|
|
|
|
|
|
|
|
|
Because this plugin rewrites `Host` to the loopback authority before any route
|
|
|
|
|
looks at it, the cookie is minted for the loopback authority too, and the
|
|
|
|
|
rewrite presents that same authority on every request afterwards. One exchange
|
|
|
|
|
therefore covers every entry domain, and the token never has to be pasted into
|
|
|
|
|
the address bar by hand again. That is why the plugin now keeps the check by
|
|
|
|
|
default instead of removing it: the token flow is the access control that makes
|
|
|
|
|
an internet-facing port defensible.
|
|
|
|
|
|
|
|
|
|
If you want the errors gone but not the exposure, leave `disableAuth` at its
|
|
|
|
|
default `false`. Only set it `true` when something else already authenticates
|
|
|
|
|
callers, and accept that the harness then has no second line of defence.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
@@ -184,7 +172,7 @@ Override any key in your profile's `cordis.patch.yml`:
|
|
|
|
|
- id: trustworthy
|
|
|
|
|
config:
|
|
|
|
|
enabled: true
|
|
|
|
|
disableAuth: false
|
|
|
|
|
disableAuth: true
|
|
|
|
|
forceClientLoopback: true
|
|
|
|
|
grantPairing: true
|
|
|
|
|
provideWebRuntime: true
|
|
|
|
@@ -197,7 +185,7 @@ Override any key in your profile's `cordis.patch.yml`:
|
|
|
|
|
| Key | Default | Effect |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `enabled` | `true` | Master switch. `false` loads the plugin and changes nothing. |
|
|
|
|
|
| `disableAuth` | `false` | **Also** removes the browser-session check, so no launch token is needed at all. The default keeps it: exchange the token once and the 30-day cookie covers every rewritten request. `true` is the one that removes access control. |
|
|
|
|
|
| `disableAuth` | `true` | **Also** removes the browser-session check, so no launch token and no per-device pairing are needed. This is the default: reachability is the only access control. Set `false` to keep the token — exchange it once and the 30-day cookie covers every rewritten request. |
|
|
|
|
|
| `forceClientLoopback` | `true` | Grants the browser-side `isLoopback` flag so the settings and model surfaces act as they do on the host. |
|
|
|
|
|
| `grantPairing` | `true` | Provides the paired-device service that plugins like the Skill Center accept instead of a loopback peer. See below. |
|
|
|
|
|
| `provideWebRuntime` | `true` | Restores the `webRuntime` trust snapshot the harness stopped publishing in 0.2.1-alpha.2, so plugins that inject it (the sidebar) mount instead of answering 405. See below. |
|
|
|
|
@@ -211,17 +199,19 @@ Override any key in your profile's `cordis.patch.yml`:
|
|
|
|
|
Every key above only answers fences. `disableAuth` is the one that changes who
|
|
|
|
|
may talk to the harness at all.
|
|
|
|
|
|
|
|
|
|
- **`false` (default).** The request-identity fence is rewritten away, and the
|
|
|
|
|
- **`true` (default).** The session check is replaced too: `connection.admit`
|
|
|
|
|
returns the owner's own peer for every request, `authorizeIndex` admits the
|
|
|
|
|
index, and `authenticatedUrl` stops appending the token to the printed URL. No
|
|
|
|
|
token, no cookie, no login, nothing to type on a phone — and anyone who reaches
|
|
|
|
|
the port controls the agent. Use it behind an authenticating proxy, on a
|
|
|
|
|
network that is already trusted, or when the port is otherwise unreachable from
|
|
|
|
|
untrusted networks.
|
|
|
|
|
- **`false`.** The request-identity fence is still rewritten away, and the
|
|
|
|
|
browser-session check is left exactly as the harness built it. A new browser
|
|
|
|
|
shows `401` until the launch URL from the process log is opened once; that
|
|
|
|
|
exchange sets the 30-day cookie, and every later request — including the ones
|
|
|
|
|
this plugin rewrote the `Host` on — carries it. This is the posture to use on a
|
|
|
|
|
port that faces anything you do not fully control.
|
|
|
|
|
- **`true`.** The session check is replaced too: `connection.admit` returns the
|
|
|
|
|
owner's own peer for every request, `authorizeIndex` admits the index, and
|
|
|
|
|
`authenticatedUrl` stops appending the token to the printed URL. No token, no
|
|
|
|
|
cookie, no login — anyone who reaches the port controls the agent. Use it only
|
|
|
|
|
behind an authenticating proxy or on a network that is already trusted.
|
|
|
|
|
this plugin rewrote the `Host` on — carries it. Each new device still has to be
|
|
|
|
|
given the token, which is why it is not the default.
|
|
|
|
|
|
|
|
|
|
The implementation replaces `admit` because that is where every shape of the
|
|
|
|
|
gate ends up: releases up to `0.2.1-alpha.2` call `requestRejection` from inside
|
|
|
|
@@ -361,8 +351,8 @@ three are `true` by default; serving over HTTPS makes the first two redundant.
|
|
|
|
|
## Compatibility
|
|
|
|
|
|
|
|
|
|
Verified against **DSH 0.1.7-rc.2**, **0.2.0-rc.1**, **0.2.1-alpha.1**,
|
|
|
|
|
**0.2.1-alpha.2**, **0.2.1-alpha.4**, and **0.2.1-rc.1**. From 0.4.0 the
|
|
|
|
|
manifest also declares the range:
|
|
|
|
|
**0.2.1-alpha.2**, **0.2.1-alpha.4**, **0.2.1-rc.1**, and **0.2.2-alpha.2**.
|
|
|
|
|
From 0.4.0 the manifest also declares the range:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
"engines": { "dsh": ">=0.1.7-rc.2 <0.3.0-0" }
|
|
|
|
@@ -372,10 +362,15 @@ manifest also declares the range:
|
|
|
|
|
provide — the harness uses it, when present, in place of guessing from
|
|
|
|
|
`@deepseek-ai/dsh-*` peer ranges. This plugin has no dsh peers at all, so the
|
|
|
|
|
declaration is the only statement of support it makes, and it is bounded above
|
|
|
|
|
at the next minor release, excluding its prereleases, rather than left open. `0.2.1-rc.2` is not listed as a
|
|
|
|
|
separate version because `dsh-client-connection`, `dsh-host-webserver`,
|
|
|
|
|
`dsh-web-app`, and the frontend static bundle are byte-identical between rc.1
|
|
|
|
|
and rc.2.
|
|
|
|
|
at the next minor release, excluding its prereleases, rather than left open.
|
|
|
|
|
|
|
|
|
|
`0.2.1-rc.2` is not listed separately because all four bundles the plugin hooks
|
|
|
|
|
are byte-identical between rc.1 and rc.2. `0.2.2-alpha.2` *is* listed: it is the
|
|
|
|
|
first release since 0.2.1-rc.1 that moves a hooked bundle, so it was re-checked live
|
|
|
|
|
rather than inferred. Its `dsh-client-connection` and `dsh-web-app` are still
|
|
|
|
|
byte-identical to `0.2.1-rc.2`; `dsh-host-webserver` and
|
|
|
|
|
`dsh-host-frontend-static` changed in ways that leave the surfaces used here
|
|
|
|
|
intact, and `dsh-session`'s stricter publication does not touch this plugin.
|
|
|
|
|
|
|
|
|
|
The plugin depends on several things that are internal rather than public API,
|
|
|
|
|
so a harness release that renames any of them will break it:
|
|
|
|
@@ -391,7 +386,8 @@ so a harness release that renames any of them will break it:
|
|
|
|
|
| the `webserver/index-inject` channel and the `ownsHost` marker | webserver + connection client |
|
|
|
|
|
|
|
|
|
|
The only one used conditionally is `connection.admit`: the bypass path replaces
|
|
|
|
|
it when `disableAuth: true`. The default posture does not touch it at all.
|
|
|
|
|
it when `disableAuth: true` (the default). With `disableAuth: false` the plugin
|
|
|
|
|
does not touch it at all.
|
|
|
|
|
|
|
|
|
|
Every one of those is probed before use. If a release reshapes the surface, the
|
|
|
|
|
plugin logs which capability it lost and carries on with the rest, rather than
|
|
|
|
@@ -404,6 +400,59 @@ interceptor was not installed and a Host fence will still refuse a remote
|
|
|
|
|
window; the harness surface may have changed
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### What was checked on 0.2.2-alpha.2
|
|
|
|
|
|
|
|
|
|
The first release since 0.2.1-rc.1 that moves a bundle this plugin hooks, so it was
|
|
|
|
|
re-checked end to end instead of inferred from byte-identity.
|
|
|
|
|
|
|
|
|
|
**What moved.** `dsh-client-connection` and `dsh-web-app` are still
|
|
|
|
|
byte-identical to `0.2.1-rc.2`, so the allow path — `admit`, `trustedHosts`,
|
|
|
|
|
`requestRejection`, `authorizeIndex`, `authenticatedUrl` — is untouched. The two
|
|
|
|
|
surfaces that did move are `dsh-host-webserver` and `dsh-host-frontend-static`.
|
|
|
|
|
The webserver gained a second route kind (`{ resource }`: a Fetch-API
|
|
|
|
|
`Request → Response` handler, plus a `readResource` variant) beside the plain
|
|
|
|
|
`{ handler }` one; `server`, `register`, `tapIndex`, `host`, `port`, and
|
|
|
|
|
`protocol` are unchanged, and the interceptor wraps the raw server's request
|
|
|
|
|
emission before routing, so a route's kind does not matter to it. The frontend
|
|
|
|
|
static bundle still authorizes the index through
|
|
|
|
|
`connection.authorizeIndex(request, shim)` and still emits
|
|
|
|
|
`webserver/index-inject`, so the browser grant, the shims, the viewport, and the
|
|
|
|
|
PWA route inject exactly as before. `dsh-session` tightened store-owned
|
|
|
|
|
publication (`cannot append outside a SessionStore`), which this plugin never
|
|
|
|
|
does. The CLI's new optional bundles do not change a profile's explicit bundle
|
|
|
|
|
list, so nothing new is inserted next to this one.
|
|
|
|
|
|
|
|
|
|
**Measured on a sandbox of the published `@deepseek-ai/[email protected]`** (the
|
|
|
|
|
npm `alpha` tag; `latest` still points at `0.2.1-rc.2`), with a copy of a real
|
|
|
|
|
profile, over a non-loopback peer:
|
|
|
|
|
|
|
|
|
|
| Check | Result |
|
|
|
|
|
|---|---|
|
|
|
|
|
| interceptor answers `GET /` for a foreign `Host` | `200` index, no cookie |
|
|
|
|
|
| WebSocket upgrade for a foreign `Host` | `101` |
|
|
|
|
|
| `/api/*` over the non-loopback peer and over a named host | `200`, not the `400` trust fence |
|
|
|
|
|
| browser grant, shims, viewport, and PWA markers in the served index | all present |
|
|
|
|
|
| PWA manifest | `200 application/manifest+json` |
|
|
|
|
|
| Files pane over a foreign `Host` — `fs.tree`, `fs.read`, `GET /sidebar/file` download | `200`, and the downloaded bytes are the file's |
|
|
|
|
|
| `dsh plugin` load | no skip line, no missing-surface warning |
|
|
|
|
|
|
|
|
|
|
`node scripts/live-probe.mjs` passes **11/11** against that sandbox, including
|
|
|
|
|
the sidebar Files API row. A control run with the bundle disabled answers `401`
|
|
|
|
|
to `GET /` — the token gate stands — so a remote browser never gets as far as
|
|
|
|
|
the pane; that is the difference the bypass makes. The installed sidebar bundle
|
|
|
|
|
(0.28.0) no longer injects `webRuntime` at all, so on this harness its Files
|
|
|
|
|
routes register whether or not the service is provided; `provideWebRuntime`
|
|
|
|
|
stays for bundles that still inject it (0.26 and older), where the missing
|
|
|
|
|
service is what left the pane answering `405`.
|
|
|
|
|
|
|
|
|
|
One harness deployment change to know about: since DSH 0.2.1-alpha.2, `dsh web --host` refuses
|
|
|
|
|
a wildcard address (`0.0.0.0`, `::`) — *"is an unspecified (wildcard) address,
|
|
|
|
|
which is not supported: binding every interface would expose remote code
|
|
|
|
|
execution to the network; bind one concrete IPv4 or IPv6 address instead"* — so
|
|
|
|
|
a container that bound wildcard must pass its concrete container IP. The bind
|
|
|
|
|
address is still accepted as an authority by the trust snapshot, so
|
|
|
|
|
`provideWebRuntime` and the no-`--trusted-host` posture keep working.
|
|
|
|
|
|
|
|
|
|
### What was checked on 0.2.1-rc.1
|
|
|
|
|
|
|
|
|
|
This is the release the 0.4.0 change answers. Two things moved.
|
|
|
|
@@ -417,9 +466,10 @@ now replaces `admit` itself and returns the owner's peer (`browserPeer` on this
|
|
|
|
|
release, `operator` before alpha.3); measured on a sandboxed rc.1 with a
|
|
|
|
|
non-loopback `Host`, the upgrade answered `101` with no cookie.
|
|
|
|
|
|
|
|
|
|
**The session check is now exercised by the default posture.** The plugin
|
|
|
|
|
rewrites `Host`/`Origin` to `127.0.0.1:<port>`, which is also the authority the
|
|
|
|
|
harness mints the session cookie for. Measured on the same sandbox, in order:
|
|
|
|
|
**The session check, when enabled, survives the rewrite.** The plugin rewrites
|
|
|
|
|
`Host`/`Origin` to `127.0.0.1:<port>`, which is also the authority the harness
|
|
|
|
|
mints the session cookie for. Measured on a sandbox, with `disableAuth: false`,
|
|
|
|
|
in order:
|
|
|
|
|
|
|
|
|
|
| Request (`Host: ai.milesward.dev`) | Result |
|
|
|
|
|
|---|---|
|
|
|
|
@@ -431,8 +481,9 @@ harness mints the session cookie for. Measured on the same sandbox, in order:
|
|
|
|
|
The cookie payload's `authority` is `127.0.0.1:<port>` — the rewritten one — so
|
|
|
|
|
the browser keeps the cookie for the public origin it opened, and the plugin's
|
|
|
|
|
rewrite presents the matching authority on every request afterwards. This is
|
|
|
|
|
what lets the 30-day session survive a Host rewrite, and it is why the default
|
|
|
|
|
no longer needs to remove the check.
|
|
|
|
|
what lets the 30-day session survive a Host rewrite, and it is why
|
|
|
|
|
`disableAuth: false` is a viable posture for anyone who would rather keep the
|
|
|
|
|
check.
|
|
|
|
|
|
|
|
|
|
The token rotates whenever the process restarts (`dsh web: …?token=…` in the
|
|
|
|
|
process log; the container entrypoint prints that line into the Docker log from
|
|
|
|
@@ -565,14 +616,14 @@ Three guards follow from that, and each has a test:
|
|
|
|
|
`isTrustedApiRequest`, before the `Origin` check and regardless of the
|
|
|
|
|
trusted-host list. No header rewrite can defeat it, and this plugin does not
|
|
|
|
|
try. It only guards requests a browser itself marks as cross-site, so it has
|
|
|
|
|
no effect on normal navigation or on the WebSocket. Set `disableAuth: true`
|
|
|
|
|
and the fence is skipped entirely.
|
|
|
|
|
no effect on normal navigation or on the WebSocket. With `disableAuth: true`
|
|
|
|
|
(the default) the gate that calls it is replaced, so it does not run either.
|
|
|
|
|
- Rewriting `Host` decides the **cookie authority** the harness derives from it
|
|
|
|
|
(`dsh-auth-<sha256(authority)>`). The launch token is exchanged for the
|
|
|
|
|
rewritten authority, so the resulting 30-day cookie matches every request the
|
|
|
|
|
plugin intercepts — that is what makes the default posture work. The
|
|
|
|
|
authority is the loopback bind (`127.0.0.1:<port>`), so changing `--port`
|
|
|
|
|
mints a new one and requires one new exchange. A session cookie you already
|
|
|
|
|
(`dsh-auth-<sha256(authority)>`). With `disableAuth: false` the launch token is
|
|
|
|
|
exchanged for the rewritten authority, so the resulting 30-day cookie matches
|
|
|
|
|
every request the plugin intercepts. The authority is the loopback bind
|
|
|
|
|
(`127.0.0.1:<port>`), so changing `--port` mints a new one and requires one new
|
|
|
|
|
exchange. A session cookie you already
|
|
|
|
|
hold under the public hostname is not reused; expect one re-login on enabling
|
|
|
|
|
the plugin.
|
|
|
|
|
- `Referer` is read by no layer of the harness, core or plugin. It is rewritten
|
|
|
|
@@ -654,7 +705,7 @@ node test/web-runtime.test.mjs # the restored webRuntime value, and when it is
|
|
|
|
|
node scripts/live-probe.mjs # against the running harness, over a non-loopback peer
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
All five suites together — **60 tests** (fence 8, apply 21, handover 15,
|
|
|
|
|
All five suites together — **61 tests** (fence 8, apply 22, handover 15,
|
|
|
|
|
shims 9, web-runtime 7) — are `node --test test/*.test.mjs` from the plugin
|
|
|
|
|
directory. The shell has to expand that glob: `node --test test/` fails with `MODULE_NOT_FOUND`
|
|
|
|
|
on Node 22.
|
|
|
|
@@ -683,6 +734,8 @@ remote client and always looks like it passes.
|
|
|
|
|
|
|
|
|
|
| Version | What changed |
|
|
|
|
|
|---|---|
|
|
|
|
|
| **0.5.1** | Documentation and compatibility only — **no code change from 0.5.0**. Records the 0.2.2-alpha.2 review: the allow path's bundles are byte-identical, the webserver's new route kind does not touch the interceptor, and `scripts/live-probe.mjs` passes 11/11 against a sandbox of the published release (Files pane, PWA, shell, Skill Center, shims). Also notes the new `--host` wildcard refusal. |
|
|
|
|
|
| **0.5.0** | Restores `disableAuth: true` as the default: no launch token and no per-device pairing, which is what the plugin exists to remove. `0.4.0`'s keep-the-check posture remains available with `disableAuth: false`. No code change beyond the default and the documentation; validated on DSH `0.2.1-rc.2`, where the bypass still replaces `connection.admit`. |
|
|
|
|
|
| **0.4.0** | Keeps the browser-session check by default (`disableAuth: false`) and makes the 0.2.1-alpha.3 launch-token → 30-day-cookie flow survive the Host rewrite, including on a remote origin; the no-check posture moves to `disableAuth: true` and now replaces `connection.admit` as well, because the gate moved there. Declares `engines.dsh` (the 0.2.1-alpha.4 recommendation) and is validated on 0.2.1-alpha.4 and 0.2.1-rc.1. |
|
|
|
|
|
| **0.3.0** | Provides the `webRuntime` trust snapshot that `0.2.1-alpha.2` stopped publishing (`lib/web-runtime.js`, `provideWebRuntime`), so a plugin that injects it — the sidebar among them — mounts instead of answering 405 on every request. The value is read live from `connection.trustedHosts` plus the listener's bind address, and an existing provider is left alone. |
|
|
|
|
|
| 0.2.1 | Documentation and compatibility only — **no code change from 0.2.0**. Records the 0.2.1-alpha.1 validation above, and how to install so the market can update it. |
|
|
|
|
|