From ebe0d9baa25c31f2faacaf6d25dff0bca574cfc7 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 22:10:23 +0000 Subject: [PATCH] docs(skills): master_detail deleteBehavior admits cascade/restrict only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The published objectstack-data skill taught `deleteBehavior: 'set_null'` on a `master_detail` field in four places. That was already wrong before #9689 — the engine resolved every non-`restrict` value on this type to `cascade`, so the declaration promised keep-the-children and delivered delete-the-children — and since #9689 landed (PR #11406) it is a named parse-time rejection: an AI author following the skill produced metadata that fails publish with a 422. Teaches the per-type vocabulary instead: `master_detail` admits `cascade` / `restrict`; `set_null` belongs on `lookup`, where children survive the parent. Correction, not expansion — net line delta is exactly 0 in both files. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01RMTpSRF5CjMmQBFfPtPCwJ --- skills/objectstack-data/rules/field-types.md | 4 ++-- skills/objectstack-data/rules/relationships.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/skills/objectstack-data/rules/field-types.md b/skills/objectstack-data/rules/field-types.md index b6a503b0b3..f7257cddab 100644 --- a/skills/objectstack-data/rules/field-types.md +++ b/skills/objectstack-data/rules/field-types.md @@ -68,8 +68,8 @@ options: [ | Type | When to Use | Key Config | |:-----|:------------|:-----------| -| `lookup` | Reference another object (independent) | `reference`, `lookupFilters`, `multiple` | -| `master_detail` | Parent–child with lifecycle control | `reference`, `deleteBehavior` (cascade/restrict/set_null) | +| `lookup` | Reference another object (independent) | `reference`, `lookupFilters`, `multiple`, `deleteBehavior` | +| `master_detail` | Parent–child with lifecycle control | `reference`, `deleteBehavior` (`cascade`/`restrict` — `set_null` is refused) | | `tree` | Hierarchical self-reference | `reference` | | `user` | Person picker — a lookup specialized to `sys_user` (assignee, watchers). Stored identically to `lookup` | `multiple` (collaborators), `defaultValue: 'current_user'` | diff --git a/skills/objectstack-data/rules/relationships.md b/skills/objectstack-data/rules/relationships.md index 10ad74cae4..1018426b25 100644 --- a/skills/objectstack-data/rules/relationships.md +++ b/skills/objectstack-data/rules/relationships.md @@ -14,7 +14,7 @@ Guide for modeling relationships between objects using `lookup`, `master_detail` ### Use `lookup` When: - Child record can exist independently -- Parent deletion should not affect child +- Parent deletion should not affect child (`deleteBehavior: 'set_null'`) - No roll-up aggregations needed - Relationship is optional - **Example:** `task.assigned_to → user` (task can exist without assignment) @@ -150,19 +150,19 @@ export default ObjectSchema.create({ ## Delete Behaviors -Configure `deleteBehavior` on `master_detail` relationships: +Configure `deleteBehavior` on `master_detail` — `cascade` or `restrict` **only**; +an authored `set_null` is refused at publish (it would orphan the detail row). | Behavior | Effect | Use Case | |:---------|:-------|:---------| | `cascade` | Delete all child records | Invoice → Line Items | | `restrict` | Prevent parent deletion if children exist | Department → Employees | -| `set_null` | Set child reference to null | Manager → Employees (manager leaves) | ```typescript { type: 'master_detail', reference: 'parent_object', - deleteBehavior: 'cascade', // or 'restrict' or 'set_null' + deleteBehavior: 'cascade', // or 'restrict' — 'set_null' is refused here } ``` @@ -402,7 +402,7 @@ export default ObjectSchema.create({ 1. **Use lookup by default** — Only use master_detail when lifecycle coupling is required 2. **Unique constraints on junctions** — Prevent duplicate many-to-many entries 3. **Meaningful junction names** — Use descriptive names like `project_assignment` not `project_employee` -4. **deleteBehavior on master_detail** — Always specify cascade/restrict/set_null +4. **deleteBehavior on master_detail** — Always specify `cascade` or `restrict` 5. **Required on master_detail** — Child should always require parent 6. **Roll-ups for aggregation** — Use summary fields on parent for counts/sums 7. **lookupFilters for scoping** — Limit lookup options to relevant records (`lookupFilters: [{ field, operator: 'eq', value }]`)