Skip to content

fix(spec): declare ownership as a first-class ObjectSchema field (#3175) - #3185

Merged
os-zhuang merged 1 commit into
mainfrom
claude/server-hosted-fields-schema-ohgdf8
Jul 18, 2026
Merged

fix(spec): declare ownership as a first-class ObjectSchema field (#3175)#3185
os-zhuang merged 1 commit into
mainfrom
claude/server-hosted-fields-schema-ohgdf8

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Context

Fixes#3175 — the ownership collision surfaced during #3168 (#3058).

The object-level record-ownership modelownership: 'user' | 'org' | 'none', which drives the registry's owner_id auto-provisioning (applySystemFields) — sat in a contract hole:

Per the direction chosen on #3175, this formalizes the property the engine already honors (Option A) rather than renaming it or removing the author surface.

Changes

  • specObjectSchema declares ownership: z.enum(['user','org','none']).optional() with a describe + JSDoc that explicitly distinguishes it from the own/extend contribution kind. The registry now reads schema.ownership off the typed schema (no as any). A retired ownership: 'own' | 'extend' value fails with guidance pointing at the record-ownership model and noting own/extend is set via registerObject, not on the object schema.
  • cli — the object scaffold no longer emits the invalid ownership: 'own' (owner injection is the default; consistent with the app/plugin scaffold cleanup in CHANGELOG feat(spec)!: remove tool.requiresConfirmation — a safety flag nothing enforced (#3715, ADR-0033 §2) #3876); objectstack info labels the record model with the correct user default.
  • Regenerated content/docs/references/data/object.mdx (one new row); added the ownership liveness-ledger entry and a changeset.

No runtime behavior change: applySystemFields and its owner_id injection logic are untouched — this makes the already-honored property legally authorable and consistently typed.

Verification

  • @objectstack/spec — full suite 6914 pass (+3 new ownership create() tests: opt-out values accepted, omitted → undefined, retired own rejected with guidance); check:liveness green; reference doc regenerated deterministically.
  • @objectstack/objectqlregistry.test.ts 63 pass (opt-out behavior equivalence); registry.ts typechecks with the as any removed (verified against the built spec dts).
  • CLI info/generate have no type surface change (obj is any; scaffold is a template string).

🤖 Generated with Claude Code

https://claude.ai/code/session_014343Qv6DFAykuAJc9yjANb


Generated by Claude Code

…3175)
The object-level record-ownership model — `ownership: 'user' | 'org' | 'none'`,
which drives the registry's `owner_id` auto-provisioning (`applySystemFields`) —
was read by the engine via `(schema as any).ownership` while `ObjectSchema.create()`
REJECTED it as an unknown top-level key (ADR-0032 "no silent failure" / #1535). So a
tested engine opt-out (`ownership: 'org' | 'none'` on catalog / junction tables)
could not be authored through the sanctioned `create()` path, the scaffold still
emitted a now-invalid `ownership: 'own'`, and the same word was read elsewhere as the
unrelated package-contribution kind (`own` / `extend`).
Resolves the collision by formalizing the property the engine already honors:
- spec: `ObjectSchema` declares `ownership: z.enum(['user','org','none']).optional()`.
The registry reads it off the typed schema (no `as any`). A retired `own`/`extend`
value fails with guidance distinguishing it from the contribution kind (registerObject).
- cli: the `object` scaffold no longer emits the invalid `ownership: 'own'` (owner
injection is the default), and `objectstack info` labels the record model with the
correct `user` default.
- Regenerated the object reference doc; liveness ledger + changeset added.
No runtime behavior change: `applySystemFields` and its `owner_id` injection logic are
unchanged — this makes the already-honored property legally authorable and typed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014343Qv6DFAykuAJc9yjANb
@vercel

vercelBot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specBuildingBuildingPreview, CommentJul 18, 2026 6:40am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data tests tooling size/s labels Jul 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/cli, @objectstack/objectql, @objectstack/spec.

112 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/data-flow.mdx(via @objectstack/cli)
  • content/docs/api/environment-routing.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/cli, packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/objectql, packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via packages/objectql, @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/backup-restore.mdx(via @objectstack/cli)
  • content/docs/deployment/migration-from-objectql.mdx(via @objectstack/objectql)
  • content/docs/deployment/self-hosting.mdx(via @objectstack/cli)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/vercel.mdx(via @objectstack/objectql)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/cli, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/objectql, @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx(via @objectstack/cli, @objectstack/objectql)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/objectql, @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/objectql)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/cli, @objectstack/spec)
  • content/docs/protocol/kernel/realtime-protocol.mdx(via @objectstack/cli)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/objectql, @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 18, 2026 06:53
@os-zhuang
os-zhuang merged commit fefcd54 into mainJul 18, 2026
16 of 17 checks passed
@os-zhuang
os-zhuang deleted the claude/server-hosted-fields-schema-ohgdf8 branch July 18, 2026 06:53
os-zhuang added a commit that referenced this pull request Jul 18, 2026
… document the field (#3175) (#3193)
Follow-up to #3185. The VS Code `os-object` snippet still scaffolded
`ownership: 'own'` — the same now-invalid value removed from the CLI `generate`
scaffold. Since #3185 made `ownership` a typed `'user' | 'org' | 'none'` enum,
expanding the snippet produced an object that fails typecheck / `ObjectSchema.create()`.
- vscode: remove the `ownership: 'own'` line from the object snippet (owner
injection is the default; nothing to declare).
- docs: document the now first-class `ownership` record-ownership knob in the
object Additional Properties table.
Claude-Session: https://claude.ai/code/session_014343Qv6DFAykuAJc9yjANb
Co-authored-by: Claude <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 18, 2026
…3194)
`ObjectSchema.systemFields` advertised an `owner?: boolean` opt-out that nothing
read — `applySystemFields` only consumes `systemFields.tenant` and
`systemFields.audit`, and `owner_id` provisioning is governed by the object-level
`ownership` property (made first-class in #3185). The key was declared but wired to
nothing.
- spec: remove `owner` from the `systemFields` object so it only advertises the two
opt-outs it honors (`tenant`, `audit`). Runtime-compatible (the key was ignored;
it is stripped now — both no-ops). A TS author who set it gets an excess-property
error; the fix is to delete it or use `ownership: 'org' | 'none'`.
- docs: regenerated the object reference; corrected the stale objectql/security note
that called `audit` "reserved" (it is active).
Claude-Session: https://claude.ai/code/session_014343Qv6DFAykuAJc9yjANb
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/steststooling

Projects

None yet

2 participants

@os-zhuang@claude