You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b7fdd50
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: .changeset/22283-storage-limits-honoured.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ Clause-②: no (narrowing)
12
12
13
13
Setup's File Storage page has always rendered a "Limits" group — "Max upload size (MB)", "Presigned URL TTL (seconds)" and "Upload session TTL (seconds)" — and saved it, but nothing read it. `StorageServicePlugin` now reads the group on every settings pass and its upload doors honour it, on the plugin's own mount and on a host's `mountStorageRoutes` mount alike.
14
14
15
-
**What stops being accepted.** Where the plugin is bound to the `storage` settings namespace (its default, `bindToSettings: true`, with a settings service present), an upload larger than the resolved `max_upload_mb` is refused with `413` and the standard code `VALIDATION_ERROR`, in the usual error envelope, with a message naming the limit and the setting. Nothing is stored: no `sys_file` or `sys_upload_session` row is written and no byte reaches the adapter. The doors that judge it:
15
+
**What stops being accepted.** Where the plugin is bound to the `storage` settings namespace (its default, `bindToSettings: true`, with a settings service present), an upload larger than the resolved `max_upload_mb` is refused with `413` and the registered code `PAYLOAD_TOO_LARGE`, in the usual error envelope, with a message naming the limit and the setting. Nothing is stored: no `sys_file` or `sys_upload_session` row is written and no byte reaches the adapter. The doors that judge it:
16
16
17
17
-`POST /storage/upload/presigned` — the declared `size`;
18
18
-`POST /storage/upload/chunked` — the declared `totalSize`;
feat(spec): the error-code ledger lists `PAYLOAD_TOO_LARGE` under `@objectstack/service-storage`
6
+
7
+
Clause-②: yes (widening: a new owner provenance row in the published error-code ledger)
8
+
9
+
`ERROR_CODE_LEDGER['@objectstack/service-storage']` now lists `PAYLOAD_TOO_LARGE` (`413`), the code `@objectstack/rest` already registers for its import row ceilings. The storage upload doors answer it for an upload over the File Storage settings' `max_upload_mb`: the presigned upload's declared `size`, the chunked upload's declared `totalSize`, the local raw PUT body and each chunk's running total.
10
+
11
+
No code is added. `ErrorCode`, `RegisteredErrorCode` and `REGISTERED_ERROR_CODES` are unchanged, so `ApiErrorSchema` accepts exactly what it accepted before. What widens is the per-package list a reader consults to learn which packages answer a code: a code emitted by several packages is listed under each of them.
fix(service-automation): a `get_record` whose `fields` leave out `id` answers the row's id as its `id` output on the SQL drivers
6
+
7
+
Clause-②: no
8
+
9
+
-**What was wrong.** On its single-row branch (no `limit` above 1) a `get_record` node answers `output: { record, id, object }`, and a later node reads that `id` as `{read.id}` (for a node whose id is `read`). The node handed the author's `fields` to the engine unchanged, and the SQL drivers return exactly the columns a projection names. So a `get_record` with `fields: ['title']` read a row with no `id` column, and `{read.id}` was empty with no error. A later `update_record` filtering on it was refused for a filter condition that resolved to nothing, and any other reference read nothing.
10
+
-**What it does now.** That branch names `id` in the projection it hands the engine, so `{read.id}` is the row's id whatever `fields` names, on every driver. The record the node serves, and binds to its `outputVariable`, carries that `id` beside the columns the author named, so the variable's `id` reads the same value. The stored-metadata tables (`sys_metadata`, `sys_metadata_history`) are read the same way: the served row is the named columns plus `id`.
11
+
-**Unchanged.** A `get_record` with no `fields`, or an empty list, still reads the whole row. A projection that already names `id` is handed over as written. The multi-row branch (`limit` above 1) answers `records` only and is untouched.
fix(service-automation)!: retire the `RunProvenanceContext` type; `RunDataContext` names only what `resolveRunDataContext` returns
10
+
11
+
Clause-②: no (narrowing)
12
+
13
+
<!-- adr-0087: not-required (runtime-interface-only packages/services/service-automation/src/runtime-identity.ts#RunDataContext) Two TypeScript-only declarations in one runtime file move, and neither is metadata: `RunDataContext` loses its `RunProvenanceContext` arm, and the `RunProvenanceContext` interface declared beside it in the same file is removed together with its type export. No spec key, authorable spelling, Zod schema or stored shape moves, and no stored row is read or rewritten, so `objectstack migrate meta` has nothing to rewrite. The channel that reaches an affected consumer is the compiler, at the consumer's own import. -->
14
+
15
+
**BREAKING** for TypeScript code that imports from `@objectstack/service-automation`: one type export is removed and one type narrows. It ships as `minor` under the launch-window convention for breaking changes. No runtime behaviour changes in any package.
16
+
17
+
**What is removed.** The `RunProvenanceContext` type export, the `{ flowRunId }`-only "provenance" envelope, and its arm of `RunDataContext`. No code in this repository builds or reads one. Since ADR-0096 D5, the data engine's security middleware refuses a context that carries no principal and is not a system context (`403 PERMISSION_DENIED`, for every verb). So the type described a context the engine refuses, while its docstring said such a context was "indistinguishable from passing no context at all" and was let through.
18
+
19
+
**What `RunDataContext` is now.** Exactly what `resolveRunDataContext` returns: `isSystem: true` for a `runAs: 'system'` run, and the triggering user's principal for a `runAs: 'user'` run. A run that resolves no principal is refused before any data operation (`AUTOMATION_UNSCOPED_RUN_DATA_ACCESS`), as before.
20
+
21
+
**If your code named the type.** There is no replacement, because the context it described is refused. A custom data node builds its context with `resolveRunDataContext(context)`, typed `RunDataContext`.
22
+
23
+
**`@objectstack/plugin-security`, `@objectstack/runtime`, `@objectstack/service-analytics`, `@objectstack/platform-objects`:** comment and docstring text only. Shipped comments that said the security middleware hands through, skips or falls open for a context with no principal now say that it used to, and that ADR-0096 D5 refuses such a context. Nothing these packages do changes.
Copy file name to clipboardExpand all lines: content/docs/api/error-catalog.mdx
+31-12Lines changed: 31 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ navTitle: Error Code Catalog
4
4
description: Complete reference for all ObjectStack error codes with causes, fixes, and retry strategies
5
5
---
6
6
7
-
ObjectStack uses a structured error system with **9 error categories** and **51 error codes reachable on the wire**. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
7
+
ObjectStack uses a structured error system with **9 error categories** and **52 error codes reachable on the wire**. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
8
8
9
9
This catalog documents the **wire face** — the codes a client can actually receive. That is not quite the
10
10
`StandardErrorCode` enum: the enum also carries in-process spellings the REST door translates at the
@@ -62,16 +62,10 @@ entry's cross-reference sentence so the in-process one stays findable.
62
62
**Fix:** Check the `fields` array for specific field-level issues.
63
63
**Retry:**`no_retry`
64
64
65
-
<Callouttype="warn">
66
-
**`VALIDATION_ERROR` is `400` with one exception: the storage upload doors answer `413` for
67
-
an upload over the File Storage settings' `max_upload_mb`.**
68
-
69
-
The presigned-upload door (the declared `size`), the chunked-upload start (the declared
70
-
`totalSize`), the local adapter's raw upload (the body) and the chunk door (the bytes the
71
-
upload already holds plus the chunk) refuse it before anything is stored. The message names
72
-
the size, the limit and the setting. Raise the setting or send a smaller file; resending the
73
-
same upload cannot succeed. The protocol page carries the same exception:
| 413 |`validation`|`VALIDATION_ERROR` on an upload over the storage settings' `max_upload_mb` (see [above](#validation_error)) — this row is an exception to the 400 row, not a second home for the code|
939
+
| 413 |`validation`|`PAYLOAD_TOO_LARGE` — an upload over the storage settings' `max_upload_mb`, or an import over its row ceiling (see [above](#payload_too_large))|
921
940
| 422 |`validation`|`MISSING_REQUIRED_FIELD` on an absent `controlled_by_parent` master reference (see [above](#missing_required_field)) — this row is an exception to the 400 row, not a second home for the code |
Copy file name to clipboardExpand all lines: content/docs/protocol/kernel/error-handling.mdx
+6-8Lines changed: 6 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -214,7 +214,7 @@ ObjectStack uses standard HTTP status codes:
214
214
| **403** | Forbidden | Authenticated but insufficient permissions |
215
215
| **404** | Not Found | Resource doesn't exist |
216
216
| **409** | Conflict | Resource already exists or version mismatch |
217
-
| **413** | Content Too Large | An upload over the storage settings' `max_upload_mb`— answered as [`VALIDATION_ERROR`](#validation_error), its one exception to 400 |
217
+
| **413** | Content Too Large | An upload over the storage settings' `max_upload_mb`, or an import over its row ceiling — answered as [`PAYLOAD_TOO_LARGE`](/docs/api/error-catalog#payload_too_large) |
218
218
| **422** | Unprocessable Entity | Semantic validation failed (e.g. metadata spec validation); also an absent `controlled_by_parent` master reference — see [`MISSING_REQUIRED_FIELD`](#missing_required_field) |
219
219
| **429** | Too Many Requests | Rate limit exceeded |
220
220
| **500** | Internal Server Error | Server-side error |
@@ -402,7 +402,7 @@ if (body.code === 'VALIDATION_FAILED') {
402
402
```
403
403
404
404
#### `VALIDATION_ERROR`
405
-
**HTTP Status:** 400 — with one documented exception, which answers **413** (see below)
405
+
**HTTP Status:** 400
406
406
**Meaning:** The request is malformed — the generic "you sent something wrong" code
407
407
**Envelope:** **both**, and one emitter writes neither (see the warning below)
408
408
@@ -418,12 +418,10 @@ Where it comes from:
418
418
specific.
419
419
- **Query-parameter refusals.** `refuseUnknownQueryParams` and `refuseRepeatedQueryParams`
420
420
answer 400 `VALIDATION_ERROR` for an unrecognised or repeated query parameter.
421
-
- **Upload size refusals — the one 413.** The storage upload doors answer **413**
422
-
`VALIDATION_ERROR` for an upload over the File Storage settings' `max_upload_mb`: the
423
-
presigned-upload door (the declared `size`), the chunked-upload start (the declared
424
-
`totalSize`), the local adapter's raw upload (the body) and the chunk door (the bytes the
425
-
upload already holds plus the chunk), each before anything is stored. The message names the
426
-
size, the limit and the setting.
421
+
422
+
Not from a request too large for its door: an upload over the File Storage settings'
423
+
`max_upload_mb` answers **413** with the registered code
424
+
[`PAYLOAD_TOO_LARGE`](/docs/api/error-catalog#payload_too_large), not this one.
427
425
428
426
**Nested** (the dispatcher door, status-derived — `GET /api/v1/packages/:id?version=1&version=2`):
0 commit comments