Skip to content

docs(data-modeling): add Import Mappings and Object Extensions guides - #10341

Merged
os-elon merged 1 commit into
mainfrom
claude/issue-10213-mappings-object-extensions
Aug 21, 2026
Merged

docs(data-modeling): add Import Mappings and Object Extensions guides#10341
os-elon merged 1 commit into
mainfrom
claude/issue-10213-mappings-object-extensions

Conversation

@os-elon

Copy link
Copy Markdown
Collaborator

Fixes#10213 (sub-issue of #10206)

Two authorable metadata surfaces had no page in Data Modeling. This adds one each, both written from the implementation rather than from the schema alone.

content/docs/data-modeling/import-mappings.mdx (new)

mapping is a full metadata kind, and the reason it is a kind is that a consumer landed: POST /api/v1/data/:object/import resolves a registered artifact by mappingName. Grepping the hand-written docs for mappingName returned zero hits before this PR, so the page is built around that request rather than around the shape.

What is on it, and where each claim comes from:

  • Declaring onedefineMapping() + defineStack({ mappings }), plus the two build-time refusals in validateCrossReferences (stack.zod.ts:1067): an unknown targetObject, and a javascript transform.
  • The two origins — packaged, or saved at runtime. The runtime half is allowRuntimeCreate: true on the mapping registry entry (metadata-plugin.zod.ts:755); both origins are addressed identically because resolveNamedMapping goes through getMetaItem, which reads the sys_metadata rows first and the in-memory registry second.
  • Transformations — a table of all seven TransformType values against what applyMappingToRows (import-mapping.ts:115-167) actually executes: five applied, lookup a deliberate pass-through, javascript a 400.
  • The request end to end — a real mappingName body and the real response envelope, taken from the route handler (rest-server.ts:6999-7040).
  • Inline mapping vs mappingName — the strict-projection difference. The artifact path emits only mapped targets; the inline rename passes unmapped columns through. This is the trap the seam comment in import-mapping.ts was written for.
  • Every pre-row rejectionMAPPING_NOT_FOUND, MAPPING_TARGET_MISMATCH, MAPPING_FORMAT_UNSUPPORTED, MAPPING_FORMAT_MISMATCH, UNSUPPORTED_TRANSFORM, CONFLICTING_MAPPING, INVALID_REQUEST, PAYLOAD_TOO_LARGE, with statuses.
  • "A row that does not match" — answered from import-runner.ts:713-740 rather than assumed. It is three different outcomes, chosen by write mode and match count: created (upsert), skipped/NO_MATCH (update), failed/AMBIGUOUS_MATCH (more than one match), plus BLANK_MATCH_KEY.

content/docs/data-modeling/object-extensions.mdx (new)

objectExtensions was documented only inside protocol/objectql/schema.mdx, which is written for implementers. The protocol page is cross-linked, not edited (/docs/protocol/objectql/schema#object-extensions).

  • What the merge carries — the seven keys mergeObjectDefinitions (registry.ts:137) actually reads, with each one's behaviour: fields additive with same-name replacement, validations and indexes concatenated, three scalars last-writer-wins.
  • What it refusesactions, hooks, listViews, fieldGroups, each with the alternative the schema's own guidance block prescribes. These are enforced refusals, not omissions.
  • Priority and collisions — contributors are sorted ascending and folded in that order, so higher wins. Same-name field collisions between two packages are silent, which the page says plainly.
  • The ownership modelown / overlay / extend, and the ADR-0029 D9.2 base selection (overlay ?? own) that makes extension fields survive a tenant-customized object.
  • The 2026-08-13 ruling — an extension's label/pluralLabel/description yield once the base has been authored away from the packaged owner's value (tenantAuthoredScalars, registry.ts:1718). Carried as a Callout because an author cannot discover it from the schema.

Verifying the dispatch's three mechanism assumptions

All three were checked before writing, and two came back different from the premise:

  1. import-coercion.ts bounds what the page may promise about transformation — partly. That file holds the vocabulary (boolean tokens, reference types) as constants; the coercion logic is packages/rest/src/import-coerce.ts, and mapping transforms are a third thing again, in import-mapping.ts. The page keeps the three separate: the mapping decides which value lands in which field, coercion converts it afterwards from the target object's field metadata.
  2. objectExtensions interacts with the customization overlay system — yes, but not through supportsOverlay. That flag is false for object and gates only assertDeleteAllowed (the metadata-plugin.zod.ts:693 warning says so explicitly and calls a "fix" to it a regression). The real interaction is the schema registry's three-kind contributor model, and the page describes that.
  3. namespace-prefix.ts governs prefixing for fields an extension addsno.validateObjectNamespacePrefix is applied by validateNamespacePrefix to config.objects only; it never walks objectExtensions, and it is about object names, not field names. The page says the platform applies no prefix rule here and recommends prefixing as a convention, which is what the shipped extensions do (plugin-auth's oidc_client_secret, the showcase's loyalty_tier).

Declared deviation from the file surface

.claude/workflows/docs-accuracy-audit.js is in this diff. It is the mechanical output of node scripts/docs-audit/check-audit-scope.mjs --write — the only remedy for the check:docs-audit-scope red that adding a page causes, and a file the gate rejects hand-edits to. Two lines, one per new page.

That puts .claude/** in the path surface, so this PR is human-merge-only (#9866, Prime Directive #14). It is deliberately left in draft: not flipped ready, not queued, no auto-merge armed.

Findings filed, not documented around

Two gaps surfaced while verifying. Both are domain:spec calls, so they are filed rather than written up as if they worked — and each has a Callout on the page pointing at it, to be deleted when the issue lands:

Gates

Derived from the real diff with node scripts/pm/dispatch-gates.mjs (no paths passed) after the final commit, and run at 3e85784bd. All 15 derived families plus check:skill-examples and check:nul-bytes, green:

GateVerdict line
check:doc-anchors✅ check-doc-anchors: 259 internal #fragment link(s) across 401 source file(s) all resolve to a real heading
check:doc-authoring✓ doc authoring guard: 382 files clean — no bare metadata literals.
check:docs-audit-scope✓ docs-accuracy-audit scope is in sync with content/docs/: 182 hand-written doc(s).
check:docs-redirectscheck-docs-redirects: OK (apps/docs/redirects.mjs: 92 entries ...)
check:published-readme-links✓ check:published-readme-links — 152 outbound link(s) across 60 published markdown file(s)
check:role-wordcheck-role-word: OK, no new occurrences of the reserved word.
check:cross-package-test-inputsOK: 12 package(s) read outside themselves, all declared
check:nul-bytescheck-nul-bytes: OK (scanned 6092 text file(s) ... no raw ASCII control bytes).
check:pm-governed-merges✓ check-governed-merges --self-test: 81 assertions
check:skill-frame-sync✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic
check:doc-formula-expressions✓ ... 22 record-scoped formula example(s) across 408 files / 1420 TS blocks judged clean by @objectstack/formula.
check:empty-state✓ all classified (1 closed, 2 open, 4 output, 9 scope)
check:liveness✓ every governed-type property at the walk's one-level granularity is classified ...
check:strictness-ledger✓ strictness ledger: 61 file(s) across 5 triaged director(ies)
check:variant-docs✓ variant/doc gate: 18 discriminated union(s) — 8 governed, 10 exempt
check:skill-examples✅ 212 prose examples type-check against @objectstack/spec

The three {/* os:check */} blocks were confirmed extracted, not silently skipped — the gate log names each one:

