@ultimat3/http 19.0.0 → 19.1.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.
package/README.md CHANGED
@@ -257,6 +257,30 @@ const handle = createServer({
257
257
  Static paths are registered in Bun's native `routes` table; param/wildcard paths fall
258
258
  through to `fetch`. Method resolution stays ours so a 405 still carries problem+json.
259
259
 
260
+ ### No WebSocket upgrade on the `web` role, and no hand-written `api/` route
261
+
262
+ `As of 2026-09-05`, and stated because an app went looking for both. The `web` role's
263
+ `Bun.serve` is built with no `websocket` handler (`server.ts`: "the `web` role does not use one"),
264
+ so nothing under `/api` can `server.upgrade()` a request; and `/api/*` is a **projection** —
265
+ `apiRoutes()` in `@ultimat3/cli` mounts every `action` and `query` the registries hold, and
266
+ `x g route --surface api` does not exist (`readSurface` refuses `api` by name). A raw socket is
267
+ not an action, so it has no home on this role.
268
+
269
+ The framework's one WebSocket is the `sync` role's (`@ultimat3/realtime/server`, `PORT + 1`),
270
+ authenticated by `SyncAuthenticator` and reached from the browser through `LiveClient`. A
271
+ bidirectional stream — a PTY, a log tail — is written as **two halves that already exist**:
272
+
273
+ | Direction | Primitive | Why |
274
+ |---|---|---|
275
+ | server → browser | a `channel` topic on the sync socket (`ChannelHub`, `topic(...)`, `client.subscribe(topic, …)`) | ordered frames, reconnect and backpressure are the sync node's, not a second socket's |
276
+ | browser → server | an `action` — one call per keystroke batch | it gets a policy, a schema, rate limiting, audit and the typed client for free; a socket message gets none |
277
+
278
+ A `web`-role upgrade hook was refused rather than half-built: the pipeline returns a `Response` at
279
+ every stage (middleware, finalize, security headers), and an upgraded request must return
280
+ `undefined` from `fetch` — a second exit from the pipeline with none of its guarantees. If the two
281
+ halves above cannot carry a case, the fallback is a long-poll `action` (`GET`-shaped, returning
282
+ `{ frames, cursor }` and re-called on return), which is what the app that asked shipped.
283
+
260
284
  ## Inbound webhooks
261
285
 
262
286
  `verifyWebhookSignature(request, { secret })` is the receiving half of the framework's webhook
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/http",
3
- "version": "19.0.0",
3
+ "version": "19.1.1",
4
4
  "description": "Owned request lifecycle over Bun.serve: router, ordered pipeline, problem+json errors",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,9 +31,9 @@
31
31
  "test": "bun test"
32
32
  },
33
33
  "dependencies": {
34
- "@ultimat3/core": "19.0.0",
35
- "@ultimat3/i18n": "19.0.0",
36
- "@ultimat3/schema": "19.0.0",
37
- "@ultimat3/time": "19.0.0"
34
+ "@ultimat3/core": "19.1.1",
35
+ "@ultimat3/i18n": "19.1.1",
36
+ "@ultimat3/schema": "19.1.1",
37
+ "@ultimat3/time": "19.1.1"
38
38
  }
39
39
  }
package/src/error-map.ts CHANGED
@@ -141,6 +141,12 @@ export const ERROR_STATUS = {
141
141
  X_INVARIANT_VIOLATED: 422,
142
142
  X_TENANCY_UNSCOPED: 500,
143
143
  X_DB_DRIFT: 500,
144
+ // Both are the server's verdict on a statement the app wrote, which is the app's fault and not
145
+ // the caller's: a request cannot repair a missing migration or a wrong column list.
146
+ X_DB_SCHEMA_STALE: 500,
147
+ X_DB_STATEMENT_FAILED: 500,
148
+ // Logged at boot, never thrown into a request; the row exists so the table stays closed.
149
+ X_MCP_APP_UNMOUNTED: 500,
144
150
  // The three tenancy refusals, all 403, and all deliberately NOT the 404 `X_STORAGE_ORG_MISMATCH`
145
151
  // takes: that one answers 404 because a 403 on a KEY the caller supplied confirms the key exists.
146
152
  // These three name no resource and read no row — the comparison is the actor against an argument