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:
@@ -0,0 +1,112 @@
|
||||
# @suaveplan/api-db-worker-proxy - Worker-side proxy for the api `db` capability. Marshals AdminDatabaseLike / TenantScopedDatabaseLike calls — including transactions and cursor streams — over @suaveplan/api-worker-rpc MessagePort frames. Tenant scoping is enforced main-side; this package is the transport.
|
||||
|
||||
Worker-side proxy for the api `db` capability. Marshals
|
||||
`AdminDatabaseLike` and `TenantScopedDatabaseLike` calls — including
|
||||
transactions and cursor streams — over `@suaveplan/api-worker-rpc`
|
||||
`MessagePort` frames.
|
||||
|
||||
The main side mounts a real DB adapter and exposes it over a port;
|
||||
the worker side imports a proxy whose API surface is identical to a
|
||||
direct adapter. Worker plugin code never touches a real connection
|
||||
and never sees plaintext credentials.
|
||||
|
||||
**Tenant scoping is enforced on the main side**, NOT in this package.
|
||||
`wrapTenantScoped(adminProxy, tenantId)` is purely a type-level facade
|
||||
that prevents an admin reference from being passed where a tenant
|
||||
reference is required by the type system.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [error-codes](./src/error-codes/error-codes.md) — This module owns the `DB_PROXY.*` stable error-code registry for `@suaveplan/api-db-worker-proxy`. Every failure that c…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — This module owns the `DB_PROXY.*` stable error-code registry for `@suaveplan/api-db-worker-proxy`. Every failure that c…
|
||||
- [main-side](./src/main-side/main-side.md) — This module exposes `createDbProxyServer(port, db)` — the trusted-side endpoint of the worker DB proxy. It mounts an `A…
|
||||
- [main-side](./src/main-side/main-side.md) — This module exposes `createDbProxyServer(port, db)` — the trusted-side endpoint of the worker DB proxy. It mounts an `A…
|
||||
- [tenant-scoped](./src/tenant-scoped/tenant-scoped.md) — This module exposes `wrapTenantScoped(adminProxy, tenantId)` — a worker-side type-level facade that re-presents an admi…
|
||||
- [tenant-scoped](./src/tenant-scoped/tenant-scoped.md) — This module exposes `wrapTenantScoped(adminProxy, tenantId)` — a worker-side type-level facade that re-presents an admi…
|
||||
- [testing](./src/testing/testing.md) — This module provides the in-memory test harness for `@suaveplan/api-db-worker-proxy`. It exposes `createInMemoryAdminDb…
|
||||
- [testing](./src/testing/testing.md) — This module provides the in-memory test harness for `@suaveplan/api-db-worker-proxy`. It exposes `createInMemoryAdminDb…
|
||||
- [worker-side](./src/worker-side/worker-side.md) — This module exposes `createDbProxyClient(port, { engine })` — the untrusted-side endpoint of the worker DB proxy. It re…
|
||||
- [worker-side](./src/worker-side/worker-side.md) — This module exposes `createDbProxyClient(port, { engine })` — the untrusted-side endpoint of the worker DB proxy. It re…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Why
|
||||
|
||||
Per the `api-plugin` foundation design (§5.1, §5.2a, §6) every
|
||||
capability ships in two surfaces: a direct in-process binding for
|
||||
trusted plugins and a `MessagePort`-marshalled binding for
|
||||
isolated / sandboxed plugins. The `db` capability is special because
|
||||
|
||||
1. its operations return result sets that can be huge (favouring
|
||||
streaming over buffering),
|
||||
2. its operations are transactional (transaction handles MUST be
|
||||
bound to a single connection lifetime), and
|
||||
3. tenant-scoping is a security boundary the worker MUST NOT be able
|
||||
to circumvent.
|
||||
|
||||
This package is Stage-3 worker-isolation infrastructure: every
|
||||
Stage-4 DB adapter (`api-db-adapter`, `api-db-sqlite-memory`, …) MUST
|
||||
pass conformance under BOTH the direct surface AND this proxy
|
||||
surface before can be declared complete.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/api-db-worker-proxy
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
// main side
|
||||
import { createDbProxyServer } from "@suaveplan/api-db-worker-proxy/main-side";
|
||||
import { MessageChannel, Worker } from "node:worker_threads";
|
||||
|
||||
const channel = new MessageChannel();
|
||||
createDbProxyServer(channel.port1, realAdminAdapter);
|
||||
|
||||
const worker = new Worker("./plugin-worker.js");
|
||||
worker.postMessage({ port: channel.port2, engine: "sqlite" }, [channel.port2]);
|
||||
```
|
||||
|
||||
```ts
|
||||
// worker side
|
||||
import { parentPort } from "node:worker_threads";
|
||||
import { createDbProxyClient } from "@suaveplan/api-db-worker-proxy/worker-side";
|
||||
import { wrapTenantScoped } from "@suaveplan/api-db-worker-proxy/tenant-scoped";
|
||||
import type { TenantId } from "@suaveplan/api-types/tenant";
|
||||
|
||||
parentPort?.once("message", (boot) => {
|
||||
const admin = createDbProxyClient(boot.port, { engine: boot.engine });
|
||||
|
||||
// request scope
|
||||
const tenantScoped = wrapTenantScoped(admin, "acme" as TenantId);
|
||||
void runHandler(tenantScoped);
|
||||
});
|
||||
```
|
||||
|
||||
## Surface
|
||||
|
||||
- `./main-side` — `createDbProxyServer(port, db)`: serves an
|
||||
`AdminDatabaseLike` over `@suaveplan/api-worker-rpc`. Returns a
|
||||
`DbProxyServer` with `close()`, `activeTransactionCount()`,
|
||||
`activePreparedCount()`.
|
||||
- `./worker-side` — `createDbProxyClient(port, { engine })`: returns
|
||||
an `AdminDatabaseLike`-shaped object plus `cursor(sql, params)`
|
||||
for streaming row iteration and `dispose()` for abrupt teardown.
|
||||
- `./tenant-scoped` — `wrapTenantScoped(adminProxy, tenantId)`:
|
||||
type-level facade. Tenant scoping is enforced main-side.
|
||||
- `./error-codes` — `DB_PROXY.*` codes:
|
||||
`UNSAFE_NOT_PERMITTED`, `TRANSACTION_LOST`, `STREAM_INTERRUPTED`,
|
||||
`PROXY_DISPOSED`.
|
||||
- `./testing` — `createInMemoryAdminDb` + `createDbProxyHarness` for
|
||||
downstream conformance suites.
|
||||
|
||||
## Co-located docs
|
||||
|
||||
- [`src/main-side/main-side.md`](./src/main-side/main-side.md)
|
||||
- [`src/worker-side/worker-side.md`](./src/worker-side/worker-side.md)
|
||||
- [`src/tenant-scoped/tenant-scoped.md`](./src/tenant-scoped/tenant-scoped.md)
|
||||
- [`src/error-codes/error-codes.md`](./src/error-codes/error-codes.md)
|
||||
- [`src/testing/testing.md`](./src/testing/testing.md)
|
||||
|
||||
Reference in New Issue
Block a user