Skip to content

feat(cli): support per-workflow deletion dependencies in transcend.yml - #402

Open
iamtheluckyest wants to merge 3 commits into
mainfrom
annalisa/wal-10452-push-per-workflow-deletion-dependencies
Open

feat(cli): support per-workflow deletion dependencies in transcend.yml#402
iamtheluckyest wants to merge 3 commits into
mainfrom
annalisa/wal-10452-push-per-workflow-deletion-dependencies

Conversation

@iamtheluckyest

@iamtheluckyest iamtheluckyest commented Aug 11, 2026

Copy link
Copy Markdown
Member

Part 1 of 2 for WAL-10452. Part 2 adds the pull side and is stacked on this branch.

What

deletion-dependencies is either a list of titles (global config only) or a list of objects (required once any per-workflow override is present). Mixing titles and objects in the same list is not allowed.

Global only:

deletion-dependencies:
  - Identity Service
  - CRM Warehouse

With overrides (whole list is objects; global becomes { titles }):

deletion-dependencies:
  - titles: [Identity Service]       # global
  - workflow: GDPR Erasure           # override for one workflow
    titles: [Identity Service, CRM Warehouse]
  - workflow: CCPA Delete
    titles: []                       # explicit empty override
  - workflow: Legacy Erasure
    reset-to-global: true            # remove the override

A workflow that isn't listed keeps whatever it already has, so pushing a global-only config never silently wipes overrides.

Blocked on

Do not merge before https://github.com/transcend-io/main/pull/46818 deploys. Push now sends dependedOnDataSilos instead of the deprecated dependedOnDataSiloTitles, and that input field is not on staging yet, so merging early would break transcend inventory push for anyone using deletion dependencies at all.

Notes

  • syncDataSiloDependencies changes signature, hence the major bump on the SDK changeset.
  • workflow maps to workflowConfigInternalName, so no ID lookup is needed on push.
  • The JSON schema files are regenerated from the codec.

Test plan

  • pnpm run --dir packages/cli test
  • pnpm run --dir packages/sdk test
  • Typecheck and build both packages
  • Push a config with a workflow override once #46818 is on staging

Made with Cursor

Entries under `deletion-dependencies` may now carry an optional `workflow`
to override the global configuration for a single erasure workflow, or
`reset-to-global: true` to drop an override. Bare title strings still work.

Pushes through the `dependedOnDataSilos` mutation input instead of the
deprecated `dependedOnDataSiloTitles`.
@linear-code

linear-code Bot commented Aug 11, 2026

Copy link
Copy Markdown

WAL-10452

@pkg-pr-new

pkg-pr-new Bot commented Aug 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@transcend-io/airgap.js-types

pnpm add https://pkg.pr.new/@transcend-io/airgap.js-types@402
yarn add https://pkg.pr.new/@transcend-io/airgap.js-types@402.tgz

@transcend-io/cli

pnpm add https://pkg.pr.new/@transcend-io/cli@402
yarn add https://pkg.pr.new/@transcend-io/cli@402.tgz

@transcend-io/design-tokens

pnpm add https://pkg.pr.new/@transcend-io/design-tokens@402
yarn add https://pkg.pr.new/@transcend-io/design-tokens@402.tgz

@transcend-io/internationalization

pnpm add https://pkg.pr.new/@transcend-io/internationalization@402
yarn add https://pkg.pr.new/@transcend-io/internationalization@402.tgz

@transcend-io/privacy-types

pnpm add https://pkg.pr.new/@transcend-io/privacy-types@402
yarn add https://pkg.pr.new/@transcend-io/privacy-types@402.tgz

@transcend-io/sdk

pnpm add https://pkg.pr.new/@transcend-io/sdk@402
yarn add https://pkg.pr.new/@transcend-io/sdk@402.tgz

@transcend-io/type-utils

pnpm add https://pkg.pr.new/@transcend-io/type-utils@402
yarn add https://pkg.pr.new/@transcend-io/type-utils@402.tgz

@transcend-io/utils

pnpm add https://pkg.pr.new/@transcend-io/utils@402
yarn add https://pkg.pr.new/@transcend-io/utils@402.tgz

@transcend-io/mcp

pnpm add https://pkg.pr.new/@transcend-io/mcp@402
yarn add https://pkg.pr.new/@transcend-io/mcp@402.tgz

@transcend-io/mcp-server-admin

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-admin@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-admin@402.tgz

@transcend-io/mcp-server-assessment

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-assessment@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-assessment@402.tgz

@transcend-io/mcp-server-base

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-base@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-base@402.tgz

@transcend-io/mcp-server-consent

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-consent@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-consent@402.tgz

@transcend-io/mcp-server-discovery

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-discovery@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-discovery@402.tgz

