bc-cli 0.3.0__tar.gz → 0.5.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.
- {bc_cli-0.3.0 → bc_cli-0.5.0}/.gitignore +8 -0
- bc_cli-0.5.0/CHANGELOG.md +548 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/PKG-INFO +8 -1
- bc_cli-0.5.0/bcli-site/README.md +46 -0
- bc_cli-0.5.0/bcli-site/src/components/CodeBlock.astro +14 -0
- bc_cli-0.5.0/bcli-site/src/components/Hero.astro +32 -0
- bc_cli-0.5.0/bcli-site/src/pages/index.astro +118 -0
- bc_cli-0.5.0/bcli-site/src/styles/global.css +27 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/mcp-server.md +54 -31
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/saved-queries.md +74 -1
- bc_cli-0.5.0/packs/cronus-demo/batches/month-end-cronus.yaml +64 -0
- bc_cli-0.5.0/packs/cronus-demo/fragments/cronus-orientation.md +30 -0
- bc_cli-0.5.0/packs/cronus-demo/fragments/month-end-walkthrough.md +45 -0
- bc_cli-0.5.0/packs/cronus-demo/pack.yaml +23 -0
- bc_cli-0.5.0/packs/cronus-demo/queries/cronus-sample.yaml +53 -0
- bc_cli-0.5.0/packs/starter-generic/batches/month-end-readonly-audit.yaml +39 -0
- bc_cli-0.5.0/packs/starter-generic/batches/weekly-ar-snapshot.yaml +35 -0
- bc_cli-0.5.0/packs/starter-generic/fragments/common-errors.md +50 -0
- bc_cli-0.5.0/packs/starter-generic/fragments/endpoint-discovery.md +39 -0
- bc_cli-0.5.0/packs/starter-generic/fragments/filter-syntax-cheatsheet.md +51 -0
- bc_cli-0.5.0/packs/starter-generic/pack.yaml +31 -0
- bc_cli-0.5.0/packs/starter-generic/queries/ar-aging-buckets.yaml +17 -0
- bc_cli-0.5.0/packs/starter-generic/queries/customer-by-no.yaml +11 -0
- bc_cli-0.5.0/packs/starter-generic/queries/inventory-on-hand.yaml +14 -0
- bc_cli-0.5.0/packs/starter-generic/queries/open-pos.yaml +14 -0
- bc_cli-0.5.0/packs/starter-generic/queries/recent-posted-invoices.yaml +18 -0
- bc_cli-0.5.0/packs/starter-generic/queries/vendor-by-no.yaml +11 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/pyproject.toml +29 -1
- bc_cli-0.5.0/src/bcli/ask/__init__.py +32 -0
- bc_cli-0.5.0/src/bcli/ask/_claude.py +160 -0
- bc_cli-0.5.0/src/bcli/ask/_factory.py +98 -0
- bc_cli-0.5.0/src/bcli/ask/_openai.py +165 -0
- bc_cli-0.5.0/src/bcli/ask/_protocol.py +72 -0
- bc_cli-0.5.0/src/bcli/ask/_providers.py +106 -0
- bc_cli-0.5.0/src/bcli/batch/__init__.py +9 -0
- bc_cli-0.5.0/src/bcli/batch/ledger.py +563 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/client/_async.py +148 -4
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/client/_transport.py +40 -6
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/config/_model.py +64 -0
- bc_cli-0.5.0/src/bcli/context/__init__.py +82 -0
- bc_cli-0.5.0/src/bcli/context/_bundle.py +318 -0
- bc_cli-0.5.0/src/bcli/context/_http_tail.py +173 -0
- bc_cli-0.5.0/src/bcli/context/_last_error.py +286 -0
- bc_cli-0.5.0/src/bcli/context/_protocol.py +414 -0
- bc_cli-0.5.0/src/bcli/context/_redact.py +411 -0
- bc_cli-0.5.0/src/bcli/exit_codes.py +69 -0
- bc_cli-0.5.0/src/bcli/packs/__init__.py +81 -0
- bc_cli-0.5.0/src/bcli/packs/_installer.py +710 -0
- bc_cli-0.5.0/src/bcli/packs/_ledger.py +294 -0
- bc_cli-0.5.0/src/bcli/packs/_loader.py +282 -0
- bc_cli-0.5.0/src/bcli/packs/_protocol.py +171 -0
- bc_cli-0.5.0/src/bcli/packs/_registry.py +148 -0
- bc_cli-0.5.0/src/bcli/result_envelope.py +140 -0
- bc_cli-0.5.0/src/bcli/workflow/_models.py +114 -0
- bc_cli-0.5.0/src/bcli_cli/_envelope_wrap.py +344 -0
- bc_cli-0.5.0/src/bcli_cli/_error_handler.py +140 -0
- bc_cli-0.5.0/src/bcli_cli/_progress.py +92 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/_safety.py +6 -5
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/app.py +105 -4
- bc_cli-0.5.0/src/bcli_cli/commands/action_cmd.py +215 -0
- bc_cli-0.5.0/src/bcli_cli/commands/ask_cmd.py +234 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/attach_cmd.py +81 -45
- bc_cli-0.5.0/src/bcli_cli/commands/batch_cmd.py +1123 -0
- bc_cli-0.5.0/src/bcli_cli/commands/delete_cmd.py +119 -0
- bc_cli-0.5.0/src/bcli_cli/commands/describe_cmd.py +562 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/extract_cmd.py +47 -0
- bc_cli-0.5.0/src/bcli_cli/commands/pack_cmd.py +339 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/patch_cmd.py +61 -19
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/post_cmd.py +63 -16
- bc_cli-0.5.0/src/bcli_cli/commands/skill_cmd.py +599 -0
- bc_cli-0.5.0/src/bcli_cli/commands/skill_init_cmd.py +755 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/output/_formatters.py +19 -10
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_mcp/__main__.py +2 -2
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_mcp/_runner.py +38 -32
- bc_cli-0.5.0/src/bcli_mcp/_server.py +243 -0
- bc_cli-0.5.0/src/bcli_mcp/_tool_generator.py +195 -0
- bc_cli-0.5.0/tests/test_ask/test_cli_dry_run.py +158 -0
- bc_cli-0.5.0/tests/test_ask/test_factory.py +138 -0
- bc_cli-0.5.0/tests/test_ask/test_providers.py +153 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_batch_cmd_ledger.py +265 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_idempotency_replay.py +225 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_ledger_idempotency.py +214 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_ledger_schema.py +340 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_rollback_cmd.py +299 -0
- bc_cli-0.5.0/tests/test_batch_ledger/test_state_list_cmds.py +124 -0
- bc_cli-0.5.0/tests/test_cli/test_action_cmd.py +188 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_batch_safety.py +13 -1
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_output_format.py +9 -2
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_safety.py +2 -2
- bc_cli-0.5.0/tests/test_context/test_bundle.py +167 -0
- bc_cli-0.5.0/tests/test_context/test_http_tail.py +134 -0
- bc_cli-0.5.0/tests/test_context/test_last_error.py +135 -0
- bc_cli-0.5.0/tests/test_context/test_protocol.py +180 -0
- bc_cli-0.5.0/tests/test_context/test_redact.py +191 -0
- bc_cli-0.5.0/tests/test_describe/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_describe/test_describe_cmd.py +493 -0
- bc_cli-0.5.0/tests/test_describe/test_describe_positionals_limits.py +119 -0
- bc_cli-0.5.0/tests/test_envelope/conftest.py +143 -0
- bc_cli-0.5.0/tests/test_envelope/test_batch_envelope_with_ledger.py +286 -0
- bc_cli-0.5.0/tests/test_envelope/test_envelope_other_verbs.py +245 -0
- bc_cli-0.5.0/tests/test_envelope/test_envelope_policy_violation.py +163 -0
- bc_cli-0.5.0/tests/test_envelope/test_envelope_post.py +289 -0
- bc_cli-0.5.0/tests/test_envelope/test_result_envelope.py +165 -0
- bc_cli-0.5.0/tests/test_errors/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_errors/test_did_you_mean.py +116 -0
- bc_cli-0.5.0/tests/test_exit_codes/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_exit_codes/test_taxonomy.py +57 -0
- bc_cli-0.5.0/tests/test_idempotency/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_idempotency/conftest.py +64 -0
- bc_cli-0.5.0/tests/test_idempotency/test_cli_flags.py +135 -0
- bc_cli-0.5.0/tests/test_idempotency/test_idempotency_key.py +117 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_mcp/test_runner.py +66 -33
- bc_cli-0.5.0/tests/test_mcp/test_server_tools.py +328 -0
- bc_cli-0.5.0/tests/test_mcp/test_tool_generator.py +395 -0
- bc_cli-0.5.0/tests/test_output/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_output/test_json_on_pipe.py +85 -0
- bc_cli-0.5.0/tests/test_packs/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_packs/conftest.py +106 -0
- bc_cli-0.5.0/tests/test_packs/test_builtins.py +106 -0
- bc_cli-0.5.0/tests/test_packs/test_installer.py +219 -0
- bc_cli-0.5.0/tests/test_packs/test_loader.py +93 -0
- bc_cli-0.5.0/tests/test_packs/test_registry.py +46 -0
- bc_cli-0.5.0/tests/test_progress/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_progress/test_progress_events.py +157 -0
- bc_cli-0.5.0/tests/test_registry/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_skill_init/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_skill_init/conftest.py +147 -0
- bc_cli-0.5.0/tests/test_skill_init/test_skill_init_wizard.py +555 -0
- bc_cli-0.5.0/tests/test_skill_install/__init__.py +1 -0
- bc_cli-0.5.0/tests/test_skill_install/test_skill_install.py +484 -0
- bc_cli-0.5.0/tests/test_telemetry/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_url/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_url/test_bound_action_resolve.py +204 -0
- bc_cli-0.5.0/tests/test_workflow/__init__.py +0 -0
- bc_cli-0.5.0/tests/test_workflow/test_method_alias.py +153 -0
- bc_cli-0.5.0/tests/test_workflow/test_rollback_url_bound_action.py +61 -0
- bc_cli-0.3.0/.env.example +0 -5
- bc_cli-0.3.0/.github/ISSUE_TEMPLATE/bug_report.md +0 -39
- bc_cli-0.3.0/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- bc_cli-0.3.0/.github/PULL_REQUEST_TEMPLATE.md +0 -23
- bc_cli-0.3.0/.github/workflows/publish.yml +0 -90
- bc_cli-0.3.0/.github/workflows/tests.yml +0 -50
- bc_cli-0.3.0/AGENTS.md +0 -258
- bc_cli-0.3.0/CHANGELOG.md +0 -254
- bc_cli-0.3.0/CODE_OF_CONDUCT.md +0 -76
- bc_cli-0.3.0/CONTRIBUTING.md +0 -87
- bc_cli-0.3.0/SECURITY.md +0 -32
- bc_cli-0.3.0/src/bcli/workflow/_models.py +0 -68
- bc_cli-0.3.0/src/bcli_cli/commands/batch_cmd.py +0 -416
- bc_cli-0.3.0/src/bcli_cli/commands/delete_cmd.py +0 -76
- bc_cli-0.3.0/src/bcli_mcp/_server.py +0 -162
- bc_cli-0.3.0/tests/test_mcp/test_server_tools.py +0 -215
- bc_cli-0.3.0/uv.lock +0 -3330
- {bc_cli-0.3.0 → bc_cli-0.5.0}/LICENSE +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/NOTICE +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/README.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/authentication.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/batch-operations.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/business-central-admin-setup.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/command-reference.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/configuration.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/contributing.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/custom-apis.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/demo-setup.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/extraction.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/getting-started.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/multi-company.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/plans/team-deployment.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/querying.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/sdk-usage.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/docs/write-operations.md +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/ap-monthly-review.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/attach-purchase-invoice-pdf.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/create-purchase-invoice.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/extract/purchase_invoice_lines.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/month-end-cronus.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/examples/queries/sample.yaml +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/_url.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/_version.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/audit/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/audit/_factory.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/audit/_protocol.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/audit/_redact.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_base.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_browser.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_credentials.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_device_code.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_secure_io.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/auth/_token_cache.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/_apply.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/_fetch.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/_manifest.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/_publish.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/bundle/_verify.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/client/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/client/_safety.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/client/_sync.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/config/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/config/_defaults.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/config/_loader.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/diagnostics/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/diagnostics/_checks.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/errors.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_auth.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_bridge.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_client.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_generic.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_polaris.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/etl/_stampers.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_claude.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_factory.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_openai.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_pdf.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_protocol.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_schema.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/extract/_yaml_writer.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/_escape.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/_filter_fields.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/_pagination.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/_query.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/odata/_response.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/py.typed +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/registry/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/registry/_importers.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/registry/_registry.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/registry/_schema.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/registry/standard_v2.json +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/telemetry/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/telemetry/_azure_monitor.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/telemetry/_factory.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/telemetry/_protocol.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/telemetry/events.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/workflow/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/workflow/_loader.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/workflow/_query_search.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli/workflow/_resolver.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/_audit_wrap.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/_dry_run.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/_state.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/_url_resolve.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/auth_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/company_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/config_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/context_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/doctor_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/endpoint_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/env_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/etl_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/get_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/query_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/refresh_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/registry_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/commands/test_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/output/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_cli/output/_display.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/src/bcli_mcp/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/conftest.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/fixtures/sample_postman_collection.json +0 -0
- {bc_cli-0.3.0/tests/test_audit → bc_cli-0.5.0/tests/test_ask}/__init__.py +0 -0
- {bc_cli-0.3.0/tests/test_auth → bc_cli-0.5.0/tests/test_audit}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_audit/test_factory.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_audit/test_redact.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_audit/test_sink.py +0 -0
- {bc_cli-0.3.0/tests/test_bundle → bc_cli-0.5.0/tests/test_auth}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_auth/test_browser_auth.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_auth/test_secure_io.py +0 -0
- {bc_cli-0.3.0/tests/test_cli → bc_cli-0.5.0/tests/test_batch_ledger}/__init__.py +0 -0
- {bc_cli-0.3.0/tests/test_client → bc_cli-0.5.0/tests/test_bundle}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_bundle/test_bundle_roundtrip.py +0 -0
- {bc_cli-0.3.0/tests/test_config → bc_cli-0.5.0/tests/test_cli}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_audit_wrap.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_company_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_config_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_dry_run.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_pipe_handling.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_query_cmd.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_records_format.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_cli/test_state.py +0 -0
- {bc_cli-0.3.0/tests/test_diagnostics → bc_cli-0.5.0/tests/test_client}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_client/test_resolve_url.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_client/test_safety.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_client/test_transport.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_client/test_upload_attachment.py +0 -0
- {bc_cli-0.3.0/tests/test_etl → bc_cli-0.5.0/tests/test_config}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_config/test_config.py +0 -0
- {bc_cli-0.3.0/tests/test_extract → bc_cli-0.5.0/tests/test_context}/__init__.py +0 -0
- {bc_cli-0.3.0/tests/test_mcp → bc_cli-0.5.0/tests/test_diagnostics}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_diagnostics/test_checks.py +0 -0
- {bc_cli-0.3.0/tests/test_odata → bc_cli-0.5.0/tests/test_envelope}/__init__.py +0 -0
- {bc_cli-0.3.0/tests/test_registry → bc_cli-0.5.0/tests/test_etl}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_etl/test_bridge.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_etl/test_generic.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_etl/test_stampers.py +0 -0
- {bc_cli-0.3.0/tests/test_telemetry → bc_cli-0.5.0/tests/test_extract}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_claude.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_factory.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_openai.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_pdf.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_schema.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_extract/test_yaml_writer.py +0 -0
- {bc_cli-0.3.0/tests/test_url → bc_cli-0.5.0/tests/test_mcp}/__init__.py +0 -0
- {bc_cli-0.3.0/tests/test_workflow → bc_cli-0.5.0/tests/test_odata}/__init__.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_odata/test_escape.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_odata/test_filter_fields.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_odata/test_query.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_registry/test_caution.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_registry/test_importers.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_registry/test_metadata_fields.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_registry/test_registry.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_telemetry/test_events.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_telemetry/test_sink.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_url/test_origin_allowlist.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_url/test_url_builder.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_workflow/test_batch_integration.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_workflow/test_loader.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_workflow/test_models.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_workflow/test_query_search.py +0 -0
- {bc_cli-0.3.0 → bc_cli-0.5.0}/tests/test_workflow/test_resolver.py +0 -0
|
@@ -36,3 +36,11 @@ bcapi_cli_prd.md
|
|
|
36
36
|
|
|
37
37
|
# Codex CLI session metadata — local-only, not part of the repo
|
|
38
38
|
.context/
|
|
39
|
+
|
|
40
|
+
# bcli-site (Astro) — generated files
|
|
41
|
+
bcli-site/node_modules/
|
|
42
|
+
bcli-site/dist/
|
|
43
|
+
bcli-site/.astro/
|
|
44
|
+
bcli-site/pnpm-lock.yaml
|
|
45
|
+
bcli-site/package-lock.json
|
|
46
|
+
bcli-site/yarn.lock
|
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.5.0] - 2026-05-25
|
|
11
|
+
|
|
12
|
+
### Added — Part 3 (`bcli-site/` landing page v0)
|
|
13
|
+
|
|
14
|
+
- **`bcli-site/`** — Astro + Tailwind landing page scaffold for
|
|
15
|
+
bcli.sh. Single page (v0): hero, install instructions, three
|
|
16
|
+
example commands, features grid, GitHub link.
|
|
17
|
+
- Stack: Astro 4 + Tailwind 3 + TypeScript 5 (`extends:
|
|
18
|
+
astro/tsconfigs/strict`).
|
|
19
|
+
- Copy reflects what's actually shipped: packs, ask, MCP server,
|
|
20
|
+
describe. Does NOT oversell the deferred `bcli agent` mode (R9).
|
|
21
|
+
- `.github/workflows/site.yml` builds the site on changes under
|
|
22
|
+
`bcli-site/**`; Vercel deploy stub is wired but commented out
|
|
23
|
+
until `VERCEL_TOKEN` etc. are added to repo secrets.
|
|
24
|
+
- `bcli-site/node_modules`, `dist`, `.astro`, and lockfiles are
|
|
25
|
+
gitignored.
|
|
26
|
+
|
|
27
|
+
### Added — Part 2 (`bcli ask`)
|
|
28
|
+
|
|
29
|
+
- **`bcli ask "<question>"`** — second-opinion oracle. Bundles the
|
|
30
|
+
operator's recent failing context (last-error, http-tail,
|
|
31
|
+
profile, describe excerpt) via :mod:`bcli.context`, ships it to
|
|
32
|
+
a configured LLM backend, and prints the answer. Opt-in: NullAsker
|
|
33
|
+
is the default; set `[ask] backend = "claude"` (or `"openai"`) to
|
|
34
|
+
activate.
|
|
35
|
+
- Built-in backends: `null` (default), `claude` (Anthropic — extras
|
|
36
|
+
`[ask-claude]`), `openai` (extras `[ask-openai]`). Third-party
|
|
37
|
+
backends register by import path `module.path:ClassName`. Mirror
|
|
38
|
+
of the `extract` factory shape exactly.
|
|
39
|
+
- **`--dry-run`** prints the exact redacted bundle that would be
|
|
40
|
+
sent before any network call. **`--no-context`** suppresses the
|
|
41
|
+
auto-bundle. **`--attach PATH`** pins a file with redaction +
|
|
42
|
+
truncation. **`--backend NAME`** is a one-shot override.
|
|
43
|
+
- **`bcli.ask.context_providers` entry-point group (R8)** —
|
|
44
|
+
downstream packages add domain-specific context (glossaries,
|
|
45
|
+
schema hints) via a registered callable. Strictly opt-in: a pack
|
|
46
|
+
may recommend a provider but never auto-enables it; user config
|
|
47
|
+
in `[ask] context_providers = [...]` is the binding decision.
|
|
48
|
+
- New `AskConfig` section in `bcli.config._model` exposing
|
|
49
|
+
`backend`, `model`, `api_key_env`, `max_tokens`,
|
|
50
|
+
`include_describe`, `include_http_tail`, `context_providers`.
|
|
51
|
+
|
|
52
|
+
### Added — Part 1 (`bcli pack`)
|
|
53
|
+
|
|
54
|
+
- **`bcli pack`** command group: `list`, `info`, `install`,
|
|
55
|
+
`uninstall`. Discovers packs from three sources: built-in
|
|
56
|
+
(``packs/`` in the repo), entry-point group ``bcli.packs``, and
|
|
57
|
+
``--path <dir>`` for local development.
|
|
58
|
+
- **Pack manifest format** (``pack.yaml``) with `agent_fragments`,
|
|
59
|
+
`queries`, `batches`, `registry_presets`, and
|
|
60
|
+
`recommended_context_providers`. Each fragment declares
|
|
61
|
+
`targets:` (`agents` and/or `claude`); default `[agents]` (R3).
|
|
62
|
+
- **Install ledger** at
|
|
63
|
+
``~/.config/bcli/packs/<profile>/<pack>.json`` recording every
|
|
64
|
+
artefact written, with per-entry `rendered_hash` and `owner` so
|
|
65
|
+
uninstall is provenance-driven (R2).
|
|
66
|
+
- **Conflict detection** on registry presets (R7): a second pack
|
|
67
|
+
cannot silently overwrite an endpoint owned by another pack —
|
|
68
|
+
``--replace-owned --accept-conflicts`` is the two-flag escape
|
|
69
|
+
hatch.
|
|
70
|
+
- **Idempotent re-install**: marker blocks in AGENTS.md / CLAUDE.md
|
|
71
|
+
are replaced in place via ID + content_hash, never duplicated.
|
|
72
|
+
- **Two built-in packs**: `starter-generic` (6 queries, 2 batches,
|
|
73
|
+
3 fragments — uses only standard v2.0 endpoints) and
|
|
74
|
+
`cronus-demo` (Microsoft CRONUS demo workflow).
|
|
75
|
+
|
|
76
|
+
### Added — Part 0 (context infrastructure for LLM features)
|
|
77
|
+
|
|
78
|
+
- **`bcli.context` package** — shared, model-bound context layer that
|
|
79
|
+
future LLM-driven features consume (`bcli ask`, future `bcli agent`).
|
|
80
|
+
Standalone in this release; no CLI consumers yet.
|
|
81
|
+
- **Typed `ContextBundle` dataclass** with `to_dict()` / `to_prompt_text()`
|
|
82
|
+
renderers. Frozen, JSON-serialisable, token-budgeted with source
|
|
83
|
+
attribution and an explicit `RedactionRecord` audit trail (R4).
|
|
84
|
+
- **Three-layer redaction** (`bcli.context._redact`) — composes the
|
|
85
|
+
existing `bcli/audit/_redact.py` key-based stripper, the
|
|
86
|
+
`bcli/telemetry/events.py` token-pattern regex, and a new URL
|
|
87
|
+
query-param / GUID / attachment scrubber (R5). Every redaction is
|
|
88
|
+
logged with a stable `rule_id` so regressions are catchable in CI.
|
|
89
|
+
- **Last-error capture** — central `BCLIError` handler now drops a
|
|
90
|
+
redacted snapshot to `~/.config/bcli/last-error.json`. **No
|
|
91
|
+
tracebacks by default**; `--debug` invocations also write a
|
|
92
|
+
`last-error-debug.json` sidecar at mode 0600 (R6).
|
|
93
|
+
- **`bcli.http` rolling tail** — opt-in NDJSON tail at
|
|
94
|
+
`~/.config/bcli/http-tail.ndjson` enabled by `[context] tail = true`.
|
|
95
|
+
Size-bounded via `RotatingFileHandler`; URLs are query-stripped on
|
|
96
|
+
read so the bundle stays safe.
|
|
97
|
+
- **`ContextConfig`** — new `[context]` config section with `tail`,
|
|
98
|
+
`redact_company_ids`, `attachment_max_bytes` knobs.
|
|
99
|
+
|
|
100
|
+
## [0.4.0] — 2026-05-18 — Agent Interface Profile v0.1
|
|
101
|
+
|
|
102
|
+
The Agent Interface Profile (AIP) v0.1 lands: a small kernel of CLI
|
|
103
|
+
primitives that any agent runtime can drive deterministically, without
|
|
104
|
+
parallel schemas or hand-written MCP tools.
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
|
|
108
|
+
- **`bcli describe --format json`** — canonical machine-readable
|
|
109
|
+
projection of the live Typer surface + endpoint registry + active
|
|
110
|
+
profile. One command MCP, completions, and docs all consume; new CLI
|
|
111
|
+
commands light up automatically. Cached at
|
|
112
|
+
`~/.config/bcli/describe/<profile>.<hash>.json` with mtime
|
|
113
|
+
invalidation. Subtree mode (`bcli describe get`, `bcli describe batch
|
|
114
|
+
run`) returns narrow output for token-constrained agents. Includes
|
|
115
|
+
forward-compat declarations: `emits_result_envelope`,
|
|
116
|
+
`emits_operation_state`, `requires_confirmation: "production"`, plus
|
|
117
|
+
the new `exit_codes` taxonomy and per-command `positionals` /
|
|
118
|
+
`required` / `limits` extensions.
|
|
119
|
+
- **Mutation result envelope (`--result-out PATH` / `--result-fd N`)**
|
|
120
|
+
on every mutating verb (`post`, `patch`, `delete`, `attach upload`,
|
|
121
|
+
`batch run`). Frozen 18-field JSON envelope written atomically
|
|
122
|
+
(`os.replace` + `fsync`); contains profile, environment, company,
|
|
123
|
+
method, endpoint, resolved URL, record id, status, exit code, BC
|
|
124
|
+
correlation id, started_at, duration_ms. Failed envelopes carry the
|
|
125
|
+
exit code (4 = not found, 6 = remote 4xx, 7 = remote 5xx, 8 = policy
|
|
126
|
+
refusal, etc.) so an agent can read it side-channel and act without
|
|
127
|
+
scraping stdout. For `batch run` the envelope's `record_id` is the
|
|
128
|
+
ledger run id — pivot directly to `bcli batch state <run-id>` for
|
|
129
|
+
per-step detail.
|
|
130
|
+
- **Batch operation ledger (SQLite)** — one
|
|
131
|
+
`~/.config/bcli/batch/<run-id>.db` per `bcli batch run` invocation.
|
|
132
|
+
WAL + `synchronous=NORMAL`, intent row written before each HTTP call
|
|
133
|
+
(survives SIGKILL); outcome row after. Derived run state
|
|
134
|
+
distinguishes `partially_committed` from a stale `running` stamp. New
|
|
135
|
+
commands: `bcli batch state <run-id>`, `bcli batch list [--state
|
|
136
|
+
STATE] [--limit N]`, `bcli batch rollback <run-id> [--dry-run]
|
|
137
|
+
[--yes]`. Rollback issues `DELETE` for committed POSTs only; PATCH /
|
|
138
|
+
DELETE marked `rollback_skipped` (no clean inverse without pre-image
|
|
139
|
+
snapshots). `disable_writes` is a hard refusal on rollback (no
|
|
140
|
+
`--yes` bypass).
|
|
141
|
+
- **Exit code taxonomy** — `bcli.exit_codes` defines 0/1/2/3/4/5/6/7/8
|
|
142
|
+
with short labels; `bcli describe` projects the map; centralized
|
|
143
|
+
error handler maps `BCLIError` subclasses (`AuthError → 3`,
|
|
144
|
+
`RegistryError → 4`, `ValidationError → 5`, `ConfigError → 2`,
|
|
145
|
+
`SafetyError → 8`).
|
|
146
|
+
- **"Did you mean" remediation hints** on `BCLIError` paths: auth →
|
|
147
|
+
`Run 'bcli auth login --profile X'`, config (no profiles) →
|
|
148
|
+
`Run 'bcli config init'`, config (unknown profile) → fuzzy match,
|
|
149
|
+
registry (no fuzzy) → `Run 'bcli registry import …'`.
|
|
150
|
+
- **JSON on pipe by default** — when stdout isn't a TTY and no
|
|
151
|
+
`--format` was passed, emit JSON. Pipelines, redirects, CI steps,
|
|
152
|
+
agent runtimes all get the canonical machine-readable shape with no
|
|
153
|
+
flag dance. The `CLAUDECODE` and `BCLI_AGENT` env hints keep their
|
|
154
|
+
markdown semantics (explicit user opt-in); legacy Windows console
|
|
155
|
+
host stays on markdown for the mojibake reason. `BCLI_FORMAT` and
|
|
156
|
+
explicit `--format` always win.
|
|
157
|
+
- **`--idempotency-key KEY`** on `post`, `patch`, `delete`, `attach
|
|
158
|
+
upload`. IETF `Idempotency-Key` HTTP header sent on the first call
|
|
159
|
+
(gateway-level dedup remains in play). Same-run replay protection in
|
|
160
|
+
`bcli batch run`: if two mutating steps share an `idempotency_key:`
|
|
161
|
+
in the YAML, the second is replayed (no second HTTP, no duplicate
|
|
162
|
+
ledger row), and the result entry carries `prior_seq`,
|
|
163
|
+
`prior_step_id`, `prior_bc_correlation_id`. Ledger schema migrates
|
|
164
|
+
v1 → v2 non-destructively via `ALTER TABLE step ADD COLUMN
|
|
165
|
+
idempotency_key`.
|
|
166
|
+
- **Progress events (`--progress-fd N`)** on `bcli batch run` and
|
|
167
|
+
`bcli extract run`. JSON-lines `step_started` / `step_completed`
|
|
168
|
+
written to a dedicated fd (separate from `--result-fd`). Stderr
|
|
169
|
+
stays human-readable; the fd channel is structured and stable for
|
|
170
|
+
agents to demux. Replayed steps emit a synthetic pair with
|
|
171
|
+
`status="replayed"` so the progress stream tells the truth.
|
|
172
|
+
- **23 dynamically-generated MCP tools** in `bcli_mcp` (was 4
|
|
173
|
+
hand-written). Server subprocesses `bcli describe` once on startup
|
|
174
|
+
and registers one tool per command; new CLI commands light up as
|
|
175
|
+
MCP tools automatically. Five new mutating tools (`bcli_post`,
|
|
176
|
+
`bcli_patch`, `bcli_delete`, `bcli_attach_upload`, `bcli_batch_run`)
|
|
177
|
+
pass `--result-out` and return the envelope as their tool result.
|
|
178
|
+
`status="failed"` envelopes surface as MCP `ToolError` with the BC
|
|
179
|
+
correlation id quoted.
|
|
180
|
+
- **`AsyncBCClient.delete_url(url, *, etag="*")`** — new SDK method
|
|
181
|
+
for absolute-URL deletes (used by the rollback path; avoids
|
|
182
|
+
re-resolving the registry at undo time).
|
|
183
|
+
- **`bcli skill install`** — generates `.claude/commands/bcli-<name>.md`
|
|
184
|
+
per saved query and per batch template (`~/.config/bcli/batches/
|
|
185
|
+
<profile>/*.yaml`). Generates a top-level
|
|
186
|
+
`.claude/skills/bcli/SKILL.md` index grouped by `categories:`.
|
|
187
|
+
SHA-256 content hash embedded in the provenance comment for
|
|
188
|
+
byte-stable idempotency — no `generated_at` timestamp, so re-runs on
|
|
189
|
+
unchanged sources are mtime-preserving no-ops. `manual: true` in a
|
|
190
|
+
file's YAML frontmatter protects it from regeneration. `--dry-run`
|
|
191
|
+
previews; `--target` resolves to explicit path > CWD with `.claude/`
|
|
192
|
+
> `$HOME`. Stdlib only — no jinja2; atomic writes via
|
|
193
|
+
`tempfile.mkstemp` + `os.replace`.
|
|
194
|
+
- **`bcli skill init`** — interactive wizard that reads `bcli describe
|
|
195
|
+
--format json` via subprocess, runs 4 Rich prompts (role / top-three
|
|
196
|
+
daily questions / slash-command style / generate-new-queries y/N),
|
|
197
|
+
fuzzy-matches existing saved queries against the top-three free
|
|
198
|
+
text (stdlib `difflib`), and proposes new role-tailored queries via
|
|
199
|
+
entry-point providers — each with a per-query `[y/N]` approval gate.
|
|
200
|
+
Generates `~/.claude/skills/bcli-<user>/SKILL.md` with YAML
|
|
201
|
+
provenance frontmatter. Atomic commit phase: snapshots existing
|
|
202
|
+
content, writes all targets, restores on first failure. Guardrails
|
|
203
|
+
via `_assert_writable` restrict writes to `~/.config/bcli/queries/`,
|
|
204
|
+
`~/.claude/skills/bcli-<user>/`, and `~/.config/bcli/skills/`;
|
|
205
|
+
symlink-safe via `Path.resolve(strict=False)` + `is_relative_to`.
|
|
206
|
+
- **`bcli skill update`** — idempotent re-run via state cache at
|
|
207
|
+
`~/.config/bcli/skills/.last-init.json`. The cache persists both
|
|
208
|
+
the interview answers AND the approved-query bodies so a later
|
|
209
|
+
`--non-interactive` replay re-writes the same queries verbatim
|
|
210
|
+
(without re-asking the operator). Describe-payload-hash mismatch
|
|
211
|
+
refuses silent replay and asks for a re-interview when the describe
|
|
212
|
+
surface changed under the user's feet.
|
|
213
|
+
- **Saved-query YAML schema extension** — three additive fields
|
|
214
|
+
(`description`, `categories`, `args`). Existing saved-query bundles
|
|
215
|
+
without these still work: when `args:` is omitted, `bcli skill
|
|
216
|
+
install` derives it from `params:` keys (required first, optional
|
|
217
|
+
second, both in YAML insertion order). Documented in
|
|
218
|
+
`docs/saved-queries.md`'s new "Slash-command projection" section.
|
|
219
|
+
- **Entry-point group `bcli.skill_init.role_templates`** — OSS bcli
|
|
220
|
+
ships with an opinion-free default proposer (returns `[]` for every
|
|
221
|
+
role). Downstream packages plug in role templates by registering
|
|
222
|
+
callables under this entry-point group via standard Python
|
|
223
|
+
packaging. Discovered at wizard time via
|
|
224
|
+
`importlib.metadata.entry_points`. The provider signature is
|
|
225
|
+
`(interview, payload) -> list[ProposedQuery]`; downstream
|
|
226
|
+
integrators publish their own integration documentation.
|
|
227
|
+
|
|
228
|
+
### Changed
|
|
229
|
+
|
|
230
|
+
- **Policy refusal exit code 1 → 8.** Scripts that grep `if exit==1`
|
|
231
|
+
for "the read-only profile blocked me" need updating. Agents
|
|
232
|
+
consuming `bcli describe`'s new `exit_codes` field pick up the new
|
|
233
|
+
code automatically.
|
|
234
|
+
- **MCP tool renames** (breaking for existing MCP clients — Claude
|
|
235
|
+
Desktop, MCP Inspector configs referencing the old names need an
|
|
236
|
+
update):
|
|
237
|
+
- `query` → `bcli_get`
|
|
238
|
+
- `list_endpoints` → `bcli_endpoint_list`
|
|
239
|
+
- `describe_endpoint` → `bcli_endpoint_info` (with
|
|
240
|
+
`bcli_endpoint_fields` split out for field discovery)
|
|
241
|
+
- `list_companies` → `bcli_company_list`
|
|
242
|
+
|
|
243
|
+
Migration table in `docs/mcp-server.md`. Tool names now consistently
|
|
244
|
+
match the CLI command path.
|
|
245
|
+
- **MCP `bcli_get --top` cap remains 50 default / 1000 max** — parity
|
|
246
|
+
with the pre-rewrite hand-written `query` tool. CLI shell users can
|
|
247
|
+
still pass `--top 100000` directly; the cap is enforced only at the
|
|
248
|
+
MCP schema level (advisory for agent runtimes).
|
|
249
|
+
- **Stderr routing for `bcli batch run` metadata** — the ledger path
|
|
250
|
+
and run id print to stderr, not stdout. Stdout matches legacy batch
|
|
251
|
+
output byte-for-byte (required by the additive constraint).
|
|
252
|
+
|
|
253
|
+
### Fixed
|
|
254
|
+
|
|
255
|
+
- **Clean SIGPIPE handling for piped output** — `bcli <cmd> | head`,
|
|
256
|
+
`| grep -m 1`, and similar pipe-truncating consumers now terminate
|
|
257
|
+
the CLI silently, matching `cat` and `grep` conventions, instead of
|
|
258
|
+
emitting a `BrokenPipeError: [Errno 32] Broken pipe` traceback at
|
|
259
|
+
interpreter shutdown. Implemented as a new `bcli_cli.app:main`
|
|
260
|
+
console-script entry point that installs `SIGPIPE -> SIG_DFL` on
|
|
261
|
+
POSIX with a `BrokenPipeError` safety net for Windows.
|
|
262
|
+
- **Hyphenated saved-query param names** — the workflow template
|
|
263
|
+
resolver now accepts hyphens in identifiers, so references like
|
|
264
|
+
`${{ params.vendor-no }}` substitute correctly. Previously the regex
|
|
265
|
+
matched only `[\w.]`, silently leaving the literal `${{ … }}` token
|
|
266
|
+
in the rendered filter (BC then 400'd or, worse, returned mismatched
|
|
267
|
+
rows). Affects both `bcli q` saved queries and `bcli batch`
|
|
268
|
+
workflows.
|
|
269
|
+
|
|
270
|
+
### Breaking changes
|
|
271
|
+
|
|
272
|
+
The two items above (exit code 1→8 + MCP tool renames) are intentional
|
|
273
|
+
breaking changes called out in the AIP plan. Both have one-line
|
|
274
|
+
migration paths. Skill install / skill init / skill update are
|
|
275
|
+
additive — no breaking changes from the Skills layer.
|
|
276
|
+
|
|
277
|
+
### Deferred to v0.5
|
|
278
|
+
|
|
279
|
+
- **Cross-run idempotency replay** — would require scanning every
|
|
280
|
+
`*.db` in `~/.config/bcli/batch/` on each mutating call. Same-run
|
|
281
|
+
protection covers the agent-retry case which is the common one;
|
|
282
|
+
gateway-level Idempotency-Key dedup covers the rest.
|
|
283
|
+
- **`batch run --idempotency-key`** as a run-level flag — collides
|
|
284
|
+
across multiple mutating steps. Per-step `idempotency_key:` in the
|
|
285
|
+
batch YAML is the correct surface.
|
|
286
|
+
- **`telemetry_event_id` / `audit_log_offset` on the envelope** —
|
|
287
|
+
currently always `null`. Wiring requires extending the
|
|
288
|
+
`TelemetrySink` and audit protocols to return the emitted event id /
|
|
289
|
+
log offset, touching every backend including the optional Azure
|
|
290
|
+
Monitor extra.
|
|
291
|
+
- **Plan-token binding for single mutations** — `batch run --plan-out`
|
|
292
|
+
works; `bcli post --plan-out` does not. Defer until requested.
|
|
293
|
+
- **Direct FastMCP schema-introspection test** — the `__signature__`
|
|
294
|
+
patch is indirectly covered via tool-list registration tests; a
|
|
295
|
+
future FastMCP upgrade could silently degrade tool input schemas
|
|
296
|
+
without breaking tests.
|
|
297
|
+
- **Etag capture in ledger** — rollback DELETEs use `etag="*"`. A
|
|
298
|
+
future concurrent edit between POST and rollback could clobber.
|
|
299
|
+
- **CWD-relative batch template discovery** for `bcli skill install` —
|
|
300
|
+
today only `~/.config/bcli/batches/<profile>/*.yaml` is scanned;
|
|
301
|
+
project-local batches in `./batches/` would also be useful for the
|
|
302
|
+
per-project `.claude/` workflow.
|
|
303
|
+
- **SKILL.md frontmatter `generated_at` churn cleanup** — the
|
|
304
|
+
timestamp ticks forward on every `bcli skill update
|
|
305
|
+
--non-interactive` replay, so the frontmatter changes even when the
|
|
306
|
+
body is byte-stable. Idempotency tests compare body-only; downstream
|
|
307
|
+
content-hash watchers would see noise. Cosmetic.
|
|
308
|
+
- **`bcli skill update` separated from `init`** — today
|
|
309
|
+
`update_command` delegates to `init_command(...)` verbatim.
|
|
310
|
+
Documented for future evolution.
|
|
311
|
+
- **Public `bcli.skill_init` namespace for the entry-point contract**
|
|
312
|
+
— downstream packages currently couple to
|
|
313
|
+
`bcli_cli.commands.skill_init_cmd` for `InterviewState` /
|
|
314
|
+
`ProposedQuery`. A future release could promote the protocol types
|
|
315
|
+
to a public `bcli.skill_init` namespace.
|
|
316
|
+
|
|
317
|
+
## [0.2.0] — 2026-05-06
|
|
318
|
+
|
|
319
|
+
### Added
|
|
320
|
+
|
|
321
|
+
- **Structured `--dry-run` output** — write commands (`post`, `patch`,
|
|
322
|
+
`delete`, `attach upload`) now emit a stable JSON envelope on stdout
|
|
323
|
+
when `--format json` / `ndjson` / `raw` is selected. Includes
|
|
324
|
+
`dry_run`, `method`, `endpoint`, `resolved_url`, `profile`,
|
|
325
|
+
`environment`, `company_id`, `body`, and `record_id` (when applicable).
|
|
326
|
+
Agents can parse the envelope before deciding whether to proceed. The
|
|
327
|
+
human format keeps the same yellow rich panel on stderr but is now
|
|
328
|
+
augmented with the resolved URL and profile context. See
|
|
329
|
+
`docs/write-operations.md`.
|
|
330
|
+
- **Opt-in audit log** — new `[audit]` config section persists every
|
|
331
|
+
write to a per-profile JSONL file. Each entry captures the resolved
|
|
332
|
+
URL, response status, BC `correlation_id`, latency, redacted request
|
|
333
|
+
body, and outcome (`completed` / `failed` / `dry_run`). Bounded disk
|
|
334
|
+
usage via single-backup rotation. SDK (`AsyncBCClient`) does NOT
|
|
335
|
+
auto-emit; this is a CLI-layer ergonomic on top of BC permission sets.
|
|
336
|
+
See `docs/configuration.md#audit-log`.
|
|
337
|
+
- **Endpoint `caution` flag** — `EndpointMetadata` now carries a
|
|
338
|
+
`caution: low | medium | high` level. Importers populate it
|
|
339
|
+
automatically from a verb-name heuristic (entities containing `post`,
|
|
340
|
+
`release`, `cancel`, `void`, `reverse`, `apply`, `unapply` are flagged
|
|
341
|
+
`high`). Surfaced in `bcli endpoint info` and the `list_endpoints` MCP
|
|
342
|
+
tool so agents can require explicit user confirmation before mutating
|
|
343
|
+
posted/closed records.
|
|
344
|
+
- New `AGENTS.md` recipes for dry-run-first writes, caution-level
|
|
345
|
+
interpretation, and audit-log location.
|
|
346
|
+
|
|
347
|
+
## [0.1.5] — 2026-05-05
|
|
348
|
+
|
|
349
|
+
### Added
|
|
350
|
+
|
|
351
|
+
- **Business Central admin setup guide** — new
|
|
352
|
+
`docs/business-central-admin-setup.md` walks a zero-knowledge user
|
|
353
|
+
through Entra app registration, localhost redirect setup, delegated BC
|
|
354
|
+
permissions, admin consent, BC user permission sets, first `bcli
|
|
355
|
+
config init`, and verification.
|
|
356
|
+
- **`bcli-mcp` preview server** — an MCP (Model Context Protocol) server
|
|
357
|
+
that lets Claude Desktop and other MCP clients drive bcli. Four
|
|
358
|
+
read-only tools: `query`, `list_endpoints`, `describe_endpoint`,
|
|
359
|
+
`list_companies`. Subprocess-only architecture inherits profile, auth,
|
|
360
|
+
retry, telemetry, and `disable_writes` from the CLI. Install with
|
|
361
|
+
`pip install "bc-cli[mcp]"`. See `docs/mcp-server.md`.
|
|
362
|
+
|
|
363
|
+
### Changed
|
|
364
|
+
|
|
365
|
+
- `bcli config init` now defaults to browser PKCE auth for local humans
|
|
366
|
+
and agents. New `--automation` and `--headless` shortcuts create
|
|
367
|
+
client-credentials and device-code profiles respectively.
|
|
368
|
+
- CLI runtime dependencies now ship with the base `bc-cli` install, so
|
|
369
|
+
`pip install bc-cli` and `uv tool install bc-cli` provide a working
|
|
370
|
+
`bcli` command without requiring an extra.
|
|
371
|
+
- `bcli company list` accepts `--format` (`json`, `markdown`, `csv`,
|
|
372
|
+
`ndjson`, `table`). Stable JSON shape:
|
|
373
|
+
`[{"id", "name", "alias", "is_default"}]`.
|
|
374
|
+
- `bcli endpoint list` and `bcli endpoint info` accept `--format json`.
|
|
375
|
+
Stable JSON shapes documented inline in each command's help text.
|
|
376
|
+
|
|
377
|
+
### Removed
|
|
378
|
+
|
|
379
|
+
- Removed WorkOS AuthKit support. Browser PKCE is now the delegated auth
|
|
380
|
+
path, Business Central remains the permission boundary, and
|
|
381
|
+
client-credentials profiles cover automation.
|
|
382
|
+
|
|
383
|
+
## [0.1.2] — 2026-04-29
|
|
384
|
+
|
|
385
|
+
Security release. Closes four findings from a strix.ai run against the
|
|
386
|
+
repo. No public SDK signature changes; the CLI gains one new flag
|
|
387
|
+
(`bcli batch run --yes`).
|
|
388
|
+
|
|
389
|
+
### Security
|
|
390
|
+
|
|
391
|
+
- **vuln-0001 (HIGH, CWE-352)** — WorkOS localhost callback now binds a
|
|
392
|
+
per-login high-entropy `state` token. Before this release, any local
|
|
393
|
+
request reaching `127.0.0.1:8401/callback?code=…` during the login
|
|
394
|
+
window would be exchanged for a role-bearing WorkOS identity and
|
|
395
|
+
cached on disk. The handler now rejects callbacks whose path is not
|
|
396
|
+
`/callback` (404) or whose `state` doesn't match the per-login token
|
|
397
|
+
(400), and surfaces invalid callbacks as auth failures rather than
|
|
398
|
+
masking them as timeouts.
|
|
399
|
+
- **vuln-0002 (MEDIUM, CWE-841)** — `bcli batch run` now enforces the
|
|
400
|
+
`disable_writes` profile gate that direct `post`/`patch`/`delete`
|
|
401
|
+
commands already honour. Mutating batch steps on a read-only profile
|
|
402
|
+
prompt for confirmation interactively or abort with exit 1 in
|
|
403
|
+
non-interactive sessions. New `--yes` / `-y` flag opts scripted use
|
|
404
|
+
past the prompt. Pure GET batches are unaffected, and `--dry-run`
|
|
405
|
+
still skips the gate so workflows can be previewed.
|
|
406
|
+
- **vuln-0003 (MEDIUM)** — Browser auth callback listener now binds an
|
|
407
|
+
ephemeral kernel-assigned port instead of a hard-coded 8400, and
|
|
408
|
+
serves continuously until a state-bound callback arrives or the
|
|
409
|
+
timeout expires. Stray requests (e.g. `/favicon.ico`) and
|
|
410
|
+
state-mismatched callbacks no longer consume the only callback slot.
|
|
411
|
+
Microsoft Entra accepts any port for `http://localhost` redirect URIs
|
|
412
|
+
on public clients per RFC 8252, so existing app registrations
|
|
413
|
+
continue to work without changes.
|
|
414
|
+
- **vuln-0004 (HIGH, CWE-841)** — `SafeContext` writes are now bound to
|
|
415
|
+
the explicit `environment` and `company_id` passed to
|
|
416
|
+
`client.safe_write(env, company)`, not the client's profile-bound
|
|
417
|
+
target. Previously the safety gate validated operator intent but the
|
|
418
|
+
underlying URL still resolved against the profile, so writes inside
|
|
419
|
+
`safe_write("Sandbox", "company-SANDBOX")` could still hit
|
|
420
|
+
`Production/company-PROD`. Closes the documentation-vs-behaviour
|
|
421
|
+
mismatch where the README/changelog claimed the gate prevented
|
|
422
|
+
wrong-environment writes.
|
|
423
|
+
|
|
424
|
+
### Changed
|
|
425
|
+
|
|
426
|
+
- `bcli batch run` accepts a new `--yes` / `-y` flag (see vuln-0002
|
|
427
|
+
above). Existing automation against writable profiles is unaffected;
|
|
428
|
+
CI scripts that run mutating batches against a `disable_writes`
|
|
429
|
+
profile must pass `--yes` or migrate to a writable profile.
|
|
430
|
+
|
|
431
|
+
## [0.1.1] — 2026-04-29
|
|
432
|
+
|
|
433
|
+
OSS-readiness polish. No SDK behaviour changes; one CLI rename and a
|
|
434
|
+
README/docstring cleanup pass.
|
|
435
|
+
|
|
436
|
+
### Changed
|
|
437
|
+
|
|
438
|
+
- **Renamed the document-attachment CLI command** to `bcli attach`,
|
|
439
|
+
with subcommands `bcli attach upload` and `bcli attach test`.
|
|
440
|
+
Functionality is unchanged. The previous name was a customer-name
|
|
441
|
+
leftover from internal development; the workflow is generic to any
|
|
442
|
+
Business Central tenant.
|
|
443
|
+
- Genericised customer-named example values in
|
|
444
|
+
`docs/authentication.md`, `examples/attach-purchase-invoice-pdf.yaml`,
|
|
445
|
+
and SDK docstrings.
|
|
446
|
+
|
|
447
|
+
### Fixed
|
|
448
|
+
|
|
449
|
+
- README license badge said Apache 2.0 but the License section said
|
|
450
|
+
MIT. Now consistent: Apache 2.0 throughout (matches the actual
|
|
451
|
+
`LICENSE` file and `pyproject.toml`).
|
|
452
|
+
|
|
453
|
+
## [0.1.0] — 2026-04-29
|
|
454
|
+
|
|
455
|
+
First public release on PyPI as **`bc-cli`**.
|
|
456
|
+
|
|
457
|
+
> **Note on the package name.** The PyPI distribution name is `bc-cli`,
|
|
458
|
+
> not `bcli` — the latter is squatted by an unrelated 2018-era
|
|
459
|
+
> "EC2 Cluster Creator" package. The Python import name (`import bcli`)
|
|
460
|
+
> and the CLI binary on PATH (`bcli`) are unaffected.
|
|
461
|
+
|
|
462
|
+
### Added
|
|
463
|
+
|
|
464
|
+
- **SDK** — `BCClient` (sync) and `AsyncBCClient` (async) for Microsoft
|
|
465
|
+
Dynamics 365 Business Central. Two construction modes: profile-based
|
|
466
|
+
(TOML config files) and programmatic (pass auth params directly).
|
|
467
|
+
- **CLI** — Typer-based `bcli` command with subcommands for query
|
|
468
|
+
(`get`), write (`post`/`patch`/`delete`/`attach`), config, auth,
|
|
469
|
+
registry import, batch operations, saved queries (`q`), and ETL
|
|
470
|
+
pipelines.
|
|
471
|
+
- **Three-tier endpoint resolution.** Custom registry → standard v2.0 →
|
|
472
|
+
fuzzy-match suggestion. Custom APIs imported from Postman v2.1
|
|
473
|
+
collections, raw JSON, or live `$metadata`.
|
|
474
|
+
- **Auth** — Client-credentials, device-code, browser (PKCE), and
|
|
475
|
+
WorkOS AuthKit (role → BC client_id mapping). Token cache with 5-min
|
|
476
|
+
expiry buffer; OS keychain integration via `keyring`.
|
|
477
|
+
- **Write safety** — `SafeContext` gate enforces explicit `environment`
|
|
478
|
+
+ `company_id` on writes; production writes require
|
|
479
|
+
`confirm_production=True`. CLI's `disable_writes` profile flag adds
|
|
480
|
+
an interactive confirmation prompt before any mutating call.
|
|
481
|
+
- **Saved queries** (`bcli q`) — Hide OData syntax behind named,
|
|
482
|
+
parameterised aliases stored per-profile. Per-param `type`,
|
|
483
|
+
`pattern`, `min`/`max`, and `enum` validation runs locally before any
|
|
484
|
+
HTTP call. String parameters interpolated into `filter:` are escaped
|
|
485
|
+
using OData v4 single-quote rules so an injection-shaped value cannot
|
|
486
|
+
break the literal.
|
|
487
|
+
- **ETL pipeline** — Built-in [dlt](https://dlthub.com) source for
|
|
488
|
+
incremental backup. Polaris REST catalog integration for Iceberg
|
|
489
|
+
snapshots. Generic + bcli-bridge layers.
|
|
490
|
+
- **Telemetry** — Pluggable backend with `null`, `console`,
|
|
491
|
+
`azure_monitor`, and arbitrary `module:Class` sinks. Privacy-first
|
|
492
|
+
defaults: token redaction in error messages, opt-in capture of filter
|
|
493
|
+
text and signed-in UPN. Every event carries `version`, `os`,
|
|
494
|
+
`os_release`, `arch`, `python_version`, and a stable per-laptop
|
|
495
|
+
`install_id` for downstream slicing.
|
|
496
|
+
- **Structured logging** — JSON request logs to the `bcli.http` logger
|
|
497
|
+
with method/url/status/retry-count/latency/correlation-id.
|
|
498
|
+
|
|
499
|
+
### Security
|
|
500
|
+
|
|
501
|
+
The 0.1.0 release went through two independent security review passes
|
|
502
|
+
before publish. Findings addressed:
|
|
503
|
+
|
|
504
|
+
- Pinned wheel-version installer scripts; scrubbed registry `supports`
|
|
505
|
+
arrays to `["GET"]` for read-only profiles; removed sensitive field
|
|
506
|
+
metadata from public artefacts shipped by the bootstrap installer.
|
|
507
|
+
- **Critical:** Project-level `.bcli.toml` files cannot override
|
|
508
|
+
`[telemetry] backend`. Closes an arbitrary-Python-import RCE on
|
|
509
|
+
`bcli` invocation in any directory containing a malicious
|
|
510
|
+
`.bcli.toml`.
|
|
511
|
+
- **High:** Token caches and identity caches written with `0o600`
|
|
512
|
+
perms via atomic write; parent dir tightened to `0o700`; one-shot
|
|
513
|
+
warning on insecure existing perms.
|
|
514
|
+
- **High:** WorkOS role cache now expires after 1 hour; revoked roles
|
|
515
|
+
no longer keep mapping to privileged BC apps indefinitely.
|
|
516
|
+
- **Medium:** Absolute-URL paths (`@odata.nextLink`) validated against
|
|
517
|
+
a `*.businesscentral.dynamics.com` / `*.bc.dynamics.com` host
|
|
518
|
+
allowlist before the bearer token is attached. Closes a
|
|
519
|
+
bearer-exfiltration vector via tampered BC responses.
|
|
520
|
+
- **Medium:** CI hardened — third-party actions pinned by full commit
|
|
521
|
+
SHA, default `permissions: contents: read`, `uv sync --locked` for
|
|
522
|
+
reproducible installs from a committed `uv.lock`.
|
|
523
|
+
- **Medium:** Saved-query OData injection prevention (filter-context
|
|
524
|
+
escape + per-parameter `type`/`pattern`/`min`/`max`/`enum`
|
|
525
|
+
validation).
|
|
526
|
+
|
|
527
|
+
### Known limitations
|
|
528
|
+
|
|
529
|
+
- Alpha software. The SDK and CLI surface may change in 0.x releases;
|
|
530
|
+
track this CHANGELOG for breaking changes.
|
|
531
|
+
- Some BC custom-API edge cases (zero-GUID ids on
|
|
532
|
+
`SourceTableTemporary` pages) require the `--standard` flag to
|
|
533
|
+
bypass the registry — see `bcli attach upload --help`.
|
|
534
|
+
|
|
535
|
+
## [Pre-0.1.0 history]
|
|
536
|
+
|
|
537
|
+
Earlier development happened under the working name `bcapi`, then
|
|
538
|
+
moved to `bcli` (April 2026), then to the PyPI distribution name
|
|
539
|
+
`bc-cli` (April 2026, after discovering the `bcli` PyPI name was
|
|
540
|
+
squatted by an unrelated 2018 package).
|
|
541
|
+
|
|
542
|
+
[Unreleased]: https://github.com/igor-ctrl/bcli/compare/v0.4.0...HEAD
|
|
543
|
+
[0.4.0]: https://github.com/igor-ctrl/bcli/compare/v0.2.0...v0.4.0
|
|
544
|
+
[0.2.0]: https://github.com/igor-ctrl/bcli/compare/v0.1.5...v0.2.0
|
|
545
|
+
[0.1.5]: https://github.com/igor-ctrl/bcli/compare/v0.1.2...v0.1.5
|
|
546
|
+
[0.1.2]: https://github.com/igor-ctrl/bcli/compare/v0.1.1...v0.1.2
|
|
547
|
+
[0.1.1]: https://github.com/igor-ctrl/bcli/compare/v0.1.0...v0.1.1
|
|
548
|
+
[0.1.0]: https://github.com/igor-ctrl/bcli/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bc-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Python SDK and CLI for Microsoft Dynamics 365 Business Central APIs
|
|
5
5
|
Project-URL: Homepage, https://github.com/igor-ctrl/bcli
|
|
6
6
|
Project-URL: Repository, https://github.com/igor-ctrl/bcli
|
|
@@ -30,6 +30,13 @@ Requires-Dist: pyyaml>=6.0
|
|
|
30
30
|
Requires-Dist: rich>=13.0
|
|
31
31
|
Requires-Dist: tomlkit>=0.13
|
|
32
32
|
Requires-Dist: typer>=0.12
|
|
33
|
+
Provides-Extra: ask
|
|
34
|
+
Requires-Dist: anthropic>=0.40; extra == 'ask'
|
|
35
|
+
Requires-Dist: openai>=1.50; extra == 'ask'
|
|
36
|
+
Provides-Extra: ask-claude
|
|
37
|
+
Requires-Dist: anthropic>=0.40; extra == 'ask-claude'
|
|
38
|
+
Provides-Extra: ask-openai
|
|
39
|
+
Requires-Dist: openai>=1.50; extra == 'ask-openai'
|
|
33
40
|
Provides-Extra: cli
|
|
34
41
|
Provides-Extra: dev
|
|
35
42
|
Requires-Dist: anthropic>=0.40; extra == 'dev'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# bcli-site
|
|
2
|
+
|
|
3
|
+
Astro + Tailwind landing site for [bcli](https://github.com/igor-ctrl/bcli).
|
|
4
|
+
Single page (v0): hero + install + example commands + features.
|
|
5
|
+
|
|
6
|
+
## Development
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd bcli-site/
|
|
10
|
+
corepack enable # ensures pnpm is on PATH
|
|
11
|
+
pnpm install # one-time
|
|
12
|
+
pnpm dev # http://localhost:4321
|
|
13
|
+
pnpm build # static output → dist/
|
|
14
|
+
pnpm preview # preview the built site
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Deploy
|
|
18
|
+
|
|
19
|
+
Intended target is Vercel; the project root in Vercel should be set
|
|
20
|
+
to `bcli-site/`. The GH workflow at `.github/workflows/site.yml`
|
|
21
|
+
performs a build + (commented-out) deploy step — uncomment and add
|
|
22
|
+
`VERCEL_TOKEN` + `VERCEL_PROJECT_ID` + `VERCEL_ORG_ID` to the repo
|
|
23
|
+
secrets to enable auto-deploy from `main`.
|
|
24
|
+
|
|
25
|
+
## Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
bcli-site/
|
|
29
|
+
astro.config.mjs # Astro + Tailwind
|
|
30
|
+
tailwind.config.mjs # palette + fonts (matches the terminal-y bcli vibe)
|
|
31
|
+
tsconfig.json # extends astro/tsconfigs/strict
|
|
32
|
+
src/
|
|
33
|
+
pages/index.astro # hero + install + 3 examples + feature grid
|
|
34
|
+
components/
|
|
35
|
+
Hero.astro
|
|
36
|
+
CodeBlock.astro
|
|
37
|
+
styles/global.css # Tailwind base + small layer overrides
|
|
38
|
+
public/
|
|
39
|
+
og.png.placeholder # TODO: real OG card
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Content rules (matches Part 3 / R9)
|
|
43
|
+
|
|
44
|
+
The copy must describe what's actually shipped — packs, ask, MCP
|
|
45
|
+
server, describe. Do NOT oversell the `bcli agent` mode (deferred
|
|
46
|
+
to Part 4). Once the agent loop lands, add a section here.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
caption?: string;
|
|
4
|
+
lang?: string;
|
|
5
|
+
}
|
|
6
|
+
const { caption, lang = "bash" } = Astro.props;
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<figure class="my-6">
|
|
10
|
+
{caption && (
|
|
11
|
+
<figcaption class="text-sm text-muted mb-2">{caption}</figcaption>
|
|
12
|
+
)}
|
|
13
|
+
<pre class="rounded-lg bg-black/40 border border-white/10 p-4 text-sm leading-relaxed overflow-x-auto"><code data-lang={lang}><slot /></code></pre>
|
|
14
|
+
</figure>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Hero — first impression, tagline, install one-liner.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<section class="container-wide pt-24 pb-16">
|
|
6
|
+
<p class="text-sm uppercase tracking-widest text-accent2">
|
|
7
|
+
bcli — Business Central CLI & SDK
|
|
8
|
+
</p>
|
|
9
|
+
<h1 class="mt-3 text-4xl md:text-6xl font-semibold tracking-tight leading-tight">
|
|
10
|
+
Business Central from the terminal.<br />
|
|
11
|
+
<span class="text-accent">Designed for humans and AI agents.</span>
|
|
12
|
+
</h1>
|
|
13
|
+
<p class="mt-6 max-w-2xl text-lg text-muted leading-relaxed">
|
|
14
|
+
A discovery-first command line and Python SDK for Microsoft Dynamics 365
|
|
15
|
+
Business Central. Reusable packs, second-opinion oracle, and an MCP server
|
|
16
|
+
so every agent runtime can drive it deterministically.
|
|
17
|
+
</p>
|
|
18
|
+
<div class="mt-8 flex flex-col sm:flex-row gap-4">
|
|
19
|
+
<a
|
|
20
|
+
href="#install"
|
|
21
|
+
class="rounded-md bg-accent text-ink font-medium px-5 py-3 hover:opacity-90 transition"
|
|
22
|
+
>
|
|
23
|
+
Install
|
|
24
|
+
</a>
|
|
25
|
+
<a
|
|
26
|
+
href="https://github.com/igor-ctrl/bcli"
|
|
27
|
+
class="rounded-md border border-white/15 px-5 py-3 hover:bg-white/5 transition"
|
|
28
|
+
>
|
|
29
|
+
View on GitHub
|
|
30
|
+
</a>
|
|
31
|
+
</div>
|
|
32
|
+
</section>
|