src-auth-perms-sync 0.5.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.github/workflows/validate.yml +7 -2
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.gitignore +2 -5
- src_auth_perms_sync-0.7.0/.markdownlint-cli2.yaml +15 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/AGENTS.md +12 -3
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/PKG-INFO +54 -6
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/README.md +53 -5
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/TODO.md +1 -11
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/engineering-requests.md +9 -9
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/mapping-efficiency.md +2 -2
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/memory-efficiency.md +3 -3
- src_auth_perms_sync-0.7.0/examples/import.py +63 -0
- src_auth_perms_sync-0.7.0/package-lock.json +1377 -0
- src_auth_perms_sync-0.7.0/package.json +11 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/pyproject.toml +4 -1
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/__init__.py +2 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/cli.py +152 -34
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/orgs/command.py +2 -2
- src_auth_perms_sync-0.7.0/src/src_auth_perms_sync/orgs/queries.py +90 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/orgs/sync.py +502 -97
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/orgs/types.py +6 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/command.py +106 -30
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/full_set.py +3 -2
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/mapping.py +1 -1
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/maps.py +22 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/queries.py +39 -5
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/sourcegraph.py +6 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/workflow.py +16 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/queries.py +10 -1
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/run_context.py +8 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/saml_groups.py +92 -4
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/sourcegraph.py +4 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/types.py +24 -0
- src_auth_perms_sync-0.7.0/tests/confusables.py +215 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/case_runner.py +206 -6
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/set-users-sync-saml-orgs-noop/before.json +108 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/set-users-sync-saml-orgs-noop/maps.yaml +8 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/after.json +109 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/before.json +104 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/maps.yaml +8 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/sync-saml-orgs-full-cleanup/after.json +111 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/sync-saml-orgs-full-cleanup/before.json +106 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/sync-saml-orgs-users-scoped/after.json +113 -0
- src_auth_perms_sync-0.7.0/tests/e2e/fixtures/sync-saml-orgs-users-scoped/before.json +107 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/test_local_cases.py +84 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/run.py +5 -1
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/tests.yaml +916 -27
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_cli_config.py +63 -13
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_command_files.py +1 -1
- src_auth_perms_sync-0.7.0/tests/unit/test_confusables.py +35 -0
- src_auth_perms_sync-0.7.0/tests/unit/test_mapping_rules.py +116 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_module_api.py +57 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_saml_groups.py +86 -0
- src_auth_perms_sync-0.5.0/.env.example +0 -36
- src_auth_perms_sync-0.5.0/.markdownlint-cli2.yaml +0 -9
- src_auth_perms_sync-0.5.0/dev/PLAN.md +0 -458
- src_auth_perms_sync-0.5.0/src/src_auth_perms_sync/orgs/queries.py +0 -44
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.github/CODEOWNERS +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.github/workflows/ci.yml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.github/workflows/release.yml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/.python-version +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/LICENSE +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/SECURITY.md +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/audit-dead-code.md +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/hooks/pre-commit +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/memory-efficiency-analyze.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/memory-efficiency-generate.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/memory-efficiency-monitor-sourcegraph.sh +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/update-python-versions.md +0 -0
- /src_auth_perms_sync-0.5.0/maps-example.yaml → /src_auth_perms_sync-0.7.0/examples/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/renovate.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/__main__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/orgs/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/apply.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/restore.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/snapshot.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/permissions/types.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/backups.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/src/src_auth_perms_sync/shared/site_config.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/README.md +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-by-email-and-list/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-by-email-and-list/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-by-email-and-list/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-preserves-existing/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-preserves-existing/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/add-users-preserves-existing/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/and-filters-intersect/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/and-filters-intersect/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/and-filters-intersect/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/empty-maps-noop/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/empty-maps-noop/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-dry-run/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-unions/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-unions/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-unions/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-with-backup/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-with-backup/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/full-overwrite-with-backup/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/get-full-snapshot/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/get-repos-without-explicit-perms/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/get-user-grants/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-bad-regex/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-bad-regex/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-missing-repos-section/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-missing-repos-section/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-restore-wrong-schema-version/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-restore-wrong-schema-version/snapshot.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-created-after-date/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-created-after-date/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-repos-created-after-date/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-repos-created-after-date/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-unknown-repo/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-unknown-repo/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-unknown-user/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-set-unknown-user/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-unknown-selector-field/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/invalid-unknown-selector-field/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/match-provider-and-host-fields/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/match-provider-and-host-fields/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/match-provider-and-host-fields/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/no-match-noop/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/no-match-noop/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/regex-filters-scope/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/regex-filters-scope/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/regex-filters-scope/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-applies-snapshot/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-applies-snapshot/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-applies-snapshot/snapshot.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-dry-run-noop/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-dry-run-noop/snapshot.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-missing-file/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-restores-pending/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-restores-pending/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/restore-restores-pending/snapshot.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-filter/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-filter/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-filter/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-live/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-live/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/saml-group-live/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-created-after-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-created-after-temp-user/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-created-after-temp-user/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-created-after-temp-user/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-full-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after-noop/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after-noop/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-created-after-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-filter/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-filter/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-filter/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-repos-without-perms-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-created-after/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-created-after/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-created-after/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-created-after-noop/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-created-after-noop/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/after.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/before.json +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/e2e/fixtures/set-users-without-perms-sync-saml-orgs-dry-run/maps.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/integration/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/integration/test_cli_entrypoint.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/setup.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/setup.yaml +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/__init__.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_apply.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_backups.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_command_additive.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_maps.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_permissions_sourcegraph.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_restore.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/tests/unit/test_snapshot.py +0 -0
- {src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/uv.lock +0 -0
|
@@ -127,6 +127,7 @@ jobs:
|
|
|
127
127
|
runs-on: ubuntu-24.04
|
|
128
128
|
env:
|
|
129
129
|
MARKDOWNLINT_CLI2_VERSION: "0.22.1"
|
|
130
|
+
MARKDOWNLINT_RELATIVE_LINKS_VERSION: "5.1.0"
|
|
130
131
|
|
|
131
132
|
steps:
|
|
132
133
|
- name: Check out code
|
|
@@ -139,10 +140,14 @@ jobs:
|
|
|
139
140
|
uses: actions/cache@v5
|
|
140
141
|
with:
|
|
141
142
|
path: ~/.npm
|
|
142
|
-
key: npm-${{ runner.os }}-markdownlint-cli2-${{ env.MARKDOWNLINT_CLI2_VERSION }}
|
|
143
|
+
key: npm-${{ runner.os }}-markdownlint-cli2-${{ env.MARKDOWNLINT_CLI2_VERSION }}-relative-links-${{ env.MARKDOWNLINT_RELATIVE_LINKS_VERSION }}
|
|
143
144
|
|
|
144
145
|
- name: Lint Markdown
|
|
145
|
-
run:
|
|
146
|
+
run: >
|
|
147
|
+
npx --yes
|
|
148
|
+
-p "markdownlint-cli2@${MARKDOWNLINT_CLI2_VERSION}"
|
|
149
|
+
-p "markdownlint-rule-relative-links@${MARKDOWNLINT_RELATIVE_LINKS_VERSION}"
|
|
150
|
+
markdownlint-cli2
|
|
146
151
|
|
|
147
152
|
python:
|
|
148
153
|
name: Validate Python
|
|
@@ -7,13 +7,13 @@ __pycache__
|
|
|
7
7
|
.pytest_cache
|
|
8
8
|
.ruff_cache
|
|
9
9
|
.venv
|
|
10
|
+
node_modules/
|
|
10
11
|
*.env*
|
|
11
12
|
*.gql
|
|
12
13
|
*.py[cod]
|
|
13
14
|
*.py[oc]
|
|
14
15
|
*.swp
|
|
15
16
|
*.tsv
|
|
16
|
-
*.yaml
|
|
17
17
|
build/
|
|
18
18
|
dist/
|
|
19
19
|
logs*/
|
|
@@ -22,7 +22,4 @@ src-auth-perms-sync-runs/
|
|
|
22
22
|
wheels/
|
|
23
23
|
|
|
24
24
|
# Allow
|
|
25
|
-
|
|
26
|
-
!.markdownlint-cli2.yaml
|
|
27
|
-
!maps-example.yaml
|
|
28
|
-
!tests/**/*.yaml
|
|
25
|
+
!examples/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
globs:
|
|
2
|
+
- "**/*.md"
|
|
3
|
+
ignores:
|
|
4
|
+
- ".venv/**"
|
|
5
|
+
- "build/**"
|
|
6
|
+
- "dist/**"
|
|
7
|
+
- "node_modules/**"
|
|
8
|
+
modulePaths:
|
|
9
|
+
- "./node_modules"
|
|
10
|
+
customRules:
|
|
11
|
+
- markdownlint-rule-relative-links
|
|
12
|
+
config:
|
|
13
|
+
MD013:
|
|
14
|
+
line_length: 100
|
|
15
|
+
relative-links: true
|
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
actionlint
|
|
13
13
|
|
|
14
14
|
### Markdown files
|
|
15
|
-
npx --yes markdownlint-cli2@0.22.1
|
|
15
|
+
npx --yes -p markdownlint-cli2@0.22.1 -p markdownlint-rule-relative-links@5.1.0 markdownlint-cli2
|
|
16
|
+
|
|
17
|
+
### Confusable Unicode characters in non-Python files
|
|
18
|
+
# (ruff RUF001-RUF003 covers Python strings/comments/docstrings)
|
|
19
|
+
uv run python tests/confusables.py
|
|
16
20
|
|
|
17
21
|
### Python files
|
|
18
22
|
|
|
@@ -37,7 +41,8 @@ own checks.
|
|
|
37
41
|
|
|
38
42
|
```bash
|
|
39
43
|
# Fast, no network (also what the pre-commit hook runs):
|
|
40
|
-
# lint, format, pyright, unit + fixture
|
|
44
|
+
# lint, format, pyright, confusable-character scan, unit + fixture
|
|
45
|
+
# tests, CLI rejection matrix,
|
|
41
46
|
# randomized permission invariants
|
|
42
47
|
uv run tests/run.py
|
|
43
48
|
|
|
@@ -97,7 +102,7 @@ uv run ruff format --check src/src_auth_perms_sync/ tests/
|
|
|
97
102
|
uv run pyright
|
|
98
103
|
uv run python -m unittest discover -s tests
|
|
99
104
|
uv run src-auth-perms-sync --help
|
|
100
|
-
npx --yes markdownlint-cli2@0.22.1
|
|
105
|
+
npx --yes -p markdownlint-cli2@0.22.1 -p markdownlint-rule-relative-links@5.1.0 markdownlint-cli2
|
|
101
106
|
uv build --wheel --sdist --out-dir /tmp/src-auth-perms-sync-release-check --no-create-gitignore
|
|
102
107
|
rm -rf /tmp/src-auth-perms-sync-release-check
|
|
103
108
|
```
|
|
@@ -252,6 +257,10 @@ removed names like `ev`, `ex`, `exc`, `cfg`, `conn`, `resp`, `fn`,
|
|
|
252
257
|
|
|
253
258
|
Short names that ARE acceptable (don't rewrite these on sight):
|
|
254
259
|
|
|
260
|
+
- **Established domain abbreviations**: `org` / `orgs` for Sourcegraph
|
|
261
|
+
organizations, matching the `sync-saml-orgs` command, the `orgs/`
|
|
262
|
+
package, and the `sync_saml_orgs` config field. Do not expand these
|
|
263
|
+
back to `organization(s)` in identifiers.
|
|
255
264
|
- **TypedDict / dataclass fields that mirror the wire format**: `id`,
|
|
256
265
|
`url`, `kind` on `ExternalService` etc. These match GraphQL/JSON
|
|
257
266
|
keys and renaming would break the contract.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: src-auth-perms-sync
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Set Sourcegraph permissions from authentication provider data
|
|
5
5
|
Project-URL: Homepage, https://github.com/sourcegraph/src-auth-perms-sync
|
|
6
6
|
Project-URL: Issues, https://github.com/sourcegraph/src-auth-perms-sync/issues
|
|
@@ -170,11 +170,30 @@ for provider in get_result.auth_providers:
|
|
|
170
170
|
for code_host in get_result.code_hosts:
|
|
171
171
|
...
|
|
172
172
|
|
|
173
|
+
# Mapping rules can be passed in memory instead of a maps YAML file —
|
|
174
|
+
# same structure and validation as maps.yaml entries:
|
|
175
|
+
rules: list[src.MappingRule] = [
|
|
176
|
+
{
|
|
177
|
+
"name": "Map 1",
|
|
178
|
+
"users": {"usernameRegexes": [".*"]},
|
|
179
|
+
"repos": {"codeHostConnection": {"kind": "GITHUB"}},
|
|
180
|
+
},
|
|
181
|
+
]
|
|
182
|
+
result = src.Set(config, mapping_rules=rules)
|
|
183
|
+
# When files are enabled, the rules actually used are written into the
|
|
184
|
+
# run directory for auditability. Snapshots still gate apply=True unless
|
|
185
|
+
# no_files=True and no_backup=True are both set explicitly.
|
|
186
|
+
|
|
173
187
|
# Other command wrappers:
|
|
174
188
|
# result = src.Restore(config)
|
|
175
189
|
# result = src.SyncSamlOrgs(config)
|
|
176
190
|
```
|
|
177
191
|
|
|
192
|
+
The import API does not read environment variables or `.env` files on its
|
|
193
|
+
own — those apply to the CLI only. Pass every value explicitly to
|
|
194
|
+
`src.Config(...)` (read `os.environ` yourself if you want env-driven
|
|
195
|
+
configuration, as the example above does).
|
|
196
|
+
|
|
178
197
|
Module mode never touches your `logging` handlers or the root logger — your
|
|
179
198
|
application's logging config stays in charge. To see progress messages:
|
|
180
199
|
|
|
@@ -203,7 +222,7 @@ snapshots that make `--apply` reversible.
|
|
|
203
222
|
- Environment variables (CLI), or src.Config args (Python import)
|
|
204
223
|
- `SRC_ENDPOINT`
|
|
205
224
|
- `SRC_ACCESS_TOKEN` from a user with site-admin perms
|
|
206
|
-
- See [.env.example](
|
|
225
|
+
- See [.env.example](./examples/.env.example)
|
|
207
226
|
|
|
208
227
|
- YAML maps file
|
|
209
228
|
- By default: `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
|
|
@@ -217,7 +236,7 @@ snapshots that make `--apply` reversible.
|
|
|
217
236
|
- Each mapping rule takes
|
|
218
237
|
- A map of filters for users
|
|
219
238
|
- A map of filters for repos
|
|
220
|
-
- See [maps
|
|
239
|
+
- See [maps.yaml](./examples/maps.yaml)
|
|
221
240
|
- An empty maps.yaml file is created for you on the first `get` run
|
|
222
241
|
|
|
223
242
|
## Usage: Permission sync
|
|
@@ -237,7 +256,7 @@ snapshots that make `--apply` reversible.
|
|
|
237
256
|
|
|
238
257
|
- Edit `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
|
|
239
258
|
- Add mapping rules under the `maps:` top level key
|
|
240
|
-
- See [maps
|
|
259
|
+
- See [maps.yaml](./examples/maps.yaml)
|
|
241
260
|
|
|
242
261
|
3. **Set: Dry run**
|
|
243
262
|
|
|
@@ -278,7 +297,7 @@ snapshots that make `--apply` reversible.
|
|
|
278
297
|
1. **Get user and org metadata**
|
|
279
298
|
|
|
280
299
|
```bash
|
|
281
|
-
src-auth-perms-sync sync-saml-orgs
|
|
300
|
+
src-auth-perms-sync sync-saml-orgs --full
|
|
282
301
|
```
|
|
283
302
|
|
|
284
303
|
- Queries the Sourcegraph instance for auth providers, users, users' SAML groups, and orgs
|
|
@@ -287,12 +306,41 @@ snapshots that make `--apply` reversible.
|
|
|
287
306
|
2. **Apply org sync**
|
|
288
307
|
|
|
289
308
|
```bash
|
|
290
|
-
src-auth-perms-sync sync-saml-orgs --apply
|
|
309
|
+
src-auth-perms-sync sync-saml-orgs --full --apply
|
|
291
310
|
```
|
|
292
311
|
|
|
293
312
|
- Creates the orgs if they don't exist, and sync the members from the SAML groups to the orgs
|
|
294
313
|
- `--sync-saml-orgs` can also be added to a `set` run, to run both at the same time
|
|
295
314
|
|
|
315
|
+
3. **Scoped org sync for selected users**
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
src-auth-perms-sync sync-saml-orgs --users alice,bob
|
|
319
|
+
src-auth-perms-sync sync-saml-orgs --created-after 2026-06-01
|
|
320
|
+
src-auth-perms-sync sync-saml-orgs --users-without-explicit-perms
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
- Same user filters as `get` and `set`; a mode flag is required — there
|
|
324
|
+
is no bare `sync-saml-orgs`
|
|
325
|
+
|
|
326
|
+
### Org sync behavior
|
|
327
|
+
|
|
328
|
+
- Org names are `synced-<configID>-<group name>` (non-alphanumeric characters
|
|
329
|
+
become `-`). The `synced-` prefix marks tool ownership: the sync only ever
|
|
330
|
+
modifies orgs whose name carries it, so manually created orgs are never touched.
|
|
331
|
+
- The org sync mode is always explicit — no surprises:
|
|
332
|
+
- **Full** (`sync-saml-orgs --full`, or `set --full` / `--repos*`
|
|
333
|
+
`--sync-saml-orgs`): converges every synced org against all users. A synced
|
|
334
|
+
org whose SAML group disappeared has all members removed, but the org itself
|
|
335
|
+
is kept (its settings survive in case the group comes back).
|
|
336
|
+
- **Scoped** (user filters on `sync-saml-orgs`, or `set --users` /
|
|
337
|
+
`--users-without-explicit-perms` / `--created-after` with
|
|
338
|
+
`--sync-saml-orgs`): syncs org membership for exactly the selected users —
|
|
339
|
+
per-user additions AND removals, computed from each user's own SAML
|
|
340
|
+
assertion and org list. Other users' memberships never change, and no full
|
|
341
|
+
user scan or org member listing is needed, so API traffic stays
|
|
342
|
+
proportional to the selection.
|
|
343
|
+
|
|
296
344
|
## Options
|
|
297
345
|
|
|
298
346
|
Run `src-auth-perms-sync --help` for options
|
|
@@ -147,11 +147,30 @@ for provider in get_result.auth_providers:
|
|
|
147
147
|
for code_host in get_result.code_hosts:
|
|
148
148
|
...
|
|
149
149
|
|
|
150
|
+
# Mapping rules can be passed in memory instead of a maps YAML file —
|
|
151
|
+
# same structure and validation as maps.yaml entries:
|
|
152
|
+
rules: list[src.MappingRule] = [
|
|
153
|
+
{
|
|
154
|
+
"name": "Map 1",
|
|
155
|
+
"users": {"usernameRegexes": [".*"]},
|
|
156
|
+
"repos": {"codeHostConnection": {"kind": "GITHUB"}},
|
|
157
|
+
},
|
|
158
|
+
]
|
|
159
|
+
result = src.Set(config, mapping_rules=rules)
|
|
160
|
+
# When files are enabled, the rules actually used are written into the
|
|
161
|
+
# run directory for auditability. Snapshots still gate apply=True unless
|
|
162
|
+
# no_files=True and no_backup=True are both set explicitly.
|
|
163
|
+
|
|
150
164
|
# Other command wrappers:
|
|
151
165
|
# result = src.Restore(config)
|
|
152
166
|
# result = src.SyncSamlOrgs(config)
|
|
153
167
|
```
|
|
154
168
|
|
|
169
|
+
The import API does not read environment variables or `.env` files on its
|
|
170
|
+
own — those apply to the CLI only. Pass every value explicitly to
|
|
171
|
+
`src.Config(...)` (read `os.environ` yourself if you want env-driven
|
|
172
|
+
configuration, as the example above does).
|
|
173
|
+
|
|
155
174
|
Module mode never touches your `logging` handlers or the root logger — your
|
|
156
175
|
application's logging config stays in charge. To see progress messages:
|
|
157
176
|
|
|
@@ -180,7 +199,7 @@ snapshots that make `--apply` reversible.
|
|
|
180
199
|
- Environment variables (CLI), or src.Config args (Python import)
|
|
181
200
|
- `SRC_ENDPOINT`
|
|
182
201
|
- `SRC_ACCESS_TOKEN` from a user with site-admin perms
|
|
183
|
-
- See [.env.example](
|
|
202
|
+
- See [.env.example](./examples/.env.example)
|
|
184
203
|
|
|
185
204
|
- YAML maps file
|
|
186
205
|
- By default: `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
|
|
@@ -194,7 +213,7 @@ snapshots that make `--apply` reversible.
|
|
|
194
213
|
- Each mapping rule takes
|
|
195
214
|
- A map of filters for users
|
|
196
215
|
- A map of filters for repos
|
|
197
|
-
- See [maps
|
|
216
|
+
- See [maps.yaml](./examples/maps.yaml)
|
|
198
217
|
- An empty maps.yaml file is created for you on the first `get` run
|
|
199
218
|
|
|
200
219
|
## Usage: Permission sync
|
|
@@ -214,7 +233,7 @@ snapshots that make `--apply` reversible.
|
|
|
214
233
|
|
|
215
234
|
- Edit `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
|
|
216
235
|
- Add mapping rules under the `maps:` top level key
|
|
217
|
-
- See [maps
|
|
236
|
+
- See [maps.yaml](./examples/maps.yaml)
|
|
218
237
|
|
|
219
238
|
3. **Set: Dry run**
|
|
220
239
|
|
|
@@ -255,7 +274,7 @@ snapshots that make `--apply` reversible.
|
|
|
255
274
|
1. **Get user and org metadata**
|
|
256
275
|
|
|
257
276
|
```bash
|
|
258
|
-
src-auth-perms-sync sync-saml-orgs
|
|
277
|
+
src-auth-perms-sync sync-saml-orgs --full
|
|
259
278
|
```
|
|
260
279
|
|
|
261
280
|
- Queries the Sourcegraph instance for auth providers, users, users' SAML groups, and orgs
|
|
@@ -264,12 +283,41 @@ snapshots that make `--apply` reversible.
|
|
|
264
283
|
2. **Apply org sync**
|
|
265
284
|
|
|
266
285
|
```bash
|
|
267
|
-
src-auth-perms-sync sync-saml-orgs --apply
|
|
286
|
+
src-auth-perms-sync sync-saml-orgs --full --apply
|
|
268
287
|
```
|
|
269
288
|
|
|
270
289
|
- Creates the orgs if they don't exist, and sync the members from the SAML groups to the orgs
|
|
271
290
|
- `--sync-saml-orgs` can also be added to a `set` run, to run both at the same time
|
|
272
291
|
|
|
292
|
+
3. **Scoped org sync for selected users**
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
src-auth-perms-sync sync-saml-orgs --users alice,bob
|
|
296
|
+
src-auth-perms-sync sync-saml-orgs --created-after 2026-06-01
|
|
297
|
+
src-auth-perms-sync sync-saml-orgs --users-without-explicit-perms
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
- Same user filters as `get` and `set`; a mode flag is required — there
|
|
301
|
+
is no bare `sync-saml-orgs`
|
|
302
|
+
|
|
303
|
+
### Org sync behavior
|
|
304
|
+
|
|
305
|
+
- Org names are `synced-<configID>-<group name>` (non-alphanumeric characters
|
|
306
|
+
become `-`). The `synced-` prefix marks tool ownership: the sync only ever
|
|
307
|
+
modifies orgs whose name carries it, so manually created orgs are never touched.
|
|
308
|
+
- The org sync mode is always explicit — no surprises:
|
|
309
|
+
- **Full** (`sync-saml-orgs --full`, or `set --full` / `--repos*`
|
|
310
|
+
`--sync-saml-orgs`): converges every synced org against all users. A synced
|
|
311
|
+
org whose SAML group disappeared has all members removed, but the org itself
|
|
312
|
+
is kept (its settings survive in case the group comes back).
|
|
313
|
+
- **Scoped** (user filters on `sync-saml-orgs`, or `set --users` /
|
|
314
|
+
`--users-without-explicit-perms` / `--created-after` with
|
|
315
|
+
`--sync-saml-orgs`): syncs org membership for exactly the selected users —
|
|
316
|
+
per-user additions AND removals, computed from each user's own SAML
|
|
317
|
+
assertion and org list. Other users' memberships never change, and no full
|
|
318
|
+
user scan or org member listing is needed, so API traffic stays
|
|
319
|
+
proportional to the selection.
|
|
320
|
+
|
|
273
321
|
## Options
|
|
274
322
|
|
|
275
323
|
Run `src-auth-perms-sync --help` for options
|
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
# TODO
|
|
2
2
|
|
|
3
|
-
## Follow-up: in-memory mapping rules for Set (PLAN.md Track A Phase A4)
|
|
4
|
-
|
|
5
|
-
The rest of [PLAN.md](./PLAN.md) is implemented (src-py-lib v0.3.0 +
|
|
6
|
-
the consumer refactor-logging-and-files PR). The one deliberately
|
|
7
|
-
deferred piece, marked optional in the plan: let module callers pass
|
|
8
|
-
parsed mapping rules to `Set` instead of a maps file, so the full
|
|
9
|
-
get → assemble → dry-run loop never touches disk. Snapshots must stay
|
|
10
|
-
on disk for `--apply` (reversibility invariant); `no_files` + `apply`
|
|
11
|
-
must keep requiring `no_backup`.
|
|
12
|
-
|
|
13
3
|
## High priority: Remote trigger on demand
|
|
14
4
|
|
|
15
5
|
- Sourcegraph webhook for new user coming in v7.4.0
|
|
@@ -88,7 +78,7 @@ If/when we revisit:
|
|
|
88
78
|
|
|
89
79
|
Phase 1 now avoids per-repo username sets for non-overlapping full-set maps.
|
|
90
80
|
If memory remains too high after re-measuring, implement the Phase 2 grouped
|
|
91
|
-
plan in [mapping-efficiency.md](./mapping-efficiency.md): combine map-entry
|
|
81
|
+
plan in [mapping-efficiency.md](./memory-analysis/mapping-efficiency.md): combine map-entry
|
|
92
82
|
overlays into final groups of repos that share the same desired username tuple.
|
|
93
83
|
|
|
94
84
|
## Low priority: Expand group-membership filters beyond SAML
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Engineering requests
|
|
2
2
|
|
|
3
3
|
Use this when opening Sourcegraph Engineering issues from memory-efficiency
|
|
4
|
-
evidence. Capture steps stay in [memory-efficiency.md](./memory-efficiency.md);
|
|
4
|
+
evidence. Capture steps stay in [memory-efficiency.md](./memory-analysis/memory-efficiency.md);
|
|
5
5
|
this file keeps the request-ready problem statement, evidence, proposed API
|
|
6
6
|
shape, and copy/paste issue text.
|
|
7
7
|
|
|
@@ -85,16 +85,16 @@ small `set` command. Instance: single `pgsql-0` on an 8-core node.
|
|
|
85
85
|
|
|
86
86
|
Observed during the concurrent captures:
|
|
87
87
|
|
|
88
|
-
- `pgsql-0` CPU (`kubectl top`): 7,636
|
|
89
|
-
- `frontend` / `gitserver` CPU: 124
|
|
88
|
+
- `pgsql-0` CPU (`kubectl top`): 7,636-7,683 millicores of 8,000 (saturated).
|
|
89
|
+
- `frontend` / `gitserver` CPU: 124-138m / 2-3m (idle bystanders).
|
|
90
90
|
- `pg_stat_activity`: 29 active statements, all
|
|
91
91
|
`permsStore.ListUserPermissions`, **zero wait events** — pure CPU, no lock
|
|
92
92
|
contention.
|
|
93
93
|
- `pg_stat_statements`: `permsStore.ListUserPermissions` at 24,026 calls,
|
|
94
94
|
27,635.6s total, 1,150ms mean.
|
|
95
|
-
- Per-client capture throughput: 23 users/sec solo → 2
|
|
95
|
+
- Per-client capture throughput: 23 users/sec solo → 2-4 users/sec at 4-way
|
|
96
96
|
concurrency.
|
|
97
|
-
- Aggregate throughput: 8
|
|
97
|
+
- Aggregate throughput: 8-16 users/sec at 4-way — **below the 23 users/sec a
|
|
98
98
|
single client achieves alone** (negative scaling).
|
|
99
99
|
- ALB (CloudWatch): no 5xx, no rejected connections — the edge and frontend
|
|
100
100
|
are not the bottleneck.
|
|
@@ -104,7 +104,7 @@ Observed during the concurrent captures:
|
|
|
104
104
|
Implications for the engineering request:
|
|
105
105
|
|
|
106
106
|
- A single per-user `permissionsInfo.repositories(source: API)` read costs
|
|
107
|
-
roughly 0.3
|
|
107
|
+
roughly 0.3-0.4s of Postgres CPU at this state size (1,150ms mean execution
|
|
108
108
|
under contention), so one operator at modest parallelism can saturate the
|
|
109
109
|
database by itself, and two concurrent operators degrade each other below
|
|
110
110
|
single-operator throughput.
|
|
@@ -112,7 +112,7 @@ Implications for the engineering request:
|
|
|
112
112
|
client read timeout, retries re-run the same expensive queries, adding load
|
|
113
113
|
exactly when the database is saturated.
|
|
114
114
|
- A bulk read API (one query returning explicit grants for many users or for
|
|
115
|
-
whole repos) would replace ~10,000
|
|
115
|
+
whole repos) would replace ~10,000 x ~1s statements per capture with a
|
|
116
116
|
single scan, and would also make concurrent operators viable.
|
|
117
117
|
|
|
118
118
|
## Sourcegraph codepath findings
|
|
@@ -142,7 +142,7 @@ from `github.com/sourcegraph/sourcegraph`:
|
|
|
142
142
|
## Presence-check resolver internals (2026-06-12)
|
|
143
143
|
|
|
144
144
|
Measured on the 10k-user / 50k-repo test instance, the presence probe
|
|
145
|
-
`User.permissionsInfo.repositories(source: API, first: 1)` costs 225
|
|
145
|
+
`User.permissionsInfo.repositories(source: API, first: 1)` costs 225-350ms of
|
|
146
146
|
server work per user, and alias batching barely helps (21,004 single-user
|
|
147
147
|
probes averaged 351.6ms; 25-user batches averaged 5,616ms ≈ 224.7ms/user). A
|
|
148
148
|
single `set --users-without-explicit-perms` run probing all 10,002 users at
|
|
@@ -180,7 +180,7 @@ Client-side mitigation shipped in `src-auth-perms-sync` (2026-06-12):
|
|
|
180
180
|
locally BEFORE probing, so probes scale with the rule-matched user count
|
|
181
181
|
instead of the instance's user count, and user hydration runs as aliased
|
|
182
182
|
25-user batches instead of one `UserByID` request per user. The remaining
|
|
183
|
-
inherent cost — ~225ms
|
|
183
|
+
inherent cost — ~225ms x probed user — is exactly what the
|
|
184
184
|
presence/filter API requested below would remove, and
|
|
185
185
|
`get --users-without-explicit-perms` still has to probe every active user
|
|
186
186
|
because its semantics are instance-wide.
|
{src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/mapping-efficiency.md
RENAMED
|
@@ -64,7 +64,7 @@ user-group-b -> repo-group-2
|
|
|
64
64
|
Each `maps:` entry is naturally a grouped rule:
|
|
65
65
|
|
|
66
66
|
```text
|
|
67
|
-
selected users
|
|
67
|
+
selected users x selected repos
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
The maps schema keeps this restrictive: `users:` and `repos:` are selector
|
|
@@ -91,7 +91,7 @@ The old full-set planner immediately expanded every map entry into:
|
|
|
91
91
|
repo_id -> set(username)
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
That is expensive for rectangular maps such as `10000 users
|
|
94
|
+
That is expensive for rectangular maps such as `10000 users x 1000 repos`:
|
|
95
95
|
the username strings are shared, but each repo owns a large Python set with one
|
|
96
96
|
hash-table entry per planned grant.
|
|
97
97
|
|
{src_auth_perms_sync-0.5.0 → src_auth_perms_sync-0.7.0}/dev/memory-analysis/memory-efficiency.md
RENAMED
|
@@ -4,7 +4,7 @@ Use this when full snapshot capture or full-set apply is slow. The goal is to
|
|
|
4
4
|
correlate `src-auth-perms-sync` structured logs with Sourcegraph Jaeger spans
|
|
5
5
|
and pod/Postgres load. Request-ready evidence and copy/paste text for
|
|
6
6
|
Sourcegraph Engineering live in
|
|
7
|
-
[engineering-requests.md](
|
|
7
|
+
[engineering-requests.md](../engineering-requests.md).
|
|
8
8
|
|
|
9
9
|
## Capture a focused trace
|
|
10
10
|
|
|
@@ -157,7 +157,7 @@ The lower-level helper remains available for focused profiling outside a full
|
|
|
157
157
|
e2e run:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
|
-
dev/memory-efficiency-monitor-sourcegraph.sh \
|
|
160
|
+
dev/memory-analysis/memory-efficiency-monitor-sourcegraph.sh \
|
|
161
161
|
--namespace m \
|
|
162
162
|
--output-dir /tmp/src-auth-perms-sync-sourcegraph-load-$(date -u +%Y%m%d-%H%M%S)
|
|
163
163
|
```
|
|
@@ -174,4 +174,4 @@ run.
|
|
|
174
174
|
|
|
175
175
|
Request-ready trace findings, stress evidence, Sourcegraph codepath notes,
|
|
176
176
|
proposed GraphQL APIs, and copy/paste issue text now live in
|
|
177
|
-
[engineering-requests.md](
|
|
177
|
+
[engineering-requests.md](../engineering-requests.md).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.11"
|
|
3
|
+
# dependencies = ["src-auth-perms-sync"]
|
|
4
|
+
# ///
|
|
5
|
+
"""Sync Sourcegraph repo permissions from your own Python code.
|
|
6
|
+
|
|
7
|
+
export SRC_ENDPOINT="https://sourcegraph.example.com"
|
|
8
|
+
export SRC_ACCESS_TOKEN="sgp_..." # site-admin token
|
|
9
|
+
uv run example-import.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
import src_auth_perms_sync as src
|
|
16
|
+
|
|
17
|
+
# Configure your logger
|
|
18
|
+
logging.basicConfig(level=logging.INFO)
|
|
19
|
+
|
|
20
|
+
# The import API does not read environment variables or .env files on its
|
|
21
|
+
# own (the CLI does); pass every value explicitly.
|
|
22
|
+
config = src.Config(
|
|
23
|
+
src_endpoint=os.environ["SRC_ENDPOINT"],
|
|
24
|
+
src_access_token=os.environ["SRC_ACCESS_TOKEN"],
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# Discover the instance's auth providers and code hosts
|
|
28
|
+
discovery = src.Get(config)
|
|
29
|
+
for auth_provider in discovery.auth_providers:
|
|
30
|
+
print("auth provider:", auth_provider.get("displayName"))
|
|
31
|
+
for code_host in discovery.code_hosts:
|
|
32
|
+
print("code host:", code_host.get("displayName"))
|
|
33
|
+
|
|
34
|
+
# Configure your mapping rules
|
|
35
|
+
mapping_rules: list[src.MappingRule] = [
|
|
36
|
+
{
|
|
37
|
+
"name": "LOB1-GROUP1 members get the LOB1-SA1 repos",
|
|
38
|
+
"users": {"authProvider": {"samlGroup": "LOB1-GROUP1"}},
|
|
39
|
+
"repos": {"codeHostConnection": {"username": "LOB1-SA1"}},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "LOB2-GROUP2 members get the LOB2-SA2 repos",
|
|
43
|
+
"users": {"authProvider": {"samlGroup": "LOB2-GROUP2"}},
|
|
44
|
+
"repos": {"codeHostConnection": {"username": "LOB2-SA2"}},
|
|
45
|
+
},
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
# Run the set dry run, also syncing SAML groups to Sourcegraph organizations
|
|
49
|
+
result = src.Set(
|
|
50
|
+
config.model_copy(update={"full": True, "apply": False, "sync_saml_orgs": True}),
|
|
51
|
+
mapping_rules=mapping_rules,
|
|
52
|
+
)
|
|
53
|
+
# Print if it succeeded
|
|
54
|
+
print("permission sync dry run:", "ok" if result else "failed")
|
|
55
|
+
|
|
56
|
+
# Run the set apply, also syncing SAML groups to Sourcegraph organizations
|
|
57
|
+
result = src.Set(
|
|
58
|
+
config.model_copy(update={"full": True, "apply": True, "sync_saml_orgs": True}),
|
|
59
|
+
mapping_rules=mapping_rules,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Print if it succeeded
|
|
63
|
+
print("permission sync apply:", "ok" if result else "failed")
|