• content/docs/data-modeling/import-mappings.mdx:24 → docs__data-modeling_import-mappings__1.ts
• content/docs/data-modeling/object-extensions.mdx:35 → docs__data-modeling_object-extensions__1.ts
• content/docs/data-modeling/object-extensions.mdx:158 → docs__data-modeling_object-extensions__2.ts

check:doc-formula-expressions needed @objectstack/formula built first — a fresh-worktree dependency-closure miss, not a defect in this diff.

No changeset

Docs pages plus a generated scope list; nothing published. skip-changeset applied.


Generated by Claude Code

…#10213)
Two authorable metadata surfaces had no page in Data Modeling.
`mapping` is a full metadata kind whose reason for existing is a consumer:
`POST /data/:object/import` resolves a registered artifact by `mappingName`.
That parameter had zero occurrences in the hand-written docs, so the new page
is built around the request itself — the artifact shape, the five transforms
the pipeline actually executes, the strict-projection difference from an inline
`mapping`, every pre-row rejection code, and the three different things "a row
that does not match" means depending on write mode.
`objectExtensions` was documented only inside protocol/objectql/schema.mdx,
which is written for implementers. The new page covers when to extend rather
than define, the seven keys the merge carries, the four it refuses (with the
alternative each one needs), priority ordering, field-name collisions, and the
own/overlay/extend contributor model including the 2026-08-13 ruling that an
extension's scalars yield to a tenant-renamed base. The protocol page is
cross-linked, not edited.
Both pages are written from the implementation. Two gaps found while verifying
are filed rather than documented as working: #10329 (the `lookup` transform's
params are read by nothing) and #10330 (`mappingName` is undeclared on
ImportRequestSchema, so the typed SDK cannot express it).
`.claude/workflows/docs-accuracy-audit.js` is the mechanical output of
`node scripts/docs-audit/check-audit-scope.mjs --write`, which is the only
remedy for the `check:docs-audit-scope` red that adding a page causes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GawRwpD44VwBDVy3hs77AX
@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation labels Aug 20, 2026
@os-elonos-elon added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 20, 2026 — with Claude
@os-elon
os-elon requested a review from os-zhuangAugust 20, 2026 16:07
@os-elon
os-elon marked this pull request as ready for review August 21, 2026 00:55
@os-elon
os-elon added this pull request to the merge queueAug 21, 2026
@os-elonClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landed by the PM under the maintainer's explicit instruction — audit record.

This is a governed PR (.claude/workflows/docs-accuracy-audit.js, the #9866 collision), so under the standing regime the merge is the maintainer's own act and their click is the review record. It is being landed by an agent instead, on instruction. This comment exists so the entry is legible in check-governed-merges rather than reading as an unexplained agent merge.

Provenance — who, what, where. The repository owner, in the PM session driving epic #10206, 2026-08-20. Authorization verbatim: 「你帮我处理合并吧」. Their per-PR verdict on this one, verbatim: 「可合」 — 「两个派发 premise 被实测推翻并如实入文,两个 spec 缺口立卡不粉饰」.

PM position, recorded rather than dropped. I stated before acting that an agent-executed governed merge removes the human click the fence treats as the review record, and that the audit would flag it. The maintainer instructed anyway. The decision is theirs; this is the record of it, not a silent reinterpretation of the rule.

Landing route. A direct merge is refused by repository rules (405 Changes must be made through the merge queue), so this PR was flipped ready and entered the merge queue via auto-merge — the only sanctioned path. It lands only if the full-suite queue build passes; the queue has been dequeuing on an unrelated @objectstack/example-showcase failure tonight (see #10253), so a dequeue here would not be this PR's defect.


Generated by Claude Code

Merged via the queue into main with commit 6620dbdAug 21, 2026
24 checks passed
@os-elon
os-elon deleted the claude/issue-10213-mappings-object-extensions branch August 21, 2026 01:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(data-modeling): import mapping has no guide at all, and objectExtensions is documented only inside the protocol spec

2 participants

@os-elon@claude