Skip to content

fix(permissions): resolve 8 bugs preventing blueprint/action permissions from importing#70

Merged
EricFernandezPort merged 2 commits into
port-experimental:mainfrom
bgilleran-port:feature/fix-permissions-import
May 28, 2026
Merged

fix(permissions): resolve 8 bugs preventing blueprint/action permissions from importing#70
EricFernandezPort merged 2 commits into
port-experimental:mainfrom
bgilleran-port:feature/fix-permissions-import

Conversation

@bgilleran-port

Copy link
Copy Markdown
Contributor

Summary

  • Fix JSON loader ignoring permissions: loadJSON() never read BlueprintPermissions or ActionPermissions keys, silently dropping all RBAC data on JSON-format imports. Now handles both PascalCase (legacy) and snake_case keys.
  • Fix JSON export key name mismatch: WriteJSON() emitted PascalCase keys (BlueprintPermissions) while every other field and the tar format used snake_case. Aligned to blueprint_permissions / action_permissions.
  • Fix false success reporting: Execute() unconditionally set Success: true after permission import, masking failures. Now sets Success: false with error count when any errors occur.
  • Fix --include flag not enforced for permissions: Permission diff ran unconditionally regardless of --include filter. Now properly gated by shouldImport("blueprint-permissions") / shouldImport("action-permissions").
  • Fix unreliable reflect.DeepEqual comparison: Permission diff used raw reflect.DeepEqual which produces false positives from JSON type mismatches. Replaced with resourcesEqual() for normalized JSON comparison.
  • Fix dry-run not reporting permission changes: Added BlueprintPermissionsUpdated and ActionPermissionsUpdated to Result struct, populated in both dry-run and real import, displayed in CLI text and JSON output.
  • Fix silent permission fetch failures in collector: Permission GET failures were silently swallowed during current-state export. Now records warnings in Data.Warnings for visibility.
  • Fix port migrate ignoring permissions entirely: exportFromSource() never collected permissions; importToTarget() never applied them. Added full blueprint/action permission collection and import pass with dry-run counts.
  • Fix CLI swallowing error details on failure: The import command exited immediately on !result.Success before printing any counts, diff analysis, or categorized errors. Now prints full results before returning error status.

Files changed (8)

File Changes
internal/modules/import_module/loader.go Added permission loading to loadJSON()
internal/modules/export/export.go Changed WriteJSON() to snake_case keys
internal/modules/import_module/import.go Conditional success, permission counts in Result/dry-run
internal/modules/import_module/diff.go --include gating + normalized comparison for permissions
internal/modules/export/collector.go Added Warnings field, record permission fetch failures
internal/modules/migrate/migrate.go Full permission collection + import + dry-run counts
internal/commands/import.go Permission counts in output, no early exit on errors
internal/modules/export/export_test.go Updated test to expect snake_case keys

Test plan

  • go vet ./... passes
  • make format applied
  • make test — all tests pass (including updated TestWriteJSON_IncludesPermissions)
  • Manual E2E: exported org with 48 blueprints, verified blueprint_permissions.json (48 entries, 156KB) and action_permissions.json (16 entries) present in tar.gz
  • Manual E2E: imported to second org, verified "Blueprint permissions updated: 1" in output with full error details visible

Made with Cursor

…ons from importing

- Fix JSON loader ignoring permissions: loadJSON() now reads BlueprintPermissions
  and ActionPermissions keys (both PascalCase and snake_case for backward compat)
- Fix JSON export key mismatch: WriteJSON() now emits snake_case keys consistent
  with tar format (blueprint_permissions, action_permissions)
- Fix false success on permission errors: Execute() now sets Success=false when
  errors are present instead of unconditionally reporting success
- Fix --include flag not enforced: permission diff now gated by shouldImport()
  for blueprint-permissions and action-permissions resource types
- Fix unreliable permission comparison: replace reflect.DeepEqual with
  resourcesEqual() for normalized JSON comparison (prevents false positives
  from type mismatches after JSON unmarshaling)
- Fix dry-run not reporting permissions: add BlueprintPermissionsUpdated and
  ActionPermissionsUpdated to Result struct, populate in dry-run and real import,
  display in CLI text and JSON output
- Fix silent permission fetch failures: collector now records warnings when
  blueprint/action permission GETs fail instead of silently skipping
- Fix migrate ignoring permissions: exportFromSource() now collects blueprint
  and action permissions; importToTarget() applies permission changes after
  resource import; dry-run includes permission counts
- Fix CLI swallowing error details: import command now prints full results
  (counts, diff analysis, categorized errors) before returning error status

Co-authored-by: Cursor <cursoragent@cursor.com>
EricFernandezPort added a commit to bgilleran-port/port-cli that referenced this pull request May 28, 2026
- fix: importPermissions now returns actual success counts (not planned
  diff size); previously BlueprintPermissionsUpdated/ActionPermissionsUpdated
  reported the full diff even when some API calls failed
- fix: gate action-permissions collection in migrate.go behind
  shouldCollect("action-permissions") to match blueprint-permissions
  behavior; previously --include actions fetched action permissions
  unconditionally
- fix: record warnings in migrate.go exportFromSource when blueprint or
  action permission fetches fail, consistent with collector.go behavior
- test: add TestImportPermissions_CountsOnlySuccesses
- test: add TestLoader_LoadJSON_LegacyPascalCasePermissions and SnakeCase
- test: add TestExportFromSource_ActionPermissionsNotCollectedWhenExcluded
- test: add TestExportFromSource_ActionPermissionsFetchFailureRecordsWarning

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: efb168341b34
@bgilleran-port bgilleran-port force-pushed the feature/fix-permissions-import branch from 062cec9 to 794793e Compare May 28, 2026 15:09
EricFernandezPort added a commit to bgilleran-port/port-cli that referenced this pull request May 28, 2026
- importPermissions returns actual success counts (not planned diff counts)
- shouldCollect gate on action-permissions loops in migrate.go
- Warnings recorded when permission fetches fail (blueprint and action)
- 5 new tests covering count tracking, exclusion gating, and failure warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 8141444f4dfe
EricFernandezPort added a commit to bgilleran-port/port-cli that referenced this pull request May 28, 2026
- importPermissions returns actual success counts (not planned diff counts)
- shouldCollect gate on action-permissions loops in migrate.go
- Warnings recorded when permission fetches fail (blueprint and action)
- 5 new tests covering count tracking, exclusion gating, and failure warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 8141444f4dfe
@EricFernandezPort EricFernandezPort force-pushed the feature/fix-permissions-import branch from 33817b2 to 3c6462c Compare May 28, 2026 15:28
- importPermissions returns actual success counts (not planned diff counts)
- shouldCollect gate on action-permissions loops in migrate.go
- Warnings recorded when permission fetches fail (blueprint and action)
- 5 new tests covering count tracking, exclusion gating, and failure warnings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 8141444f4dfe
@EricFernandezPort EricFernandezPort force-pushed the feature/fix-permissions-import branch from 3c6462c to 9714f8c Compare May 28, 2026 15:50
@EricFernandezPort EricFernandezPort merged commit 0dbf2f6 into port-experimental:main May 28, 2026
4 checks passed
bgilleran-port pushed a commit to bgilleran-port/port-cli that referenced this pull request Jun 5, 2026
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>
EricFernandezPort added a commit that referenced this pull request Jun 5, 2026
…nt fields (#75)

* fix(migrate): add topological sorting and retry for dependent blueprint 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>

* test(permissions): add test coverage for page permissions

Add missing tests for the page permissions feature introduced in PRs #70
and #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>

* test(migrate): add tests for dependent field ordering and retry

- 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>

* fix(review): apply pre-landing review fixes

- 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

* style: run make format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 55a24cc72286

---------

Co-authored-by: Bill Gilleran <bgilleran@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: EricFernandezPort <ericf@getport.io>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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