---
apiVersion: data-spec/v1
id: campaignmemberstatus-exclusive-default-flow-20260421
description: "Register a runtime flow that clears sibling IsDefault flags when a CampaignMemberStatus is saved as default"
issue: "#1495"
created: 2026-04-21
scope: production-only
status: pending
tables: [FlowDefinition, Flow]
depends_on: []
---

# CampaignMemberStatus Exclusive Default Flow

## Summary

Registers a runtime `RecordAfterSave` flow on `CampaignMemberStatus` that enforces
the Salesforce invariant behind issue `#1495`: when a status is saved with
`IsDefault=true`, sibling statuses from the same Campaign are flipped to
`IsDefault=false`.

The flow metadata source of truth lives at
`backend/internal/features/automation/testdata/campaign_member_status_flows/CampaignMemberStatus_Exclusive_Default.flow.json`.

## Changes

### 1. Upsert the `CampaignMemberStatus_Exclusive_Default` flow definition and active version

```sql
SET @flow_definition_insert_id := 'flowdef-campaignmemberstatus-exclusive-default-20260421';
SET @flow_version_insert_id := 'flowver-campaignmemberstatus-exclusive-default-v1-20260421';

INSERT INTO FlowDefinition (
  Id,
  DeveloperName,
  MasterLabel,
  Description,
  ProcessType,
  TriggerType,
  TriggerObjectOrEvent,
  ActiveVersionId,
  LatestVersionId,
  IsDeleted
) VALUES (
  @flow_definition_insert_id,
  'CampaignMemberStatus_Exclusive_Default',
  'CampaignMemberStatus Exclusive Default',
  'When a CampaignMemberStatus is saved as default, clear IsDefault on sibling statuses from the same Campaign.',
  'AutoLaunchedFlow',
  'RecordAfterSave',
  'CampaignMemberStatus',
  NULL,
  NULL,
  0
)
ON DUPLICATE KEY UPDATE
  MasterLabel = VALUES(MasterLabel),
  Description = VALUES(Description),
  ProcessType = VALUES(ProcessType),
  TriggerType = VALUES(TriggerType),
  TriggerObjectOrEvent = VALUES(TriggerObjectOrEvent),
  IsDeleted = 0,
  LastModifiedDate = CURRENT_TIMESTAMP;

SET @flow_definition_id := (
  SELECT Id
  FROM FlowDefinition
  WHERE DeveloperName = 'CampaignMemberStatus_Exclusive_Default'
  LIMIT 1
);

INSERT INTO Flow (
  Id,
  DefinitionId,
  MasterLabel,
  VersionNumber,
  Status,
  Description,
  ProcessType,
  Metadata,
  IsDeleted
) VALUES (
  @flow_version_insert_id,
  @flow_definition_id,
  'CampaignMemberStatus Exclusive Default',
  1,
  'Active',
  'When a CampaignMemberStatus is saved as default, clear IsDefault on sibling statuses from the same Campaign.',
  'AutoLaunchedFlow',
  CONVERT(FROM_BASE64('eyJhcGlWZXJzaW9uIjo2Mywic3RhdHVzIjoiQWN0aXZlIiwibGFiZWwiOiJDYW1wYWlnbk1lbWJlclN0YXR1cyBFeGNsdXNpdmUgRGVmYXVsdCIsImRlc2NyaXB0aW9uIjoiV2hlbiBhIENhbXBhaWduTWVtYmVyU3RhdHVzIGlzIHNhdmVkIGFzIGRlZmF1bHQsIGNsZWFyIElzRGVmYXVsdCBvbiBzaWJsaW5nIHN0YXR1c2VzIGZyb20gdGhlIHNhbWUgQ2FtcGFpZ24uIiwic3RhcnQiOnsibG9jYXRpb25YIjo0MCwibG9jYXRpb25ZIjowLCJjb25uZWN0b3IiOnsidGFyZ2V0UmVmZXJlbmNlIjoiQ2xlYXJTaWJsaW5nRGVmYXVsdHMifSwib2JqZWN0IjoiQ2FtcGFpZ25NZW1iZXJTdGF0dXMiLCJ0cmlnZ2VyVHlwZSI6IlJlY29yZEFmdGVyU2F2ZSIsInJlY29yZFRyaWdnZXJUeXBlIjoiQ3JlYXRlQW5kVXBkYXRlIiwiZmlsdGVyTG9naWMiOiJhbmQiLCJmaWx0ZXJzIjpbeyJmaWVsZCI6IklzRGVmYXVsdCIsIm9wZXJhdG9yIjoiRXF1YWxUbyIsInZhbHVlIjp0cnVlfV19LCJ2YXJpYWJsZXMiOlt7Im5hbWUiOiIkUmVjb3JkIiwiZGF0YVR5cGUiOiJTT2JqZWN0IiwiaXNJbnB1dCI6dHJ1ZSwiaXNPdXRwdXQiOnRydWUsIm9iamVjdFR5cGUiOiJDYW1wYWlnbk1lbWJlclN0YXR1cyJ9XSwicmVjb3JkVXBkYXRlcyI6W3sibmFtZSI6IkNsZWFyU2libGluZ0RlZmF1bHRzIiwibGFiZWwiOiJDbGVhciBzaWJsaW5nIGRlZmF1bHRzIiwibG9jYXRpb25YIjo0MCwibG9jYXRpb25ZIjoxMjAsIm9iamVjdCI6IkNhbXBhaWduTWVtYmVyU3RhdHVzIiwiZmlsdGVyTG9naWMiOiJhbmQiLCJmaWx0ZXJzIjpbeyJmaWVsZCI6IkNhbXBhaWduSWQiLCJvcGVyYXRvciI6IkVxdWFsVG8iLCJ2YWx1ZSI6eyJlbGVtZW50UmVmZXJlbmNlIjoiJFJlY29yZC5DYW1wYWlnbklkIn19LHsiZmllbGQiOiJJZCIsIm9wZXJhdG9yIjoiTm90RXF1YWxUbyIsInZhbHVlIjp7ImVsZW1lbnRSZWZlcmVuY2UiOiIkUmVjb3JkLklkIn19XSwiaW5wdXRBc3NpZ25tZW50cyI6W3siZmllbGQiOiJJc0RlZmF1bHQiLCJ2YWx1ZSI6ZmFsc2V9XX1dfQo=') USING utf8mb4),
  0
)
ON DUPLICATE KEY UPDATE
  MasterLabel = VALUES(MasterLabel),
  Status = VALUES(Status),
  Description = VALUES(Description),
  ProcessType = VALUES(ProcessType),
  Metadata = VALUES(Metadata),
  IsDeleted = 0,
  LastModifiedDate = CURRENT_TIMESTAMP;

SET @flow_version_id := (
  SELECT Id
  FROM Flow
  WHERE DefinitionId = @flow_definition_id
    AND VersionNumber = 1
  LIMIT 1
);

UPDATE FlowDefinition
SET
  ProcessType = 'AutoLaunchedFlow',
  TriggerType = 'RecordAfterSave',
  TriggerObjectOrEvent = 'CampaignMemberStatus',
  ActiveVersionId = @flow_version_id,
  LatestVersionId = @flow_version_id,
  IsDeleted = 0,
  LastModifiedDate = CURRENT_TIMESTAMP
WHERE Id = @flow_definition_id;
```

**Idempotency**: The flow definition is keyed by unique `DeveloperName`, and the
flow version is keyed by `(DefinitionId, VersionNumber)`. Re-running the spec
updates the same logical flow metadata and re-points `ActiveVersionId` /
`LatestVersionId` to the current version row.

## Rollback

```sql
DELETE f
FROM Flow f
JOIN FlowDefinition fd ON fd.Id = f.DefinitionId
WHERE fd.DeveloperName = 'CampaignMemberStatus_Exclusive_Default';

DELETE FROM FlowDefinition
WHERE DeveloperName = 'CampaignMemberStatus_Exclusive_Default';
```
