src-auth-perms-sync 0.6.0__tar.gz → 0.8.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.
Files changed (196) hide show
  1. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.github/workflows/release.yml +2 -2
  2. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.github/workflows/validate.yml +17 -9
  3. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.gitignore +2 -5
  4. src_auth_perms_sync-0.8.0/.markdownlint-cli2.yaml +15 -0
  5. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/AGENTS.md +20 -12
  6. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/PKG-INFO +59 -25
  7. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/README.md +56 -22
  8. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/TODO.md +6 -6
  9. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/engineering-requests.md +16 -16
  10. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/memory-analysis/mapping-efficiency.md +2 -2
  11. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/memory-analysis/memory-efficiency-analyze.py +1 -1
  12. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/memory-analysis/memory-efficiency.md +3 -3
  13. src_auth_perms_sync-0.8.0/examples/import.py +63 -0
  14. src_auth_perms_sync-0.6.0/maps-example.yaml → src_auth_perms_sync-0.8.0/examples/maps.yaml +2 -2
  15. src_auth_perms_sync-0.8.0/package-lock.json +1377 -0
  16. src_auth_perms_sync-0.8.0/package.json +11 -0
  17. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/pyproject.toml +6 -5
  18. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/cli.py +184 -109
  19. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/orgs/command.py +2 -2
  20. src_auth_perms_sync-0.8.0/src/src_auth_perms_sync/orgs/queries.py +90 -0
  21. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/orgs/sync.py +573 -105
  22. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/orgs/types.py +6 -0
  23. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/apply.py +8 -8
  24. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/command.py +125 -55
  25. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/full_set.py +11 -11
  26. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/mapping.py +17 -17
  27. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/maps.py +93 -74
  28. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/queries.py +42 -8
  29. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/restore.py +9 -9
  30. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/snapshot.py +9 -9
  31. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/sourcegraph.py +16 -6
  32. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/types.py +1 -1
  33. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/workflow.py +4 -4
  34. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/backups.py +3 -3
  35. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/queries.py +10 -1
  36. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/run_context.py +11 -3
  37. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/saml_groups.py +98 -9
  38. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/site_config.py +11 -11
  39. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/sourcegraph.py +5 -1
  40. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/types.py +25 -0
  41. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/README.md +23 -23
  42. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/case_runner.py +194 -14
  43. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-noop/after.json +114 -0
  44. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-noop/before.json +108 -0
  45. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-noop/maps.yaml +8 -0
  46. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/after.json +109 -0
  47. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/before.json +104 -0
  48. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-sync-saml-orgs-scoped/maps.yaml +8 -0
  49. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/sync-saml-orgs-full-cleanup/after.json +111 -0
  50. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/sync-saml-orgs-full-cleanup/before.json +106 -0
  51. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/sync-saml-orgs-users-scoped/after.json +113 -0
  52. src_auth_perms_sync-0.8.0/tests/e2e/fixtures/sync-saml-orgs-users-scoped/before.json +107 -0
  53. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/test_local_cases.py +4 -4
  54. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/integration/test_cli_entrypoint.py +8 -1
  55. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/run.py +286 -27
  56. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/setup.py +220 -7
  57. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/tests.yaml +952 -59
  58. src_auth_perms_sync-0.8.0/tests/unicode_scan.py +65 -0
  59. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_backups.py +3 -3
  60. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_cli_config.py +85 -38
  61. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_command_additive.py +2 -2
  62. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_command_files.py +17 -9
  63. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_maps.py +3 -2
  64. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_permissions_sourcegraph.py +2 -2
  65. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_restore.py +4 -4
  66. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_saml_groups.py +94 -2
  67. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_snapshot.py +1 -1
  68. src_auth_perms_sync-0.8.0/tests/unit/test_unicode_scan.py +22 -0
  69. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/uv.lock +50 -50
  70. src_auth_perms_sync-0.6.0/.env.example +0 -36
  71. src_auth_perms_sync-0.6.0/.markdownlint-cli2.yaml +0 -9
  72. src_auth_perms_sync-0.6.0/dev/PLAN.md +0 -458
  73. src_auth_perms_sync-0.6.0/src/src_auth_perms_sync/orgs/queries.py +0 -44
  74. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.github/CODEOWNERS +0 -0
  75. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.github/workflows/ci.yml +0 -0
  76. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/.python-version +0 -0
  77. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/LICENSE +0 -0
  78. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/SECURITY.md +0 -0
  79. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/audit-dead-code.md +0 -0
  80. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/hooks/pre-commit +0 -0
  81. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/memory-analysis/memory-efficiency-generate.py +0 -0
  82. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/memory-analysis/memory-efficiency-monitor-sourcegraph.sh +0 -0
  83. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/dev/update-python-versions.md +0 -0
  84. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/renovate.json +0 -0
  85. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/__init__.py +0 -0
  86. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/__main__.py +0 -0
  87. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/orgs/__init__.py +0 -0
  88. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/permissions/__init__.py +0 -0
  89. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/src/src_auth_perms_sync/shared/__init__.py +0 -0
  90. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/__init__.py +0 -0
  91. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/__init__.py +0 -0
  92. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-by-email-and-list/after.json +0 -0
  93. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-by-email-and-list/before.json +0 -0
  94. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-by-email-and-list/maps.yaml +0 -0
  95. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-preserves-existing/after.json +0 -0
  96. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-preserves-existing/before.json +0 -0
  97. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/add-users-preserves-existing/maps.yaml +0 -0
  98. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/and-filters-intersect/after.json +0 -0
  99. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/and-filters-intersect/before.json +0 -0
  100. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/and-filters-intersect/maps.yaml +0 -0
  101. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/empty-maps-noop/before.json +0 -0
  102. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/empty-maps-noop/maps.yaml +0 -0
  103. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-dry-run/before.json +0 -0
  104. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-dry-run/maps.yaml +0 -0
  105. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/after.json +0 -0
  106. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/before.json +0 -0
  107. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-preserves-pending/maps.yaml +0 -0
  108. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/after.json +0 -0
  109. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/before.json +0 -0
  110. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-removes-stale-grant/maps.yaml +0 -0
  111. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-unions/after.json +0 -0
  112. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-unions/before.json +0 -0
  113. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-unions/maps.yaml +0 -0
  114. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-with-backup/after.json +0 -0
  115. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-with-backup/before.json +0 -0
  116. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/full-overwrite-with-backup/maps.yaml +0 -0
  117. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/get-full-snapshot/before.json +0 -0
  118. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/get-repos-without-explicit-perms/before.json +0 -0
  119. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/get-user-grants/before.json +0 -0
  120. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-bad-regex/before.json +0 -0
  121. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-bad-regex/maps.yaml +0 -0
  122. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-missing-repos-section/before.json +0 -0
  123. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-missing-repos-section/maps.yaml +0 -0
  124. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-restore-wrong-schema-version/before.json +0 -0
  125. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-restore-wrong-schema-version/snapshot.json +0 -0
  126. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-created-after-date → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-repos-created-after-date}/before.json +0 -0
  127. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-created-after-date → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-repos-created-after-date}/maps.yaml +0 -0
  128. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-repos-created-after-date → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-unknown-repo}/before.json +0 -0
  129. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-set-unknown-repo/maps.yaml +0 -0
  130. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-unknown-repo → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-unknown-user}/before.json +0 -0
  131. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-set-unknown-user/maps.yaml +0 -0
  132. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-unknown-user → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-users-created-after-date}/before.json +0 -0
  133. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/invalid-set-repos-created-after-date → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/invalid-set-users-created-after-date}/maps.yaml +0 -0
  134. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-unknown-selector-field/before.json +0 -0
  135. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/invalid-unknown-selector-field/maps.yaml +0 -0
  136. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/match-provider-and-host-fields/after.json +0 -0
  137. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/match-provider-and-host-fields/before.json +0 -0
  138. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/match-provider-and-host-fields/maps.yaml +0 -0
  139. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/no-match-noop/before.json +0 -0
  140. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/no-match-noop/maps.yaml +0 -0
  141. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/regex-filters-scope/after.json +0 -0
  142. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/regex-filters-scope/before.json +0 -0
  143. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/regex-filters-scope/maps.yaml +0 -0
  144. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-applies-snapshot/after.json +0 -0
  145. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-applies-snapshot/before.json +0 -0
  146. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-applies-snapshot/snapshot.json +0 -0
  147. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-dry-run-noop/before.json +0 -0
  148. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-dry-run-noop/snapshot.json +0 -0
  149. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-missing-file/before.json +0 -0
  150. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-restores-pending/after.json +0 -0
  151. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-restores-pending/before.json +0 -0
  152. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/restore-restores-pending/snapshot.json +0 -0
  153. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-filter/after.json +0 -0
  154. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-filter/before.json +0 -0
  155. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-filter/maps.yaml +0 -0
  156. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-live/after.json +0 -0
  157. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-live/before.json +0 -0
  158. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/saml-group-live/maps.yaml +0 -0
  159. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-created-after-sync-saml-orgs-dry-run → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-full-sync-saml-orgs-dry-run}/maps.yaml +0 -0
  160. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-created-after/after.json +0 -0
  161. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-created-after/before.json +0 -0
  162. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-created-after/maps.yaml +0 -0
  163. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-created-after-noop/before.json +0 -0
  164. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-created-after-noop/maps.yaml +0 -0
  165. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-full-sync-saml-orgs-dry-run → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-repos-created-after-sync-saml-orgs-dry-run}/maps.yaml +0 -0
  166. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-filter/after.json +0 -0
  167. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-filter/before.json +0 -0
  168. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-filter/maps.yaml +0 -0
  169. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-repos-created-after-sync-saml-orgs-dry-run → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-repos-sync-saml-orgs-dry-run}/maps.yaml +0 -0
  170. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/after.json +0 -0
  171. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/before.json +0 -0
  172. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-repos-without-explicit-perms/maps.yaml +0 -0
  173. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-repos-sync-saml-orgs-dry-run → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-repos-without-perms-sync-saml-orgs-dry-run}/maps.yaml +0 -0
  174. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-created-after/after.json +0 -0
  175. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-created-after/before.json +0 -0
  176. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-created-after/maps.yaml +0 -0
  177. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-created-after-noop/before.json +0 -0
  178. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-created-after-noop/maps.yaml +0 -0
  179. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-repos-without-perms-sync-saml-orgs-dry-run → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-created-after-sync-saml-orgs-dry-run}/maps.yaml +0 -0
  180. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-created-after-temp-user → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-created-after-temp-user}/after.json +0 -0
  181. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-created-after-temp-user → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-created-after-temp-user}/before.json +0 -0
  182. {src_auth_perms_sync-0.6.0/tests/e2e/fixtures/set-created-after-temp-user → src_auth_perms_sync-0.8.0/tests/e2e/fixtures/set-users-created-after-temp-user}/maps.yaml +0 -0
  183. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-sync-saml-orgs-dry-run/maps.yaml +0 -0
  184. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms/after.json +0 -0
  185. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms/before.json +0 -0
  186. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms/maps.yaml +0 -0
  187. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/after.json +0 -0
  188. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/before.json +0 -0
  189. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-explicit-perms-default-batch/maps.yaml +0 -0
  190. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/e2e/fixtures/set-users-without-perms-sync-saml-orgs-dry-run/maps.yaml +0 -0
  191. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/integration/__init__.py +0 -0
  192. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/setup.yaml +0 -0
  193. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/__init__.py +0 -0
  194. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_apply.py +0 -0
  195. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_mapping_rules.py +0 -0
  196. {src_auth_perms_sync-0.6.0 → src_auth_perms_sync-0.8.0}/tests/unit/test_module_api.py +0 -0
