netbox-super-cli 1.6.3__tar.gz → 1.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.
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/bench.yml +2 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/claude.yml +2 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/docs.yml +5 -5
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/e2e.yml +37 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/lint.yml +6 -6
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/release.yml +3 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/test.yml +2 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.gitignore +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.pre-commit-config.yaml +2 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/AGENTS.md +2 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/CHANGELOG.md +123 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/CLAUDE.md +2 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/PKG-INFO +24 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/README.md +20 -0
- netbox_super_cli-1.8.0/SECURITY.md +12 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/http-client.md +14 -5
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/overview.md +3 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/release-process.md +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/concepts.md +16 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/first-run.md +6 -2
- netbox_super_cli-1.8.0/docs/guides/branching.md +135 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/ci-and-automation.md +17 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/interactive-tui.md +16 -0
- netbox_super_cli-1.8.0/docs/guides/keyring.md +86 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/managing-profiles.md +29 -6
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/output-formats.md +5 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/using-with-ai-agents.md +1 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/working-with-plugins.md +11 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/writes-and-safety.md +17 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/index.md +3 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/config.md +2 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/justfile +14 -4
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/mkdocs.yml +2 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/_version.py +1 -1
- netbox_super_cli-1.8.0/nsc/auth/keyring_store.py +77 -0
- netbox_super_cli-1.8.0/nsc/auth/verify.py +199 -0
- netbox_super_cli-1.8.0/nsc/branching/__init__.py +5 -0
- netbox_super_cli-1.8.0/nsc/branching/api.py +100 -0
- netbox_super_cli-1.8.0/nsc/branching/errors.py +82 -0
- netbox_super_cli-1.8.0/nsc/branching/jobs.py +57 -0
- netbox_super_cli-1.8.0/nsc/branching/models.py +42 -0
- netbox_super_cli-1.8.0/nsc/branching/resolve.py +46 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/aliases_commands.py +4 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/app.py +38 -1
- netbox_super_cli-1.8.0/nsc/cli/branch_commands.py +460 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/cache_commands.py +7 -4
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/globals.py +15 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/handlers.py +23 -9
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/login_commands.py +153 -25
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/profiles_commands.py +2 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/registration.py +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/runtime.py +106 -9
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/tui_commands.py +19 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/bulk.py +3 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/cache_probe.py +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/callbacks.py +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/loader.py +11 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/models.py +31 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/writer.py +6 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/audit.py +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/client.py +66 -41
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/errors.py +4 -0
- netbox_super_cli-1.8.0/nsc/http/pagination.py +78 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/retry.py +5 -4
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/loader.py +4 -4
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/source.py +6 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/__init__.py +2 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/app.py +6 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/keymap.py +1 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/list.py +104 -7
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/styles.tcss +6 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/view.py +11 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/pyproject.toml +11 -5
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/scripts/gen_docs.py +1 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/skills/netbox-super-cli/SKILL.md +31 -1
- netbox_super_cli-1.8.0/tests/auth/test_keyring_store.py +58 -0
- netbox_super_cli-1.8.0/tests/auth/test_verify.py +283 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/benchmarks/test_startup.py +7 -2
- netbox_super_cli-1.8.0/tests/branching/_fixtures.py +54 -0
- netbox_super_cli-1.8.0/tests/branching/test_api.py +159 -0
- netbox_super_cli-1.8.0/tests/branching/test_jobs.py +70 -0
- netbox_super_cli-1.8.0/tests/branching/test_resolve.py +106 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_aliases_commands.py +106 -129
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_app_smoke.py +23 -27
- netbox_super_cli-1.8.0/tests/cli/test_branch_commands.py +275 -0
- netbox_super_cli-1.8.0/tests/cli/test_branch_lifecycle.py +179 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_cache_commands.py +31 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_commands_dump.py +10 -7
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_handlers.py +72 -0
- netbox_super_cli-1.8.0/tests/cli/test_lazy_httpx2_import.py +52 -0
- netbox_super_cli-1.8.0/tests/cli/test_lazy_keyring_import.py +27 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_login_commands.py +57 -43
- netbox_super_cli-1.8.0/tests/cli/test_login_keyring.py +528 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_ndjson_input.py +14 -15
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_profiles_commands.py +6 -10
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_respx_integration.py +39 -37
- netbox_super_cli-1.8.0/tests/cli/test_runtime_branch.py +135 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_tui_command.py +2 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_writes_respx.py +108 -120
- netbox_super_cli-1.8.0/tests/config/test_keyring_tag.py +67 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_models.py +6 -0
- netbox_super_cli-1.8.0/tests/conftest.py +85 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/README.md +12 -0
- netbox_super_cli-1.8.0/tests/e2e/branching/Dockerfile +5 -0
- netbox_super_cli-1.8.0/tests/e2e/branching/plugins.py +21 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/conftest.py +13 -5
- netbox_super_cli-1.8.0/tests/e2e/docker-compose.branching.yml +45 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_audit_redaction.py +2 -2
- netbox_super_cli-1.8.0/tests/e2e/test_branching.py +137 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_bulk_create_with_loop_fallback.py +3 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_full_cycle.py +2 -2
- netbox_super_cli-1.8.0/tests/e2e/test_keyring_roundtrip.py +79 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_login.py +55 -4
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_ndjson.py +3 -3
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_preflight_blocks_apply.py +2 -2
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_validation_error_envelope_from_netbox.py +2 -2
- netbox_super_cli-1.8.0/tests/http/test_client.py +412 -0
- netbox_super_cli-1.8.0/tests/http/test_client_branch.py +112 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_client_redaction_threading.py +10 -10
- netbox_super_cli-1.8.0/tests/http/test_pagination.py +127 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_retry.py +7 -7
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_loader.py +14 -24
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_source.py +29 -35
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_source_ttl.py +46 -50
- netbox_super_cli-1.8.0/tests/tui/__init__.py +0 -0
- netbox_super_cli-1.8.0/tests/tui/test_branch_indicator.py +24 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_list_screen.py +298 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_view.py +17 -1
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/uv.lock +365 -285
- netbox_super_cli-1.6.3/nsc/auth/verify.py +0 -143
- netbox_super_cli-1.6.3/tests/auth/test_verify.py +0 -84
- netbox_super_cli-1.6.3/tests/conftest.py +0 -41
- netbox_super_cli-1.6.3/tests/http/test_client.py +0 -384
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/docs.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/dependabot.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/pull_request_template.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.github/workflows/skill-convention-review.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/.python-version +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/LICENSE +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/caching.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/command-generation.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/architecture/schema-loading.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/detail.svg +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/filter.svg +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/list.svg +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/picker.svg +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/assets/tui/search.svg +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/adding-bundled-schemas.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/branching.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/contributing/development.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/getting-started/install.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/guides/audit-log.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/cli.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/exit-codes.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/docs/reference/schemas.md +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/__main__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/aliases/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/aliases/resolver.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/auth/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/builder/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/builder/build.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cache/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cache/store.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/commands_dump.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/config_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/init_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/skill_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/apply.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/coercion.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/confirmation.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/input.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/cli/writes/preflight.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/completion/providers.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/saved_searches.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/config/settings.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/http/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/model/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/model/command_model.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/_console.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/colors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/csv_.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/errors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/explain.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/flatten.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/headers.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/json_.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/jsonl.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/render.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/table.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/output/yaml_.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/custom_fields.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/objecttypes.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/params.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/store.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/savedfilters/tags.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/hashing.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schema/models.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/manifest.yaml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/netbox-4.5.10.json.gz +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/schemas/bundled/netbox-4.6.0.json.gz +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/skill/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/_bindings.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/bulk.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/catalog.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/columns.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/errors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/filters.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/fk.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/forms.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/nav.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/relations.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/bulk_edit_form.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/columns.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/detail.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/edit_form.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/filter.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/global_search.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/picker.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/record_picker.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/screens/saved_search_picker.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/search.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/selection.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/_modal.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/bulk_diff.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/bulk_summary.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/confirm.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/diff.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/help.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/nsc/tui/widgets/nav_tree.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/scripts/sync_agents_md.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/aliases/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/aliases/test_resolver.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/audit/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/audit/test_redaction_full.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/auth/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/benchmarks/__init__.py +0 -0
- {netbox_super_cli-1.6.3/tests/builder → netbox_super_cli-1.8.0/tests/branching}/__init__.py +0 -0
- {netbox_super_cli-1.6.3/tests/cache → netbox_super_cli-1.8.0/tests/builder}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_build.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_default_columns.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_fk_metadata.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_redaction_marking.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/builder/test_request_body_shape.py +0 -0
- {netbox_super_cli-1.6.3/tests/cli → netbox_super_cli-1.8.0/tests/cache}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cache/test_prune.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cache/test_store.py +0 -0
- {netbox_super_cli-1.6.3/tests/cli/writes → netbox_super_cli-1.8.0/tests/cli}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_completion_protocol_smoke.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_completion_smoke.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_config_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_dynamic_completion.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_explain.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_globals_color.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_init_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_lazy_textual_import.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_meta_subcommands_under_broken_config.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_registration.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_runtime.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_runtime_color.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_skill_commands.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/test_stdin_sniffer.py +0 -0
- {netbox_super_cli-1.6.3/tests/config → netbox_super_cli-1.8.0/tests/cli/writes}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_apply.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_bulk.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_confirmation.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_handler_helpers.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_handlers_audit.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_input.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/cli/writes/test_preflight.py +0 -0
- {netbox_super_cli-1.6.3/tests/http → netbox_super_cli-1.8.0/tests/config}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_loader.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_saved_search_fallback.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_saved_searches.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_settings_private_dir.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_atomicity.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_dotted_paths.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/config/test_writer_roundtrip.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/docker-compose.yml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/test_auth_error_envelope.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/e2e/wait_for_netbox.sh +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/profiles/single_profile.yaml +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/auth_401.json +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/circuits_providers_list.json +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_get.json +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_list_p1.json +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/fixtures/responses/dcim_devices_list_p2.json +0 -0
- {netbox_super_cli-1.6.3/tests/model → netbox_super_cli-1.8.0/tests/http}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit_permissions.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_audit_redaction.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/http/test_errors.py +0 -0
- {netbox_super_cli-1.6.3/tests/output → netbox_super_cli-1.8.0/tests/model}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/model/test_command_model.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/model/test_request_body_shape.py +0 -0
- {netbox_super_cli-1.6.3/tests/savedfilters → netbox_super_cli-1.8.0/tests/output}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_colors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_console.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_csv.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors_aliases.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_errors_color.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_explain.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_explain_color.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_flatten.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_input_error_envelope.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_json.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_jsonl.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_render_dispatch.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_table.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_table_color.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/output/test_yaml.py +0 -0
- {netbox_super_cli-1.6.3/tests/schema → netbox_super_cli-1.8.0/tests/savedfilters}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_custom_fields.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_objecttypes.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_params.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_store.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/savedfilters/test_tags.py +0 -0
- {netbox_super_cli-1.6.3/tests/scripts → netbox_super_cli-1.8.0/tests/schema}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_hashing.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/schema/test_models.py +0 -0
- {netbox_super_cli-1.6.3/tests/skill → netbox_super_cli-1.8.0/tests/scripts}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/scripts/test_gen_docs.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/scripts/test_sync_agents_md.py +0 -0
- {netbox_super_cli-1.6.3/tests/tui → netbox_super_cli-1.8.0/tests/skill}/__init__.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/skill/test_bundle.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/test_packaging.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_app.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bindings.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_apply.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_diff.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_diff_modal.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_edit_form.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_import_isolation.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_bulk_summary.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_catalog.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_column_chooser.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_columns.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_detail_screen.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_diff.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_diff_modal.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_edit_form.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_errors.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_filter_screen.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_filters.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_fk_resolve.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_forms.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_global_search.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_help_overlay.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_keymap.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_picker.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_record_picker.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_relations.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_saved_filter_integration.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_search.py +0 -0
- {netbox_super_cli-1.6.3 → netbox_super_cli-1.8.0}/tests/tui/test_selection.py +0 -0
|
@@ -13,8 +13,8 @@ jobs:
|
|
|
13
13
|
startup-time:
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@v7
|
|
17
|
-
- uses: astral-sh/setup-uv@
|
|
16
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
17
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
18
18
|
- name: Install
|
|
19
19
|
run: uv sync --all-extras --dev
|
|
20
20
|
- name: Benchmark
|
|
@@ -41,13 +41,13 @@ jobs:
|
|
|
41
41
|
actions: read # Required for Claude to read CI results on PRs
|
|
42
42
|
steps:
|
|
43
43
|
- name: Checkout repository
|
|
44
|
-
uses: actions/checkout@v7
|
|
44
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
45
45
|
with:
|
|
46
46
|
fetch-depth: 1
|
|
47
47
|
|
|
48
48
|
- name: Run Claude Code
|
|
49
49
|
id: claude
|
|
50
|
-
uses: anthropics/claude-code-action@v1
|
|
50
|
+
uses: anthropics/claude-code-action@db77d4d3c98f3f6380e7cd45ffba2342a3dbde3c # v1
|
|
51
51
|
with:
|
|
52
52
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
53
53
|
|
|
@@ -26,9 +26,9 @@ jobs:
|
|
|
26
26
|
build:
|
|
27
27
|
runs-on: ubuntu-latest
|
|
28
28
|
steps:
|
|
29
|
-
- uses: actions/checkout@v7
|
|
29
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
30
30
|
- name: Install uv
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
31
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
32
32
|
with:
|
|
33
33
|
enable-cache: true
|
|
34
34
|
- name: Install Python
|
|
@@ -36,10 +36,10 @@ jobs:
|
|
|
36
36
|
- name: Sync deps (runtime + docs)
|
|
37
37
|
run: uv sync --frozen --group docs
|
|
38
38
|
- name: Build site (strict)
|
|
39
|
-
run: uv run
|
|
39
|
+
run: uv run zensical build --strict
|
|
40
40
|
- name: Upload Pages artifact
|
|
41
41
|
if: github.ref_type == 'tag'
|
|
42
|
-
uses: actions/upload-pages-artifact@v5
|
|
42
|
+
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
|
|
43
43
|
with:
|
|
44
44
|
path: site
|
|
45
45
|
|
|
@@ -52,4 +52,4 @@ jobs:
|
|
|
52
52
|
url: ${{ steps.deployment.outputs.page_url }}
|
|
53
53
|
steps:
|
|
54
54
|
- id: deployment
|
|
55
|
-
uses: actions/deploy-pages@v5
|
|
55
|
+
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5
|
|
@@ -6,6 +6,11 @@ on:
|
|
|
6
6
|
pull_request:
|
|
7
7
|
paths:
|
|
8
8
|
- 'nsc/http/**'
|
|
9
|
+
- 'nsc/branching/**'
|
|
10
|
+
- 'nsc/cli/branch_commands.py'
|
|
11
|
+
- 'nsc/auth/**'
|
|
12
|
+
- 'nsc/cli/login_commands.py'
|
|
13
|
+
- 'nsc/cli/profiles_commands.py'
|
|
9
14
|
- 'nsc/cli/handlers.py'
|
|
10
15
|
- 'nsc/cli/registration.py'
|
|
11
16
|
- 'nsc/cli/writes/**'
|
|
@@ -34,8 +39,8 @@ jobs:
|
|
|
34
39
|
env:
|
|
35
40
|
NETBOX_IMAGE: netboxcommunity/netbox:${{ matrix.netbox-version }}
|
|
36
41
|
steps:
|
|
37
|
-
- uses: actions/checkout@v7
|
|
38
|
-
- uses: astral-sh/setup-uv@
|
|
42
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
43
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
39
44
|
- name: Sync deps
|
|
40
45
|
run: uv sync --frozen
|
|
41
46
|
- name: Start NetBox
|
|
@@ -54,3 +59,33 @@ jobs:
|
|
|
54
59
|
- name: Stop NetBox
|
|
55
60
|
if: always()
|
|
56
61
|
run: docker compose -f tests/e2e/docker-compose.yml down -v
|
|
62
|
+
|
|
63
|
+
e2e-branching:
|
|
64
|
+
name: e2e-branching (v4.7.3 + branching 1.2.2)
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
timeout-minutes: 20
|
|
67
|
+
env:
|
|
68
|
+
NETBOX_IMAGE: netboxcommunity/netbox:v4.7.3
|
|
69
|
+
COMPOSE: -f tests/e2e/docker-compose.yml -f tests/e2e/docker-compose.branching.yml
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
72
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
73
|
+
- name: Sync deps
|
|
74
|
+
run: uv sync --frozen
|
|
75
|
+
- name: Build and start NetBox with Branching
|
|
76
|
+
run: docker compose $COMPOSE up -d --build
|
|
77
|
+
- name: Wait for NetBox
|
|
78
|
+
run: tests/e2e/wait_for_netbox.sh
|
|
79
|
+
- name: Run branching e2e tests
|
|
80
|
+
env:
|
|
81
|
+
NSC_E2E: '1'
|
|
82
|
+
NSC_E2E_BRANCHING: '1'
|
|
83
|
+
NSC_URL: http://127.0.0.1:8080
|
|
84
|
+
NSC_TOKEN: '0123456789abcdef0123456789abcdef01234567'
|
|
85
|
+
run: uv run pytest tests/e2e/test_branching.py -v
|
|
86
|
+
- name: Dump container logs on failure
|
|
87
|
+
if: failure()
|
|
88
|
+
run: docker compose $COMPOSE logs
|
|
89
|
+
- name: Stop NetBox
|
|
90
|
+
if: always()
|
|
91
|
+
run: docker compose $COMPOSE down -v
|
|
@@ -12,9 +12,9 @@ jobs:
|
|
|
12
12
|
lint:
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@v7
|
|
15
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
16
16
|
- name: Install uv
|
|
17
|
-
uses: astral-sh/setup-uv@
|
|
17
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
18
18
|
with:
|
|
19
19
|
enable-cache: true
|
|
20
20
|
- name: Install Python
|
|
@@ -31,9 +31,9 @@ jobs:
|
|
|
31
31
|
docs-reference-fresh:
|
|
32
32
|
runs-on: ubuntu-latest
|
|
33
33
|
steps:
|
|
34
|
-
- uses: actions/checkout@v7
|
|
34
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
35
35
|
- name: Install uv
|
|
36
|
-
uses: astral-sh/setup-uv@
|
|
36
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
37
37
|
with:
|
|
38
38
|
enable-cache: true
|
|
39
39
|
- name: Install Python
|
|
@@ -46,9 +46,9 @@ jobs:
|
|
|
46
46
|
agents-md-fresh:
|
|
47
47
|
runs-on: ubuntu-latest
|
|
48
48
|
steps:
|
|
49
|
-
- uses: actions/checkout@v7
|
|
49
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
50
50
|
- name: Install uv
|
|
51
|
-
uses: astral-sh/setup-uv@
|
|
51
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
52
52
|
with:
|
|
53
53
|
enable-cache: true
|
|
54
54
|
- name: Install Python
|
|
@@ -39,7 +39,7 @@ jobs:
|
|
|
39
39
|
# prerequisites).
|
|
40
40
|
steps:
|
|
41
41
|
- name: Checkout (full history for changelog notes)
|
|
42
|
-
uses: actions/checkout@
|
|
42
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
43
43
|
with:
|
|
44
44
|
fetch-depth: 0
|
|
45
45
|
|
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
echo "Tag $GITHUB_REF_NAME ($GITHUB_SHA) is on main."
|
|
63
63
|
|
|
64
64
|
- name: Install uv
|
|
65
|
-
uses: astral-sh/setup-uv@
|
|
65
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
66
66
|
with:
|
|
67
67
|
enable-cache: true
|
|
68
68
|
|
|
@@ -110,7 +110,7 @@ jobs:
|
|
|
110
110
|
fi
|
|
111
111
|
|
|
112
112
|
- name: Publish to PyPI (trusted publishing)
|
|
113
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
113
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
114
114
|
with:
|
|
115
115
|
# No `password:` — trusted publishing uses the OIDC token bound
|
|
116
116
|
# to id-token: write above. PyPI must have a Trusted Publisher
|
|
@@ -16,9 +16,9 @@ jobs:
|
|
|
16
16
|
matrix:
|
|
17
17
|
python: ["3.12", "3.13", "3.14"]
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@v7
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
20
20
|
- name: Install uv
|
|
21
|
-
uses: astral-sh/setup-uv@
|
|
21
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
22
22
|
with:
|
|
23
23
|
enable-cache: true
|
|
24
24
|
- name: Install Python
|
|
@@ -27,11 +27,12 @@ repos:
|
|
|
27
27
|
- click>=8.1
|
|
28
28
|
- typer>=0.12
|
|
29
29
|
- rich>=13.7
|
|
30
|
-
-
|
|
30
|
+
- httpx2>=2.5
|
|
31
31
|
- "ruamel.yaml>=0.18"
|
|
32
32
|
- structlog>=24.1
|
|
33
33
|
- platformdirs>=4.2
|
|
34
34
|
- textual>=0.50
|
|
35
|
+
- keyring>=25.0
|
|
35
36
|
- types-PyYAML>=6.0
|
|
36
37
|
args: [--strict]
|
|
37
38
|
files: ^(nsc|scripts)/
|
|
@@ -15,11 +15,12 @@ This is the contributor guide for AI agents (and humans!) modifying this repo. T
|
|
|
15
15
|
- `nsc/model/` — the normalized command tree (data only, framework-free). The "brain".
|
|
16
16
|
- `nsc/builder/` — converts a parsed schema into a `CommandModel`.
|
|
17
17
|
- `nsc/cli/` — the Typer app; consumes a `CommandModel`.
|
|
18
|
-
- `nsc/http/` — thin
|
|
18
|
+
- `nsc/http/` — thin httpx2 wrapper: auth, retries, audit log.
|
|
19
19
|
- `nsc/output/` — formatters (table/json/jsonl/yaml/csv) + error envelope.
|
|
20
20
|
- `nsc/config/` — config loader + Pydantic models + ruamel.yaml round-trip writer.
|
|
21
21
|
- `nsc/cache/` — disk cache for generated command-models.
|
|
22
22
|
- `nsc/auth/` — login verification helpers (pre-flight probes, token rotate).
|
|
23
|
+
- `nsc/branching/` — NetBox Branching: branch name→schema_id resolution, lifecycle API calls, job polling. Framework-free; `nsc/http` must not import it (the client takes a resolver callable).
|
|
23
24
|
- `nsc/aliases/` — curated alias resolver (`ls`, `get`, `rm`, `search`). Framework-free.
|
|
24
25
|
- `nsc/completion/` — dynamic shell-completion: framework-free providers + cheap on-disk cache probe + Typer `shell_complete` callbacks.
|
|
25
26
|
- `nsc/skill/` — bundle-path helper for the portable `SKILL.md` shipped in the wheel.
|
|
@@ -2,6 +2,129 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to netbox-super-cli are tracked here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loosely. From v1.0.0 onward, releases follow [Semantic Versioning](https://semver.org/) and the version in `pyproject.toml` matches the git tag. Pre-1.0 milestones (Phase 1-5) were pinned by tag while `pyproject.toml` stayed at `0.0.1`.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## v1.8.0 — 2026-10-22
|
|
8
|
+
|
|
9
|
+
Minor release. Adds NetBox Branching support (`--branch`, `NSC_BRANCH`,
|
|
10
|
+
`nsc branch …`), so changes can be staged in a branch, reviewed and merged.
|
|
11
|
+
Also adds OS keyring token storage, lazy TUI pagination with CLI truncation
|
|
12
|
+
notices, and a fix for `nsc login` reporting the wrong user.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **NetBox Branching support** ([#166]). Run any command inside a
|
|
17
|
+
[NetBox Branching](https://netboxlabs.com/docs/extensions/branching/) branch
|
|
18
|
+
with `--branch NAME`, `NSC_BRANCH`, or a sticky per-profile branch set by
|
|
19
|
+
`nsc branch use NAME` (`--branch main` forces main). nsc resolves the name
|
|
20
|
+
to the plugin's `schema_id` and sends `X-NetBox-Branch` on every request.
|
|
21
|
+
Each command run in a branch prints `⎇ branch: <name>` on stderr, and the
|
|
22
|
+
TUI header shows it. A missing or non-`ready` branch fails loudly (exit
|
|
23
|
+
9/12) and never falls back to main. New `nsc branch` group: `list`, `show`,
|
|
24
|
+
`current`, `create` (waits until ready, `--use`), `use` / `use --main`,
|
|
25
|
+
`diff`, and `sync` / `merge` / `revert` / `archive` / `delete`. Like every
|
|
26
|
+
nsc write, these are dry-run unless you pass `--apply`. Conflicts exit 10
|
|
27
|
+
with `details.conflicts`, and `--acknowledge-conflicts` proceeds anyway.
|
|
28
|
+
Targets NetBox 4.7 with `netboxlabs-netbox-branching` 1.2.x; a new
|
|
29
|
+
`e2e-branching` CI job runs it live. See the
|
|
30
|
+
[branching guide](docs/guides/branching.md).
|
|
31
|
+
- **OS keyring token storage** ([#1]). A new `token: !keyring NAME` config tag
|
|
32
|
+
resolves the token from the OS keyring (macOS Keychain, Secret Service,
|
|
33
|
+
Windows Credential Manager) under service `nsc`, username `NAME`.
|
|
34
|
+
`nsc login --new|--rotate --store keyring [--keyring-name NAME]` verifies the
|
|
35
|
+
token, writes it to the keyring, and stores only the `!keyring` reference in
|
|
36
|
+
`~/.nsc/config.yaml`, so the plaintext token never touches disk. Any
|
|
37
|
+
invocation that builds the dynamic command tree reads the keyring, including
|
|
38
|
+
bare `nsc` and `nsc --help`; shell completion and the meta commands
|
|
39
|
+
(`config`, `profiles`, `cache`, `init`, `commands`, `skill`) do not. A missing
|
|
40
|
+
entry or an unavailable backend yields a `config` error envelope (exit 12),
|
|
41
|
+
except that `--help` on a static command still prints usage. `nsc login`
|
|
42
|
+
refuses to overwrite a keyring entry that another profile still references
|
|
43
|
+
(for example after `nsc profiles rename`) and asks for a distinct
|
|
44
|
+
`--keyring-name`. `keyring`
|
|
45
|
+
is a new core dependency, imported lazily so it adds no startup cost. See
|
|
46
|
+
the new [OS keyring storage guide](docs/guides/keyring.md).
|
|
47
|
+
`--keyring-name` is stripped of surrounding whitespace, and a blank name is
|
|
48
|
+
rejected as a usage error before the token prompt.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- **`nsc login` / `nsc profiles add` no longer report a random user** ([#150]).
|
|
53
|
+
The identity probe used to take the owner of the first row of
|
|
54
|
+
`/api/users/tokens/`, which for admins is often another user's token. The
|
|
55
|
+
caller is now identified from the token they presented: v2 (`nbt_…`) tokens
|
|
56
|
+
are looked up by their non-secret key id; v1 tokens are matched client-side
|
|
57
|
+
against the retrievable plaintext when NetBox exposes it
|
|
58
|
+
(`ALLOW_TOKEN_RETRIEVAL`; the plaintext is never sent in a query string), or
|
|
59
|
+
by every visible token sharing one owner. When the user cannot be determined reliably, nsc prints
|
|
60
|
+
`authenticated (user unknown)` instead of guessing.
|
|
61
|
+
- **`nsc tui` lists are no longer capped at the first page** ([#151]). The list
|
|
62
|
+
screen loads 100 rows at a time and fetches the next chunk (following NetBox
|
|
63
|
+
`next` links) when the cursor reaches the last row or you press <kbd>m</kbd>.
|
|
64
|
+
The header shows `N of M` (rows loaded vs. the server's `count`). Loading stops
|
|
65
|
+
at 10,000 rows with a hint to filter instead. A page that fails mid-chunk
|
|
66
|
+
keeps the rows already received (retry with <kbd>m</kbd>), and a refresh no
|
|
67
|
+
longer drops selections made beyond the first chunk.
|
|
68
|
+
- **A negative `--limit` is now a usage error** instead of a Python traceback,
|
|
69
|
+
and `defaults.page_size` must be at least 1.
|
|
70
|
+
- **CLI `list` / `ls` / `search` now report truncation** ([#151]). When the
|
|
71
|
+
default page size hides records the server still has, a one-line
|
|
72
|
+
`nsc: showing 50 of 1234 results; pass --all ...` notice is printed on stderr
|
|
73
|
+
(stdout is unchanged). The default page also no longer fetches one extra page
|
|
74
|
+
from the server just to discard it.
|
|
75
|
+
- **Pages after the first keep multi-value filters** ([#151]). Following a
|
|
76
|
+
NetBox `next` link no longer drops repeated query keys, so
|
|
77
|
+
`--site a --site b --all` returns both sites on every page.
|
|
78
|
+
- **Pagination works when NetBox is served under a sub-path** (`BASE_PATH`,
|
|
79
|
+
e.g. `https://host/netbox`). The second and later pages no longer 404 from a
|
|
80
|
+
doubled path prefix.
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- `NetBoxClient.paginate` now returns a lazy, resumable `Pager`
|
|
85
|
+
(`nsc/http/pagination.py`) exposing the server `total` and `has_more`, shared
|
|
86
|
+
by the CLI and the TUI.
|
|
87
|
+
- `nsc login --store` now rejects unknown values. Previously any value other
|
|
88
|
+
than `env` silently fell back to plaintext, so a typo could write the token
|
|
89
|
+
to disk. `nsc login --rotate` with no `--store` keeps an existing
|
|
90
|
+
`!keyring` reference instead of replacing it with plaintext.
|
|
91
|
+
|
|
92
|
+
[#1]: https://github.com/thomaschristory/netbox-super-cli/issues/1
|
|
93
|
+
[#166]: https://github.com/thomaschristory/netbox-super-cli/issues/166
|
|
94
|
+
[#150]: https://github.com/thomaschristory/netbox-super-cli/issues/150
|
|
95
|
+
[#151]: https://github.com/thomaschristory/netbox-super-cli/issues/151
|
|
96
|
+
|
|
97
|
+
## v1.7.0 — 2026-09-10
|
|
98
|
+
|
|
99
|
+
Minor release. Migrates the HTTP stack from `httpx` to Pydantic's maintained
|
|
100
|
+
`httpx2` fork, and keeps `httpx2` off the `nsc --help` cold-start path. No
|
|
101
|
+
user-facing CLI or behavior changes.
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- **Migrated the HTTP stack from `httpx` to `httpx2`** ([#146]). `httpx2` is
|
|
106
|
+
Pydantic's stewardship continuation of httpx (same author, API-identical) —
|
|
107
|
+
httpx itself has seen limited activity, and httpx2 is the reliably-maintained
|
|
108
|
+
path forward with timely security updates. The dependency floor is now
|
|
109
|
+
`httpx2>=2.5`; the source layer is a mechanical rename (`import httpx2`,
|
|
110
|
+
`httpx2.Client`/`httpx2.Response`/…). Test mocking moves from global `respx`
|
|
111
|
+
to the `pytest-httpx2` plugin's `httpx2_mock` fixture (a `respx.Router`, by
|
|
112
|
+
respx's own author), which targets httpx2's `httpcore2` transport. No
|
|
113
|
+
user-facing behavior or CLI surface changes.
|
|
114
|
+
- **httpx2 is now kept off the `nsc --help` / cold-start path** ([#13]). httpx2 is
|
|
115
|
+
the single heaviest import in the tree (~65ms cold), and nothing on the startup
|
|
116
|
+
path needs an HTTP client. It was being pulled in eagerly through the
|
|
117
|
+
runtime → client → retry chain (plus `cache`, `schema`, and `login`
|
|
118
|
+
command modules). All of these now import httpx2 lazily, at first request. Cold
|
|
119
|
+
startup drops by roughly httpx2's import cost, bringing the median back under the
|
|
120
|
+
300ms project target. A new guard test (`test_lazy_httpx2_import.py`) asserts
|
|
121
|
+
httpx2 never loads on `nsc --help`, and the startup benchmark's threshold is
|
|
122
|
+
re-baselined to 300ms so an over-threshold skip once again signals a real
|
|
123
|
+
regression instead of firing on every run.
|
|
124
|
+
|
|
125
|
+
[#13]: https://github.com/thomaschristory/netbox-super-cli/issues/13
|
|
126
|
+
[#146]: https://github.com/thomaschristory/netbox-super-cli/issues/146
|
|
127
|
+
|
|
5
128
|
## v1.6.3 — 2026-07-03
|
|
6
129
|
|
|
7
130
|
Patch release. Stops an offline instance from rebuilding the command model from
|
|
@@ -8,11 +8,12 @@ This is the contributor guide for AI agents (and humans!) modifying this repo. T
|
|
|
8
8
|
- `nsc/model/` — the normalized command tree (data only, framework-free). The "brain".
|
|
9
9
|
- `nsc/builder/` — converts a parsed schema into a `CommandModel`.
|
|
10
10
|
- `nsc/cli/` — the Typer app; consumes a `CommandModel`.
|
|
11
|
-
- `nsc/http/` — thin
|
|
11
|
+
- `nsc/http/` — thin httpx2 wrapper: auth, retries, audit log.
|
|
12
12
|
- `nsc/output/` — formatters (table/json/jsonl/yaml/csv) + error envelope.
|
|
13
13
|
- `nsc/config/` — config loader + Pydantic models + ruamel.yaml round-trip writer.
|
|
14
14
|
- `nsc/cache/` — disk cache for generated command-models.
|
|
15
15
|
- `nsc/auth/` — login verification helpers (pre-flight probes, token rotate).
|
|
16
|
+
- `nsc/branching/` — NetBox Branching: branch name→schema_id resolution, lifecycle API calls, job polling. Framework-free; `nsc/http` must not import it (the client takes a resolver callable).
|
|
16
17
|
- `nsc/aliases/` — curated alias resolver (`ls`, `get`, `rm`, `search`). Framework-free.
|
|
17
18
|
- `nsc/completion/` — dynamic shell-completion: framework-free providers + cheap on-disk cache probe + Typer `shell_complete` callbacks.
|
|
18
19
|
- `nsc/skill/` — bundle-path helper for the portable `SKILL.md` shipped in the wheel.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: netbox-super-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Dynamic NetBox CLI generated from the live OpenAPI schema.
|
|
5
5
|
Project-URL: Homepage, https://github.com/thomaschristory/netbox-super-cli
|
|
6
6
|
Project-URL: Documentation, https://thomaschristory.github.io/netbox-super-cli/
|
|
@@ -23,7 +23,8 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
23
23
|
Classifier: Topic :: System :: Networking
|
|
24
24
|
Requires-Python: >=3.12
|
|
25
25
|
Requires-Dist: click>=8.1
|
|
26
|
-
Requires-Dist:
|
|
26
|
+
Requires-Dist: httpx2>=2.5
|
|
27
|
+
Requires-Dist: keyring>=25.0
|
|
27
28
|
Requires-Dist: platformdirs>=4.2
|
|
28
29
|
Requires-Dist: pydantic>=2.7
|
|
29
30
|
Requires-Dist: rich>=13.7
|
|
@@ -64,6 +65,7 @@ One binary, any NetBox version, every plugin endpoint — the schema, not hand-w
|
|
|
64
65
|
- **Plugins just work.** If your install has plugins, their endpoints appear as commands automatically.
|
|
65
66
|
- **Multi-instance.** Named profiles per NetBox instance, plus env-var overrides.
|
|
66
67
|
- **Safe by default.** POST/PATCH/PUT/DELETE preview as dry-runs unless you pass `--apply`.
|
|
68
|
+
- **NetBox Branching.** Stage changes in a branch (`--branch`, `NSC_BRANCH`, `nsc branch use`), review with `nsc branch diff`, merge with `nsc branch merge --apply`. See [the guide](docs/guides/branching.md).
|
|
67
69
|
- **Agent-friendly.** Deterministic command shape, machine-readable JSON output, stable error envelope with documented exit codes.
|
|
68
70
|
- **Interactive TUI.** `nsc tui` opens a keyboard-driven terminal UI — see below.
|
|
69
71
|
|
|
@@ -208,6 +210,25 @@ The wire body sent to NetBox is **not** redacted — only the audit log. A faile
|
|
|
208
210
|
|
|
209
211
|
For a stricter posture, set `audit_redaction: full` in `~/.nsc/config.yaml` (the default is `safe`, the field-level redaction described above). In `full` mode every audit line keeps only `{method, url, status_code, timestamp, profile}` — all request and response bodies are dropped, and the `url` is sanitized (query string and any `user:pass@` credentials stripped).
|
|
210
212
|
|
|
213
|
+
## NetBox Branching
|
|
214
|
+
|
|
215
|
+
If your NetBox runs the [Branching plugin](https://netboxlabs.com/docs/extensions/branching/),
|
|
216
|
+
any command can stage its changes in a branch for review:
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
nsc branch create add-london --use # create, wait until ready, make it sticky
|
|
220
|
+
nsc dcim sites create -f london.yaml --apply # lands in the branch; stderr shows "⎇ branch: add-london"
|
|
221
|
+
nsc branch diff # review the staged changes
|
|
222
|
+
nsc branch merge # dry-run, validated server-side
|
|
223
|
+
nsc branch merge --apply # merge into main
|
|
224
|
+
nsc branch use --main # back to main
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`--branch NAME` and `NSC_BRANCH` select a branch for a single command or a
|
|
228
|
+
whole shell, and agents should use these. A merged, missing or not-ready branch
|
|
229
|
+
fails loudly and never falls back to main. See the
|
|
230
|
+
[branching guide](docs/guides/branching.md).
|
|
231
|
+
|
|
211
232
|
## Curated aliases
|
|
212
233
|
|
|
213
234
|
`nsc ls`, `nsc get`, `nsc rm`, and `nsc search` are short verbs over the dynamic
|
|
@@ -29,6 +29,7 @@ One binary, any NetBox version, every plugin endpoint — the schema, not hand-w
|
|
|
29
29
|
- **Plugins just work.** If your install has plugins, their endpoints appear as commands automatically.
|
|
30
30
|
- **Multi-instance.** Named profiles per NetBox instance, plus env-var overrides.
|
|
31
31
|
- **Safe by default.** POST/PATCH/PUT/DELETE preview as dry-runs unless you pass `--apply`.
|
|
32
|
+
- **NetBox Branching.** Stage changes in a branch (`--branch`, `NSC_BRANCH`, `nsc branch use`), review with `nsc branch diff`, merge with `nsc branch merge --apply`. See [the guide](docs/guides/branching.md).
|
|
32
33
|
- **Agent-friendly.** Deterministic command shape, machine-readable JSON output, stable error envelope with documented exit codes.
|
|
33
34
|
- **Interactive TUI.** `nsc tui` opens a keyboard-driven terminal UI — see below.
|
|
34
35
|
|
|
@@ -173,6 +174,25 @@ The wire body sent to NetBox is **not** redacted — only the audit log. A faile
|
|
|
173
174
|
|
|
174
175
|
For a stricter posture, set `audit_redaction: full` in `~/.nsc/config.yaml` (the default is `safe`, the field-level redaction described above). In `full` mode every audit line keeps only `{method, url, status_code, timestamp, profile}` — all request and response bodies are dropped, and the `url` is sanitized (query string and any `user:pass@` credentials stripped).
|
|
175
176
|
|
|
177
|
+
## NetBox Branching
|
|
178
|
+
|
|
179
|
+
If your NetBox runs the [Branching plugin](https://netboxlabs.com/docs/extensions/branching/),
|
|
180
|
+
any command can stage its changes in a branch for review:
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
nsc branch create add-london --use # create, wait until ready, make it sticky
|
|
184
|
+
nsc dcim sites create -f london.yaml --apply # lands in the branch; stderr shows "⎇ branch: add-london"
|
|
185
|
+
nsc branch diff # review the staged changes
|
|
186
|
+
nsc branch merge # dry-run, validated server-side
|
|
187
|
+
nsc branch merge --apply # merge into main
|
|
188
|
+
nsc branch use --main # back to main
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`--branch NAME` and `NSC_BRANCH` select a branch for a single command or a
|
|
192
|
+
whole shell, and agents should use these. A merged, missing or not-ready branch
|
|
193
|
+
fails loudly and never falls back to main. See the
|
|
194
|
+
[branching guide](docs/guides/branching.md).
|
|
195
|
+
|
|
176
196
|
## Curated aliases
|
|
177
197
|
|
|
178
198
|
`nsc ls`, `nsc get`, `nsc rm`, and `nsc search` are short verbs over the dynamic
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Only the latest release gets security fixes.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Do not open a public issue. Use the private vulnerability reporting of GitHub:
|
|
10
|
+
[Report a vulnerability](https://github.com/thomaschristory/netbox-super-cli/security/advisories/new)
|
|
11
|
+
(**Security > Report a vulnerability** on the repository). Only the maintainer sees the report.
|
|
12
|
+
The maintainer replies, fixes the problem, and publishes an advisory with the fix.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# HTTP client
|
|
2
2
|
|
|
3
|
-
`nsc/http/` is a thin wrapper around `
|
|
3
|
+
`nsc/http/` is a thin wrapper around `httpx2.Client`.
|
|
4
4
|
|
|
5
5
|
## What it adds
|
|
6
6
|
|
|
@@ -20,6 +20,15 @@
|
|
|
20
20
|
`final_attempt`; redaction is applied on every write, so a failed
|
|
21
21
|
retry never unredacts.
|
|
22
22
|
- Pagination helper that follows `next` URLs (used by `--all`).
|
|
23
|
+
- Optional NetBox Branching context. Given a `branch_resolver`, the client
|
|
24
|
+
resolves the branch lazily on its first request: the resolver's own lookups
|
|
25
|
+
go out unbranched, and every later request carries
|
|
26
|
+
`X-NetBox-Branch: <schema_id>`. Resolution is serialized under a lock, so
|
|
27
|
+
concurrent `--workers` threads wait instead of racing ahead without the
|
|
28
|
+
header. A failed resolution is stored and raised again on every later call,
|
|
29
|
+
so once a branch is selected no request can reach main. The resolver
|
|
30
|
+
itself lives in `nsc/branching/` (`nsc/http` does not import it), and
|
|
31
|
+
`nsc branch …` commands build a client without one.
|
|
23
32
|
- Audit log appender at `~/.nsc/logs/audit.jsonl` — written for writes
|
|
24
33
|
always, and for any request when `--debug` is set.
|
|
25
34
|
|
|
@@ -27,7 +36,7 @@
|
|
|
27
36
|
|
|
28
37
|
Bulk write commands accept `--workers N` (default 1, max 32) to keep up to N
|
|
29
38
|
requests in flight. Concurrency is **thread-based**: a `ThreadPoolExecutor`
|
|
30
|
-
fans the per-record loop out over the single sync `
|
|
39
|
+
fans the per-record loop out over the single sync `httpx2.Client` — there is no
|
|
31
40
|
async path. Per-record `--on-error` semantics are preserved regardless of
|
|
32
41
|
worker count. Audit appends are serialized by a module-level lock
|
|
33
42
|
(`_APPEND_LOCK` in `nsc/http/audit.py`) wrapped around the whole
|
|
@@ -40,9 +49,9 @@ each record is one well-formed JSON line.
|
|
|
40
49
|
|
|
41
50
|
A schema fetch may run before the first command request (only when the
|
|
42
51
|
TTL fast-path misses — see [Caching](caching.md)); it uses its own
|
|
43
|
-
short-lived `
|
|
52
|
+
short-lived `httpx2.Client` in `nsc/schema/`, not this `NetBoxClient`.
|
|
44
53
|
Command requests then go through a single `NetBoxClient` whose
|
|
45
|
-
`
|
|
54
|
+
`httpx2.Client` carries the auth header for the life of the process.
|
|
46
55
|
Token rotation via `nsc login --rotate` does NOT invalidate the cached
|
|
47
56
|
model (the schema hash is what keys the cache; the token never affected
|
|
48
57
|
it).
|
|
@@ -91,7 +100,7 @@ contract.
|
|
|
91
100
|
|
|
92
101
|
## What it deliberately does not do
|
|
93
102
|
|
|
94
|
-
- Async — sync only in v1, kept feasible by
|
|
103
|
+
- Async — sync only in v1, kept feasible by httpx2 if a future async path lands.
|
|
95
104
|
- Connection pooling across profiles — each profile gets its own `Client`.
|
|
96
105
|
- Caching responses — caching the command-model is enough; caching response
|
|
97
106
|
payloads would surprise users.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Architecture overview
|
|
2
2
|
|
|
3
3
|
`nsc` is layered around a framework-free "brain". The brain — schema parsing
|
|
4
|
-
and the normalized command-model — knows nothing about Typer, Rich, or
|
|
4
|
+
and the normalized command-model — knows nothing about Typer, Rich, or httpx2.
|
|
5
5
|
The CLI layer consumes the brain; a future TUI could too without changing the
|
|
6
6
|
brain.
|
|
7
7
|
|
|
@@ -11,11 +11,12 @@ nsc/
|
|
|
11
11
|
├── model/ # Normalized command-model (data only, framework-free)
|
|
12
12
|
├── builder/ # Schema → CommandModel
|
|
13
13
|
├── cli/ # Typer application; walks the model, registers commands
|
|
14
|
-
├── http/ # Thin
|
|
14
|
+
├── http/ # Thin httpx2 wrapper: auth, retries, audit
|
|
15
15
|
├── output/ # Formatters (table/json/jsonl/yaml/csv) + error envelope
|
|
16
16
|
├── config/ # Pydantic config models + ruamel.yaml writer
|
|
17
17
|
├── cache/ # On-disk cache for generated CommandModels
|
|
18
18
|
├── auth/ # Login verification helpers (verify probe, token rotate)
|
|
19
|
+
├── branching/ # NetBox Branching: branch lookup, lifecycle calls, job polling
|
|
19
20
|
├── aliases/ # Curated alias resolver (ls/get/rm/search)
|
|
20
21
|
├── completion/ # Dynamic shell-completion: providers + cache probe + Typer callbacks
|
|
21
22
|
├── skill/ # Bundle-path helper for the portable SKILL.md
|
|
@@ -11,7 +11,7 @@ on a `chore/release-X.Y.Z` feature branch, gets PR-merged into `main`,
|
|
|
11
11
|
and only then is `vX.Y.Z` tagged on the resulting merge commit.
|
|
12
12
|
|
|
13
13
|
The same `v*` tag push also publishes the documentation site.
|
|
14
|
-
`docs.yml` runs build-only (`
|
|
14
|
+
`docs.yml` runs build-only (`zensical build --strict`) on docs-touching
|
|
15
15
|
pull requests, but the GitHub Pages **deploy** job only runs on a `v*`
|
|
16
16
|
tag push — the live docs site updates on release, not on merge to
|
|
17
17
|
`main`.
|
|
@@ -70,6 +70,22 @@ nsc dcim devices create --field name=foo --field site=1 --apply
|
|
|
70
70
|
Add `--explain` to a dry-run to see the schema reasoning ("PATCH because of
|
|
71
71
|
operationId `dcim_devices_partial_update`").
|
|
72
72
|
|
|
73
|
+
## Branches (NetBox Branching)
|
|
74
|
+
|
|
75
|
+
If your server runs the NetBox Branching plugin, any command can run inside a
|
|
76
|
+
branch instead of main. Pick one with `--branch NAME`, `NSC_BRANCH=NAME`, or
|
|
77
|
+
make it sticky on the profile with `nsc branch use NAME`. While a branch is
|
|
78
|
+
active, every command prints `⎇ branch: NAME` on stderr. If the branch can't be
|
|
79
|
+
used (merged, missing, not ready), the command fails without sending anything.
|
|
80
|
+
It never quietly falls back to main. See [NetBox Branching](../guides/branching.md).
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
nsc branch create add-london --use
|
|
84
|
+
nsc dcim sites create --field name=London --field slug=london --apply # staged in the branch
|
|
85
|
+
nsc branch diff
|
|
86
|
+
nsc branch merge --apply
|
|
87
|
+
```
|
|
88
|
+
|
|
73
89
|
## Audit log
|
|
74
90
|
|
|
75
91
|
Every wire request and its response are appended to
|
|
@@ -54,9 +54,13 @@ nsc login --rotate --profile prod # rotate the token
|
|
|
54
54
|
nsc login --fetch-schema # verify, then fetch & cache the live schema
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
`nsc login` probes `GET /api/status/` and `GET /api/users/tokens
|
|
57
|
+
`nsc login` probes `GET /api/status/` and `GET /api/users/tokens/`
|
|
58
58
|
(both must succeed) and prints `✓ authenticated as <user>, NetBox <version>`
|
|
59
|
-
on success.
|
|
59
|
+
on success. NetBox has no "current user" endpoint, so the user is derived from
|
|
60
|
+
the token you presented; when that can't be done reliably (e.g. a v1 token
|
|
61
|
+
held by an admin who can see other users' tokens) it prints
|
|
62
|
+
`✓ authenticated (user unknown), NetBox <version>` rather than guessing.
|
|
63
|
+
On failure it emits the standard auth error envelope
|
|
60
64
|
(`type: auth`, exit 8).
|
|
61
65
|
|
|
62
66
|
`--new` requires both `--profile` and `--url`, prompts for the token
|