fix(transport): close 5 residual import/export fidelity holes surfaced by the round-trip guard (T8)

The Task-8 reflection round-trip suite exposed five silent-data-loss paths in
non-template entity types:
- ExternalSystemDefinition.MaxRetries/RetryDelay dropped on import Add (and Overwrite
  never updated them) — BuildExternalSystem + Overwrite branch now carry both.
- ExternalSystemMethod rows dropped on import Add — a new post-flush
  PersistAddedExternalSystemMethodsAsync pass adds them (the entity has no parent
  nav, so an Add can't cascade; idempotent vs the inline Overwrite sync).
- NotificationRecipient dropped on export — GetNotificationListByIdAsync now
  Include(Recipients) instead of a bare FindAsync.
- TemplateFolder.ParentFolderId flattened on import Add — a new
  ResolveFolderParentEdgesAsync second-pass rewire resolves ParentName→id,
  mirroring the template inheritance/composition rewires.

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-09 17:44:12 -04:00
parent e498c6e1bd
commit 7c74bbe4b5
2 changed files with 130 additions and 1 deletions
@@ -17,7 +17,12 @@ public class NotificationRepository : INotificationRepository
/// <inheritdoc />
public async Task<NotificationList?> GetNotificationListByIdAsync(int id, CancellationToken cancellationToken = default)
=> await _context.Set<NotificationList>().FindAsync(new object[] { id }, cancellationToken);
// Eager-load Recipients: single-list selection feeds the Transport exporter,
// which serializes the recipient collection — a FindAsync without the Include
// exported a recipient-less list (silent data loss).
=> await _context.Set<NotificationList>()
.Include(n => n.Recipients)
.FirstOrDefaultAsync(n => n.Id == id, cancellationToken);
/// <inheritdoc />
public async Task<IReadOnlyList<NotificationList>> GetAllNotificationListsAsync(CancellationToken cancellationToken = default)