@@ -83,7 +83,7 @@ jobs:
83
83
 
84
84
  steps:
85
85
  - name: Check out release ref
86
- uses: actions/checkout@v6
86
+ uses: actions/checkout@v7
87
87
  with:
88
88
  fetch-depth: 0
89
89
  persist-credentials: false
@@ -95,7 +95,7 @@ jobs:
95
95
  python-version: ${{ env.PYTHON_VERSION }}
96
96
 
97
97
  - name: Cache uv
98
- uses: actions/cache@v5
98
+ uses: actions/cache@v6
99
99
  with:
100
100
  path: ~/.cache/uv
101
101
  key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
@@ -98,7 +98,7 @@ jobs:
98
98
 
99
99
  steps:
100
100
  - name: Check out code
101
- uses: actions/checkout@v6
101
+ uses: actions/checkout@v7
102
102
  with:
103
103
  persist-credentials: false
104
104
  ref: ${{ inputs.ref || github.ref }}
@@ -127,22 +127,27 @@ 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
133
- uses: actions/checkout@v6
134
+ uses: actions/checkout@v7
134
135
  with:
135
136
  persist-credentials: false
136
137
  ref: ${{ inputs.ref || github.ref }}
137
138
 
138
139
  - name: Cache npm
139
- uses: actions/cache@v5
140
+ uses: actions/cache@v6
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: npx --yes "markdownlint-cli2@${MARKDOWNLINT_CLI2_VERSION}"
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
@@ -155,7 +160,7 @@ jobs:
155
160
 
