Skip to content

Add V116 migration (parent_uuid on entity_data) + sortable_handle on draggable_list#538

Merged
ddon merged 2 commits into
BeamLabEU:devfrom
mdon:dev
May 12, 2026
Merged

Add V116 migration (parent_uuid on entity_data) + sortable_handle on draggable_list#538
ddon merged 2 commits into
BeamLabEU:devfrom
mdon:dev

Conversation

@mdon
Copy link
Copy Markdown
Contributor

@mdon mdon commented May 12, 2026

Summary

Two independent additions on top of the post-V115 upstream:

  1. V116 — parent_uuid self-FK on phoenix_kit_entity_data so each
    entity-data row can point at another row of the same entity as its
    parent. System field — always present, optional, never user-removable
    (does not appear in entities.fields_definition). Same shape as V103
    (catalogue's nested categories): nullable self-FK, no ON DELETE
    cascade, b-tree index on (parent_uuid). Same-entity scope + cycle
    prevention are context-layer responsibilities in
    phoenix_kit_entities.

  2. sortable_handle attribute on <.draggable_list> so consumers
    can render their own grab handle (e.g. a hover-revealed bars icon)
    instead of making the whole card draggable. Optional, default nil
    backward-compatible with every existing call site. Mirrors the
    :on_reorder.pk-drag-handle convention <.table_default>
    already ships.

Companion PR

BeamLabEU/phoenix_kit_entities — consumes V116 (parent_uuid schema +
context layer) and the new :sortable_handle attr (card-view DnD in
Web.Entities + Web.DataNavigator).

Verification

  • mix compile — clean.
  • mix test — 1230 / 1231 pass (one pre-existing failure in
    V114Test "N >= 3 collision: exactly one plain key, N-1 distinct suffixed keys" — unrelated to this PR; the V114.down/1 collision-
    suffix logic ships a duplicate integration:openrouter:work-<8-char>
    in the test fixture).
  • V116 column add + index follow V103's exact shape; idempotent
    (IF NOT EXISTS on both the column and the index).
  • down/1 drops the index then the column; comment marker rewrites
    to '115' on rollback.

Test plan

  • mix format --check-formatted
  • mix credo --strict (no new findings)
  • mix compile --warnings-as-errors
  • mix test (1230 of 1231; 1 pre-existing flake noted above)
  • down/1 smoke: marker rewrites to 115, column + index dropped

mdon added 2 commits May 12, 2026 23:13
Nullable self-referential UUID column with a b-tree index and no
ON DELETE cascade. Lets each entity data row point at another row of
the same entity as its parent — a built-in system field on every row,
always present, optional to fill, never user-removable (it does not
appear in entities.fields_definition).

Same shape as V103 (catalogue's nested categories): the context layer
owns parent/child cascade rules so the soft-delete machinery and the
activity log stay in the loop. Same-entity enforcement (a parent must
share entity_uuid) is also a context responsibility — the self-FK has
no view of entity_uuid.

Bumps @current_version 115 → 116 in postgres.ex and adds the
LATEST-marked moduledoc entry. Originally authored as V115 against an
older dev tip; renumbered after rebasing onto upstream's V115
(phoenix_kit_annotations).
Optional attr (default nil) that, when set to a CSS selector, emits
data-sortable-handle on the container and skips the cursor-grab
styling on the item wrapper. The SortableGrid hook reads the data
attribute and feeds it to SortableJS's `handle` option, restricting
drag initiation to elements matching the selector inside each item.

Mirrors the convention <.table_default> already uses with :on_reorder
→ ".pk-drag-handle". Lets consumers render their own handle (e.g. a
hover-revealed bars icon) instead of making the whole card grabbable.

Backward-compatible: existing call sites without :sortable_handle
keep the whole-item drag behavior.
@ddon ddon merged commit 49519e7 into BeamLabEU:dev May 12, 2026
ddon pushed a commit that referenced this pull request May 12, 2026
7 findings: 1 BUG-LOW (my carry-over from PR #536 — V114 down SQL
suffix collision because UUIDv7's first 8 chars are timestamp not
random), 5 IMPROVEMENT-LOW (V116 no-op conditional, prefix_str drift,
self-loop CHECK, defensive table_exists, component test TODO widening),
1 IMPROVEMENT-LOW component (sortable_handle typo-safety).

Strengths: mirrors V103 catalogue pattern, idempotent, no-cascade
trade-off documented, sortable_handle is purely additive (JS already
supported data-sortable-handle), PR description honest about pre-
existing test failure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon pushed a commit that referenced this pull request May 12, 2026
Code (PR #538 #1 — carry-over from PR #536 follow-up):

- V114 down SQL: switch the collision-suffix source from
  `substring(uuid::text from 1 for 8)` (UUIDv7 timestamp prefix — same
  millisecond ⇒ identical prefix ⇒ duplicate suffixed keys when two+
  rows collide on (provider, name)) to `substring(uuid::text from 25
  for 8)` (the post-variant random tail, 32 bits of entropy ⇒ 1-in-4B
  collision probability per pair). Mirrored in `run_down!` in
  `v114_test.exs` since the test duplicates the SQL.
- V114 moduledoc updated to spell out the suffix source and why the
  timestamp prefix was wrong.

The fix is forward-compat: systems that already ran V114.down get the
old (potentially-collided) keys; fresh installs and any future
rollback get the corrected behavior.

Docs (PR #538 #6):

- AGENTS.md TODO entry for `<.draggable_list>` test coverage widened
  to call out the new `:sortable_handle` axis: three branches
  (`:draggable=false`, `:draggable=true + sortable_handle=nil`,
  `:draggable=true + sortable_handle=".pk-drag-handle"`).

Plus a one-line `mix format` normalization in V116 (multi-line
`execute(...)` collapsed to single line).

mix precommit: compile → format → credo --strict (0 findings) →
dialyzer (160 errors all skipped) clean.

Deferred to maintainer: #2 / #3 / #5 (cosmetics on deployed
migrations), #4 (DB-level self-loop CHECK — needs a V117), #7
(`sortable_handle` typo safety — design call on boolean shape vs
JS warning).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon pushed a commit that referenced this pull request May 12, 2026
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ddon pushed a commit that referenced this pull request May 12, 2026
CHANGELOG: covers PRs #536 (Integrations V114 + IntegrationPicker +
form fixes), #537 (V115 annotations + Etcher overlay + AnnotationComposer),
#538 (V116 entity_data parent_uuid + sortable_handle), plus all
post-merge review fixes folded into dev between merges. Organized
Added / Changed / Fixed / i18n to match the 1.7.108 entry's style.

AGENTS.md: the "entries written by the maintainer, not agents — flag
the gap and stop" line was filling context with a false rule. Replaced
with reality: agents draft the entry against the bumped @Version
heading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants