SIGN IN SIGN UP

Fix custom-only attachment timeline upgrades in v2.35 (#24679)

## Context

The production v2.34 upgrade completed for 5,653 workspaces but
deterministically failed for two workspaces whose attachment target
morph groups contain only custom-object fields. The v2.34 command
correctly looked for another morph member when the canonical
`attachment.targetPerson` field was absent, but workspace-migration
validation scoped its dependency maps to the Twenty standard
application. The selected custom-app-owned field was therefore missing
from the validator's view.

This is a valid legacy metadata shape, not customer corruption.

## Changes

- add an idempotent v2.35 workspace command that repairs missing
`attachmentLinked` and `attachmentUnlinked` timeline activity types
- prefer the canonical standard attachment target relation when present;
otherwise select a valid custom morph member deterministically
- require a complete active many-to-one morph relation before using it
- preserve partial progress by creating only missing definitions
- support dry-run and skip workspaces without timeline metadata or a
valid attachment morph target
- include the application owning a timeline activity type's
soft-referenced target relation in workspace-migration dependency maps
- register the new v2.35 command module without modifying any committed
v2.34 command

The dependency-map change is required in addition to the v2.35 command:
standard upgrade sequencing encounters the failed v2.34 command before
it can execute v2.35. Loading the referenced field's application lets
the existing v2.34 command validate and allows both hosted and
self-hosted upgrades to progress normally.

## Verification

- focused Jest suites: 8 tests passed
- direct twenty-server typecheck passed with declaration output disabled
(the clean worktree's shared dependency symlink otherwise produces
unrelated non-portable declaration-path diagnostics)
- oxlint: 0 warnings, 0 errors across all seven changed TypeScript files
- oxfmt and `git diff --check` passed
- no locale catalogs or generated translation files included

## Production rollout

After deployment:

1. dry-run the v2.35 repair for the two affected workspace IDs
2. rerun the normal upgrade for only those two workspaces
3. refresh `upgrade:status` and confirm zero workspaces behind or failed
4. verify attachment linked/unlinked activities on the active
custom-only workspace

No global rerun or direct database write is required.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/24679?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
F
Félix Malfait committed
6ab1e699e9311fdef85c6569390f57e814b4b861
Parent: eecdbd0
Committed by GitHub <noreply@github.com> on 8/24/2026, 12:25:57 PM