156
161
  steps:
157
162
  - name: Check out code
158
- uses: actions/checkout@v6
163
+ uses: actions/checkout@v7
159
164
  with:
160
165
  fetch-depth: 0
161
166
  persist-credentials: false
@@ -167,7 +172,7 @@ jobs:
167
172
  python-version: ${{ env.PYTHON_VERSION }}
168
173
 
169
174
  - name: Cache uv
170
- uses: actions/cache@v5
175
+ uses: actions/cache@v6
171
176
  with:
172
177
  path: ~/.cache/uv
173
178
  key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
@@ -180,6 +185,9 @@ jobs:
180
185
  - name: Validate lockfile
181
186
  run: uv lock --check
182
187
 
188
+ - name: Scan for Unicode characters
189
+ run: uv run --frozen python tests/unicode_scan.py
190
+
183
191
  - name: Lint Python
184
192
  run: uv run --frozen ruff check .
185
193
 
@@ -207,7 +215,7 @@ jobs:
207
215
 
208
216
  steps:
209
217
  - name: Check out code
210
- uses: actions/checkout@v6
218
+ uses: actions/checkout@v7
211
219
  with:
212
220
  fetch-depth: 0
213
221
  persist-credentials: false
@@ -219,7 +227,7 @@ jobs:
219
227
  python-version: ${{ env.PYTHON_VERSION }}
