@owlmeans/server-api 0.1.18-rc.40 → 0.1.18-rc.42
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 +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-api/SKILL.md +22 -13
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ only when composing a context without that package. WebSocket routes belong to
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
bun add @owlmeans/server-api@^0.1.18-rc.
|
|
13
|
+
bun add @owlmeans/server-api@^0.1.18-rc.42
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Concepts
|
|
@@ -240,7 +240,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
240
240
|
your project's skill store (`.agents/skills/`):
|
|
241
241
|
|
|
242
242
|
```sh
|
|
243
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
243
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.39
|
|
244
244
|
```
|
|
245
245
|
|
|
246
246
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/server-api",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-09-
|
|
4
|
+
"version": "0.1.18-rc.42",
|
|
5
|
+
"generatedAt": "2026-09-24T14:00:34.973Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -7,7 +7,7 @@ user-invocable: false
|
|
|
7
7
|
|
|
8
8
|
# @owlmeans/server-api
|
|
9
9
|
|
|
10
|
-
**Install:** `bun add @owlmeans/server-api@^0.1.18-rc.
|
|
10
|
+
**Install:** `bun add @owlmeans/server-api@^0.1.18-rc.42`
|
|
11
11
|
|
|
12
12
|
Make handlers from the protocol declaration so input and output types stay coupled to the shared
|
|
13
13
|
contract:
|
|
@@ -58,15 +58,15 @@ that one route with `HandlerMisconfiguredError`, instead of the opaque
|
|
|
58
58
|
|
|
59
59
|
## The status a thrown error answers
|
|
60
60
|
|
|
61
|
-
A thrown error (or a rejected response) is answered with
|
|
62
|
-
|
|
61
|
+
A thrown error (or a rejected response) is answered with a body chosen by the exposure (§ Error
|
|
62
|
+
exposure) and a status from `errorStatus(error)` (`./utils`), resolved in this order:
|
|
63
63
|
|
|
64
64
|
| Error | Status |
|
|
65
65
|
|---|---|
|
|
66
66
|
| `AuthForbidden`, `AccessError` or a subclass — by class or registered type name | 403 |
|
|
67
67
|
| `AuthorizationError`, `AuthFailedError` or a subclass — by class or registered type name | 401 |
|
|
68
|
-
| a class declaring `static httpStatus` as an integer 400–499 | that status |
|
|
69
|
-
| anything else, including a
|
|
68
|
+
| a class declaring `static httpStatus` as an integer 400–499, or 500–599 with `static allowServerErrorStatus = true` | that status |
|
|
69
|
+
| anything else, including a 5xx declared without the opt-in | 500 |
|
|
70
70
|
|
|
71
71
|
- **A refusal of the caller's condition declares its status; a fault declares nothing.** 400 a
|
|
72
72
|
malformed request, 402 an unpaid balance or plan, 404 an addressed target that does not exist
|
|
@@ -85,7 +85,7 @@ body and a status from `errorStatus(error)` (`./utils`), resolved in this order:
|
|
|
85
85
|
(`ResilientError.ensure`) error only when that answers 500. The thrown object is the one whose
|
|
86
86
|
class is certainly what was raised; the rebuild is what gives a status to a marshalled error that
|
|
87
87
|
crossed a hop as a plain `Error`. `ensure` returns an error from any `@owlmeans/error` copy
|
|
88
|
-
untouched, so
|
|
88
|
+
untouched, so a development body keeps the thrown class's `type` (`AuthFailedError|||api:auth:…`) even in a
|
|
89
89
|
process holding duplicate module copies (`bun --preserve-symlinks`). `executeResponse` ensures
|
|
90
90
|
nothing and answers the rejected error's status. `@owlmeans/server-socket` answers an upgrade
|
|
91
91
|
through the same `handleError`.
|
|
@@ -94,10 +94,11 @@ body and a status from `errorStatus(error)` (`./utils`), resolved in this order:
|
|
|
94
94
|
answers the same status. Match whole names, never substrings: a subclass's `typeName` does not
|
|
95
95
|
reliably embed its parent's (`EntitlementRefusal` extends `AuthForbidden`). A declared
|
|
96
96
|
`httpStatus` is a structural static read and survives duplicate copies as it is.
|
|
97
|
-
- The status
|
|
98
|
-
body
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
- **The status is what a production client can act on.** Only a development body is rebuilt into
|
|
98
|
+
its class; a production body is the incident id alone, so a client knows a refusal by its status
|
|
99
|
+
(§ Error exposure) — give a refusal the client must act on its own distinct 4xx. Nothing in the
|
|
100
|
+
framework treats a 404 specially — a missing route is a Fastify JSON body the client turns into
|
|
101
|
+
a 404 `ApiStatusError`.
|
|
101
102
|
|
|
102
103
|
`uploadedFile(request)` is the Fastify multipart boundary. Keep raw Fastify access there rather
|
|
103
104
|
than reaching through `request.original` in application code.
|
|
@@ -105,9 +106,17 @@ than reaching through `request.original` in application code.
|
|
|
105
106
|
## Error exposure
|
|
106
107
|
|
|
107
108
|
`handleError` always assigns an incident UUID, attaches it to the logged error and returns it in the
|
|
108
|
-
`X-Incident-ID` response header (
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
`X-Incident-ID` response header (`INCIDENT_ID_HEADER` in `./utils`, the same name and value
|
|
110
|
+
`@owlmeans/api` exports; exposed through CORS).
|
|
111
|
+
|
|
112
|
+
- **Production (the default):** a non-2xx body carries ONLY that incident id, under the resolved
|
|
113
|
+
HTTP status. A typed refusal is never exposed — its class, message and packed fields stay in the
|
|
114
|
+
server log under the id.
|
|
115
|
+
- **Development** (an explicit `cfg.http.errors.exposure = 'development'`): the typed marshalled
|
|
116
|
+
form with message and stack, which the client rebuilds into its class.
|
|
117
|
+
- A client reads a production failure with `@owlmeans/api`'s `./status` subpath: `httpStatusOf(e)`
|
|
118
|
+
(the status a 428 or 409 is acted on by) and `incidentIdOf(e)` (the id a person reports). Keep
|
|
119
|
+
the default production-safe, and tell a client to report the incident id.
|
|
111
120
|
|
|
112
121
|
Do not use unbound compatibility handler wrappers. For a WebSocket route use
|
|
113
122
|
`@owlmeans/server-socket`'s `connection(protocol, callback)`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-api",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.42",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"@fastify/helmet": "^13.1.0",
|
|
34
34
|
"@fastify/middie": "^9.0.2",
|
|
35
35
|
"@fastify/multipart": "^9.0.1",
|
|
36
|
-
"@owlmeans/api": "^0.1.18-rc.
|
|
37
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
38
|
-
"@owlmeans/auth-common": "^0.1.18-rc.
|
|
36
|
+
"@owlmeans/api": "^0.1.18-rc.38",
|
|
37
|
+
"@owlmeans/auth": "^0.1.18-rc.36",
|
|
38
|
+
"@owlmeans/auth-common": "^0.1.18-rc.38",
|
|
39
39
|
"@owlmeans/context": "^0.1.18-rc.32",
|
|
40
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
41
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
40
|
+
"@owlmeans/error": "^0.1.18-rc.36",
|
|
41
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.37",
|
|
42
42
|
"@owlmeans/route": "^0.1.18-rc.33",
|
|
43
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
44
|
-
"@owlmeans/server-entrypoint": "^0.1.18-rc.
|
|
43
|
+
"@owlmeans/server-context": "^0.1.18-rc.37",
|
|
44
|
+
"@owlmeans/server-entrypoint": "^0.1.18-rc.36",
|
|
45
45
|
"ajv-errors": "^3.0.0",
|
|
46
46
|
"fastify": "^5.0.0",
|
|
47
47
|
"fastify-raw-body": "^5.0.0",
|