Skip to content

feat(automations): support custom contact fields in Update Contact Field action#240

Merged
ArnasDon merged 1 commit into
mainfrom
feat/custom-fields-update-contact-action
Jun 11, 2026
Merged

feat(automations): support custom contact fields in Update Contact Field action#240
ArnasDon merged 1 commit into
mainfrom
feat/custom-fields-update-contact-action

Conversation

@ArnasDon

Copy link
Copy Markdown
Owner

Closes #235

Problem

The Update Contact Field automation action could only write the three built-in contact columns (Name, Email, Company), and its value wasn't interpolated — so workflows couldn't store richer customer data or use workflow variables.

What this does

The custom_fields / contact_custom_values tables and account-scoped RLS already existed (migrations 001 + 017); the contact detail view already reads/writes per-contact values. This PR wires the rest together — no migration needed.

  • Custom-field manager — a "Custom fields" dialog launched from the Contacts page header (admin+ gated via useCan('edit-settings')) to create / rename / delete field definitions. Inserts carry account_id + user_id.
  • Automation builder — loads account custom fields into the existing ResourcesContext (same pattern as tags/templates) and offers them in the Field dropdown, encoded as custom:<id>. A saved field that's since been deleted is preserved as an "(unknown field)" option so editing doesn't silently drop it.
  • Engine — interpolates the value ({{ vars.* }} / {{ message.text }}) for all fields. For custom:<id> it verifies the field belongs to the automation's account (defense in depth — the service-role client bypasses RLS) before upserting into contact_custom_values on its UNIQUE(contact_id, custom_field_id) key.

Tests / checks

  • npm run typecheck — clean
  • npm run lint — no new errors
  • npm run test — 394 pass, incl. 3 new engine tests (custom-value upsert, variable interpolation, cross-account rejection)

Notes

Text-only fields for now (field_type: 'text'); field-definition management stays admin+ to match existing custom_fields RLS. As a side benefit, this unblocks the broadcast personalization screens that already read custom_fields but had no creation path.

🤖 Generated with Claude Code

…eld action

The "Update Contact Field" automation action could only write the built-in
name/email/company columns. This wires up the existing custom_fields /
contact_custom_values tables so automations can read and update arbitrary
custom fields, and adds the missing UI to define them.

- Add a "Custom fields" manager dialog on the Contacts page (admin+ gated)
  to create / rename / delete field definitions. Inserts carry account_id.
- Load account custom fields into the automation builder's ResourcesContext
  and offer them in the Field dropdown, encoded as `custom:<id>`. A saved
  field that's since been deleted is preserved as an "(unknown field)"
  option so editing doesn't silently drop it.
- Engine: interpolate the value ({{ vars.* }} / {{ message.text }}) for all
  fields, and for `custom:<id>` verify the field belongs to the automation's
  account (defense in depth) before upserting into contact_custom_values.
- Tests: cover the custom-value upsert, variable interpolation, and
  cross-account rejection.

Closes #235

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

supabase Bot commented Jun 11, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project crxylxakpapcfziradbb because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@ArnasDon ArnasDon merged commit 91e6375 into main Jun 11, 2026
2 checks passed
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.

[feat] Support Custom Fields in "Update Contact Field" Action

1 participant