diff --git a/packages/rest/src/rest-sandbox-declared-status.test.ts b/packages/rest/src/rest-sandbox-declared-status.test.ts index 4a6b7d0719..0ca397a53a 100644 --- a/packages/rest/src/rest-sandbox-declared-status.test.ts +++ b/packages/rest/src/rest-sandbox-declared-status.test.ts @@ -127,8 +127,13 @@ describe('[#9967] a sandboxed body that declares a 5xx takes the sanitised 5xx a expect(r.status).toBe(503); expect(r.body.error).toBe(INTERNAL_ERROR_MESSAGE); expect(JSON.stringify(r.body)).not.toContain('close-period lock'); - // No code was declared; none is invented (ADR-0112: the producer names - // the condition). + // No code was declared; none is invented — ADR-0112 D4 governs the + // semantic-CODE channel: the producer names the condition on the CODE + // axis, and the ADR rules no HTTP status for an undeclared throw. The + // 503 above is kept on #5582's rule (this section's own heading), not + // the ADR's. See `error-response.ts`'s `resolveThrownHttpError` + // docblock for why the phrase is that file's own prose and not an ADR + // quotation. expect(r.body.code).toBeUndefined(); }); diff --git a/packages/rest/src/rest-server.ts b/packages/rest/src/rest-server.ts index 6e4457c44d..b6a58e42b3 100644 --- a/packages/rest/src/rest-server.ts +++ b/packages/rest/src/rest-server.ts @@ -9648,8 +9648,12 @@ export class RestServer { if (refusal) { // `code` is REQUIRED by the nested envelope, and the flat // classification legitimately carries none for an undeclared - // sandbox refusal (ADR-0112: the producer names the condition, - // so nothing is invented for the half it did not name). The + // sandbox refusal (ADR-0112 D4 governs the semantic-CODE + // channel: the producer names the condition on the CODE axis, + // so nothing is invented for the half it did not name; the ADR + // rules no HTTP status here, and the phrase is + // `error-response.ts`'s own prose rather than an ADR + // quotation). The // catalog's own floor fills the required field — // `standardErrorCodeForHttpStatus`, whose docblock exists for // exactly this ("Total by construction: a producer can always diff --git a/packages/rest/src/rest.test.ts b/packages/rest/src/rest.test.ts index 3d9edb7cd3..5e9b6fc378 100644 --- a/packages/rest/src/rest.test.ts +++ b/packages/rest/src/rest.test.ts @@ -2483,9 +2483,13 @@ describe('mapDataError — schema/constraint envelopes', () => { it('a 5xx that declares NO code passes its status and invents no code', () => { // The shape this case originally carried. `declaresServerFault` — the // `@objectstack/types` criterion the 5xx arm reads for the `code` half — - // needs a non-empty string `code`, and ADR-0112 says the PRODUCER names the - // condition: the declared half is honoured, the undeclared half is left - // empty rather than filled with an invented `INTERNAL_ERROR`. Same answer + // needs a non-empty string `code`, and ADR-0112 D4 governs the + // semantic-CODE channel: the producer names the condition on the CODE + // axis, so the declared half is honoured and the undeclared half is left + // empty rather than filled with an invented `INTERNAL_ERROR`. The 502 + // passes through on #5437/#5582's rule, NOT the ADR's: ADR-0112 rules no + // HTTP status for an undeclared throw, and the phrase is + // `error-response.ts`'s own prose rather than an ADR quotation. Same answer // `resolveErrorResponse` already gives this shape. const r = mapDataError( Object.assign(new Error('connect ECONNREFUSED 10.0.0.5:5432 (internal pool)'), { status: 502 }),