220
228
 
221
229
  - name: Cache uv
222
- uses: actions/cache@v5
230
+ uses: actions/cache@v6
223
231
  with:
224
232
  path: ~/.cache/uv
225
233
  key: uv-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('uv.lock') }}
@@ -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
- !.env.example
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,10 @@
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
+ ### Non-ASCII characters in tracked text files
18
+ uv run python tests/unicode_scan.py
16
19
 
17
20
  ### Python files
18
21
 
@@ -37,7 +40,8 @@ own checks.
37
40
 
38
41
  ```bash
39
42
  # Fast, no network (also what the pre-commit hook runs):
40
- # lint, format, pyright, unit + fixture tests, CLI rejection matrix,
43
+ # lint, format, pyright, non-ASCII character scan, unit + fixture
44
+ # tests, CLI rejection matrix,
41
45
  # randomized permission invariants
42
46
  uv run tests/run.py
43
47
 
@@ -59,7 +63,7 @@ uv run tests/run.py --performance --baseline-command "uvx src-auth-perms-sync@la
59
63
  uv run tests/run.py --update-golden
60
64
  ```
61
65
 
62
- - Fixture cases live in `tests/e2e/fixtures/<case>/` — see the README there
66
+ - Fixture cases live in `tests/e2e/fixtures/<case>/` - see the README there
63
67
  for the format. Add cases there to cover new mapping behaviors.
64
68
  - For manual verification against a real instance, dry-run first (no
65
69
  `--apply`), read the planned changes, then `--apply` on a scratch instance
@@ -97,7 +101,7 @@ uv run ruff format --check src/src_auth_perms_sync/ tests/
97
101
  uv run pyright
98
102
  uv run python -m unittest discover -s tests
99
103
  uv run src-auth-perms-sync --help
100
- npx --yes markdownlint-cli2@0.22.1
104
+ npx --yes -p markdownlint-cli2@0.22.1 -p markdownlint-rule-relative-links@5.1.0 markdownlint-cli2
101
105
  uv build --wheel --sdist --out-dir /tmp/src-auth-perms-sync-release-check --no-create-gitignore
102
106
  rm -rf /tmp/src-auth-perms-sync-release-check
103
107
  ```
@@ -160,7 +164,7 @@ gh run watch "${RUN_ID}" --repo "${GH_REPO}" --exit-status
160
164
  gh release view "v${VERSION}" --repo "${GH_REPO}"
161
165
  ```
162
166
 
163
- ## Hard invariants — do not break
167
+ ## Hard invariants - do not break
164
168
 
165
169
  Violating these can silently grant the wrong users access to the wrong
166
170
  repos.
@@ -201,31 +205,31 @@ organization sync maps SAML groups to Sourcegraph org membership. Read
201
205
  CLI lives in `src/src_auth_perms_sync/`; invoke with `uv run src-auth-perms-sync`.
202
206
  Strict pyright covers the package. Root modules are entrypoints only:
203
207
 
204
- - `cli.py` — `main()`, arg parsing, owns the CLI description. Module
208
+ - `cli.py` - `main()`, arg parsing, owns the CLI description. Module
205
209
  wrappers (`Get`/`Set`/`Restore`/`SyncSamlOrgs`) return result dataclasses
206
210
  and never install logging handlers; only `main()` runs CLI-mode logging.
207
- - `shared/` — cross-workflow helpers: Sourcegraph auth-provider/user list
211
+ - `shared/` - cross-workflow helpers: Sourcegraph auth-provider/user list
208
212
  helpers, shared GraphQL operations and TypedDicts, site-config validation,
209
213
  and SAML group parsing. `shared/backups.py` defines `RunPaths`: every
210
214
  filesystem path for one run, resolved once at the edge
211
- (`resolve_run_paths`) and threaded explicitly — never recompute paths
215
+ (`resolve_run_paths`) and threaded explicitly - never recompute paths
212
216
  from cwd or globals below the edge, and honor `run_paths.write_files`
213
217
  (False under `--no-files`) before any disk write.
214
218
 
215
219
  Business workflows live in packages:
216
220
 
