Skip to content

Commit dfa0021

Browse files
committed
chore(changeset): record the mapping-target refusal for spec, rest and lint
Claude-Session: https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV Co-authored-by: Claude <noreply@anthropic.com>
1 parent eab27ef commit dfa0021

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
"@objectstack/spec": minor
3+
"@objectstack/rest": minor
4+
"@objectstack/lint": minor
5+
---
6+
7+
fix(rest,lint): an import mapping target that names no field is refused on the dry run, on the commit and at `objectstack validate` alike (#20150)
8+
9+
Clause-②: yes
10+
11+
<!-- adr-0087: not-required (no-migration-prescription) Nothing authorable is renamed, retired or re-typed: `ImportFieldMappingSchema.target` keeps its declared shape and meaning ("Target object field(s)"), no stored mapping or record moves, and every mapping parses byte-identically to before. What narrows is the ACCEPT SET of the import door and of the published author-time checker, and only for mappings whose target already names no field of the object: those failed every row on the commit before this change, so no import that wrote anything is refused now. The remedy is per mapping and the refusal names it in full (the mapping, the target, its position and the object); there is no stored representation for `objectstack migrate meta` to rewrite. -->
12+
13+
**BREAKING** in the accept-set sense only, landing in the launch window as
14+
`minor`: the import route and `objectstack validate` now refuse a mapping they
15+
used to pass, and every such mapping already failed on the commit.
16+
17+
**What was wrong.** `ImportFieldMappingSchema.target` is declared as "Target
18+
object field(s)", and nothing held a mapping to it. A mapping whose target named
19+
no field of its `targetObject` (measured with `mailing_address.street` on an
20+
object whose address field is `mailing_address`):
21+
22+
- passed `objectstack validate`, `os lint` and `os build` with no diagnostic;
23+
- answered `ok` for every row on `POST /api/v1/data/:object/import` with
24+
`dryRun: true`;
25+
- then failed every row on the commit with `INVALID_FIELD` ("Unknown field
26+
'mailing_address.street' on object '…'").
27+
28+
The dry run promised what the commit refused.
29+
30+
**What changes.**
31+
32+
- `@objectstack/spec` exports ONE verdict on what a target may name, beside the
33+
schema it judges: `unknownImportMappingTargets(fieldMapping, objectDef)`, with
34+
`indexImportMappingTargets`, `judgeImportMappingTarget`,
35+
`importMappingEntryTargets` and `IMPORT_TARGET_ALWAYS_ADDRESSABLE_COLUMNS`
36+
(from `@objectstack/spec/data`). A target may name a declared field, a column
37+
the platform provisions on that object (`resolveInjectedSystemColumns`), or one
38+
of `id` / `created_at` / `updated_at`, which the engine's write door admits on
39+
every object. An object with no readable, non-empty field map is not judged.
40+
- `@objectstack/rest`: `prepareImportRequest` refuses a named mapping (`mappingName`)
41+
with a target that names no field, before any row, with `400 INVALID_FIELD` —
42+
the code the commit's per-row refusal already carried. The dry run and the
43+
commit give the same answer, and so does the async import-job route.
44+
- `@objectstack/lint`: the reference-integrity suite (`os validate`, `os lint`,
45+
`os build`) gains `validateMappingTargetFields`, rule id
46+
`mapping-target-field-unknown` (`MAPPING_TARGET_FIELD_UNKNOWN`), severity
47+
`error`, located at `mappings[i].fieldMapping[j].target`. It asks the same
48+
spec verdict, so it never refuses a target the import door accepts.
49+
50+
**What to do.** Point each reported target at a field the object declares. An
51+
array target (`split`) is judged element by element.

0 commit comments

Comments
 (0)