Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
# Worker-proxy factory — `@suaveplan/api-auth-bearer-static`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The worker-proxy surface is the second of the two Stage-4 surfaces this
adapter ships (`§5.2a`). It lets the host install the bearer-static
resolver in the main process while the actual token table lives inside an
isolated worker. The host's `SessionResolverChain` calls
`resolve(request)` exactly as for the direct surface; under the hood, the
proxy marshals the request across a `MessagePort` using
`@suaveplan/api-worker-rpc`, the worker's resolver runs, and the
`Principal | null` decision is returned to the host.
The proxy intentionally keeps the token table out of the host's address
space — useful when the host is sandboxed and the worker holds privileged
credentials, or when operators want a single auth daemon serving multiple
host workers.
## Features
- Bidirectional RPC over a `MessagePort` (or any `PortLike`) — no
process / address-space assumptions.
- Idempotent `dispose()` — coalesces multiple calls and closes the
underlying RPC client exactly once.
- Header set, request method, URL, and (optional) `peerCertificate` cross
the boundary; opaque body and abort signal are out of scope (resolution
does not need them).
- Server-side mount via `serveBearerStaticResolverOnPort` — owns the real
resolver and the token table.
- Passes the same `runAuthSessionConformance` harness as the direct
surface.
## Usage: Basic
```ts
import {
createBearerStaticResolverWorkerProxy,
serveBearerStaticResolverOnPort,
} from "@suaveplan/api-auth-bearer-static/proxy";
import { createInProcessPortPair } from "@suaveplan/api-worker-rpc";
const { clientPort, serverPort } = createInProcessPortPair();
// Worker side — owns the real table.
const server = serveBearerStaticResolverOnPort(serverPort, {
tokens: [
{
token: "T1",
principal: { id: "svc", scopes: [], claims: {} },
},
],
});
// Host side — sees only a proxy.
const proxy = createBearerStaticResolverWorkerProxy(clientPort);
const request = new Request("https://api/x", {
headers: { Authorization: "Bearer T1" },
});
const principal = await proxy.resolve(request);
await proxy.dispose();
server.close("done");
```
## Usage: Advanced
```ts
import { Worker, MessageChannel } from "node:worker_threads";
import {
createBearerStaticResolverWorkerProxy,
} from "@suaveplan/api-auth-bearer-static/proxy";
// Real Node worker boundary. The worker script imports
// `serveBearerStaticResolverOnPort` and calls it against its own port.
const { port1, port2 } = new MessageChannel();
const worker = new Worker("./auth-worker.mjs", { transferList: [port2] });
const resolver = createBearerStaticResolverWorkerProxy(port1 as never);
// Place in chain alongside direct adapters — host treats both uniformly.
import { SessionResolverChain } from "@suaveplan/api-auth";
const chain = new SessionResolverChain([resolver]);
```
## API Reference
- `serveBearerStaticResolverOnPort(port: PortLike, options: BearerStaticResolverOptions): { close(reason?: string): void }`
— mount the server-side handlers.
- `createBearerStaticResolverWorkerProxy(port: PortLike): SessionResolver`
— host-side proxy.
## Implementation Notes
The marshalled envelope is `{url, method, headers, peerCertificate?}` —
the minimal subset of `Request` that the bearer-static decision actually
needs. `peerCertificate` is structured-clone-friendly because the host
attaches whatever shape the listener surfaced; tests pass plain objects.
The proxy never sends the request body, because token resolution does not
consult it. Errors thrown by the server-side resolver (e.g. an unexpected
runtime fault) propagate as the standard `WORKER_RPC` error envelope and
surface in the host as a thrown `WorkerRpcError` — the host's resolver
chain treats this as a fail-closed `RESOLVER_THREW` per the documented
`api-auth` chain semantics. `dispose()` calls the remote `dispose` first
to drain the server-side state, then closes the local client so the
underlying port can be garbage-collected.