217
- - `permissions/` — repo permission sync (`command.py`, `maps.py`,
221
+ - `permissions/` - repo permission sync (`command.py`, `maps.py`,
218
222
  `mapping.py`, `sourcegraph.py`, `snapshot.py`, `apply.py`, `queries.py`,
219
223
  `types.py`). Add new mapping filters in `permissions/types.py` and
220
224
  `permissions/mapping.py`.
221
- - `orgs/` — SAML group → Sourcegraph organization sync (`command.py`,
225
+ - `orgs/` - SAML group -> Sourcegraph organization sync (`command.py`,
222
226
  `queries.py`, `types.py`).
223
227
 
224
228
  ## Toolchain
225
229
 
226
230
  - Python 3.11 + [uv](https://docs.astral.sh/uv/). Never invoke `python`
227
231
  directly; always `uv run ...`.
228
- - `uv run pyright` must be clean. No `# type: ignore` to silence —
232
+ - `uv run pyright` must be clean. No `# type: ignore` to silence -
229
233
  fix the underlying type.
230
234
  - Local tests use stdlib `unittest`: `uv run python -m unittest discover -s tests`.
231
235
  - For Sourcegraph mutation-path changes, also verify by dry-running `--get` /
@@ -252,6 +256,10 @@ removed names like `ev`, `ex`, `exc`, `cfg`, `conn`, `resp`, `fn`,
252
256
 
253
257
  Short names that ARE acceptable (don't rewrite these on sight):
254
258
 
259
+ - **Established domain abbreviations**: `org` / `orgs` for Sourcegraph
260
+ organizations, matching the `sync-saml-orgs` command, the `orgs/`
261
+ package, and the `sync_saml_orgs` config field. Do not expand these
262
+ back to `organization(s)` in identifiers.
255
263
  - **TypedDict / dataclass fields that mirror the wire format**: `id`,
256
264
  `url`, `kind` on `ExternalService` etc. These match GraphQL/JSON
257
265
  keys and renaming would break the contract.
@@ -259,7 +267,7 @@ Short names that ARE acceptable (don't rewrite these on sight):
259
267
  `key`, `value`, `name`, `kind`.
260
268
  - **Stdlib idioms**: `ctx` for `contextvars.copy_context()`.
261
269
  - **Loop / comprehension variables when the type is obvious from one
262
- line of context** is still discouraged — prefer `user`, `repo`,
270
+ line of context** is still discouraged - prefer `user`, `repo`,
263
271
  `provider`, `service`, `permission`, `node`, `entry`, `match`,
264
272
  `account`, `future`, `executor`, `exception`, `event`, `connection`,
265
273
  `response`, `timestamp`, `current`, `outcome`, `index`, `field_name`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: src-auth-perms-sync
3
- Version: 0.6.0
3
+ Version: 0.8.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
@@ -16,13 +16,13 @@ Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Typing :: Typed
18
18
  Requires-Python: >=3.11
19
- Requires-Dist: json5>=0.14.0
19
+ Requires-Dist: json5>=0.15.0
20
20
  Requires-Dist: pyyaml>=6.0.3
21
- Requires-Dist: src-py-lib[otel]==0.3.0
21
+ Requires-Dist: src-py-lib[otel]==0.3.1
22
22
  Description-Content-Type: text/markdown
23
23
 
24
24
  # src-auth-perms-sync
25
- <!-- HUMAN-MAINTAINED SECTION START — DO NOT EDIT THIS SECTION -->
25
+ <!-- HUMAN-MAINTAINED SECTION START - DO NOT EDIT THIS SECTION -->
26
26
 
27
27
  src-auth-perms-sync automates Sourcegraph's Explicit Permissions GraphQL API,
28
28
  setting user-to-repo permissions based on mapping rules, for example:
@@ -167,10 +167,10 @@ result = src.Set(config) # truthy on success; result.paths has run artifacts
167
167
  get_result = src.Get(config)
168
168
  for provider in get_result.auth_providers:
169
169
  ...
170
- for code_host in get_result.code_hosts:
170
+ for code_host_connection in get_result.code_host_connections:
171
171
  ...
172
172
 
173
- # Mapping rules can be passed in memory instead of a maps YAML file —
173
+ # Mapping rules can be passed in memory instead of a maps YAML file -
174
174
  # same structure and validation as maps.yaml entries:
175
175
  rules: list[src.MappingRule] = [
176
176
  {
@@ -189,7 +189,12 @@ result = src.Set(config, mapping_rules=rules)
189
189
  # result = src.SyncSamlOrgs(config)
190
190
  ```
191
191
 
192
- Module mode never touches your `logging` handlers or the root logger — your
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
+
197
+ Module mode never touches your `logging` handlers or the root logger - your
193
198
  application's logging config stays in charge. To see progress messages:
194
199
 
195
200
  ```python
@@ -217,7 +222,7 @@ snapshots that make `--apply` reversible.
217
222
  - Environment variables (CLI), or src.Config args (Python import)
218
223
  - `SRC_ENDPOINT`
219
224
  - `SRC_ACCESS_TOKEN` from a user with site-admin perms
220
- - See [.env.example](./.env.example)
225
+ - See [.env.example](./examples/.env.example)
221
226
 
222
227
  - YAML maps file
223
228
  - By default: `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
@@ -231,7 +236,7 @@ snapshots that make `--apply` reversible.
231
236
  - Each mapping rule takes
232
237
  - A map of filters for users
233
238
  - A map of filters for repos
234
- - See [maps-example.yaml](./maps-example.yaml)
239
+ - See [maps.yaml](./examples/maps.yaml)
235
240
  - An empty maps.yaml file is created for you on the first `get` run
236
241
 
237
242
  ## Usage: Permission sync
@@ -243,7 +248,7 @@ snapshots that make `--apply` reversible.
243
248
  ```
244
249
 
245
250
  - Queries the Sourcegraph instance for auth providers and code host connections
246
- - Writes generated reference files `auth-providers.yaml` and `code-hosts.yaml` under
251
+ - Writes generated reference files `auth-providers.yaml` and `code-host-connections.yaml` under
247
252
  `src-auth-perms-sync-runs/<src_endpoint>/`
248
253
  - Creates an empty `maps.yaml` if it doesn't exist
249
254
 
@@ -251,7 +256,7 @@ snapshots that make `--apply` reversible.
251
256
 
252
257
  - Edit `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
253
258
  - Add mapping rules under the `maps:` top level key
254
- - See [maps-example.yaml](./maps-example.yaml)
259
+ - See [maps.yaml](./examples/maps.yaml)
255
260
 
256
261
  3. **Set: Dry run**
257
262
 
@@ -292,7 +297,7 @@ snapshots that make `--apply` reversible.
292
297
  1. **Get user and org metadata**
293
298
 
294
299
  ```bash
295
- src-auth-perms-sync sync-saml-orgs
300
+ src-auth-perms-sync sync-saml-orgs --full
296
301
  ```
297
302
 
298
303
  - Queries the Sourcegraph instance for auth providers, users, users' SAML groups, and orgs
@@ -301,12 +306,41 @@ snapshots that make `--apply` reversible.
301
306
  2. **Apply org sync**
302
307
 
303
308
  ```bash
304
- src-auth-perms-sync sync-saml-orgs --apply
309
+ src-auth-perms-sync sync-saml-orgs --full --apply
305
310
  ```
306
311
 
307
312
  - Creates the orgs if they don't exist, and sync the members from the SAML groups to the orgs
308
313
  - `--sync-saml-orgs` can also be added to a `set` run, to run both at the same time
309
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 --users-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` / `--users-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
+
310
344
  ## Options
311
345
 
312
346
  Run `src-auth-perms-sync --help` for options
@@ -315,22 +349,22 @@ Run `src-auth-perms-sync --help` for options
315
349
 
316
350
  ```text
317
351
  src-auth-perms-sync-runs/<src_endpoint>/
318
- ├── auth-providers.yaml
319
- ├── code-hosts.yaml
320
- ├── maps.yaml
321
- └── runs
322
- └── timestamp-command
323
- ├── before.json
324
- ├── after.json
325
- ├── diff.json
326
- ├── log.json
327
- └── maps.yaml
352
+ |-- auth-providers.yaml
353
+ |-- code-host-connections.yaml
354
+ |-- maps.yaml
355
+ `-- runs
356
+ `-- timestamp-command
357
+ |-- before.json
358
+ |-- after.json
359
+ |-- diff.json
360
+ |-- log.json
361
+ `-- maps.yaml
328
362
  ```
329
363
 
330
364
  - The `src-auth-perms-sync-runs` dir is created under your current working directory
331
365
  - The `<src_endpoint>` dir is created with the hostname from `SRC_ENDPOINT`
332
366
  - If `maps.yaml` doesn't exist already, it'll be created for you
333
- - `auth-providers.yaml` and `code-hosts.yaml` are created / replaced by the `get` command,
367
+ - `auth-providers.yaml` and `code-host-connections.yaml` are created / replaced by the `get` command,
334
368
  for you to copy values from, to use in your `maps.yaml`
335
369
  - Only one `maps.yaml` file can be used at a time per Sourcegraph instance, as each `set --apply`
336
370
  command resets the state on the Sourcegraph instance to the `maps.yaml` file which was used
@@ -342,4 +376,4 @@ src-auth-perms-sync-runs/<src_endpoint>/
342
376
  - An `after.json` file, capturing the new state
343
377
  - A `diff.json` file, a shorter, reviewable file containing the diffs between before and after
344
378
 
345
- <!-- HUMAN-MAINTAINED SECTION END — DO NOT EDIT ABOVE -->
379
+ <!-- HUMAN-MAINTAINED SECTION END - DO NOT EDIT ABOVE -->
@@ -1,5 +1,5 @@
1
1
  # src-auth-perms-sync
2
- <!-- HUMAN-MAINTAINED SECTION START — DO NOT EDIT THIS SECTION -->
2
+ <!-- HUMAN-MAINTAINED SECTION START - DO NOT EDIT THIS SECTION -->
3
3
 
4
4
  src-auth-perms-sync automates Sourcegraph's Explicit Permissions GraphQL API,
5
5
  setting user-to-repo permissions based on mapping rules, for example:
@@ -144,10 +144,10 @@ result = src.Set(config) # truthy on success; result.paths has run artifacts
144
144
  get_result = src.Get(config)
145
145
  for provider in get_result.auth_providers:
146
146
  ...
147
- for code_host in get_result.code_hosts:
147
+ for code_host_connection in get_result.code_host_connections:
148
148
  ...
149
149
 
150
- # Mapping rules can be passed in memory instead of a maps YAML file —
150
+ # Mapping rules can be passed in memory instead of a maps YAML file -
151
151
  # same structure and validation as maps.yaml entries:
152
152
  rules: list[src.MappingRule] = [
153
153
  {
@@ -166,7 +166,12 @@ result = src.Set(config, mapping_rules=rules)
166
166
  # result = src.SyncSamlOrgs(config)
167
167
  ```
168
168
 
169
- Module mode never touches your `logging` handlers or the root logger — your
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
+
174
+ Module mode never touches your `logging` handlers or the root logger - your
170
175
  application's logging config stays in charge. To see progress messages:
171
176
 
172
177
  ```python
@@ -194,7 +199,7 @@ snapshots that make `--apply` reversible.
194
199
  - Environment variables (CLI), or src.Config args (Python import)
195
200
  - `SRC_ENDPOINT`
196
201
  - `SRC_ACCESS_TOKEN` from a user with site-admin perms
197
- - See [.env.example](./.env.example)
202
+ - See [.env.example](./examples/.env.example)
198
203
 
199
204
  - YAML maps file
200
205
  - By default: `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
@@ -208,7 +213,7 @@ snapshots that make `--apply` reversible.
208
213
  - Each mapping rule takes
209
214
  - A map of filters for users
210
215
  - A map of filters for repos
211
- - See [maps-example.yaml](./maps-example.yaml)
216
+ - See [maps.yaml](./examples/maps.yaml)
212
217
  - An empty maps.yaml file is created for you on the first `get` run
213
218
 
214
219
  ## Usage: Permission sync
@@ -220,7 +225,7 @@ snapshots that make `--apply` reversible.
220
225
  ```
221
226
 
222
227
  - Queries the Sourcegraph instance for auth providers and code host connections
223
- - Writes generated reference files `auth-providers.yaml` and `code-hosts.yaml` under
228
+ - Writes generated reference files `auth-providers.yaml` and `code-host-connections.yaml` under
224
229
  `src-auth-perms-sync-runs/<src_endpoint>/`
225
230
  - Creates an empty `maps.yaml` if it doesn't exist
226
231
 
@@ -228,7 +233,7 @@ snapshots that make `--apply` reversible.
228
233
 
229
234
  - Edit `src-auth-perms-sync-runs/<src_endpoint>/maps.yaml`
230
235
  - Add mapping rules under the `maps:` top level key
231
- - See [maps-example.yaml](./maps-example.yaml)
236
+ - See [maps.yaml](./examples/maps.yaml)
232
237
 
233
238
  3. **Set: Dry run**
234
239
 
@@ -269,7 +274,7 @@ snapshots that make `--apply` reversible.
269
274
  1. **Get user and org metadata**
270
275
 
271
276
  ```bash
272
- src-auth-perms-sync sync-saml-orgs
277
+ src-auth-perms-sync sync-saml-orgs --full
273
278
  ```
274
279
 
275
280
  - Queries the Sourcegraph instance for auth providers, users, users' SAML groups, and orgs
@@ -278,12 +283,41 @@ snapshots that make `--apply` reversible.
278
283
  2. **Apply org sync**
279
284
 
280
285
  ```bash
281
- src-auth-perms-sync sync-saml-orgs --apply
286
+ src-auth-perms-sync sync-saml-orgs --full --apply
282
287
  ```
283
288
 
284
289
  - Creates the orgs if they don't exist, and sync the members from the SAML groups to the orgs
285
290
  - `--sync-saml-orgs` can also be added to a `set` run, to run both at the same time
286
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 --users-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` / `--users-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
+
287
321
  ## Options
288
322
 
289
323
  Run `src-auth-perms-sync --help` for options
@@ -292,22 +326,22 @@ Run `src-auth-perms-sync --help` for options
292
326
 
293
327
  ```text
294
328
  src-auth-perms-sync-runs/<src_endpoint>/
295
- ├── auth-providers.yaml
296
- ├── code-hosts.yaml
297
- ├── maps.yaml
298
- └── runs
299
- └── timestamp-command
300
- ├── before.json
301
- ├── after.json
302
- ├── diff.json
303
- ├── log.json
304
- └── maps.yaml
329
+ |-- auth-providers.yaml
330
+ |-- code-host-connections.yaml
331
+ |-- maps.yaml
332
+ `-- runs
333
+ `-- timestamp-command
334
+ |-- before.json
335
+ |-- after.json
336
+ |-- diff.json
337
+ |-- log.json
338
+ `-- maps.yaml
305
339
  ```
306
340
 
307
341
  - The `src-auth-perms-sync-runs` dir is created under your current working directory
308
342
  - The `<src_endpoint>` dir is created with the hostname from `SRC_ENDPOINT`
309
343
  - If `maps.yaml` doesn't exist already, it'll be created for you
310
- - `auth-providers.yaml` and `code-hosts.yaml` are created / replaced by the `get` command,
344
+ - `auth-providers.yaml` and `code-host-connections.yaml` are created / replaced by the `get` command,
311
345
  for you to copy values from, to use in your `maps.yaml`
312
346
  - Only one `maps.yaml` file can be used at a time per Sourcegraph instance, as each `set --apply`
313
347
  command resets the state on the Sourcegraph instance to the `maps.yaml` file which was used
@@ -319,4 +353,4 @@ src-auth-perms-sync-runs/<src_endpoint>/
319
353
  - An `after.json` file, capturing the new state
320
354
  - A `diff.json` file, a shorter, reviewable file containing the diffs between before and after
321
355
 
322
- <!-- HUMAN-MAINTAINED SECTION END — DO NOT EDIT ABOVE -->
356
+ <!-- HUMAN-MAINTAINED SECTION END - DO NOT EDIT ABOVE -->
@@ -32,7 +32,7 @@
32
32
  - `get --repos <name>` still scans every user's explicit grants to find one
33
33
  repo's holders (~400 s at 10k users). A repo-centric read
34
34
  (`repository.permissionsInfo.users` + site-admin disambiguation, as the
35
- test harness already does) would make it seconds — see the repo-centric
35
+ test harness already does) would make it seconds - see the repo-centric
36
36
  section below.
37
37
 
38
38
  ## Low priority: Repo-centric path, when users > repos, or for cross-checking
@@ -50,10 +50,10 @@ Reasons we might want to bring it back later:
50
50
  - **Targeted snapshots.** A "planned-scope" capture (only the repos
51
51
  the mapping rules touch) is faster than a full instance scan when
52
52
  the user-centric path is the long pole AND the planned set is small.
53
- Would need either a server-side `source` filter on the repo→users
53
+ Would need either a server-side `source` filter on the repo->users
54
54
  connection, or a follow-up user-centric `source: API` query per
55
55
  ambiguous (site-admin) user to disambiguate.
56
- - **Adaptive capture path after SG adds `source` to repo→users.** Once
56
+ - **Adaptive capture path after SG adds `source` to repo->users.** Once
57
57
  `RepositoryPermissionsInfo.users(source: PermissionSource)` exists,
58
58
  compute the expected request count both ways before snapshotting:
59
59
  sum `userCount` across all auth providers and sum `repoCount` across
@@ -70,7 +70,7 @@ If/when we revisit:
70
70
  ambiguous-user follow-up to be correct).
71
71
  2. Restore `QUERY_REPO_EXPLICIT_USERS` from git history; implement
72
72
  `list_repo_explicit_users` returning `(definitely, ambiguous)` and
73
- actually consume both buckets — the previous code did neither.
73
+ actually consume both buckets - the previous code did neither.
74
74
  3. Add a CLI flag (e.g. `--cross-check-capture`) gated behind a clear
75
75
  "this doubles capture cost" warning.
76
76
 
@@ -78,7 +78,7 @@ If/when we revisit:
78
78
 
79
79
  Phase 1 now avoids per-repo username sets for non-overlapping full-set maps.
80
80
  If memory remains too high after re-measuring, implement the Phase 2 grouped
81
- 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
82
82
  overlays into final groups of repos that share the same desired username tuple.
83
83
 
84
84
  ## Low priority: Expand group-membership filters beyond SAML
@@ -89,7 +89,7 @@ SAML actually persists the group list. Recovery options for each:
89
89
  - OIDC has no `allowGroups` field on `OpenIDConnectAuthProvider`.
90
90
  `UserClaims` stores only name/email fields; the `groups` claim is never
91
91
  parsed. Recovery needs an upstream change to persist the claim.
92
- - GitHub OAuth has `allowOrgs`, `allowOrgsMap` (org→teams), and
92
+ - GitHub OAuth has `allowOrgs`, `allowOrgsMap` (org->teams), and
93
93
  `requiredSsoOrgs`. Org/team checks happen live in `verifyUserOrgs` /
94
94
  `verifyUserTeams` and are discarded. Recovery needs an upstream change to
95
95
  persist the claim.