Skip to content

feat: record clone — wire object.enable.clone to a real runtime#1961

Merged
os-zhuang merged 1 commit into
mainfrom
feat/record-clone
Jun 16, 2026
Merged

feat: record clone — wire object.enable.clone to a real runtime#1961
os-zhuang merged 1 commit into
mainfrom
feat/record-clone

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

What

object.enable.clone was a parsed-but-dead capability flag (no runtime reader, classified dead in the spec-liveness ledger). This wires it to an actual record-clone path and flips it dead → live.

This is the productization half of the spec-liveness cleanup: where a flag is worth keeping, build the feature rather than prune the flag. (The companion PR #1960 prunes the genuinely orphaned recordTypes/cdc stubs.)

objectql — protocol.cloneData({ object, id, overrides?, context? })

Reads the source record, drops engine-owned columns so the insert path re-derives them, applies caller overrides last, inserts the copy:

Dropped (re-derived on insert) Kept (copied)
id + audit created_at/created_by/updated_at/updated_by all scalar/business field values
system-flagged columns (e.g. injected organization_id)
autonumber fields (re-issued)
formula / summary fields (recomputed)
  • Shallow by design — duplicates the record's own fields, not its child records.
  • Gated on schema.enable.clone: default-on; explicit enable.clone === false403 CLONE_DISABLED.

rest — POST /api/v1/data/:object/:id/clone

  • 201 → { object, id, sourceId, record }.
  • Optional body { overrides } (or a bare field map) overrides copied values — the place to set a new name or clear a unique field before insert.
  • Honors the existing auth + enable.apiEnabled/apiMethods gates; lives in the always-on data-action group alongside lead/:id/convert.

Verification

  • 8 protocol unit tests (mock engine): field stripping, autonumber/formula/summary/system drop, overrides-win, context forwarding, CLONE_DISABLED, default-on, RECORD_NOT_FOUND, OBJECT_NOT_FOUND.
  • 5 REST route tests: registration, nested + bare overrides, 403 mapping, 501 fallback when a protocol lacks cloneData.
  • 4 real-engine integration tests (genuine ObjectQL + in-memory driver) — proves the cloned row gets a regenerated autonumber (ACC-0001ACC-0002), overrides apply, enable.clone:false → 403, missing source → 404.
  • Liveness gate green (object.enable.clone now live with evidence); @objectstack/objectql 633 passed, @objectstack/rest 121 passed.

Follow-ups (not in scope)

  • SDK client sugar (client.data.clone()) + an objectui "Clone" record action — cloneData follows the same untyped-extra-method pattern as convertLead, so neither is wired to a typed client method yet.
  • Deep clone (cascade to child records) if a use case appears; today's behavior is intentionally shallow.

🤖 Generated with Claude Code

`object.enable.clone` was a parsed-but-dead capability flag. This wires it
to an actual clone path and reclassifies it dead→live in the liveness ledger.

objectql:
  protocol.cloneData({ object, id, overrides?, context? }) reads the source,
  drops engine-owned columns (id + created_at/created_by/updated_at/updated_by,
  plus system-flagged / autonumber / formula / summary fields) so the insert
  path re-derives them, applies caller overrides last, and inserts the copy.
  Shallow by design. Gated on schema.enable.clone — explicit false → 403
  CLONE_DISABLED; absent/true → allowed.

rest:
  POST /api/v1/data/:object/:id/clone (201 → { object, id, sourceId, record }).
  Optional { overrides } body (or a bare field map) wins over copied values.
  Honors the existing auth + enable.apiEnabled/apiMethods gates.

Tests: 8 protocol unit tests (mock engine), 5 REST route tests (registration,
overrides, 403 mapping, 501 fallback), and 4 real-engine integration tests
proving autonumber regeneration (ACC-0001 → ACC-0002) and CLONE_DISABLED on a
genuine ObjectQL engine. Gate green; objectql 633, rest 121.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 16, 2026 10:03am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Jun 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/cloud-artifact-api.mdx (via packages/spec)
  • content/docs/concepts/cluster-semantics.mdx (via @objectstack/spec)
  • content/docs/concepts/core/services.mdx (via @objectstack/objectql)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/implementation-status.mdx (via @objectstack/objectql, @objectstack/rest, @objectstack/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/concepts/packages.mdx (via @objectstack/objectql, @objectstack/rest, @objectstack/spec)
  • content/docs/concepts/setup-app.mdx (via @objectstack/spec)
  • content/docs/concepts/skills.mdx (via @objectstack/spec)
  • content/docs/concepts/webhook-delivery.mdx (via @objectstack/spec)
  • content/docs/getting-started/architecture.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/core-concepts.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/guides/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/guides/ai-capabilities.mdx (via @objectstack/spec)
  • content/docs/guides/airtable-dashboard-analysis.mdx (via @objectstack/spec)
  • content/docs/guides/analytics-datasets.mdx (via @objectstack/spec)
  • content/docs/guides/api-reference.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/guides/authentication.mdx (via @objectstack/objectql)
  • content/docs/guides/business-logic.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/error-catalog.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-type-gallery.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-validation-rules.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/protocol-diagram.mdx (via packages/spec)
  • content/docs/guides/cheatsheets/query-cheat-sheet.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/quick-reference.mdx (via @objectstack/spec)
  • content/docs/guides/client-sdk.mdx (via @objectstack/spec)
  • content/docs/guides/common-patterns.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/auth-service.mdx (via packages/spec)
  • content/docs/guides/contracts/cache-service.mdx (via packages/spec)
  • content/docs/guides/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/index.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/guides/contracts/storage-service.mdx (via packages/spec)
  • content/docs/guides/data-modeling.mdx (via @objectstack/spec)
  • content/docs/guides/deployment-vercel.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/guides/driver-configuration.mdx (via @objectstack/spec)
  • content/docs/guides/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/guides/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/guides/formula.mdx (via packages/objectql, @objectstack/spec)
  • content/docs/guides/hook-bodies.mdx (via packages/spec)
  • content/docs/guides/kernel-services.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/guides/metadata/dashboard.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/field.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/flow.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/index.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/object.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/validation.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/workflow.mdx (via @objectstack/spec)
  • content/docs/guides/objectql-migration.mdx (via @objectstack/objectql)
  • content/docs/guides/packages.mdx (via @objectstack/objectql, @objectstack/rest, @objectstack/spec)
  • content/docs/guides/plugin-development.mdx (via @objectstack/spec)
  • content/docs/guides/plugins.mdx (via @objectstack/objectql, @objectstack/rest, @objectstack/spec)
  • content/docs/guides/project-scoping.mdx (via @objectstack/spec)
  • content/docs/guides/public-forms.mdx (via @objectstack/spec)
  • content/docs/guides/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/index.mdx (via packages/spec)
  • content/docs/guides/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/guides/security.mdx (via @objectstack/spec)
  • content/docs/guides/seed-data.mdx (via @objectstack/spec)
  • content/docs/guides/skills.mdx (via @objectstack/spec)
  • content/docs/guides/standards.mdx (via @objectstack/spec)
  • content/docs/guides/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/index.mdx (via @objectstack/objectql)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.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 packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/objectql, @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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant