Skip to content

Commit bcf1112

Browse files
authored
fix(service-datasource,rest,spec)!: external-datasource refusals answer their own error code (#4249) (#4263)
The three admin routes that dispatch to external-datasource answered their 400s with DATASOURCE_ADMIN_ERROR — the code the ADR-0112 ledger registers as a refusal from the OTHER service. Register EXTERNAL_DATASOURCE_ERROR under both emitting packages, derive the 400 code from the same ServiceName the route resolves (compile-time enforced via the shared sendError since #3973), and give the rest surface's two introspection routes the same failure contract instead of the adapter's non-envelope 500. Follow-ups filed: #4264 (three routes still uncaught), #4265 (closed as duplicate of #4255).
1 parent ab9fb5c commit bcf1112

19 files changed

Lines changed: 293 additions & 96 deletions
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
"@objectstack/spec": patch
3+
"@objectstack/service-datasource": patch
4+
"@objectstack/rest": patch
5+
---
6+
7+
fix(service-datasource,rest)!: external-datasource refusals answer their own error code (#4249)
8+
9+
#4225 / #4234 fixed the 503 `message` on the three routes in
10+
`service-datasource/admin-routes.ts` that dispatch to `external-datasource`
11+
rather than `datasource-admin`. The identical mis-attribution survived one field
12+
over, on the 400 path — and machine-readably: one shared `badRequest` helper
13+
hard-coded `DATASOURCE_ADMIN_ERROR`, which the ADR-0112 ledger defines as a
14+
refusal *from the datasource-admin service*. So a `no such schema` raised by the
15+
external-datasource introspector was reported as datasource-admin's, and where
16+
#4225 misled a human reading prose, this misrouted a client switching on
17+
`error.code`.
18+
19+
`EXTERNAL_DATASOURCE_ERROR` is now registered in the error-code ledger — under
20+
`@objectstack/service-datasource` and `@objectstack/rest`, the two packages that
21+
emit it; per the ledger's own rule the per-package rows are provenance, not
22+
identity — and `badRequest` takes the same `ServiceName` the route passed to
23+
`resolve` (#4234), so the code, like the 503 message, comes from the service the
24+
route actually dispatches to.
25+
26+
Wire-visible changes:
27+
28+
- **The three external-datasource routes' 400 `error.code`**
29+
`GET /datasources/:name/remote-tables`, `POST /datasources/:name/test`,
30+
`POST /datasources/:name/object-draft` — is now `EXTERNAL_DATASOURCE_ERROR`
31+
(was `DATASOURCE_ADMIN_ERROR`). Status, envelope, and `error.message` are
32+
unchanged, as is everything on the six datasource-admin routes. No consumer
33+
branches on the old code (grepped both repos, all the ADR-0112 sweep forms).
34+
- **The rest surface's two introspection routes now have a failure contract at
35+
all.** `GET /datasources/:name/external/tables` and
36+
`POST /datasources/:name/external/tables/:remote/draft` carried no
37+
`try`/`catch`, so the very same service operations that answer 400 through
38+
the admin surface surfaced here as the adapter's non-envelope
39+
`500 { error: 'No response from handler' }`. They now answer
40+
`400 EXTERNAL_DATASOURCE_ERROR` in the declared envelope — one operation, one
41+
failure contract, on both paths. (`EXTERNAL_IMPORT_ERROR` on the import route
42+
is unchanged: a refused import is a different act from a failed
43+
introspection, and its name says so.)
44+
45+
Why a new registered code rather than reusing one: ADR-0112's ledger asks
46+
*generic* conditions to reuse the standard catalog — that argument carried
47+
#4225's 503, where `SERVICE_UNAVAILABLE` is correct for all nine routes and only
48+
the free-text `message` named the service. A refusal specific to one service is
49+
exactly what registered extension codes are for, and the closed `ErrorCode`
50+
union means correcting the attribution had to be a ledger edit. Widening
51+
`EXTERNAL_IMPORT_ERROR` to cover introspection was rejected because these are
52+
not imports; leaving the throws uncaught was rejected because the adapter's 500
53+
is not the declared envelope.
54+
55+
The conformance rows that pinned the drift move with it, and each surface now
56+
pins the refusal code per route the way #4234 pinned the 503 message per route.
57+
58+
Pre-existing, like #4225: #3843 carried every code string over verbatim.

content/docs/references/api/analytics.mdx

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

content/docs/references/api/auth.mdx

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

content/docs/references/api/automation-api.mdx

Lines changed: 9 additions & 9 deletions
Large diffs are not rendered by default.

content/docs/references/api/batch.mdx

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

content/docs/references/api/contract.mdx

Lines changed: 8 additions & 8 deletions
Large diffs are not rendered by default.

content/docs/references/api/error-code-ledger.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ const result = ErrorCode.parse(data);
182182
* `EXPIRY_TOO_LONG`
183183
* `EXPLAIN_FAILED`
184184
* `EXPORT_NOT_PERMITTED`
185+
* `EXTERNAL_DATASOURCE_ERROR`
185186
* `EXTERNAL_IMPORT_ERROR`
186187
* `EXTERNAL_SCHEMA_MISMATCH`
187188
* `EXTERNAL_SCHEMA_MODE_VIOLATION`

content/docs/references/api/export.mdx

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

content/docs/references/api/metadata.mdx

Lines changed: 19 additions & 19 deletions
Large diffs are not rendered by default.

content/docs/references/api/package-api.mdx

Lines changed: 8 additions & 8 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)