1 Commits
Author SHA1 Message Date
mward4 a2700854a9 0.4.0: keep the launch-token session check by default
0.2.1-alpha.3 moved the request gate into `connection.admit`: the `/api`
gateway and the WebSocket upgrade call it directly, and `requestRejection`
became a façade over it. The 0.3.0 bypass only replaced `requestRejection`, so
under `disableAuth: true` the index loaded and every socket upgrade answered
401. Replace `admit` too, returning the peer the harness already owns
(`browserPeer` from alpha.3 on, `operator` before).

The default posture now keeps the harness's browser-session check instead of
removing it. The plugin's Host rewrite to the loopback authority is also the
authority the one-time launch token is exchanged for, so the 30-day cookie is
minted for the rewritten authority and the rewrite presents it on every later
request. Measured on 0.2.1-rc.1, 0.2.1-alpha.4 and 0.2.1-alpha.2: 401 without
the cookie, 303 + Set-Cookie on `/?token=`, 200 index and 101 upgrade with it.

Declare `engines.dsh` (`>=0.1.7-rc.2 <0.3.0-0`) as 0.2.1-alpha.4 now prefers.
The removed session check moves to an opt-in `disableAuth: true`, which still
prints a token-free URL. Tests: 60 pass, including the operator-peer fallback
and restoring the real `admit` when the fiber is disposed.
2026-10-17 06:52:12 -04:00
5 changed files with 240 additions and 54 deletions

No files matched your search

