systemlink-cli 2.1.0__tar.gz → 2.3.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.
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/PKG-INFO +2 -1
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/pyproject.toml +2 -1
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/_version.py +1 -1
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/config_click.py +54 -14
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/main.py +3 -3
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/transport.py +27 -7
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/policy_click.py +81 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/commands.md +5 -0
- systemlink_cli-2.3.0/slcli/ssl_trust.py +633 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_click.py +51 -46
- systemlink_cli-2.1.0/slcli/ssl_trust.py +0 -376
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/LICENSE +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/dff-editor/editor.js +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/dff-editor/index.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/__init__.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/__main__.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/alarm_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/asset_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/cli_formatters.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/cli_utils.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/comment_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/completion_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/config.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/credentials.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/dataframe_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/dff_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/dff_decorators.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/example_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/example_loader.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/example_provisioner.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/_schema/schema-v1.0.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-1/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-1/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-2/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-2/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/leakage-current-results.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/overvoltage-results.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/product-xyz-compliance-report.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/product-xyz-specification.csv +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/demo-data-3/thermal-response-results.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/feed_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/file_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/function_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/function_templates.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/__init__.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/crypto.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/handlers.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/minion.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/models.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/protocol.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/rest.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client/state.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/managed_client_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/mcp_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/mcp_reachability.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/mcp_server.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/mcp_skills.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/notebook_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/pkce.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/platform.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/policy_utils.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/profile_credentials.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/profiles.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/response_handlers.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/rich_output.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/routine_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skill_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/SKILL.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/COPILOT_BATCH_RUN_PROMPT.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/evals.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/evals.schema.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/files/spec-import/battery-specs.csv +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/files/webapp-package/icon.svg +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/files/webapp-package/nipkg.config.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/files/webapp-package/webapp-content/index.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/evals/trigger_evals.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/domain-concepts.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/example-authoring.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/filtering.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/import-specs.min.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/job-debugging/overview.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/nipkg/overview.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/notebook/interfaces.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/notebook/notebook-patterns.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/notebook/overview.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/python-test/overview.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/routine-examples.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/troubleshooting.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/angular-ui-packages.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/deployment.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/layout-patterns.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/nimble-angular.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/overview.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/systemlink-services.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/references/webapp/troubleshooting.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/benchmark_iteration.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/compare_iteration.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/eval_manifest.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/grade_eval_response.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/grade_iteration.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/prepare_eval_prompts.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/prepare_eval_workspace.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/render_eval_review.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/skills/slcli/scripts/spec_import_helper.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/spec_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/state_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/system_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/system_query_utils.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/systemlink-logo.svg +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/table_utils.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/tag_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/templates_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/testmonitor_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/universal_handlers.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/user_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/utils.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/version_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/web_editor.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_bootstrap.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/.gitignore +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/angular.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/package.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/scripts/filter-sbom.js +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/app-routing.module.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/app.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/app.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/app.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/app.module.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/state/app-view-state.service.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/systemlink-context.service.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/theme-sync.service.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/webapp-home-data.service.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/app/shared/states/view-state.model.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/assets/README.md +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/index.html +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/main.ts +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/src/styles.scss +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/tsconfig.app.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/webapp_templates/angular/blank/tsconfig.json +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/workflow_preview.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/workflows_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/workitem_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/workspace_click.py +0 -0
- {systemlink_cli-2.1.0 → systemlink_cli-2.3.0}/slcli/workspace_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: systemlink-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: Fred Visser
|
|
@@ -18,6 +18,7 @@ Requires-Dist: cryptography (>=49.0.0)
|
|
|
18
18
|
Requires-Dist: filelock (>=3.20,<4)
|
|
19
19
|
Requires-Dist: httpcore2 (>=2.10.0,<3) ; extra == "mcp"
|
|
20
20
|
Requires-Dist: httpx2 (>=2.12.0,<3) ; extra == "mcp"
|
|
21
|
+
Requires-Dist: idna (>=3.10,<4)
|
|
21
22
|
Requires-Dist: keyring (>=25.6.0,<26.0.0)
|
|
22
23
|
Requires-Dist: mcp (>=2,<3) ; extra == "mcp"
|
|
23
24
|
Requires-Dist: msgpack (>=1.1,<2) ; extra == "managed-client"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "systemlink-cli"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.3.0"
|
|
4
4
|
description = "SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates."
|
|
5
5
|
authors = ["Fred Visser <fred.visser@emerson.com>"]
|
|
6
6
|
packages = [{ include = "slcli" }]
|
|
@@ -29,6 +29,7 @@ click = ">=7.1.2"
|
|
|
29
29
|
filelock = ">=3.20,<4"
|
|
30
30
|
keyring = "^25.6.0"
|
|
31
31
|
requests = "^2.32.4"
|
|
32
|
+
idna = ">=3.10,<4"
|
|
32
33
|
tabulate = "^0.10.0"
|
|
33
34
|
truststore = ">=0.9,<0.11"
|
|
34
35
|
watchdog = "^6.0.0"
|
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
import re
|
|
7
7
|
import ssl
|
|
8
8
|
import sys
|
|
9
|
+
from pathlib import Path
|
|
9
10
|
from typing import Any, NoReturn, Optional
|
|
10
11
|
from urllib.parse import urlparse
|
|
11
12
|
|
|
@@ -26,14 +27,16 @@ from .platform import (
|
|
|
26
27
|
from .profiles import Profile, ProfileConfig, check_config_file_permissions
|
|
27
28
|
from .rich_output import render_table
|
|
28
29
|
from .ssl_trust import (
|
|
30
|
+
get_managed_trust_path,
|
|
29
31
|
get_managed_trust_records,
|
|
30
32
|
get_ssl_server_origin,
|
|
31
33
|
inspect_server_certificate,
|
|
34
|
+
load_ca_certificate,
|
|
32
35
|
remove_managed_trust,
|
|
33
36
|
save_managed_certificate,
|
|
34
37
|
)
|
|
35
38
|
from .table_utils import output_formatted_list
|
|
36
|
-
from .utils import ExitCodes,
|
|
39
|
+
from .utils import ExitCodes, get_base_url_resolution
|
|
37
40
|
|
|
38
41
|
API_KEY_LENGTH = 42
|
|
39
42
|
API_KEY_PATTERN = re.compile(rf"^[A-Za-z0-9_-]{{{API_KEY_LENGTH}}}$")
|
|
@@ -765,12 +768,31 @@ def register_config_commands(cli: Any) -> None:
|
|
|
765
768
|
)
|
|
766
769
|
|
|
767
770
|
certificate_details = certificate.to_dict()
|
|
771
|
+
trusted_certificate = None
|
|
772
|
+
try:
|
|
773
|
+
trusted_path = get_managed_trust_path(certificate.origin)
|
|
774
|
+
if trusted_path is not None:
|
|
775
|
+
trusted_certificate = json.loads(
|
|
776
|
+
trusted_path.with_suffix(".json").read_text(encoding="utf-8")
|
|
777
|
+
)
|
|
778
|
+
trusted_certificate["origin"] = certificate.origin
|
|
779
|
+
trusted_certificate.setdefault("trust-type", "leaf")
|
|
780
|
+
except (OSError, ValueError) as exc:
|
|
781
|
+
click.echo(f"Could not read managed certificate metadata: {exc}.", err=True)
|
|
782
|
+
trusted_certificate = None
|
|
768
783
|
if output_format == "json":
|
|
784
|
+
certificate_details["trusted-certificate"] = trusted_certificate
|
|
769
785
|
click.echo(json.dumps(certificate_details, indent=2))
|
|
770
786
|
return
|
|
771
787
|
|
|
772
788
|
click.echo(f"Server certificate for {certificate_details.get('origin', 'unknown')}")
|
|
773
789
|
_show_certificate_details(certificate_details)
|
|
790
|
+
if trusted_certificate:
|
|
791
|
+
kind = "CA" if trusted_certificate.get("trust-type") == "ca" else "leaf"
|
|
792
|
+
click.echo(f"\nTrusted {kind} certificate for this origin")
|
|
793
|
+
_show_certificate_details(trusted_certificate)
|
|
794
|
+
else:
|
|
795
|
+
click.echo("\nNo managed trust certificate for this origin.")
|
|
774
796
|
|
|
775
797
|
@trust.command(name="list")
|
|
776
798
|
@click.option(
|
|
@@ -794,13 +816,14 @@ def register_config_commands(cli: Any) -> None:
|
|
|
794
816
|
[
|
|
795
817
|
str(record.get("origin", "")),
|
|
796
818
|
str(record.get("fingerprint", "")),
|
|
819
|
+
"CA" if record.get("trust-type") == "ca" else "leaf",
|
|
797
820
|
"yes" if record.get("self-signed") else "no",
|
|
798
821
|
]
|
|
799
822
|
for record in records
|
|
800
823
|
]
|
|
801
824
|
render_table(
|
|
802
|
-
headers=["SERVER", "SHA-256", "SELF-SIGNED"],
|
|
803
|
-
column_widths=[40, 64, 12],
|
|
825
|
+
headers=["SERVER", "SHA-256", "TRUST TYPE", "SELF-SIGNED"],
|
|
826
|
+
column_widths=[40, 64, 10, 12],
|
|
804
827
|
rows=rows,
|
|
805
828
|
show_total=True,
|
|
806
829
|
total_label="certificate(s)",
|
|
@@ -808,30 +831,47 @@ def register_config_commands(cli: Any) -> None:
|
|
|
808
831
|
|
|
809
832
|
@trust.command(name="add")
|
|
810
833
|
@click.option("--url", help="HTTPS server URL (defaults to the active API URL)")
|
|
834
|
+
@click.option(
|
|
835
|
+
"--certificate",
|
|
836
|
+
type=click.Path(exists=True, dir_okay=False, path_type=Path),
|
|
837
|
+
help="Import one public CA certificate (PEM or DER), scoped to this server origin",
|
|
838
|
+
)
|
|
811
839
|
@click.option(
|
|
812
840
|
"--fingerprint",
|
|
813
841
|
required=True,
|
|
814
842
|
help="Expected SHA-256 fingerprint of the certificate to trust",
|
|
815
843
|
)
|
|
816
|
-
def add_trusted_certificate(
|
|
817
|
-
|
|
818
|
-
|
|
844
|
+
def add_trusted_certificate(
|
|
845
|
+
url: Optional[str], certificate: Optional[Path], fingerprint: str
|
|
846
|
+
) -> None:
|
|
847
|
+
"""Trust a live server certificate or imported CA after fingerprint verification."""
|
|
848
|
+
server_url = url or get_base_url_resolution().value
|
|
819
849
|
try:
|
|
820
850
|
expected_fingerprint = _normalize_fingerprint(fingerprint)
|
|
821
|
-
|
|
851
|
+
trusted_certificate = (
|
|
852
|
+
load_ca_certificate(server_url, certificate)
|
|
853
|
+
if certificate is not None
|
|
854
|
+
else inspect_server_certificate(server_url)
|
|
855
|
+
)
|
|
822
856
|
except (OSError, ValueError, ssl.SSLError) as exc:
|
|
823
|
-
_exit_with_validation_error(f"Could not
|
|
857
|
+
_exit_with_validation_error(f"Could not load the certificate: {exc}.")
|
|
824
858
|
|
|
825
|
-
|
|
826
|
-
if
|
|
859
|
+
_show_certificate_details(trusted_certificate.to_dict(), err=True)
|
|
860
|
+
if trusted_certificate.fingerprint != expected_fingerprint:
|
|
827
861
|
_exit_with_validation_error(
|
|
828
|
-
"The
|
|
862
|
+
"The certificate fingerprint does not match the supplied fingerprint."
|
|
863
|
+
)
|
|
864
|
+
if trusted_certificate.trust_type == "ca":
|
|
865
|
+
click.echo(
|
|
866
|
+
"Trusting certificates issued by this CA for this origin only; "
|
|
867
|
+
"hostname and validity verification remain enabled.",
|
|
868
|
+
err=True,
|
|
829
869
|
)
|
|
830
870
|
try:
|
|
831
|
-
path = save_managed_certificate(
|
|
871
|
+
path = save_managed_certificate(trusted_certificate)
|
|
832
872
|
except OSError as exc:
|
|
833
873
|
_exit_with_validation_error(f"Could not save the trusted certificate: {exc}.")
|
|
834
|
-
click.echo(f"✓ Trusted certificate for {
|
|
874
|
+
click.echo(f"✓ Trusted certificate for {trusted_certificate.origin}")
|
|
835
875
|
click.echo(f" Certificate file: {path}")
|
|
836
876
|
|
|
837
877
|
@trust.command(name="remove")
|
|
@@ -839,7 +879,7 @@ def register_config_commands(cli: Any) -> None:
|
|
|
839
879
|
@click.option("--force", is_flag=True, help="Skip confirmation prompt")
|
|
840
880
|
def remove_trusted_certificate(url: Optional[str], force: bool) -> None:
|
|
841
881
|
"""Remove a server certificate from the managed trust store."""
|
|
842
|
-
server_url = url or
|
|
882
|
+
server_url = url or get_base_url_resolution().value
|
|
843
883
|
try:
|
|
844
884
|
origin = get_ssl_server_origin(server_url)
|
|
845
885
|
except ValueError as exc:
|
|
@@ -35,7 +35,7 @@ from .rich_output import install_rich_output, render_table
|
|
|
35
35
|
from .routine_click import register_routine_commands
|
|
36
36
|
from .skill_click import register_skill_commands
|
|
37
37
|
from .spec_click import register_spec_commands
|
|
38
|
-
from .ssl_trust import OS_TRUST_INJECTED, OS_TRUST_REASON
|
|
38
|
+
from .ssl_trust import OS_TRUST_INJECTED, OS_TRUST_REASON, create_explicit_tls_context
|
|
39
39
|
from .state_click import register_state_commands
|
|
40
40
|
from .system_click import register_system_commands
|
|
41
41
|
from .tag_click import register_tag_commands
|
|
@@ -143,11 +143,11 @@ def _build_tls_debug_context(ssl_verify: Union[bool, str]) -> ssl.SSLContext:
|
|
|
143
143
|
return ctx
|
|
144
144
|
|
|
145
145
|
if isinstance(ssl_verify, str):
|
|
146
|
-
return
|
|
146
|
+
return create_explicit_tls_context(ssl_verify)
|
|
147
147
|
|
|
148
148
|
verify_env = os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("SSL_CERT_FILE")
|
|
149
149
|
if verify_env:
|
|
150
|
-
return
|
|
150
|
+
return create_explicit_tls_context(verify_env)
|
|
151
151
|
|
|
152
152
|
if OS_TRUST_INJECTED:
|
|
153
153
|
try:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import socket
|
|
6
|
+
import threading
|
|
6
7
|
from collections import deque
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
from urllib.parse import urlsplit
|
|
@@ -12,6 +13,7 @@ from .protocol import MAX_FRAME_SIZE, MessagePackStream, SaltMessage
|
|
|
12
13
|
|
|
13
14
|
DEFAULT_REQUEST_PORT = 4506
|
|
14
15
|
DEFAULT_PUBLISH_PORT = 4505
|
|
16
|
+
IDLE_RECEIVE_POLL_INTERVAL = 0.1
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
@dataclass(frozen=True)
|
|
@@ -53,6 +55,7 @@ class SaltChannel:
|
|
|
53
55
|
self._decoder = MessagePackStream(max_frame_size=max_frame_size)
|
|
54
56
|
self._pending: deque[SaltMessage] = deque()
|
|
55
57
|
self._closed = False
|
|
58
|
+
self._receive_lock = threading.RLock()
|
|
56
59
|
|
|
57
60
|
@classmethod
|
|
58
61
|
def connect(
|
|
@@ -80,7 +83,7 @@ class SaltChannel:
|
|
|
80
83
|
raise TransportError("Unable to send a Salt message.") from error
|
|
81
84
|
|
|
82
85
|
def receive(self, *, ignore_timeout: bool = False) -> SaltMessage:
|
|
83
|
-
"""Read
|
|
86
|
+
"""Read a complete Salt message, polling for closure when ignoring timeouts."""
|
|
84
87
|
if self._closed:
|
|
85
88
|
raise TransportError("The Salt channel is closed.")
|
|
86
89
|
if self._pending:
|
|
@@ -89,7 +92,23 @@ class SaltChannel:
|
|
|
89
92
|
if self._closed:
|
|
90
93
|
raise TransportError("The Salt channel is closed.")
|
|
91
94
|
try:
|
|
92
|
-
|
|
95
|
+
with self._receive_lock:
|
|
96
|
+
if self._closed:
|
|
97
|
+
raise TransportError("The Salt channel is closed.")
|
|
98
|
+
if ignore_timeout:
|
|
99
|
+
timeout = self._connection.gettimeout()
|
|
100
|
+
self._connection.settimeout(
|
|
101
|
+
IDLE_RECEIVE_POLL_INTERVAL
|
|
102
|
+
if timeout is None
|
|
103
|
+
else min(timeout, IDLE_RECEIVE_POLL_INTERVAL)
|
|
104
|
+
)
|
|
105
|
+
try:
|
|
106
|
+
data = self._connection.recv(65536)
|
|
107
|
+
finally:
|
|
108
|
+
if not self._closed:
|
|
109
|
+
self._connection.settimeout(timeout)
|
|
110
|
+
else:
|
|
111
|
+
data = self._connection.recv(65536)
|
|
93
112
|
except socket.timeout as error:
|
|
94
113
|
if ignore_timeout:
|
|
95
114
|
continue
|
|
@@ -105,7 +124,7 @@ class SaltChannel:
|
|
|
105
124
|
return self._pending.popleft()
|
|
106
125
|
|
|
107
126
|
def close(self) -> None:
|
|
108
|
-
"""
|
|
127
|
+
"""Interrupt active reads before releasing the socket descriptor."""
|
|
109
128
|
if self._closed:
|
|
110
129
|
return
|
|
111
130
|
self._closed = True
|
|
@@ -113,7 +132,8 @@ class SaltChannel:
|
|
|
113
132
|
self._connection.shutdown(socket.SHUT_RDWR)
|
|
114
133
|
except OSError:
|
|
115
134
|
pass
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
135
|
+
with self._receive_lock:
|
|
136
|
+
try:
|
|
137
|
+
self._connection.close()
|
|
138
|
+
except OSError:
|
|
139
|
+
pass
|
|
@@ -18,6 +18,7 @@ from .policy_utils import (
|
|
|
18
18
|
_format_template_list_row,
|
|
19
19
|
_load_statements_from_file,
|
|
20
20
|
_parse_properties_from_cli,
|
|
21
|
+
_validate_statements,
|
|
21
22
|
)
|
|
22
23
|
from .universal_handlers import FilteredResponse, UniversalResponseHandler
|
|
23
24
|
from .utils import (
|
|
@@ -534,6 +535,86 @@ def register_policy_commands(cli: Any) -> None:
|
|
|
534
535
|
except Exception as exc:
|
|
535
536
|
handle_api_error(exc)
|
|
536
537
|
|
|
538
|
+
@template_group.command(name="update")
|
|
539
|
+
@click.argument("template_id")
|
|
540
|
+
@click.option("--name", type=str, default=None, help="New policy template name")
|
|
541
|
+
@click.option(
|
|
542
|
+
"--type",
|
|
543
|
+
"template_type",
|
|
544
|
+
type=click.Choice(["user", "service"], case_sensitive=False),
|
|
545
|
+
default=None,
|
|
546
|
+
help="New policy template type",
|
|
547
|
+
)
|
|
548
|
+
@click.option(
|
|
549
|
+
"--statements-file",
|
|
550
|
+
type=click.Path(exists=True, dir_okay=False),
|
|
551
|
+
default=None,
|
|
552
|
+
help='JSON file containing a statements list or an object with a "statements" list',
|
|
553
|
+
)
|
|
554
|
+
@click.option(
|
|
555
|
+
"--properties",
|
|
556
|
+
"-p",
|
|
557
|
+
multiple=True,
|
|
558
|
+
help="Updated custom properties as key=value (repeatable)",
|
|
559
|
+
)
|
|
560
|
+
@click.option(
|
|
561
|
+
"--format",
|
|
562
|
+
"-f",
|
|
563
|
+
type=click.Choice(["table", "json"]),
|
|
564
|
+
default="table",
|
|
565
|
+
show_default=True,
|
|
566
|
+
help="Output format",
|
|
567
|
+
)
|
|
568
|
+
def update_template(
|
|
569
|
+
template_id: str,
|
|
570
|
+
name: Optional[str],
|
|
571
|
+
template_type: Optional[str],
|
|
572
|
+
statements_file: Optional[str],
|
|
573
|
+
properties: Tuple[str, ...],
|
|
574
|
+
format: str,
|
|
575
|
+
) -> None:
|
|
576
|
+
"""Update selected fields on a reusable policy template."""
|
|
577
|
+
from .utils import check_readonly_mode
|
|
578
|
+
|
|
579
|
+
check_readonly_mode("update a policy template")
|
|
580
|
+
|
|
581
|
+
try:
|
|
582
|
+
payload: Dict[str, Any] = {}
|
|
583
|
+
if name is not None:
|
|
584
|
+
payload["name"] = name
|
|
585
|
+
if template_type is not None:
|
|
586
|
+
payload["type"] = template_type.lower()
|
|
587
|
+
if statements_file is not None:
|
|
588
|
+
statements = _load_statements_from_file(statements_file)
|
|
589
|
+
is_valid, error_message = _validate_statements(
|
|
590
|
+
statements,
|
|
591
|
+
require_workspace=False,
|
|
592
|
+
)
|
|
593
|
+
if not is_valid:
|
|
594
|
+
raise ValueError(error_message or "Invalid statements")
|
|
595
|
+
payload["statements"] = statements
|
|
596
|
+
if properties:
|
|
597
|
+
payload["properties"] = _parse_properties_from_cli(properties)
|
|
598
|
+
if not payload:
|
|
599
|
+
raise ValueError("At least one update option is required")
|
|
600
|
+
except ValueError as exc:
|
|
601
|
+
click.echo(f"✗ Error: {exc}", err=True)
|
|
602
|
+
sys.exit(ExitCodes.INVALID_INPUT)
|
|
603
|
+
|
|
604
|
+
try:
|
|
605
|
+
url = f"{get_base_url()}/niauth/v1/policy-templates/{template_id}"
|
|
606
|
+
current_template = make_api_request("GET", url, payload=None).json()
|
|
607
|
+
merged_payload = {
|
|
608
|
+
field: current_template[field]
|
|
609
|
+
for field in ("name", "type", "statements", "properties")
|
|
610
|
+
if field in current_template
|
|
611
|
+
}
|
|
612
|
+
merged_payload.update(payload)
|
|
613
|
+
resp = make_api_request("PUT", url, payload=merged_payload)
|
|
614
|
+
_display_template_details(resp.json(), format)
|
|
615
|
+
except Exception as exc:
|
|
616
|
+
handle_api_error(exc)
|
|
617
|
+
|
|
537
618
|
@template_group.command(name="list")
|
|
538
619
|
@click.option(
|
|
539
620
|
"--type",
|
|
@@ -746,6 +746,7 @@ slcli auth policy diff <POLICY_ID_1> <POLICY_ID_2> # Compare two policies
|
|
|
746
746
|
# Policy templates
|
|
747
747
|
slcli auth template list [-t INT] [-f json]
|
|
748
748
|
slcli auth template create --name TEXT --statements-file PATH [--type user|service] [-p KEY=VALUE] [-f json]
|
|
749
|
+
slcli auth template update TEMPLATE_ID [--name TEXT] [--type user|service] [--statements-file PATH] [-p KEY=VALUE] [-f json]
|
|
749
750
|
slcli auth template get <TEMPLATE_ID> [-f json]
|
|
750
751
|
slcli auth template delete <TEMPLATE_ID>
|
|
751
752
|
```
|
|
@@ -759,6 +760,10 @@ or an object with a `statements` array, for example:
|
|
|
759
760
|
[{"actions": ["testresult:Read"], "resource": ["*"]}]
|
|
760
761
|
```
|
|
761
762
|
|
|
763
|
+
`auth template update` fetches the current template and preserves unspecified
|
|
764
|
+
fields before sending `PUT /niauth/v1/policy-templates/{template-id}`.
|
|
765
|
+
Supplied statements and properties replace their existing values.
|
|
766
|
+
|
|
762
767
|
Workspace fields are not required. Properties are repeatable string-valued
|
|
763
768
|
`key=value` pairs. JSON output returns the full created template, including
|
|
764
769
|
its ID. Apply that ID to a workspace using `auth policy create TEMPLATE_ID
|