Skip to content

fix(migrate): add topological sorting and retry for dependent blueprint fields#75

Merged
EricFernandezPort merged 5 commits into
port-experimental:mainfrom
bgilleran-port:fix/migrate-dependent-field-ordering
Jun 5, 2026
Merged

fix(migrate): add topological sorting and retry for dependent blueprint fields#75
EricFernandezPort merged 5 commits into
port-experimental:mainfrom
bgilleran-port:fix/migrate-dependent-field-ordering

Conversation

@bgilleran-port

Copy link
Copy Markdown
Contributor

Summary

  • Fixes aggregationProperties.pathFilter being silently nullified during port migrate when cross-blueprint dependencies aren't resolved in order
  • Fixes inherited ownership being dropped when ownership chains require dependency ordering
  • Brings migrate.go's dependent field handling in line with import.go's proven phased approach

Root Cause

The migrate.go module applied aggregationProperties, mirrorProperties, and ownership concurrently via runBlueprintPhase without any dependency ordering or retry logic. Meanwhile, import.go already had:

Protection import.go migrate.go (before)
Topo-sort aggProps TopologicalSortAggProps Concurrent, no ordering
Retry failed aggProps Phase 4 retry None
Topo-sort ownership TopologicalSortOwnership Concurrent, no ordering
Retry failed mirrorProps Phase 2e retry None

When the Port API receives a blueprint update where pathFilter references a relation path that doesn't exist yet, it returns 200 OK but silently nullifies the pathFilter. Similarly, inherited ownership referencing an unresolved relation path is silently dropped.

Changes

  • Phase 2c (mirrorProperties): Collect failures for retry after Phase 2d
  • Phase 2d (aggregationProperties): Use TopologicalSortAggProps to process levels sequentially
  • Phase 2c retry: Re-apply failed mirror props after agg props exist
  • Phase 2e (ownership): Use TopologicalSortOwnership to apply in dependency order
  • Phase 3 retry: Re-apply failed agg props after all phases complete

Test plan

  • make test — all existing tests pass
  • go build ./... — compiles clean
  • Manual test: port migrate with a dataset containing cross-blueprint aggregation properties with pathFilter
  • Manual test: port migrate with blueprints using inherited ownership chains
  • Verify no silent data loss in pathFilter or ownership after migrate

Made with Cursor

BGilleran522 and others added 2 commits June 5, 2026 08:36
…nt fields

The migrate module was applying aggregationProperties, mirrorProperties,
and ownership concurrently without dependency ordering, while the import
module already had these protections. This caused the Port API to silently
nullify pathFilter in aggregation properties and drop inherited ownership
when dependencies weren't ready yet.

Changes:
- Phase 2c (mirrorProperties): collect failures for retry after Phase 2d
- Phase 2d (aggregationProperties): use TopologicalSortAggProps to ensure
  cross-blueprint agg prop dependencies are applied in order
- Phase 2c retry: re-apply failed mirror props after agg props exist
- Phase 2e (ownership): use TopologicalSortOwnership to ensure inherited
  ownership chains are applied in dependency order
- Phase 3 retry: re-apply failed agg props after all other phases complete

Fixes: aggregationProperties.pathFilter being silently nullified and
inherited ownership being dropped during port migrate.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add missing tests for the page permissions feature introduced in PRs port-experimental#70
and port-experimental#71, following Eric's established test patterns:

- TestCollector_CollectsPagePermissions: positive collection verification
- TestLoader_LoadJSON_PagePermissions: JSON round-trip loading
- TestComparePermissions_DetectsExtraFieldsAsChange: diff detection
- TestComparePermissions_NormalizesStringSliceOrder: slice normalization
- Updated TestDiffResult_PermissionsFields to include PagePermissions

Co-authored-by: Cursor <cursoragent@cursor.com>
- TestImportToTarget_AggPropsAppliedInTopologicalOrder: verify cross-
  blueprint agg prop dependencies are applied in correct order
- TestImportToTarget_FailedAggPropsRetried: verify failed agg prop
  updates are retried in a second pass
- TestImportToTarget_OwnershipAppliedInTopologicalOrder: verify
  inherited ownership is applied after its dependency

Co-authored-by: Cursor <cursoragent@cursor.com>
@bgilleran-port bgilleran-port force-pushed the fix/migrate-dependent-field-ordering branch from 3c7747d to 86fb6a5 Compare June 5, 2026 12:42
EricFernandezPort and others added 2 commits June 5, 2026 18:07
- Validate that page-permissions requires pages in --include (export, import, migrate, compare)
  to prevent silent empty export and idempotency-breaking force-overwrite
- Fix invalidPermBodyPattern regex: add (?s) flag so multi-line JSON 422 bodies are matched
- Fix migrate errors section mislabeled as "Warnings:" → "Errors:"
- Add blueprint_permissions_updated and action_permissions_updated to migrate JSON output
- Strengthen import_test retryBody nil guard: use t.Fatal instead of silent skip
- Update ValidationWarning.Type comment to include "orphaned_permission_field"
- Rewrite CHANGELOG 0.2.19 entry to describe features and fixes, not test names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: a0896ec6ff15
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 55a24cc72286
@EricFernandezPort EricFernandezPort merged commit c7d3054 into port-experimental:main Jun 5, 2026
4 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.

3 participants