+160 -32
View File
@@ -1,17 +1,20 @@
# dsh-trustworthy
**Removes the untrusted-origin restriction from DeepSeek Harness.** Every browser
window is treated as if it were running on the harness machine itself: no process
token, no declared trusted host, and no per-plugin origin fence, because one
interceptor answers every request with the loopback authority.
**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.
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 token, no
`--trusted-host`, no per-plugin configuration, and no second listener on a
second port.
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.
---
@@ -19,6 +22,7 @@ second port.
**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.
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
@@ -26,28 +30,55 @@ 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** can issue mutating requests to the API.
- **A page on any other origin** that carries a session cookie can issue
mutating requests to the API.
- Those requests can **run commands on your machine** through the agent.
With `disableAuth: true` (the default) there is no session check either, so
**anyone who can reach the port has full control of the agent, including code
execution.** Reachability becomes the only access control.
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.
That is a reasonable posture when the port is behind something that
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.
with no authentication of its own. Decide accordingly, and re-read this section
if you change how the port is exposed.
If you want the errors gone but not the exposure, set `disableAuth: false`.
That keeps the process token as the access control while still answering the
identity fence, which is what actually produces the 403.
### The launch token, and why the default changed
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`.
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.
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.
---
## What it changes
Five things, each one reachable only by a different kind of fence.
Five things, each one reachable only by a different kind of fence. None of them
touches the browser-session check; removing that is the separate `disableAuth`
key described at the end of this section.
**1. Request identity, at the server.** The plugin installs `request` and
`upgrade` listeners with `prependListener` on the raw `node:http` server the
@@ -153,7 +184,7 @@ Override any key in your profile's `cordis.patch.yml`:
- id: trustworthy
config:
enabled: true
disableAuth: true
disableAuth: false
forceClientLoopback: true
grantPairing: true
provideWebRuntime: true
@@ -166,7 +197,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` | `true` | Also removes the browser-session check, so no process token is needed. **This is the one that removes access control.** |
| `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. |
| `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. |
@@ -175,6 +206,31 @@ Override any key in your profile's `cordis.patch.yml`:
| `shimRandomUuid` | `true` | Restores `crypto.randomUUID` on plain HTTP. See below. |
| `shimPwa` | `true` | Serves a manifest and adds the installable-app metadata. See below. |
### `disableAuth` — the two postures
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
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.
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
`admit` and wrap its answer, while `0.2.1-alpha.3` and later apply the fence and
session check in `admit` itself. `requestRejection` is replaced as well so the
older shape cannot short-circuit around the newer one, and every replacement is
liveness-aware, so a host that switches the plugin off without running its
disposers gets the real gate back.
### `provideWebRuntime` — the Files pane, and HTTP 405
`0.2.1-alpha.2` stopped providing a service named `webRuntime`. Its value was the
@@ -304,9 +360,25 @@ 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**, and
**0.2.1-alpha.2**. 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:
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:
```json
"engines": { "dsh": ">=0.1.7-rc.2 <0.3.0-0" }
```
`0.2.1-alpha.4` made `engines.dsh` the compatibility declaration a plugin should
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.
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:
| Depends on | Where |
|---|---|
@@ -314,9 +386,13 @@ than public API, so a harness release that renames any of them will break it:
| `webServer.host` — the listener's own bind address | `@deepseek-ai/dsh-host-webserver` |
| `webServer.register` / `webServer.tapIndex` — the route registry and index transforms | `@deepseek-ai/dsh-host-webserver` |
| `connection.trustedHosts` — the authorities the `/api` fence reads | `@deepseek-ai/dsh-client-connection` |
| `connection.admit` — the fence and session check, alone from 0.2.1-alpha.3 | `@deepseek-ai/dsh-client-connection` |
| `connection.requestRejection` / `authorizeIndex` / `authenticatedUrl` | `@deepseek-ai/dsh-client-connection` |
| 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.
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
failing the fiber and taking the parts that still work down with it. Losing the
@@ -328,6 +404,49 @@ 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.1-rc.1
This is the release the 0.4.0 change answers. Two things moved.
**The gate moved into `admit`.** `requestRejection` is now a façade over
`admit`, and the `/api` route and the WebSocket upgrade call `admit` directly.
A plugin that only answered `requestRejection` — which is all 0.3.0 did when
`disableAuth: true` — left the index reachable and every WebSocket refused with
`401`, so the page loaded and then showed a disconnected shell. The bypass path
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:
| Request (`Host: ai.milesward.dev`) | Result |
|---|---|
| `GET /` with no cookie | `401` |
| `GET /?token=<launch token>` | `303`, `location: ./`, `Set-Cookie: dsh-auth-…` |
| `GET /` with that cookie | `200` index |
| `Upgrade /api/remote.mux` with that cookie | `101` |
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.
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
0.2.1-alpha.4). The safety property the old bypass traded away is exactly this
one: after `disableAuth: true` the printed URL has no token and every session is
unauthenticated.
Also verified on this release: `webServer.server` / `register` / `tapIndex` and
the `webserver/index-inject` channel are unchanged, so the interceptor, the
browser grant, the shims, and the PWA route need no adjustment. The
`dsh-client-connection`, `dsh-host-webserver`, `dsh-web-app`, and
`dsh-host-frontend-static` bundles are byte-identical between 0.2.1-rc.1 and
0.2.1-rc.2.
### What was checked on 0.2.1-alpha.2
Everything in the table above is still present and still of the shape this plugin
@@ -445,14 +564,17 @@ Three guards follow from that, and each has a test:
- `sec-fetch-site: cross-site` is refused **unconditionally** by
`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 is inert with the default `disableAuth: true`, because the gateway
never reaches the fence. It is the one thing that can still refuse a request
with `disableAuth: false`.
- Rewriting `Host` changes the **cookie authority** the harness derives from it
(`dsh-auth-<sha256(authority)>`). With `disableAuth: false` that invalidates
sessions minted under the hostname you used before — one re-login — and
afterwards a single login covers every entry domain instead of one per domain.
Inert with `disableAuth: true`.
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.
- 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
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
only for third-party code that might read it.
@@ -532,11 +654,16 @@ 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 — **59 tests** (fence 8, apply 20, handover 15,
All five suites together — **60 tests** (fence 8, apply 21, 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.
The manifest pins what it supports: `engines.dsh` is
`>=0.1.7-rc.2 <0.3.0-0`, so a harness from a future minor release skips this
plugin instead of loading it against a surface it was never checked on. Bump the
range only after re-running the probe matrix above.
`test/fence.test.mjs` loads `sameOrigin()` from the installed `dshmarket` when a
profile is present and says which source it used, so a run against a bundled
copy is never mistaken for a run against the real thing. `test/shims.test.mjs`
@@ -556,6 +683,7 @@ remote client and always looks like it passes.
| Version | What changed |
|---|---|
| **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. |
| 0.2.0 | Renamed from `dsh-disable-untrusted-origin`. Added `lib/handover.js`: originals recorded once on a `Symbol.for` carrier, a liveness check (`fiber.uid === null`) on every delegated path, and an interceptor that retires a tagged predecessor. Capabilities now degrade with a warning instead of failing the fiber. |
+7 -5
View File
@@ -4,13 +4,15 @@
# (package.json declares dsh.bundle.patch).
#
# The defaults below are the plugin's stated posture: the identity fence is
# disarmed, the browser-session check is removed, the browser is granted the
# host's own isLoopback flag, and the APIs a non-secure page is denied are
# restored. Override any key in your profile patch:
# disarmed, the browser is granted the host's own isLoopback flag, and the APIs
# a non-secure page is denied are restored. The browser-session check stays in
# place: the first visit is the one-time launch token printed in the process log
# (the Docker log from 0.2.1-alpha.4 on), exchanged for a 30-day cookie.
# Override any key in your profile patch:
#
# - id: trustworthy
# config:
# disableAuth: false # keep the process token, disarm only the fence
# disableAuth: true # ALSO remove the session check; no token needed
# grantPairing: false # when dsh-remote-web-ui provides the pairing service itself
# spoofSocketAddress: true # also satisfy socket-based fences with no pairing path
# shimClipboard: false # unnecessary when you reach the harness over HTTPS
@@ -23,7 +25,7 @@
name: 'dsh-trustworthy'
config:
enabled: true
disableAuth: true
disableAuth: false
forceClientLoopback: true
grantPairing: true
spoofSocketAddress: false
+38 -13
View File
@@ -11,7 +11,13 @@
* request with `403`, which reads to the user as a button that does nothing.
*
* This plugin removes the distinction in two places, and separately restores
* the browser capabilities a non-secure page is denied.
* the browser capabilities a non-secure page is denied. It removes only the
* origin fence by default: the harness's own browser-session check stays in
* place, so the first visit is the one-time launch token from the process log
* (`dsh web: …?token=…`; the container entrypoint prints it into the Docker log
* from `0.2.1-alpha.4`), which is exchanged for a 30-day cookie bound to the
* authority it was minted under. Set `disableAuth: true` to remove that check
* as well.
*
* 1. A `request`/`upgrade` listener installed ahead of every route answers
* each connection with the loopback authority. One interception covers the
@@ -47,12 +53,13 @@
* still owns the installation — so a reload cannot leave the plugin inert while
* it believes it is mounted, nor let a superseded interceptor keep acting.
*
* Security: this is a deliberate and total removal of the request-identity
* fence across the whole HTTP surface. It defends against DNS rebinding and
* against another page in the same browser driving this API, and both
* defences stop applying once this plugin is enabled. Read the README before
* turning it on, and keep the listening port behind something that
* authenticates on your behalf.
* Security: removing the request-identity fence is deliberate and total for
* every window that reaches the port. It defends against DNS rebinding and
* against another page in the same browser driving this API, and both defences
* stop applying once this plugin is enabled. The default keeps the session
* check, so the exposure is a page that carries a live cookie; `disableAuth:
* true` removes the check too, and then reachability is the only access
* control. Read the README before turning that on.
*
* @module dsh-trustworthy
*/
@@ -121,12 +128,15 @@ export const Config = z.object({
),
disableAuth: z
.boolean()
.default(true)
.default(false)
.description(
'Also remove the browser-session check, so no process token is needed. '
+ 'Anyone who can reach the port then has full control of the agent, '
+ 'including code execution. Keep this true only behind a port or '
+ 'tunnel that authenticates on its own.',
+ 'including code execution. The default leaves the check in place: '
+ 'open the launch URL from the process log (in the Docker log on the '
+ 'container image) once, and the 30-day session cookie it exchanges '
+ 'covers this plugin\'s rewritten requests too. Set this true only '
+ 'behind a port or tunnel that authenticates on its own.',
),
forceClientLoopback: z
.boolean()
@@ -240,9 +250,17 @@ export function apply(ctx, config) {
if (config.disableAuth) {
const connection = ctx.connection
// The `/api` gateway asks one method whether the request may proceed; it
// applies the identity fence and then the session check. Answering
// `undefined` admits both.
// The gate is one method. Releases up to `0.2.1-alpha.2` asked
// `requestRejection` first and `admit` wrapped its answer; from
// `0.2.1-alpha.3` on `admit` applies the fence and the session check
// itself, and `requestRejection` is a façade over it. Replacing `admit`
// therefore satisfies both shapes, and replacing `requestRejection` keeps
// the older shape from short-circuiting around it.
//
// The peer that comes back is one the harness already owns: `operator` up
// to `0.2.1-alpha.2`, `browserPeer` from `0.2.1-alpha.3` on. There is no
// synthetic identity to invent, and returning the owner's peer is exactly
// what the session check would have produced for a logged-in browser.
//
// `authenticatedUrl` is the startup URL and the remote-access handoff;
// returning the base URL keeps the process token out of the printed link.
@@ -262,7 +280,14 @@ export function apply(ctx, config) {
const original = originalOf(connection, key)
return original === undefined ? undefined : original.apply(this, args)
}
const admit = (request) => {
const peer = connection.browserPeer ?? connection.operator
if (peer !== undefined) return { peer }
const original = originalOf(connection, 'admit')
return original === undefined ? undefined : original.call(connection, request)
}
const restore = installReplacements(connection, {
admit: delegate('admit', admit),
requestRejection: delegate('requestRejection', () => undefined),
authorizeIndex: delegate('authorizeIndex', () => true),
authenticatedUrl: delegate('authenticatedUrl', (baseUrl) => baseUrl),
+6 -3
View File
@@ -1,7 +1,7 @@
{
"name": "dsh-trustworthy",
"version": "0.3.0",
"description": "Removes the untrusted-origin restriction from DeepSeek Harness. Every browser window is treated as if it were running on the harness machine itself: no process token, no declared trusted host, and no per-plugin origin fence, because one interceptor answers every request with the loopback authority.",
"version": "0.4.0",
"description": "Removes the untrusted-origin restriction from DeepSeek Harness while keeping its own session check: every browser window is treated as if it were running on the harness machine itself, so no declared trusted host and no per-plugin origin fence refuse it. One interceptor answers every request with the loopback authority, and the one-time launch token is exchanged for a 30-day cookie exactly as on the loopback host.",
"type": "module",
"main": "lib/index.js",
"exports": {
@@ -19,6 +19,9 @@
"LICENSE"
],
"license": "MIT",
"engines": {
"dsh": ">=0.1.7-rc.2 <0.3.0-0"
},
"keywords": [
"dsh",
"dsh-plugin",
@@ -33,7 +36,7 @@
"patch": "./cordis.patch.yml"
},
"compatibility": {
"dsh": ">=0.1.7-rc.2"
"dsh": ">=0.1.7-rc.2 <0.3.0-0"
}
},
"peerDependencies": {
+29 -1
View File
@@ -25,6 +25,9 @@ async function mockHost({ rawServer = true, registry = true } = {}) {
requestRejection: function requestRejection() {
return 403
},
admit: function admit() {
return { rejection: 401 }
},
authorizeIndex: function authorizeIndex() {
return false
},
@@ -32,7 +35,12 @@ async function mockHost({ rawServer = true, registry = true } = {}) {
return `${baseUrl}?token=launch-secret`
},
}
const connection = { ...originals }
const connection = {
...originals,
// Releases up to 0.2.1-alpha.2 named the owner peer `operator`; from
// 0.2.1-alpha.3 on it is `browserPeer`. A real host has one or the other.
browserPeer: { id: 'browser-peer' },
}
const provided = new Map()
const server = createServer((_request, response) => {
response.writeHead(200)
@@ -195,21 +203,39 @@ test('disableAuth replaces the session methods and unload restores them', async
const host = await mockHost()
const { apply } = await import(PLUGIN)
apply(host.ctx, CONFIG)
assert.deepEqual(host.connection.admit({}), { peer: host.connection.browserPeer })
assert.equal(host.connection.requestRejection({}), undefined)
assert.equal(host.connection.authorizeIndex({}, {}), true)
assert.equal(host.connection.authenticatedUrl('http://box:3080'), 'http://box:3080')
host.unload()
assert.deepEqual(host.connection.admit({}), { rejection: 401 })
assert.equal(host.connection.requestRejection({}), 403)
assert.equal(host.connection.authorizeIndex({}, {}), false)
assert.equal(host.connection.authenticatedUrl('http://box:3080'), 'http://box:3080?token=launch-secret')
await new Promise((resolve) => host.server.close(resolve))
})
test('disableAuth admits through the operator peer on 0.2.1-alpha.2 and older', async () => {
const host = await mockHost()
const operator = { id: 'operator-peer' }
delete host.connection.browserPeer
host.connection.operator = operator
const { apply } = await import(PLUGIN)
apply(host.ctx, CONFIG)
try {
assert.deepEqual(host.connection.admit({}), { peer: operator })
} finally {
host.unload()
await new Promise((resolve) => host.server.close(resolve))
}
})
test('disableAuth false leaves the session methods untouched', async () => {
const host = await mockHost()
const { apply } = await import(PLUGIN)
apply(host.ctx, { ...CONFIG, disableAuth: false })
try {
assert.deepEqual(host.connection.admit({}), { rejection: 401 })
assert.equal(host.connection.requestRejection({}), 403)
assert.equal(host.connection.authorizeIndex({}, {}), false)
} finally {
@@ -418,11 +444,13 @@ test('a disposed fiber stops admitting requests', async () => {
const { apply } = await import(PLUGIN)
apply(host.ctx, CONFIG)
assert.deepEqual(host.connection.admit({}), { peer: host.connection.browserPeer }, 'admitting while mounted')
assert.equal(host.connection.requestRejection(), undefined, 'admitted while mounted')
assert.equal(host.connection.authorizeIndex(), true)
assert.equal(host.connection.authenticatedUrl('/base'), '/base')
host.ctx.fiber.uid = null
assert.deepEqual(host.connection.admit({}), { rejection: 401 }, 'the real gate answers again')
assert.equal(host.connection.requestRejection(), 403, 'the real fence answers again')
assert.equal(host.connection.authorizeIndex(), false)
assert.equal(