@transcend-io/mcp-server-docs

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-docs@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-docs@402.tgz

@transcend-io/mcp-server-dsr

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-dsr@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-dsr@402.tgz

@transcend-io/mcp-server-inventory

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-inventory@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-inventory@402.tgz

@transcend-io/mcp-server-preferences

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-preferences@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-preferences@402.tgz

@transcend-io/mcp-server-workflows

pnpm add https://pkg.pr.new/@transcend-io/mcp-server-workflows@402
yarn add https://pkg.pr.new/@transcend-io/mcp-server-workflows@402.tgz

commit: aab1463

Comment thread packages/cli/src/lib/graphql/normalizeDeletionDependencies.ts Outdated
Comment thread packages/cli/src/lib/graphql/normalizeDeletionDependencies.ts Outdated
Comment thread packages/cli/src/codecs.ts Outdated
…dencies

Reject mixed lists so global-only configs stay as title strings, while any
per-workflow override uses a full object list including global `{ titles }`.
Comment thread packages/cli/src/codecs.ts Outdated
* An empty `titles` list scoped to a workflow is an explicit override, meaning
* that workflow runs the data silo with no dependencies at all.
*/
export const DeletionDependencyGroup = t.intersection([

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this DeletionDependency instead of DeletionDependencyGroup

Comment thread packages/cli/src/codecs.ts Outdated
* Used when the list includes any per-workflow override; global dependencies
* are written as `{ titles: [...] }` in that form.
*/
export const DeletionDependencyObject = t.union([DeletionDependencyGroup, DeletionDependencyReset]);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const DeletionDependencyObject = t.union([DeletionDependencyGroup, DeletionDependencyReset]);
export const DeletionDependencyInput = t.union([DeletionDependencyGroup, DeletionDependencyReset]);

@iamtheluckyest
iamtheluckyest requested a review from a team August 11, 2026 12:28
@iamtheluckyest
iamtheluckyest marked this pull request as ready for review August 11, 2026 12:28
Comment on lines +83 to +84
// The API rejects duplicate titles, which are easy to introduce across multiple
// global `{ titles }` entries

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw if we have multiple global { titles } entries.

Comment thread packages/cli/README.md Outdated

When an erasure request runs, `deletion-dependencies` holds off deleting from a data silo until the data silos it lists have finished deleting.

Use a list of titles when there are no per-workflow overrides:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we note this as deprecated? Follow other examples in the README for deprecated fields. If there are none, let me know.

Comment thread packages/cli/README.md Outdated
- CRM Warehouse
```

Once any override is present, use a list of objects for the whole field (global deps as `{ titles }`, overrides as `{ workflow, titles }` or `{ workflow, reset-to-global: true }`). Mixing titles and objects in the same list is not allowed:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't phrase this as "Once any override is present" - this will be the new way going forward and we want to phrase it as the proper way to use the CLI.

Comment thread packages/cli/README.md

A workflow that is not listed keeps whatever configuration it already has, so pushing a config that only lists global dependencies never removes existing overrides. Use `reset-to-global: true` to remove one.

Omitting `deletion-dependencies` entirely clears the global configuration, matching how the rest of `transcend.yml` treats omitted fields.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Not for reviewers, not for Cursor] Even though it says this matches "how the rest of transcend.yml treats omitted fields" this does not seem like obvious behavior to me. If we do want to do it this way, I'm not sure that justifying it by saying "matching how the rest of transcend.yml treats omitted fields." is appropriate within the README.

Comment on lines +22 to +29
it('merges multiple global object entries into one', () => {
expect(
normalizeDeletionDependencies(
[{ titles: ['Identity Service'] }, { titles: ['CRM Warehouse'] }],
'Salesforce',
),
).to.deep.equal([{ titles: ['Identity Service', 'CRM Warehouse'] }]);
});

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should throw, not merge.

Comment on lines +31 to +38
it('deduplicates global titles across object entries', () => {
expect(
normalizeDeletionDependencies(
[{ titles: ['Identity Service'] }, { titles: ['Identity Service', 'CRM Warehouse'] }],
'Salesforce',
),
).to.deep.equal([{ titles: ['Identity Service', 'CRM Warehouse'] }]);
});

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also throw

@michaelfarrell76 michaelfarrell76 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

@jefgodesky jefgodesky left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems well-aligned at the product level, and the code LGTM, but I'll defer to @mason-hale for a proper, Waluigi-internal technical review.

@jefgodesky
jefgodesky requested a review from mason-hale August 12, 2026 19:50
Comment thread packages/cli/src/lib/graphql/normalizeDeletionDependencies.ts
Comment thread packages/cli/src/lib/graphql/normalizeDeletionDependencies.ts

@mason-hale mason-hale left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good!

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.

4 participants