nextlabs-sdk 0.2.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.
- nextlabs_sdk-0.2.0/LICENSE +21 -0
- nextlabs_sdk-0.2.0/PKG-INFO +457 -0
- nextlabs_sdk-0.2.0/README.md +429 -0
- nextlabs_sdk-0.2.0/pyproject.toml +80 -0
- nextlabs_sdk-0.2.0/setup.cfg +182 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/__init__.py +35 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/__init__.py +2 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_active_account/__init__.py +6 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_active_account/_active_account.py +34 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_active_account/_active_account_store.py +85 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_cloudaz_auth.py +434 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_pdp_auth.py +103 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_refresh_token_policy.py +58 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_static_token_auth.py +19 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_token_cache/__init__.py +8 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_token_cache/_cached_token.py +117 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_token_cache/_file_token_cache.py +101 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_token_cache/_null_token_cache.py +21 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_auth/_token_cache/_token_cache.py +25 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/__init__.py +0 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_account_menu.py +71 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_account_preferences.py +40 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_account_preferences_store.py +107 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_account_resolver.py +82 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_activity_logs_cmd.py +126 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_app.py +137 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_audit_logs_cmd.py +136 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_auth_cmd.py +341 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_binary_output.py +31 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_bulk_ids.py +65 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_cache_key.py +46 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_client_factory.py +157 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_component_types_cmd.py +245 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_components_cmd.py +334 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_context.py +23 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_dashboard_cmd.py +151 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_detail_renderers.py +49 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_error_handler.py +100 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_expiry_format.py +50 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_logging_setup.py +27 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_operators_cmd.py +64 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_output.py +74 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_output_format.py +18 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_parsing.py +35 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_payload_loader.py +85 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_pdp_cmd.py +294 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_policies_cmd.py +536 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_reporter_audit_logs_cmd.py +39 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_reports_cmd.py +388 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_system_config_cmd.py +36 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cli/_tags_cmd.py +101 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/__init__.py +109 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_activity_log_query_models.py +35 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_activity_logs_service.py +138 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_async_client.py +171 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_audit_log_models.py +55 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_audit_logs.py +99 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_client.py +176 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_component_models.py +221 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_component_search.py +328 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_component_type_models.py +125 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_component_type_search.py +237 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_component_types.py +136 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_components.py +175 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_dashboard.py +121 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_dashboard_models.py +70 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_models.py +30 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_operators.py +54 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_policies.py +379 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_policy_models.py +288 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_policy_search.py +284 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_report_models.py +252 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_reporter_audit_log_models.py +21 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_reporter_audit_logs.py +83 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_reports.py +578 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_response.py +102 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_search.py +216 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_system_config.py +30 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_system_config_models.py +20 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_cloudaz/_tags.py +129 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_config.py +18 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_http_transport.py +288 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_http_transport_logging.py +61 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_http_transport_logging_async.py +35 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_json_response.py +131 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_logging.py +106 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pagination.py +93 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/__init__.py +30 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_async_client.py +115 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_client.py +115 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_enums.py +20 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_json_serializer.py +309 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_request_models.py +73 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_response_decode.py +32 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_response_models.py +68 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_urns.py +28 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_pdp/_xml_serializer.py +285 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_retry_policy.py +83 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/_version.py +8 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/cloudaz/__init__.py +114 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/exceptions.py +132 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/pdp/__init__.py +33 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk/py.typed +0 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/PKG-INFO +457 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/SOURCES.txt +219 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/dependency_links.txt +1 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/entry_points.txt +2 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/requires.txt +7 -0
- nextlabs_sdk-0.2.0/src/nextlabs_sdk.egg-info/top_level.txt +1 -0
- nextlabs_sdk-0.2.0/tests/test_account_preferences.py +45 -0
- nextlabs_sdk-0.2.0/tests/test_account_preferences_store.py +163 -0
- nextlabs_sdk-0.2.0/tests/test_active_account_store.py +138 -0
- nextlabs_sdk-0.2.0/tests/test_activity_log_query_models.py +96 -0
- nextlabs_sdk-0.2.0/tests/test_activity_log_query_service.py +171 -0
- nextlabs_sdk-0.2.0/tests/test_async_activity_log_query_service.py +159 -0
- nextlabs_sdk-0.2.0/tests/test_async_audit_log_service.py +174 -0
- nextlabs_sdk-0.2.0/tests/test_async_cloudaz_client.py +139 -0
- nextlabs_sdk-0.2.0/tests/test_async_component_search_service.py +223 -0
- nextlabs_sdk-0.2.0/tests/test_async_component_service.py +215 -0
- nextlabs_sdk-0.2.0/tests/test_async_component_type_search_service.py +165 -0
- nextlabs_sdk-0.2.0/tests/test_async_component_type_service.py +177 -0
- nextlabs_sdk-0.2.0/tests/test_async_dashboard_service.py +131 -0
- nextlabs_sdk-0.2.0/tests/test_async_operator_service.py +70 -0
- nextlabs_sdk-0.2.0/tests/test_async_pdp_client.py +217 -0
- nextlabs_sdk-0.2.0/tests/test_async_policy_search_service.py +220 -0
- nextlabs_sdk-0.2.0/tests/test_async_policy_service.py +436 -0
- nextlabs_sdk-0.2.0/tests/test_async_report_service.py +439 -0
- nextlabs_sdk-0.2.0/tests/test_async_reporter_audit_log_service.py +73 -0
- nextlabs_sdk-0.2.0/tests/test_async_system_config_service.py +46 -0
- nextlabs_sdk-0.2.0/tests/test_async_tag_service.py +115 -0
- nextlabs_sdk-0.2.0/tests/test_audit_log_models.py +135 -0
- nextlabs_sdk-0.2.0/tests/test_audit_log_service.py +214 -0
- nextlabs_sdk-0.2.0/tests/test_cached_token.py +88 -0
- nextlabs_sdk-0.2.0/tests/test_cli_account_resolver.py +137 -0
- nextlabs_sdk-0.2.0/tests/test_cli_active_account.py +334 -0
- nextlabs_sdk-0.2.0/tests/test_cli_activity_logs.py +253 -0
- nextlabs_sdk-0.2.0/tests/test_cli_app.py +19 -0
- nextlabs_sdk-0.2.0/tests/test_cli_app_verbose.py +17 -0
- nextlabs_sdk-0.2.0/tests/test_cli_audit_logs.py +239 -0
- nextlabs_sdk-0.2.0/tests/test_cli_audit_logs_detail.py +38 -0
- nextlabs_sdk-0.2.0/tests/test_cli_auth.py +444 -0
- nextlabs_sdk-0.2.0/tests/test_cli_binary_output.py +67 -0
- nextlabs_sdk-0.2.0/tests/test_cli_bulk_ids.py +57 -0
- nextlabs_sdk-0.2.0/tests/test_cli_client_factory.py +438 -0
- nextlabs_sdk-0.2.0/tests/test_cli_component_types.py +291 -0
- nextlabs_sdk-0.2.0/tests/test_cli_component_types_detail.py +89 -0
- nextlabs_sdk-0.2.0/tests/test_cli_components.py +357 -0
- nextlabs_sdk-0.2.0/tests/test_cli_components_detail.py +82 -0
- nextlabs_sdk-0.2.0/tests/test_cli_context.py +34 -0
- nextlabs_sdk-0.2.0/tests/test_cli_dashboard.py +272 -0
- nextlabs_sdk-0.2.0/tests/test_cli_dashboard_detail.py +50 -0
- nextlabs_sdk-0.2.0/tests/test_cli_detail_renderers.py +56 -0
- nextlabs_sdk-0.2.0/tests/test_cli_error_handler.py +87 -0
- nextlabs_sdk-0.2.0/tests/test_cli_error_handler_verbose.py +127 -0
- nextlabs_sdk-0.2.0/tests/test_cli_logging_setup.py +52 -0
- nextlabs_sdk-0.2.0/tests/test_cli_operators.py +111 -0
- nextlabs_sdk-0.2.0/tests/test_cli_output.py +154 -0
- nextlabs_sdk-0.2.0/tests/test_cli_output_format.py +30 -0
- nextlabs_sdk-0.2.0/tests/test_cli_payload_loader.py +63 -0
- nextlabs_sdk-0.2.0/tests/test_cli_pdp.py +347 -0
- nextlabs_sdk-0.2.0/tests/test_cli_pdp_detail.py +72 -0
- nextlabs_sdk-0.2.0/tests/test_cli_policies.py +661 -0
- nextlabs_sdk-0.2.0/tests/test_cli_policies_detail.py +94 -0
- nextlabs_sdk-0.2.0/tests/test_cli_reporter_audit_logs.py +114 -0
- nextlabs_sdk-0.2.0/tests/test_cli_reports.py +619 -0
- nextlabs_sdk-0.2.0/tests/test_cli_reports_detail.py +70 -0
- nextlabs_sdk-0.2.0/tests/test_cli_system_config.py +73 -0
- nextlabs_sdk-0.2.0/tests/test_cli_tags.py +185 -0
- nextlabs_sdk-0.2.0/tests/test_cli_tags_detail.py +25 -0
- nextlabs_sdk-0.2.0/tests/test_cli_utils.py +45 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_auth.py +637 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_client.py +129 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_client_activity_dashboard.py +71 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_client_audit.py +61 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_client_reports.py +51 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_models.py +90 -0
- nextlabs_sdk-0.2.0/tests/test_cloudaz_response.py +292 -0
- nextlabs_sdk-0.2.0/tests/test_component_models.py +458 -0
- nextlabs_sdk-0.2.0/tests/test_component_search_service.py +245 -0
- nextlabs_sdk-0.2.0/tests/test_component_service.py +234 -0
- nextlabs_sdk-0.2.0/tests/test_component_type_models.py +275 -0
- nextlabs_sdk-0.2.0/tests/test_component_type_search_service.py +198 -0
- nextlabs_sdk-0.2.0/tests/test_component_type_service.py +207 -0
- nextlabs_sdk-0.2.0/tests/test_config.py +44 -0
- nextlabs_sdk-0.2.0/tests/test_dashboard_models.py +114 -0
- nextlabs_sdk-0.2.0/tests/test_dashboard_service.py +152 -0
- nextlabs_sdk-0.2.0/tests/test_exceptions.py +146 -0
- nextlabs_sdk-0.2.0/tests/test_expiry_format.py +69 -0
- nextlabs_sdk-0.2.0/tests/test_file_token_cache.py +166 -0
- nextlabs_sdk-0.2.0/tests/test_http_transport.py +531 -0
- nextlabs_sdk-0.2.0/tests/test_http_transport_logging.py +122 -0
- nextlabs_sdk-0.2.0/tests/test_json_response.py +120 -0
- nextlabs_sdk-0.2.0/tests/test_json_serializer.py +348 -0
- nextlabs_sdk-0.2.0/tests/test_logging_redaction.py +143 -0
- nextlabs_sdk-0.2.0/tests/test_null_token_cache.py +29 -0
- nextlabs_sdk-0.2.0/tests/test_openapi_roundtrip.py +90 -0
- nextlabs_sdk-0.2.0/tests/test_operator_service.py +93 -0
- nextlabs_sdk-0.2.0/tests/test_pagination.py +113 -0
- nextlabs_sdk-0.2.0/tests/test_pdp_auth.py +196 -0
- nextlabs_sdk-0.2.0/tests/test_pdp_client.py +273 -0
- nextlabs_sdk-0.2.0/tests/test_pdp_enums.py +36 -0
- nextlabs_sdk-0.2.0/tests/test_pdp_request_models.py +166 -0
- nextlabs_sdk-0.2.0/tests/test_pdp_response_models.py +115 -0
- nextlabs_sdk-0.2.0/tests/test_policy_models.py +456 -0
- nextlabs_sdk-0.2.0/tests/test_policy_search_service.py +226 -0
- nextlabs_sdk-0.2.0/tests/test_policy_service.py +446 -0
- nextlabs_sdk-0.2.0/tests/test_refresh_token_policy.py +61 -0
- nextlabs_sdk-0.2.0/tests/test_report_models.py +594 -0
- nextlabs_sdk-0.2.0/tests/test_report_service.py +602 -0
- nextlabs_sdk-0.2.0/tests/test_reporter_audit_log_models.py +33 -0
- nextlabs_sdk-0.2.0/tests/test_reporter_audit_log_service.py +102 -0
- nextlabs_sdk-0.2.0/tests/test_retry_policy.py +227 -0
- nextlabs_sdk-0.2.0/tests/test_search.py +370 -0
- nextlabs_sdk-0.2.0/tests/test_static_token_auth.py +15 -0
- nextlabs_sdk-0.2.0/tests/test_system_config_models.py +31 -0
- nextlabs_sdk-0.2.0/tests/test_system_config_service.py +48 -0
- nextlabs_sdk-0.2.0/tests/test_tag_service.py +151 -0
- nextlabs_sdk-0.2.0/tests/test_tools_tests_runner.py +91 -0
- nextlabs_sdk-0.2.0/tests/test_xml_serializer.py +175 -0
- nextlabs_sdk-0.2.0/version.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Steven England
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nextlabs-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A typed Python SDK wrapping the NextLabs CloudAz Console API and PDP REST API
|
|
5
|
+
Author-email: Steven England <github@steven-england.info>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/stevenengland/nextlabs_rest_api
|
|
8
|
+
Project-URL: Repository, https://github.com/stevenengland/nextlabs_rest_api
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/stevenengland/nextlabs_rest_api/issues
|
|
10
|
+
Keywords: nextlabs,cloudaz,pdp,xacml,sdk,rest-api
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
22
|
+
Requires-Dist: pydantic<3.0,>=2.0
|
|
23
|
+
Requires-Dist: defusedxml<1.0,>=0.7
|
|
24
|
+
Provides-Extra: cli
|
|
25
|
+
Requires-Dist: typer<1.0,>=0.12; extra == "cli"
|
|
26
|
+
Requires-Dist: rich<14.0,>=13.0; extra == "cli"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# nextlabs-sdk
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/nextlabs-sdk/)
|
|
32
|
+
[](https://pypi.org/project/nextlabs-sdk/)
|
|
33
|
+
[](https://github.com/stevenengland/nextlabs_rest_api/actions/workflows/code_testing.yml)
|
|
34
|
+
[](LICENSE)
|
|
35
|
+
|
|
36
|
+
> *Typed Python SDK and CLI for the NextLabs CloudAz Console & PDP REST APIs.*
|
|
37
|
+
|
|
38
|
+
> [!WARNING]
|
|
39
|
+
> **Alpha** — the public surface may still change. Unofficial project, not
|
|
40
|
+
> affiliated with NextLabs.
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
## Table of contents
|
|
45
|
+
|
|
46
|
+
- [Features](#features)
|
|
47
|
+
- [Installation](#installation)
|
|
48
|
+
- [Using the SDK](#using-the-sdk)
|
|
49
|
+
- [Using the CLI](#using-the-cli)
|
|
50
|
+
- [Configuration & authentication](#configuration--authentication)
|
|
51
|
+
- [Project layout](#project-layout)
|
|
52
|
+
- [Development](#development)
|
|
53
|
+
- [License](#license)
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- **Two API clients** — `CloudAzClient` for Console management and
|
|
58
|
+
`PdpClient` for XACML-style authorization decisions.
|
|
59
|
+
- **Sync and async parity** — every client ships in a sync
|
|
60
|
+
(`CloudAzClient`, `PdpClient`) and an async (`AsyncCloudAzClient`,
|
|
61
|
+
`AsyncPdpClient`) flavor, built on `httpx`.
|
|
62
|
+
- **Fully typed** (PEP 561, `py.typed`) with Pydantic v2 request/response
|
|
63
|
+
models — strong autocompletion under mypy and Pyright.
|
|
64
|
+
- **CloudAz coverage** — tags, components, component types, policies
|
|
65
|
+
(incl. `retrieveAllPolicies` export and named/scoped search), operators,
|
|
66
|
+
entity audit logs, reporter audit logs (Policy Activity Reports,
|
|
67
|
+
Monitors, Alerts), policy activity reports, activity logs, dashboard,
|
|
68
|
+
and system config.
|
|
69
|
+
- **PDP coverage** — `evaluate` (single decision) and `permissions`
|
|
70
|
+
(multi-action discovery), with **JSON or XML** payloads.
|
|
71
|
+
- **Resilient transport** — OIDC token acquisition + refresh,
|
|
72
|
+
configurable timeout, SSL verification, and retries with exponential
|
|
73
|
+
backoff (clamped `Retry-After` honoured on 429/503).
|
|
74
|
+
- **Typed error hierarchy** — HTTP status codes map to
|
|
75
|
+
`AuthenticationError`, `AuthorizationError`, `NotFoundError`,
|
|
76
|
+
`ValidationError`, `ConflictError`, `RateLimitError`, `ServerError`,
|
|
77
|
+
`RequestTimeoutError`, `TransportError`, and `ApiError` — all
|
|
78
|
+
subclasses of `NextLabsError`.
|
|
79
|
+
- **Pagination helpers** — `SyncPaginator` / `AsyncPaginator` iterate
|
|
80
|
+
listed endpoints page-by-page or item-by-item.
|
|
81
|
+
- **Optional CLI** — a `nextlabs` command (Typer + Rich) for scripting,
|
|
82
|
+
admin tasks, and quick exploration. Persistent OIDC token cache, four
|
|
83
|
+
output formats (`table` / `wide` / `detail` / `json`), per-call
|
|
84
|
+
verbosity for HTTP tracing.
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install nextlabs-sdk # library only
|
|
90
|
+
pip install "nextlabs-sdk[cli]" # + nextlabs CLI (Typer, Rich)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Requires Python **3.11+**.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Using the SDK
|
|
98
|
+
|
|
99
|
+
### Quick start — CloudAz (sync)
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from nextlabs_sdk import CloudAzClient
|
|
103
|
+
from nextlabs_sdk.cloudaz import TagType
|
|
104
|
+
|
|
105
|
+
with CloudAzClient(
|
|
106
|
+
base_url="https://cloudaz.example.com",
|
|
107
|
+
username="admin",
|
|
108
|
+
password="secret",
|
|
109
|
+
) as client:
|
|
110
|
+
for tag in client.tags.list(TagType.COMPONENT):
|
|
111
|
+
print(tag.id, tag.label)
|
|
112
|
+
|
|
113
|
+
tag_id = client.tags.create(TagType.COMPONENT, key="env", label="Env")
|
|
114
|
+
tag = client.tags.get(tag_id)
|
|
115
|
+
client.tags.delete(tag.id)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Quick start — CloudAz (async)
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import asyncio
|
|
122
|
+
from nextlabs_sdk import AsyncCloudAzClient
|
|
123
|
+
from nextlabs_sdk.cloudaz import TagType
|
|
124
|
+
|
|
125
|
+
async def main() -> None:
|
|
126
|
+
async with AsyncCloudAzClient(
|
|
127
|
+
base_url="https://cloudaz.example.com",
|
|
128
|
+
username="admin",
|
|
129
|
+
password="secret",
|
|
130
|
+
) as client:
|
|
131
|
+
async for tag in client.tags.list(TagType.COMPONENT):
|
|
132
|
+
print(tag.id, tag.label)
|
|
133
|
+
|
|
134
|
+
asyncio.run(main())
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Quick start — PDP
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from nextlabs_sdk import PdpClient
|
|
141
|
+
from nextlabs_sdk.pdp import (
|
|
142
|
+
Action, Application, EvalRequest, Resource, Subject,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
with PdpClient(
|
|
146
|
+
base_url="https://pdp.example.com",
|
|
147
|
+
client_id="my-client",
|
|
148
|
+
client_secret="s3cret",
|
|
149
|
+
) as pdp:
|
|
150
|
+
decision = pdp.evaluate(
|
|
151
|
+
EvalRequest(
|
|
152
|
+
subject=Subject(id="alice", attributes={"role": "engineer"}),
|
|
153
|
+
resource=Resource(
|
|
154
|
+
id="doc-42",
|
|
155
|
+
type="document",
|
|
156
|
+
attributes={"classification": "internal"},
|
|
157
|
+
),
|
|
158
|
+
action=Action(id="read"),
|
|
159
|
+
application=Application(id="wiki"),
|
|
160
|
+
return_policy_ids=True,
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
result = decision.first_result
|
|
164
|
+
print(result.decision, [p.id for p in result.policy_refs])
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Use `content_type=ContentType.XML` to exchange XACML XML payloads
|
|
168
|
+
instead of JSON. `pdp.permissions(...)` returns the set of actions a
|
|
169
|
+
subject may perform on a resource.
|
|
170
|
+
|
|
171
|
+
### Pagination
|
|
172
|
+
|
|
173
|
+
`SyncPaginator` / `AsyncPaginator` are returned by every list method.
|
|
174
|
+
Iterate page-by-page (`.pages()`) or item-by-item (default `__iter__`):
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
for tag in client.tags.list(TagType.COMPONENT): # one item at a time
|
|
178
|
+
...
|
|
179
|
+
|
|
180
|
+
for page in client.tags.list(TagType.COMPONENT).pages():
|
|
181
|
+
print(page.total, len(page.items)) # PageResult metadata
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Error handling
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from nextlabs_sdk import CloudAzClient
|
|
188
|
+
from nextlabs_sdk.exceptions import (
|
|
189
|
+
AuthenticationError, NotFoundError, NextLabsError,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
client.tags.get(123)
|
|
194
|
+
except AuthenticationError:
|
|
195
|
+
... # re-login / rotate credentials
|
|
196
|
+
except NotFoundError:
|
|
197
|
+
...
|
|
198
|
+
except NextLabsError as exc:
|
|
199
|
+
print(exc.status_code, exc.request_method, exc.request_url, exc.response_body)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Public API surface
|
|
203
|
+
|
|
204
|
+
All imports come from four public entry points:
|
|
205
|
+
|
|
206
|
+
- `nextlabs_sdk` — clients (`CloudAzClient`, `AsyncCloudAzClient`,
|
|
207
|
+
`PdpClient`, `AsyncPdpClient`), transport (`HttpConfig`,
|
|
208
|
+
`RetryConfig`, `create_http_client`, `create_async_http_client`),
|
|
209
|
+
pagination (`SyncPaginator`, `AsyncPaginator`, `PageResult`), auth
|
|
210
|
+
(`CloudAzAuth`, `PdpAuth`, `StaticTokenAuth`), token cache
|
|
211
|
+
(`TokenCache`, `CachedToken`, `FileTokenCache`, `NullTokenCache`),
|
|
212
|
+
and `__version__`.
|
|
213
|
+
- `nextlabs_sdk.cloudaz` — CloudAz domain models and enums (`Tag`,
|
|
214
|
+
`TagType`, `Operator`, audit-log / report / dashboard /
|
|
215
|
+
system-config / activity-log models).
|
|
216
|
+
- `nextlabs_sdk.pdp` — PDP request/response models and enums
|
|
217
|
+
(`Subject`, `Resource`, `Action`, `Application`, `Environment`,
|
|
218
|
+
`EvalRequest`, `EvalResponse`, `PermissionsRequest`,
|
|
219
|
+
`PermissionsResponse`, `ContentType`, `Decision`,
|
|
220
|
+
`ResourceDimension`, …).
|
|
221
|
+
- `nextlabs_sdk.exceptions` — the `NextLabsError` hierarchy.
|
|
222
|
+
|
|
223
|
+
Anything with a leading underscore (`nextlabs_sdk._cloudaz`,
|
|
224
|
+
`nextlabs_sdk._pdp`, `nextlabs_sdk._cli`, `nextlabs_sdk._auth`, …)
|
|
225
|
+
is an internal implementation detail and may change without notice.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Using the CLI
|
|
230
|
+
|
|
231
|
+
The optional CLI exposes most CloudAz operations plus PDP evaluation.
|
|
232
|
+
|
|
233
|
+
### Quick start
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
pip install "nextlabs-sdk[cli]"
|
|
237
|
+
|
|
238
|
+
export NEXTLABS_BASE_URL="https://cloudaz.example.com"
|
|
239
|
+
export NEXTLABS_USERNAME="admin"
|
|
240
|
+
|
|
241
|
+
nextlabs auth login # acquire & cache a token
|
|
242
|
+
nextlabs auth status # is the cached token still valid?
|
|
243
|
+
nextlabs policies search --status APPROVED
|
|
244
|
+
nextlabs pdp eval --subject alice --resource doc-42 \
|
|
245
|
+
--resource-type document --action read --application wiki
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Command groups
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
auth login | logout | status | test | accounts | use
|
|
252
|
+
tags list (positional <tag_type>) | get | create | delete
|
|
253
|
+
components search | get | create | update | delete
|
|
254
|
+
component-types list | get | create | update | delete
|
|
255
|
+
policies search | get | export-all | tags
|
|
256
|
+
audit-logs search (--start-date / --end-date in epoch-ms)
|
|
257
|
+
reports ...
|
|
258
|
+
dashboard ...
|
|
259
|
+
pdp eval | permissions
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Use `nextlabs <group> --help` for the exact flags of each subcommand.
|
|
263
|
+
|
|
264
|
+
### Output formats
|
|
265
|
+
|
|
266
|
+
Every list/get command accepts `-o` / `--output`. Values are
|
|
267
|
+
case-insensitive.
|
|
268
|
+
|
|
269
|
+
| Format | When to use |
|
|
270
|
+
| -------- | ------------------------------------------------------------- |
|
|
271
|
+
| `table` | Default. Compact columns; long values wrap (never truncated). |
|
|
272
|
+
| `wide` | Table plus extra columns (owner, timestamps, version, …). |
|
|
273
|
+
| `detail` | Sectioned per-item output, `kubectl describe` style. |
|
|
274
|
+
| `json` | Raw JSON dump of the response model(s). Machine-readable. |
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
nextlabs -o wide policies search
|
|
278
|
+
nextlabs -o detail policies get 17
|
|
279
|
+
nextlabs --output json components search # machine-readable
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Recipes
|
|
283
|
+
|
|
284
|
+
Real workflows assembled from the commands shipped today.
|
|
285
|
+
|
|
286
|
+
**1. Daily admin — find an approved policy and read it.**
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
nextlabs auth login
|
|
290
|
+
nextlabs policies search --status APPROVED --text "billing"
|
|
291
|
+
nextlabs policies get 17 -o detail
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**2. CI authorization smoke test — fail the build if `alice` cannot read the wiki.**
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
nextlabs --token "$NEXTLABS_TOKEN" \
|
|
298
|
+
pdp eval --subject alice --resource doc-42 --resource-type document \
|
|
299
|
+
--action read --application wiki -o json \
|
|
300
|
+
| jq -e '.eval_results[0].decision == "Permit"'
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**3. Export the policy catalogue to version control.**
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
nextlabs -o json policies search --page-size 1000 > policies.json
|
|
307
|
+
git add policies.json && git commit -m "chore: snapshot policies"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**4. Audit recent activity (last hour).**
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
END=$(date +%s%3N)
|
|
314
|
+
START=$((END - 3600000))
|
|
315
|
+
nextlabs audit-logs search --start-date "$START" --end-date "$END"
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**5. Run in CI without an interactive login.**
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
NEXTLABS_BASE_URL="https://cloudaz.example.com" \
|
|
322
|
+
NEXTLABS_TOKEN="$(vault kv get -field=token secret/nextlabs/ci)" \
|
|
323
|
+
nextlabs policies search --page-size 50
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
`NEXTLABS_TOKEN` (or `--token`) bypasses the OIDC login flow **and** the
|
|
327
|
+
token cache — nothing is read from or written to disk.
|
|
328
|
+
|
|
329
|
+
**6. Templated extraction with `jq`.**
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
nextlabs -o json components search | jq '.[].id'
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
For more day-to-day fixes (auth cache, SSL trust, missing PDP attributes,
|
|
336
|
+
…) see [`docs/troubleshooting.md`](docs/troubleshooting.md).
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Configuration & authentication
|
|
341
|
+
|
|
342
|
+
Both the SDK and the CLI share the same transport, retry, and OIDC
|
|
343
|
+
machinery.
|
|
344
|
+
|
|
345
|
+
### `HttpConfig` and `RetryConfig`
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from nextlabs_sdk import CloudAzClient, HttpConfig, RetryConfig
|
|
349
|
+
|
|
350
|
+
client = CloudAzClient(
|
|
351
|
+
base_url="https://cloudaz.example.com",
|
|
352
|
+
username="admin",
|
|
353
|
+
password="secret",
|
|
354
|
+
http_config=HttpConfig(
|
|
355
|
+
timeout=15.0,
|
|
356
|
+
verify_ssl=True,
|
|
357
|
+
retry=RetryConfig(max_retries=5, base_delay=0.5, max_delay=10.0),
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Retries use exponential backoff with jitter and apply to transient
|
|
363
|
+
transport failures and 5xx / 429 responses. `Retry-After` is honoured
|
|
364
|
+
and clamped to `max_delay`.
|
|
365
|
+
|
|
366
|
+
### OIDC tokens, caching, and environment variables
|
|
367
|
+
|
|
368
|
+
The CLI persists OIDC tokens between invocations so users do not
|
|
369
|
+
re-authenticate on every command. The SDK defaults to `NullTokenCache`
|
|
370
|
+
(no silent filesystem writes); library consumers opt in explicitly:
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
from nextlabs_sdk import CloudAzClient, FileTokenCache
|
|
374
|
+
|
|
375
|
+
client = CloudAzClient(
|
|
376
|
+
base_url="https://cloudaz.example.com",
|
|
377
|
+
username="admin",
|
|
378
|
+
password="secret",
|
|
379
|
+
token_cache=FileTokenCache(), # or any custom TokenCache
|
|
380
|
+
)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Token cache lookup precedence** (CLI):
|
|
384
|
+
|
|
385
|
+
1. `--cache-dir <path>` or `NEXTLABS_CACHE_DIR` → `<path>/tokens.json`
|
|
386
|
+
2. `$XDG_CACHE_HOME/nextlabs-sdk/tokens.json`
|
|
387
|
+
3. `~/.cache/nextlabs-sdk/tokens.json`
|
|
388
|
+
|
|
389
|
+
The file is written `0600` inside a `0700` directory; writes are atomic
|
|
390
|
+
(temp file + `os.replace`). The cache key is
|
|
391
|
+
`"{token_url}|{username}|{client_id}"` so multiple profiles coexist.
|
|
392
|
+
|
|
393
|
+
Refresh tokens are used transparently when available; on refresh failure
|
|
394
|
+
the CLI falls back to the password grant (if `--password` /
|
|
395
|
+
`NEXTLABS_PASSWORD` is set) and otherwise raises `AuthenticationError`
|
|
396
|
+
with a "Run `nextlabs auth login`" hint.
|
|
397
|
+
|
|
398
|
+
**Environment variables**
|
|
399
|
+
|
|
400
|
+
| Variable | Purpose |
|
|
401
|
+
| -------------------------- | ------------------------------------------------------------- |
|
|
402
|
+
| `NEXTLABS_BASE_URL` | CloudAz base URL |
|
|
403
|
+
| `NEXTLABS_USERNAME` | CloudAz username |
|
|
404
|
+
| `NEXTLABS_PASSWORD` | CloudAz password |
|
|
405
|
+
| `NEXTLABS_CLIENT_ID` | OIDC client ID (default: `ControlCenterOIDCClient`) |
|
|
406
|
+
| `NEXTLABS_CLIENT_SECRET` | PDP client secret |
|
|
407
|
+
| `NEXTLABS_PDP_URL` | PDP base URL (defaults to `--base-url`) |
|
|
408
|
+
| `NEXTLABS_TOKEN` | Pre-issued bearer token; bypasses the login flow and cache |
|
|
409
|
+
| `NEXTLABS_CACHE_DIR` | Directory holding `tokens.json` (overrides XDG default) |
|
|
410
|
+
|
|
411
|
+
Top-level CLI flags worth knowing: `--no-verify` (skip TLS verification —
|
|
412
|
+
dev only), `-v` / `-vv` (verbose; `-vv` logs every HTTP request and
|
|
413
|
+
response body), `--token` (one-shot bearer override).
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Project layout
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
src/nextlabs_sdk/
|
|
421
|
+
├── cloudaz/ # Public: CloudAz models & enums (re-exports)
|
|
422
|
+
├── pdp/ # Public: PDP models & enums (re-exports)
|
|
423
|
+
├── exceptions.py # Public: NextLabsError hierarchy
|
|
424
|
+
├── _auth/ # Internal: OIDC auth flows + token cache
|
|
425
|
+
├── _cloudaz/ # Internal: CloudAz service classes + models
|
|
426
|
+
├── _pdp/ # Internal: PDP client + JSON/XML serializers
|
|
427
|
+
├── _cli/ # Internal: Typer-based CLI (optional extra)
|
|
428
|
+
├── _config.py # Internal (re-exported): HttpConfig, RetryConfig
|
|
429
|
+
├── _http_transport.py
|
|
430
|
+
└── _pagination.py # Internal (re-exported): paginators
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Development
|
|
434
|
+
|
|
435
|
+
See [docs/development.md](docs/development.md) for the full development
|
|
436
|
+
guide. Quick reference:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
python ./tools/checks.py # Black + Flake8 + MyPy + Pyright
|
|
440
|
+
python ./tools/tests.py --short # unit tests
|
|
441
|
+
python ./tools/tests.py --short --e2e # E2E tests only (requires Docker)
|
|
442
|
+
python ./tools/tests.py --short --all # unit + E2E tests (requires Docker)
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
A `.devcontainer` is provided; pre-commit hooks (`black`, `flake8`,
|
|
446
|
+
`mypy`, `pyright`) are preconfigured. The CLI demo above is regenerated
|
|
447
|
+
with `vhs docs/cast/demo.tape` — see
|
|
448
|
+
[`docs/cast/README.md`](docs/cast/README.md).
|
|
449
|
+
|
|
450
|
+
## License
|
|
451
|
+
|
|
452
|
+
MIT — see [LICENSE](LICENSE).
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
[Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) ·
|
|
457
|
+
[Changelog](CHANGELOG.md) · [Troubleshooting](docs/troubleshooting.md)
|