Skip to content

SMOODEV-2644: th api crm assoc — CRM entity associations from the CLI#218

Merged
brentrager merged 2 commits into
mainfrom
SMOODEV-2644-th-crm-assoc
Jul 15, 2026
Merged

SMOODEV-2644: th api crm assoc — CRM entity associations from the CLI#218
brentrager merged 2 commits into
mainfrom
SMOODEV-2644-th-crm-assoc

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

The CRM now models entity-to-entity associations (contacts ↔ companies ↔ deals ↔ tasks/proposals/funnels/custom objects) beyond the legacy single FKs, but th had no way to create, inspect, or remove them. SMOODEV-2644.

Solution

Adds a th api crm assoc command group (aliases: associations, association, links) plus thin sugar wrappers over the legacy FKs — all in crates/smooth-cli/src/smooai/crm.rs, matching the file's existing clap-derive + org-resolution + UserClient + output-helper style.

assoc subcommands — entities are TYPE:REF operands (contact:jane@x.com, company:Acme, deal:"Big Deal", or task:<uuid>):

  • link <FROM> <TO> [--as <type>] [--label <text>] — resolve both refs, POST the association
  • unlink <FROM> <TO> [--as <type>] — GET the matching row(s), DELETE; errors listing the types when several link the pair and --as is absent
  • list <ENTITY> [--type <otherType>] [--as <assocType>] [--json] — readable table (type, label, other entity + sublabel, id)
  • set-type <ASSOCIATION_ID> <type> / set-label <ASSOCIATION_ID> <text> — PATCH by id

contact/company/deal refs resolve by name/email/title via the existing resolve_*_id helpers (uuid passthrough); task/proposal/funnel/custom_object accept a uuid only (clear error otherwise, since no resolver exists yet).

Sugar wrappers (reuse the simpler legacy PATCH/association endpoints; each takes none/- to clear):

  • contacts set-company <CONTACT> <COMPANY|none> — PATCH companyId
  • deals set-contact <DEAL> <CONTACT|none> / deals set-company <DEAL> <COMPANY|none> — PATCH contactId/companyId
  • companies set-parent <COMPANY> <PARENT|none> — POST a parent association (clearing = find + DELETE the parent row)

Verification

  • cargo test -p smooai-smooth-cli — 19 passing, including 5 new unit tests for the pure TYPE:REF parser / type normalization / clear-token sentinels
  • cargo fmt -- --check clean; cargo clippy introduces no new denied lints (pedantic/nursery stay advisory per the repo's CI policy)
  • th api crm assoc --help and each sugar subcommand's --help parse and render as expected
  • Added a @smooai/smooth minor changeset

API dependency: the association endpoints land with SmooAI/smooai#3068 (native api-prime). Built against that contract — the commands 404 against prod until it deploys.

🤖 Generated with Claude Code

Adds `th api crm assoc link/unlink/list/set-type/set-label`, taking
entities as TYPE:REF operands (contact:jane@x.com, company:Acme,
deal:"Big Deal", task:<uuid>). contact/company/deal refs resolve by
name/email/title via the existing resolvers; other types accept a uuid.
Also adds thin sugar over the legacy FKs: contacts set-company, deals
set-contact, deals set-company, companies set-parent (each takes
none/- to clear).

Backed by the native api-prime associations endpoints from
SmooAI/smooai#3068 — the commands 404 against prod until that deploys.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnpE2VsHBgEq5XNQuXNLse
@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cb6f46

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@smooai/smooth Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

…ulary

The associations API returns direction as "source"/"target" (not
"outgoing"/"incoming"). Parent links are stored child—parent→parent, so
querying the child returns its parent row with direction=="source".
Extract the predicate to a pure, unit-tested `parent_row_points_up` and
match on "source".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnpE2VsHBgEq5XNQuXNLse
@brentrager brentrager merged commit 50f1aa5 into main Jul 15, 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.

1 participant