bt-cli 0.4.36__tar.gz → 0.4.37__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.
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/epml/SKILL.md +11 -4
- {bt_cli-0.4.36 → bt_cli-0.4.37}/CLAUDE.md +1 -1
- {bt_cli-0.4.36 → bt_cli-0.4.37}/PKG-INFO +1 -1
- {bt_cli-0.4.36 → bt_cli-0.4.37}/pyproject.toml +1 -1
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/data/CLAUDE.md +1 -1
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/epml/SKILL.md +11 -4
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/client/base.py +54 -8
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_roles.py +77 -24
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/.claude}/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/.env.example +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/.github/workflows/release.yml +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/.gitignore +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/README.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/assets/cli-help.png +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/assets/cli-output.png +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/bt-cli.spec +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/bt_entry.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/epml-implementation-plan.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/cli.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/commands/configure.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.36/tests/pws → bt_cli-0.4.37/src/bt_cli/data}/__init__.py +0 -0
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.36/.claude → bt_cli-0.4.37/src/bt_cli/data}/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/client/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/audit.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/client_pkg.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/external_apis.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/hosts.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/iolog.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/license.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/quick.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_cmdgrps.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_entitlement.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_hostgrps.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_policy.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_tests.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_tmdategrps.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_tx.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/rbp_usergrps.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/settings.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/siems.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/commands/users.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epml/models/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/conftest.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epml/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epml/test_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epml/test_commands.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.36/src/bt_cli/data → bt_cli-0.4.37/tests/pws}/__init__.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.36 → bt_cli-0.4.37}/tests/pws-smoke-test.sh +0 -0
|
@@ -132,13 +132,17 @@ bt epml rbp tmdategrps tmdates replace <tmdategrp_id> --file tmdates.json
|
|
|
132
132
|
|
|
133
133
|
# Roles + assignments
|
|
134
134
|
bt epml rbp roles list
|
|
135
|
-
bt epml rbp roles create --name "Helpdesk Role"
|
|
135
|
+
bt epml rbp roles create --name "Helpdesk Role" --action A \
|
|
136
|
+
--iolog '/iologs/%date%/%uniqueid%.iolog' \
|
|
137
|
+
--message "This session is logged."
|
|
136
138
|
bt epml rbp roles duplicate <role_id>
|
|
137
|
-
bt epml rbp roles cmdgrps add
|
|
139
|
+
bt epml rbp roles cmdgrps add <role_id> --ids 1,2 # cmdgrps & tmdategrps: just IDs
|
|
140
|
+
bt epml rbp roles tmdategrps add <role_id> --ids 1
|
|
141
|
+
bt epml rbp roles hostgrps add <role_id> --ids 1 --kind B # B = both Submit and Run-as
|
|
142
|
+
bt epml rbp roles usergrps add <role_id> --ids 4 --kind S # S = Submit (who requests)
|
|
143
|
+
bt epml rbp roles usergrps add <role_id> --ids 3 --kind R # R = Run-as (whose identity)
|
|
138
144
|
bt epml rbp roles cmdgrps remove <role_id> <cmdgrp_id>
|
|
139
145
|
bt epml rbp roles hostgrps list <role_id>
|
|
140
|
-
bt epml rbp roles usergrps add <role_id> --ids 5
|
|
141
|
-
bt epml rbp roles tmdategrps add <role_id> --ids 1
|
|
142
146
|
|
|
143
147
|
# Entitlement report ('who can do what')
|
|
144
148
|
bt epml rbp entitlement run
|
|
@@ -200,6 +204,9 @@ bt epml quick tests-then-deploy --suite <suite_id> # commits if pass; rollb
|
|
|
200
204
|
- **`POST /usergrps/multiple`** (bulk create): body is `{"usergroups": [...]}` — undocumented wrapper key.
|
|
201
205
|
- **POST on child collections is additive**, not replacing. Calling `commands add` twice with the same command will get you a duplicate.
|
|
202
206
|
- **Children share the parent's `id`** in GET responses — the listed `id` field is the cmdgrp/hostgrp/usergrp ID, not unique per child. The actual identifier is the `cmd`/`host`/`user` text.
|
|
207
|
+
- **Role assignments take a single object per request, not an array**. The CLI loops under the hood; the wire body is e.g. `{"cmds": 35}`, `{"hosts": 1, "type": "S"}`, `{"users": 4, "type": "R"}`, `{"tmdates": 1}`.
|
|
208
|
+
- **Hostgrp / usergrp assignments require a `type` field** (`S` = Submit / who requests, `R` = Run-as / whose identity the command runs under). Without `type` the request 400s with "RBP role type not in: [S,R]". CLI: `--kind S|R|B` on `roles hostgrps add` and `roles usergrps add`. `B` (default) creates both an S row and an R row for the same id — appropriate when the same group plays both roles. For "Admin requests, runs as root", do `--ids 4 --kind S` and `--ids 3 --kind R` separately.
|
|
209
|
+
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report. Not yet exposed by the CLI — file-level edit via export/import is the workaround.
|
|
203
210
|
|
|
204
211
|
## Known gaps (TODO)
|
|
205
212
|
|
|
@@ -132,13 +132,17 @@ bt epml rbp tmdategrps tmdates replace <tmdategrp_id> --file tmdates.json
|
|
|
132
132
|
|
|
133
133
|
# Roles + assignments
|
|
134
134
|
bt epml rbp roles list
|
|
135
|
-
bt epml rbp roles create --name "Helpdesk Role"
|
|
135
|
+
bt epml rbp roles create --name "Helpdesk Role" --action A \
|
|
136
|
+
--iolog '/iologs/%date%/%uniqueid%.iolog' \
|
|
137
|
+
--message "This session is logged."
|
|
136
138
|
bt epml rbp roles duplicate <role_id>
|
|
137
|
-
bt epml rbp roles cmdgrps add
|
|
139
|
+
bt epml rbp roles cmdgrps add <role_id> --ids 1,2 # cmdgrps & tmdategrps: just IDs
|
|
140
|
+
bt epml rbp roles tmdategrps add <role_id> --ids 1
|
|
141
|
+
bt epml rbp roles hostgrps add <role_id> --ids 1 --kind B # B = both Submit and Run-as
|
|
142
|
+
bt epml rbp roles usergrps add <role_id> --ids 4 --kind S # S = Submit (who requests)
|
|
143
|
+
bt epml rbp roles usergrps add <role_id> --ids 3 --kind R # R = Run-as (whose identity)
|
|
138
144
|
bt epml rbp roles cmdgrps remove <role_id> <cmdgrp_id>
|
|
139
145
|
bt epml rbp roles hostgrps list <role_id>
|
|
140
|
-
bt epml rbp roles usergrps add <role_id> --ids 5
|
|
141
|
-
bt epml rbp roles tmdategrps add <role_id> --ids 1
|
|
142
146
|
|
|
143
147
|
# Entitlement report ('who can do what')
|
|
144
148
|
bt epml rbp entitlement run
|
|
@@ -200,6 +204,9 @@ bt epml quick tests-then-deploy --suite <suite_id> # commits if pass; rollb
|
|
|
200
204
|
- **`POST /usergrps/multiple`** (bulk create): body is `{"usergroups": [...]}` — undocumented wrapper key.
|
|
201
205
|
- **POST on child collections is additive**, not replacing. Calling `commands add` twice with the same command will get you a duplicate.
|
|
202
206
|
- **Children share the parent's `id`** in GET responses — the listed `id` field is the cmdgrp/hostgrp/usergrp ID, not unique per child. The actual identifier is the `cmd`/`host`/`user` text.
|
|
207
|
+
- **Role assignments take a single object per request, not an array**. The CLI loops under the hood; the wire body is e.g. `{"cmds": 35}`, `{"hosts": 1, "type": "S"}`, `{"users": 4, "type": "R"}`, `{"tmdates": 1}`.
|
|
208
|
+
- **Hostgrp / usergrp assignments require a `type` field** (`S` = Submit / who requests, `R` = Run-as / whose identity the command runs under). Without `type` the request 400s with "RBP role type not in: [S,R]". CLI: `--kind S|R|B` on `roles hostgrps add` and `roles usergrps add`. `B` (default) creates both an S row and an R row for the same id — appropriate when the same group plays both roles. For "Admin requests, runs as root", do `--ids 4 --kind S` and `--ids 3 --kind R` separately.
|
|
209
|
+
- **Roles need `rpt: 1`** to appear in `bt epml rbp entitlement run`. The role still functions for policy evaluation either way, but only `rpt=1` roles are surfaced in the report. Not yet exposed by the CLI — file-level edit via export/import is the workaround.
|
|
203
210
|
|
|
204
211
|
## Known gaps (TODO)
|
|
205
212
|
|
|
@@ -489,9 +489,13 @@ class EPMLClient:
|
|
|
489
489
|
h = self.host(host_id)
|
|
490
490
|
return self.get(f"/api/pbul/{h}/rbp/roles/{role_id}/cmdgrps")
|
|
491
491
|
|
|
492
|
-
def add_role_cmdgrps(self, role_id: int, cmdgrp_ids: List[int], host_id: Optional[int] = None) -> Any:
|
|
492
|
+
def add_role_cmdgrps(self, role_id: int, cmdgrp_ids: List[int], host_id: Optional[int] = None) -> List[Any]:
|
|
493
|
+
"""Add cmdgrps to a role. The API accepts ONE assignment per request
|
|
494
|
+
as a bare object (`{cmds: <id>}`) — not an array. Loop here.
|
|
495
|
+
"""
|
|
493
496
|
h = self.host(host_id)
|
|
494
|
-
|
|
497
|
+
path = f"/api/pbul/{h}/rbp/roles/{role_id}/cmdgrps"
|
|
498
|
+
return [self.post(path, json={"cmds": cid}) for cid in cmdgrp_ids]
|
|
495
499
|
|
|
496
500
|
def remove_role_cmdgrp(self, role_id: int, cmdgrp_id: int, host_id: Optional[int] = None) -> None:
|
|
497
501
|
h = self.host(host_id)
|
|
@@ -501,9 +505,31 @@ class EPMLClient:
|
|
|
501
505
|
h = self.host(host_id)
|
|
502
506
|
return self.get(f"/api/pbul/{h}/rbp/roles/{role_id}/hostgrps")
|
|
503
507
|
|
|
504
|
-
def add_role_hostgrps(
|
|
508
|
+
def add_role_hostgrps(
|
|
509
|
+
self,
|
|
510
|
+
role_id: int,
|
|
511
|
+
hostgrp_ids: List[int],
|
|
512
|
+
kind: str = "B",
|
|
513
|
+
host_id: Optional[int] = None,
|
|
514
|
+
) -> List[Any]:
|
|
515
|
+
"""Add hostgrps to a role. Each assignment carries a `type`:
|
|
516
|
+
S = Submit (where the request comes from)
|
|
517
|
+
R = Run-as (where the command actually runs)
|
|
518
|
+
|
|
519
|
+
For a typical "users on these hosts can run on these same hosts" rule,
|
|
520
|
+
you usually want BOTH — pass `kind="B"` (default) and the client posts
|
|
521
|
+
twice, once with type S and once with type R.
|
|
522
|
+
"""
|
|
505
523
|
h = self.host(host_id)
|
|
506
|
-
|
|
524
|
+
path = f"/api/pbul/{h}/rbp/roles/{role_id}/hostgrps"
|
|
525
|
+
types = ("S", "R") if kind.upper() == "B" else (kind.upper(),)
|
|
526
|
+
if not all(t in ("S", "R") for t in types):
|
|
527
|
+
raise ValueError(f"hostgrp kind must be S, R, or B (both); got {kind!r}")
|
|
528
|
+
results = []
|
|
529
|
+
for hid in hostgrp_ids:
|
|
530
|
+
for t in types:
|
|
531
|
+
results.append(self.post(path, json={"hosts": hid, "type": t}))
|
|
532
|
+
return results
|
|
507
533
|
|
|
508
534
|
def remove_role_hostgrp(self, role_id: int, hostgrp_id: int, host_id: Optional[int] = None) -> None:
|
|
509
535
|
h = self.host(host_id)
|
|
@@ -513,9 +539,27 @@ class EPMLClient:
|
|
|
513
539
|
h = self.host(host_id)
|
|
514
540
|
return self.get(f"/api/pbul/{h}/rbp/roles/{role_id}/usergrps")
|
|
515
541
|
|
|
516
|
-
def add_role_usergrps(
|
|
542
|
+
def add_role_usergrps(
|
|
543
|
+
self,
|
|
544
|
+
role_id: int,
|
|
545
|
+
usergrp_ids: List[int],
|
|
546
|
+
kind: str = "B",
|
|
547
|
+
host_id: Optional[int] = None,
|
|
548
|
+
) -> List[Any]:
|
|
549
|
+
"""Add usergrps to a role. Same S/R/B `type` semantics as hostgrps.
|
|
550
|
+
S = Submit user (who requests)
|
|
551
|
+
R = Run-as user (whose identity the command runs under)
|
|
552
|
+
"""
|
|
517
553
|
h = self.host(host_id)
|
|
518
|
-
|
|
554
|
+
path = f"/api/pbul/{h}/rbp/roles/{role_id}/usergrps"
|
|
555
|
+
types = ("S", "R") if kind.upper() == "B" else (kind.upper(),)
|
|
556
|
+
if not all(t in ("S", "R") for t in types):
|
|
557
|
+
raise ValueError(f"usergrp kind must be S, R, or B (both); got {kind!r}")
|
|
558
|
+
results = []
|
|
559
|
+
for uid in usergrp_ids:
|
|
560
|
+
for t in types:
|
|
561
|
+
results.append(self.post(path, json={"users": uid, "type": t}))
|
|
562
|
+
return results
|
|
519
563
|
|
|
520
564
|
def remove_role_usergrp(self, role_id: int, usergrp_id: int, host_id: Optional[int] = None) -> None:
|
|
521
565
|
h = self.host(host_id)
|
|
@@ -525,9 +569,11 @@ class EPMLClient:
|
|
|
525
569
|
h = self.host(host_id)
|
|
526
570
|
return self.get(f"/api/pbul/{h}/rbp/roles/{role_id}/tmdategrps")
|
|
527
571
|
|
|
528
|
-
def add_role_tmdategrps(self, role_id: int, tmdategrp_ids: List[int], host_id: Optional[int] = None) -> Any:
|
|
572
|
+
def add_role_tmdategrps(self, role_id: int, tmdategrp_ids: List[int], host_id: Optional[int] = None) -> List[Any]:
|
|
573
|
+
"""Add tmdategrps to a role. Single object per request, key is `tmdates`."""
|
|
529
574
|
h = self.host(host_id)
|
|
530
|
-
|
|
575
|
+
path = f"/api/pbul/{h}/rbp/roles/{role_id}/tmdategrps"
|
|
576
|
+
return [self.post(path, json={"tmdates": tid}) for tid in tmdategrp_ids]
|
|
531
577
|
|
|
532
578
|
def remove_role_tmdategrp(self, role_id: int, tmdategrp_id: int, host_id: Optional[int] = None) -> None:
|
|
533
579
|
h = self.host(host_id)
|
|
@@ -46,20 +46,37 @@ def create_role(
|
|
|
46
46
|
name: str = typer.Option(..., "--name", "-n"),
|
|
47
47
|
description: str = typer.Option("", "--description", "-d"),
|
|
48
48
|
action: str = typer.Option("A", "--action", "-a", help="Role verdict: A=Allow, R=Reject"),
|
|
49
|
+
iolog: Optional[str] = typer.Option(
|
|
50
|
+
None, "--iolog",
|
|
51
|
+
help="I/O log path template (e.g. /iologs/%date%/%uniqueid%.iolog). Omit to disable.",
|
|
52
|
+
),
|
|
53
|
+
message: Optional[str] = typer.Option(None, "--message", "-m", help="Message shown to the requesting user"),
|
|
54
|
+
comment: Optional[str] = typer.Option(None, "--comment", help="Internal comment"),
|
|
55
|
+
disabled: bool = typer.Option(False, "--disabled", help="Create the role disabled"),
|
|
49
56
|
host: Optional[int] = _host_opt(),
|
|
50
57
|
):
|
|
51
58
|
"""Create a role.
|
|
52
59
|
|
|
53
60
|
The API requires `action` to be exactly `A` (Allow) or `R` (Reject) —
|
|
54
61
|
not 'Allow'/'Reject'. Defaults to A.
|
|
62
|
+
|
|
63
|
+
`iolog` accepts the appliance's path template syntax — typical value is
|
|
64
|
+
`/iologs/%date%/%uniqueid%.iolog`. Omit to disable I/O logging on this role.
|
|
55
65
|
"""
|
|
56
66
|
from bt_cli.epml.client import get_client
|
|
57
67
|
if action not in ("A", "R"):
|
|
58
68
|
typer.echo(f"--action must be 'A' or 'R', got {action!r}", err=True)
|
|
59
69
|
raise typer.Exit(2)
|
|
70
|
+
body = {"name": name, "description": description, "action": action, "disabled": disabled}
|
|
71
|
+
if iolog is not None:
|
|
72
|
+
body["iolog"] = iolog
|
|
73
|
+
if message is not None:
|
|
74
|
+
body["message"] = message
|
|
75
|
+
if comment is not None:
|
|
76
|
+
body["comment"] = comment
|
|
60
77
|
try:
|
|
61
78
|
with get_client() as c:
|
|
62
|
-
result = c.create_role(
|
|
79
|
+
result = c.create_role(body, host_id=host)
|
|
63
80
|
print_json(result)
|
|
64
81
|
except httpx.HTTPStatusError as e:
|
|
65
82
|
print_api_error(e, "create role"); raise typer.Exit(1)
|
|
@@ -104,15 +121,20 @@ def duplicate_role(
|
|
|
104
121
|
|
|
105
122
|
# ---- assignments: cmdgrps / hostgrps / usergrps / tmdategrps ----
|
|
106
123
|
|
|
107
|
-
def _make_assignment_app(label: str, list_fn: str, add_fn: str, remove_fn: str):
|
|
108
|
-
"""Build a sub-typer for managing one role-child resource type.
|
|
124
|
+
def _make_assignment_app(label: str, list_fn: str, add_fn: str, remove_fn: str, has_kind: bool = False):
|
|
125
|
+
"""Build a sub-typer for managing one role-child resource type.
|
|
126
|
+
|
|
127
|
+
has_kind: if True, expose --kind S|R|B (Submit / Run-as / Both). Used for
|
|
128
|
+
hostgrps and usergrps where each assignment carries a type. Cmdgrps and
|
|
129
|
+
tmdategrps don't take a kind.
|
|
130
|
+
"""
|
|
109
131
|
sub = typer.Typer(no_args_is_help=True, help=f"Manage {label} on a role")
|
|
110
132
|
|
|
111
133
|
@sub.command("list")
|
|
112
134
|
def _list(
|
|
113
135
|
role_id: int = typer.Argument(..., help="Role ID"),
|
|
114
136
|
host: Optional[int] = _host_opt(),
|
|
115
|
-
output: OutputFormat = typer.Option(OutputFormat.
|
|
137
|
+
output: OutputFormat = typer.Option(OutputFormat.JSON, "--output", "-o"),
|
|
116
138
|
):
|
|
117
139
|
f"""List {label} assigned to a role."""
|
|
118
140
|
from bt_cli.epml.client import get_client
|
|
@@ -123,29 +145,60 @@ def _make_assignment_app(label: str, list_fn: str, add_fn: str, remove_fn: str):
|
|
|
123
145
|
print_json(data)
|
|
124
146
|
else:
|
|
125
147
|
rows = data if isinstance(data, list) else (data.get("data", []) if isinstance(data, dict) else [])
|
|
126
|
-
|
|
148
|
+
# Best-effort table: include `type` column when present
|
|
149
|
+
if rows and isinstance(rows[0], dict) and "type" in rows[0]:
|
|
150
|
+
cols = [(k.upper(), k) for k in rows[0].keys()]
|
|
151
|
+
else:
|
|
152
|
+
cols = [("ID", "id"), ("Name", "name")]
|
|
153
|
+
print_table(rows, cols, title=f"{label} on role {role_id}")
|
|
127
154
|
except httpx.HTTPStatusError as e:
|
|
128
155
|
print_api_error(e, f"list role {label}"); raise typer.Exit(1)
|
|
129
156
|
except Exception as e:
|
|
130
157
|
print_api_error(e, f"list role {label}"); raise typer.Exit(1)
|
|
131
158
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
159
|
+
if has_kind:
|
|
160
|
+
@sub.command("add")
|
|
161
|
+
def _add(
|
|
162
|
+
role_id: int = typer.Argument(..., help="Role ID"),
|
|
163
|
+
ids: str = typer.Option(..., "--ids", help=f"Comma-separated {label} IDs to add"),
|
|
164
|
+
kind: str = typer.Option(
|
|
165
|
+
"B", "--kind", "-k",
|
|
166
|
+
help="Assignment type: S=Submit, R=Run-as, B=Both (creates two assignments per id)",
|
|
167
|
+
),
|
|
168
|
+
host: Optional[int] = _host_opt(),
|
|
169
|
+
):
|
|
170
|
+
f"""Add {label} to a role."""
|
|
171
|
+
from bt_cli.epml.client import get_client
|
|
172
|
+
if kind.upper() not in ("S", "R", "B"):
|
|
173
|
+
typer.echo(f"--kind must be S, R, or B; got {kind!r}", err=True)
|
|
174
|
+
raise typer.Exit(2)
|
|
175
|
+
try:
|
|
176
|
+
id_list = [int(x.strip()) for x in ids.split(",") if x.strip()]
|
|
177
|
+
with get_client() as c:
|
|
178
|
+
result = getattr(c, add_fn)(role_id, id_list, kind=kind.upper(), host_id=host)
|
|
179
|
+
print_json(result)
|
|
180
|
+
except httpx.HTTPStatusError as e:
|
|
181
|
+
print_api_error(e, f"add role {label}"); raise typer.Exit(1)
|
|
182
|
+
except Exception as e:
|
|
183
|
+
print_api_error(e, f"add role {label}"); raise typer.Exit(1)
|
|
184
|
+
else:
|
|
185
|
+
@sub.command("add")
|
|
186
|
+
def _add(
|
|
187
|
+
role_id: int = typer.Argument(..., help="Role ID"),
|
|
188
|
+
ids: str = typer.Option(..., "--ids", help=f"Comma-separated {label} IDs to add"),
|
|
189
|
+
host: Optional[int] = _host_opt(),
|
|
190
|
+
):
|
|
191
|
+
f"""Add {label} to a role."""
|
|
192
|
+
from bt_cli.epml.client import get_client
|
|
193
|
+
try:
|
|
194
|
+
id_list = [int(x.strip()) for x in ids.split(",") if x.strip()]
|
|
195
|
+
with get_client() as c:
|
|
196
|
+
result = getattr(c, add_fn)(role_id, id_list, host_id=host)
|
|
197
|
+
print_json(result)
|
|
198
|
+
except httpx.HTTPStatusError as e:
|
|
199
|
+
print_api_error(e, f"add role {label}"); raise typer.Exit(1)
|
|
200
|
+
except Exception as e:
|
|
201
|
+
print_api_error(e, f"add role {label}"); raise typer.Exit(1)
|
|
149
202
|
|
|
150
203
|
@sub.command("remove")
|
|
151
204
|
def _remove(
|
|
@@ -168,6 +221,6 @@ def _make_assignment_app(label: str, list_fn: str, add_fn: str, remove_fn: str):
|
|
|
168
221
|
|
|
169
222
|
|
|
170
223
|
app.add_typer(_make_assignment_app("cmdgrps", "list_role_cmdgrps", "add_role_cmdgrps", "remove_role_cmdgrp"), name="cmdgrps")
|
|
171
|
-
app.add_typer(_make_assignment_app("hostgrps", "list_role_hostgrps", "add_role_hostgrps", "remove_role_hostgrp"), name="hostgrps")
|
|
172
|
-
app.add_typer(_make_assignment_app("usergrps", "list_role_usergrps", "add_role_usergrps", "remove_role_usergrp"), name="usergrps")
|
|
224
|
+
app.add_typer(_make_assignment_app("hostgrps", "list_role_hostgrps", "add_role_hostgrps", "remove_role_hostgrp", has_kind=True), name="hostgrps")
|
|
225
|
+
app.add_typer(_make_assignment_app("usergrps", "list_role_usergrps", "add_role_usergrps", "remove_role_usergrp", has_kind=True), name="usergrps")
|
|
173
226
|
app.add_typer(_make_assignment_app("tmdategrps", "list_role_tmdategrps", "add_role_tmdategrps", "remove_role_tmdategrp"), name="tmdategrps")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|