diff --git a/docs/requirements/Component-CLI.md b/docs/requirements/Component-CLI.md index ebad0ef7..2c53fd4b 100644 --- a/docs/requirements/Component-CLI.md +++ b/docs/requirements/Component-CLI.md @@ -62,17 +62,17 @@ scadabridge template create --name [--description ] [--parent-id [--name ] [--description ] [--parent-id ] scadabridge template validate --id scadabridge template delete --id -scadabridge template attribute add --template-id --name --data-type [--value ] [--description ] [--data-source ] [--locked ] -scadabridge template attribute update --id [--name ] [--data-type ] [--value ] [--description ] [--data-source ] [--locked ] +scadabridge template attribute add --template-id --name --data-type [--value ] [--description ] [--data-source ] [--locked] +scadabridge template attribute update --id [--name ] [--data-type ] [--value ] [--description ] [--data-source ] [--locked] scadabridge template attribute delete --id -scadabridge template alarm add --template-id --name --trigger-type --priority [--description ] [--trigger-config ] [--locked ] -scadabridge template alarm update --id [--name ] [--trigger-type ] [--priority ] [--description ] [--trigger-config ] [--locked ] +scadabridge template alarm add --template-id --name --trigger-type --priority [--description ] [--trigger-config ] [--locked] +scadabridge template alarm update --id --name --trigger-type --priority [--description ] [--trigger-config ] [--locked] scadabridge template alarm delete --id -scadabridge template script add --template-id --name --code --trigger-type [--trigger-config ] [--locked ] [--parameters ] [--return-def ] -scadabridge template script update --id [--name ] [--code ] [--trigger-type ] [--trigger-config ] [--locked ] [--parameters ] [--return-def ] +scadabridge template script add --template-id --name --code --trigger-type [--trigger-config ] [--locked] [--parameters ] [--return-def ] +scadabridge template script update --id --name --code --trigger-type [--trigger-config ] [--locked] [--parameters ] [--return-def ] scadabridge template script delete --id scadabridge template composition add --template-id --instance-name --composed-template-id -scadabridge template composition delete --template-id --instance-name +scadabridge template composition delete --id scadabridge template native-alarm-source add --template-id --name --connection --source-ref [--filter ] [--description ] [--locked] scadabridge template native-alarm-source list --template-id scadabridge template native-alarm-source remove --id @@ -165,8 +165,8 @@ scadabridge deploy status [--instance-id ] [--status ] [--page ] ``` scadabridge data-connection list [--site-id ] scadabridge data-connection get --id -scadabridge data-connection create --site-id --name --protocol [--backup-config ] [--failover-retry-count ] -scadabridge data-connection update --id [--name ] [--protocol ] [--backup-config ] [--failover-retry-count ] +scadabridge data-connection create --site-id --name --protocol [--primary-config ] [--backup-config ] [--failover-retry-count ] +scadabridge data-connection update --id --name --protocol [--primary-config ] [--backup-config ] [--failover-retry-count ] scadabridge data-connection delete --id ``` @@ -192,32 +192,36 @@ scadabridge notification create --name --emails scadabridge notification update --id [--name ] [--emails ] scadabridge notification delete --id scadabridge notification smtp list -scadabridge notification smtp update --id --server --port --auth-mode --from-address +scadabridge notification smtp update --id --server --port --auth-mode --from-address [--tls-mode ] [--credentials ] ``` ### Security Commands ``` scadabridge security api-key list -scadabridge security api-key create --name -scadabridge security api-key update --id --enabled -scadabridge security api-key delete --id +scadabridge security api-key create --name --methods +scadabridge security api-key update --key-id --enabled +scadabridge security api-key set-methods --key-id --methods +scadabridge security api-key delete --key-id scadabridge security role-mapping list scadabridge security role-mapping create --ldap-group --role scadabridge security role-mapping update --id [--ldap-group ] [--role ] scadabridge security role-mapping delete --id -scadabridge security scope-rule list [--mapping-id ] +scadabridge security scope-rule list --mapping-id scadabridge security scope-rule add --mapping-id --site-id scadabridge security scope-rule delete --id ``` -### Audit Log Commands +### Configuration-Change Audit Commands + +The `audit-config` group queries the configuration-change audit trail (the `IAuditService` +record of admin edits). `audit-log` is a deprecated alias that still works but emits a +warning; migrate scripts to `audit-config`. + ``` -scadabridge audit-log query [--user ] [--entity-type ] [--action ] [--from ] [--to ] [--page ] [--page-size ] +scadabridge audit-config query [--user ] [--entity-type ] [--action ] [--from ] [--to ] [--page ] [--page-size ] ``` -The legacy `audit-log query` above targets the original configuration-change audit -(IAuditService) surface. The new centralized Audit Log component (#23) is exposed via -the `scadabridge audit` group below. +The new centralized Audit Log component (#23) is exposed via the `scadabridge audit` group below. ### Centralized Audit Commands @@ -230,7 +234,7 @@ require the `OperationalAudit` permission; `audit export` additionally requires exit code 2) on denial. ``` -scadabridge audit query --since [--until ] [--channel ] [--kind ] [--status ] [--site ] [--instance ] [--target ] [--actor ] [--correlation-id ] [--errors-only] [--page ] [--page-size ] +scadabridge audit query [--since ] [--until ] [--channel ] [--kind ] [--status ] [--site ] [--target ] [--actor ] [--correlation-id ] [--execution-id ] [--parent-execution-id ] [--errors-only] [--page-size ] [--all] scadabridge audit export --since --until --format csv|jsonl|parquet --output [--channel ] [--kind ] [--status ] [--site ] [--target ] [--actor ] scadabridge audit verify-chain --month ``` @@ -298,10 +302,21 @@ scadabridge db-connection delete --id scadabridge api-method list scadabridge api-method get --id scadabridge api-method create --name --script [--timeout ] [--parameters ] [--return-def ] -scadabridge api-method update --id [--script ] [--timeout ] [--parameters ] [--return-def ] +scadabridge api-method update --id --script [--timeout ] [--parameters ] [--return-def ] scadabridge api-method delete --id ``` +### Bundle Commands (Transport #24) + +``` +scadabridge bundle export --output [--passphrase ] [--all] [--include-dependencies] [--templates ] [--shared-scripts ] [--external-systems ] [--db-connections ] [--notification-lists ] [--smtp-configs ] [--api-methods ] [--source-environment ] +scadabridge bundle preview --input [--passphrase ] +scadabridge bundle import --input [--passphrase ] [--on-conflict skip|overwrite|rename] +``` + +Inbound API keys are not transported between environments — re-create them on the destination via CLI or UI. +Bundle commands use a 5-minute timeout. + The `--format json|table` option is recursive and accepted on every command above. ## Configuration diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/README.md b/src/ZB.MOM.WW.ScadaBridge.CLI/README.md index e98ea94e..3d21431e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/README.md +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/README.md @@ -226,48 +226,62 @@ scadabridge --url template attribute delete --id Add an alarm definition to a template. ```sh -scadabridge --url template alarm add --template-id --name --trigger-attribute --condition --setpoint [--severity ] [--notification-list ] +scadabridge --url template alarm add --template-id --name --trigger-type --priority [--description ] [--trigger-config ] [--locked] [typed-setpoint-flags] ``` | Option | Required | Description | |--------|----------|-------------| | `--template-id` | yes | Template ID | | `--name` | yes | Alarm name | -| `--trigger-attribute` | yes | Attribute that triggers the alarm | -| `--condition` | yes | Trigger condition (e.g. `GreaterThan`, `LessThan`, `Equal`) | -| `--setpoint` | yes | Setpoint value | -| `--severity` | no | Alarm severity (default: `Warning`) | -| `--notification-list` | no | Notification list name to notify on alarm | +| `--trigger-type` | yes | Trigger type (e.g. `ValueMatch`, `RangeViolation`, `RateOfChange`, `HiLo`, `Expression`) | +| `--priority` | yes | Alarm priority (0–1000) | +| `--description` | no | Description | +| `--trigger-config` | no | Trigger configuration as a JSON string (overrides typed flags when both are supplied) | +| `--locked` | no | Lock the alarm in derived templates | +| `--attribute` | no | Attribute name the trigger watches (all trigger types except `Expression`) | +| `--match-value` | no | `ValueMatch`: value to compare against | +| `--not-equals` | no | `ValueMatch`: match when the value is NOT equal | +| `--min` | no | `RangeViolation`: minimum allowed value | +| `--max` | no | `RangeViolation`: maximum allowed value | +| `--threshold-per-second` | no | `RateOfChange`: rate threshold per second | +| `--window-seconds` | no | `RateOfChange`: sliding window in seconds | +| `--direction` | no | `RateOfChange`: direction (`rising`, `falling`, or `either`) | +| `--lolo` | no | `HiLo`: low-low setpoint | +| `--lo` | no | `HiLo`: low setpoint | +| `--hi` | no | `HiLo`: high setpoint | +| `--hihi` | no | `HiLo`: high-high setpoint | +| `--expression` | no | `Expression`: boolean trigger expression | #### `template alarm update` -Update an alarm definition on a template. +Update an alarm definition on a template. An update **replaces** the whole entity — every +required field below must be supplied with its post-update value, even if unchanged. ```sh -scadabridge --url template alarm update --template-id --name [--condition ] [--setpoint ] [--severity ] [--notification-list ] +scadabridge --url template alarm update --id --name --trigger-type --priority [--description ] [--trigger-config ] [--locked] ``` | Option | Required | Description | |--------|----------|-------------| -| `--template-id` | yes | Template ID | -| `--name` | yes | Alarm name to update | -| `--condition` | no | Updated trigger condition | -| `--setpoint` | no | Updated setpoint value | -| `--severity` | no | Updated severity | -| `--notification-list` | no | Updated notification list name | +| `--id` | yes | Alarm ID | +| `--name` | yes | Alarm name | +| `--trigger-type` | yes | Trigger type | +| `--priority` | yes | Alarm priority (0–1000) | +| `--description` | no | Description | +| `--trigger-config` | no | Trigger configuration JSON | +| `--locked` | no | Lock the alarm in derived templates | #### `template alarm delete` Remove an alarm definition from a template. ```sh -scadabridge --url template alarm delete --template-id --name +scadabridge --url template alarm delete --id ``` | Option | Required | Description | |--------|----------|-------------| -| `--template-id` | yes | Template ID | -| `--name` | yes | Alarm name to delete | +| `--id` | yes | Alarm ID | #### `template native-alarm-source add` @@ -309,60 +323,64 @@ scadabridge --url template native-alarm-source remove --id Add a script to a template. ```sh -scadabridge --url template script add --template-id --name --trigger-type [--trigger-attribute ] [--interval ] --code +scadabridge --url template script add --template-id --name --trigger-type --code [--trigger-config ] [--locked] [--parameters ] [--return-def ] ``` | Option | Required | Description | |--------|----------|-------------| | `--template-id` | yes | Template ID | | `--name` | yes | Script name | -| `--trigger-type` | yes | Trigger type: `OnChange`, `Periodic`, `OnAlarm` | -| `--trigger-attribute` | no | Attribute name for `OnChange` trigger | -| `--interval` | no | Interval in milliseconds for `Periodic` trigger | -| `--code` | yes | Script source code (or `@filepath` to read from file) | +| `--trigger-type` | yes | Trigger type (e.g. `OnChange`, `Periodic`, `OnAlarm`) | +| `--code` | yes | Script source code | +| `--trigger-config` | no | Trigger configuration as a JSON string (e.g. interval, attribute name) | +| `--locked` | no | Lock the script in derived templates | +| `--parameters` | no | Parameter definitions JSON | +| `--return-def` | no | Return definition JSON | #### `template script update` -Update a script on a template. +Update a script on a template. An update **replaces** the whole entity — every required +field below must be supplied with its post-update value, even if unchanged. ```sh -scadabridge --url template script update --template-id --name [--trigger-type ] [--trigger-attribute ] [--interval ] [--code ] +scadabridge --url template script update --id --name --trigger-type --code [--trigger-config ] [--locked] [--parameters ] [--return-def ] ``` | Option | Required | Description | |--------|----------|-------------| -| `--template-id` | yes | Template ID | -| `--name` | yes | Script name to update | -| `--trigger-type` | no | Updated trigger type | -| `--trigger-attribute` | no | Updated trigger attribute | -| `--interval` | no | Updated interval | -| `--code` | no | Updated script source code (or `@filepath`) | +| `--id` | yes | Script ID | +| `--name` | yes | Script name | +| `--trigger-type` | yes | Trigger type | +| `--code` | yes | Script source code | +| `--trigger-config` | no | Trigger configuration JSON | +| `--locked` | no | Lock the script in derived templates | +| `--parameters` | no | Parameter definitions JSON | +| `--return-def` | no | Return definition JSON | #### `template script delete` Remove a script from a template. ```sh -scadabridge --url template script delete --template-id --name +scadabridge --url template script delete --id ``` | Option | Required | Description | |--------|----------|-------------| -| `--template-id` | yes | Template ID | -| `--name` | yes | Script name to delete | +| `--id` | yes | Script ID | #### `template composition add` Add a feature module composition to a template. ```sh -scadabridge --url template composition add --template-id --module-template-id --instance-name +scadabridge --url template composition add --template-id --composed-template-id --instance-name ``` | Option | Required | Description | |--------|----------|-------------| | `--template-id` | yes | Target template ID | -| `--module-template-id` | yes | Feature module template ID to compose | +| `--composed-template-id` | yes | Feature module template ID to compose | | `--instance-name` | yes | Instance name for the composed module (used in path-qualified addressing) | #### `template composition delete` @@ -508,6 +526,84 @@ scadabridge --url instance set-bindings --id --bindings | `--id` | yes | Instance ID | | `--bindings` | yes | JSON array of `[attributeName, dataConnectionId]` pairs (e.g. `[["Speed",7],["Temperature",7]]`) | +#### `instance set-overrides` + +Set attribute value overrides for an instance. + +```sh +scadabridge --url instance set-overrides --id --overrides +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--id` | yes | Instance ID | +| `--overrides` | yes | JSON object of attribute name to value (e.g. `{"Speed": "100", "Mode": null}`); null clears an override | + +#### `instance alarm-override set` + +Set (upsert) an alarm override on an instance. + +```sh +scadabridge --url instance alarm-override set --instance-id --alarm [--trigger-config ] [--priority ] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--instance-id` | yes | Instance ID | +| `--alarm` | yes | Alarm canonical name (e.g. `TempLevels` or `Pump.TempSensor.Heat`) | +| `--trigger-config` | no | JSON override for TriggerConfiguration (HiLo: partial merge; others: whole-replace) | +| `--priority` | no | Priority override (0–1000) | + +#### `instance alarm-override delete` + +Remove an alarm override on an instance. + +```sh +scadabridge --url instance alarm-override delete --instance-id --alarm +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--instance-id` | yes | Instance ID | +| `--alarm` | yes | Alarm canonical name | + +#### `instance alarm-override list` + +List all alarm overrides for an instance. + +```sh +scadabridge --url instance alarm-override list --instance-id +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--instance-id` | yes | Instance ID | + +#### `instance set-area` + +Reassign an instance to a different area (or clear its area assignment). + +```sh +scadabridge --url instance set-area --id [--area-id ] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--id` | yes | Instance ID | +| `--area-id` | no | Area ID; omit to clear area assignment | + +#### `instance diff` + +Show the deployment diff between the currently deployed configuration and the current template state. + +```sh +scadabridge --url instance diff --id +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--id` | yes | Instance ID | + --- ### `site` — Manage sites @@ -537,7 +633,7 @@ scadabridge --url site list Register a new site. ```sh -scadabridge --url site create --name --identifier [--description ] +scadabridge --url site create --name --identifier [--description ] [--node-a-address ] [--node-b-address ] [--grpc-node-a-address ] [--grpc-node-b-address ] ``` | Option | Required | Description | @@ -545,6 +641,29 @@ scadabridge --url site create --name --identifier [--des | `--name` | yes | Human-readable site name | | `--identifier` | yes | Unique machine identifier used for cluster routing (e.g. `site-a`) | | `--description` | no | Site description | +| `--node-a-address` | no | Akka.NET cluster address for Node A | +| `--node-b-address` | no | Akka.NET cluster address for Node B | +| `--grpc-node-a-address` | no | gRPC streaming address for Node A | +| `--grpc-node-b-address` | no | gRPC streaming address for Node B | + +#### `site update` + +Update an existing site. An update **replaces** the whole entity — every required field +below must be supplied with its post-update value, even if unchanged. + +```sh +scadabridge --url site update --id --name [--description ] [--node-a-address ] [--node-b-address ] [--grpc-node-a-address ] [--grpc-node-b-address ] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--id` | yes | Site ID | +| `--name` | yes | Human-readable site name | +| `--description` | no | Site description | +| `--node-a-address` | no | Akka.NET cluster address for Node A | +| `--node-b-address` | no | Akka.NET cluster address for Node B | +| `--grpc-node-a-address` | no | gRPC streaming address for Node A | +| `--grpc-node-b-address` | no | gRPC streaming address for Node B | #### `site delete` @@ -587,14 +706,14 @@ scadabridge --url site area list --site-id Create an area within a site. ```sh -scadabridge --url site area create --site-id --name [--parent-area-id ] +scadabridge --url site area create --site-id --name [--parent-id ] ``` | Option | Required | Description | |--------|----------|-------------| | `--site-id` | yes | Site ID | | `--name` | yes | Area name | -| `--parent-area-id` | no | Parent area ID for nested areas | +| `--parent-id` | no | Parent area ID for nested areas | #### `site area update` @@ -885,17 +1004,18 @@ scadabridge --url notification smtp list Update the SMTP configuration. ```sh -scadabridge --url notification smtp update --host --port --auth-type [--username ] [--password ] [--from-address ] +scadabridge --url notification smtp update --id --server --port --auth-mode --from-address [--tls-mode ] [--credentials ] ``` | Option | Required | Description | |--------|----------|-------------| -| `--host` | yes | SMTP server hostname | +| `--id` | yes | SMTP config ID | +| `--server` | yes | SMTP server hostname | | `--port` | yes | SMTP server port | -| `--auth-type` | yes | Authentication type: `OAuth2` or `Basic` | -| `--username` | no | SMTP username (for Basic auth) | -| `--password` | no | SMTP password (for Basic auth) | -| `--from-address` | no | Sender email address | +| `--auth-mode` | yes | Authentication mode (e.g. `OAuth2ClientCredentials`, `Basic`) | +| `--from-address` | yes | Sender email address | +| `--tls-mode` | no | TLS mode: `None`, `StartTLS`, or `SSL` (preserves existing if omitted) | +| `--credentials` | no | SMTP credentials — `username:password` for Basic, or client secret for OAuth2 (preserves existing if omitted) | --- @@ -914,38 +1034,51 @@ scadabridge --url security api-key list Create a new inbound API key. The generated key value is returned in the response and not stored in plaintext — save it immediately. ```sh -scadabridge --url security api-key create --name +scadabridge --url security api-key create --name --methods ``` | Option | Required | Description | |--------|----------|-------------| | `--name` | yes | Descriptive label for the key | +| `--methods` | yes | Comma-separated API method names this key may call (e.g. `"MethodA,MethodB"`) | #### `security api-key update` -Update an API key's name or enabled status. +Enable or disable an API key. ```sh -scadabridge --url security api-key update --id [--name ] [--enabled ] +scadabridge --url security api-key update --key-id --enabled ``` | Option | Required | Description | |--------|----------|-------------| -| `--id` | yes | API key ID | -| `--name` | no | Updated label | -| `--enabled` | no | Enable or disable the key (`true` or `false`) | +| `--key-id` | yes | API key ID | +| `--enabled` | yes | Enable or disable the key (`true` or `false`) | + +#### `security api-key set-methods` + +Replace the method scopes on an existing API key. + +```sh +scadabridge --url security api-key set-methods --key-id --methods +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--key-id` | yes | API key ID | +| `--methods` | yes | Comma-separated API method names (replaces the existing set) | #### `security api-key delete` Revoke and delete an API key. ```sh -scadabridge --url security api-key delete --id +scadabridge --url security api-key delete --key-id ``` | Option | Required | Description | |--------|----------|-------------| -| `--id` | yes | API key ID | +| `--key-id` | yes | API key ID | #### `security role-mapping list` @@ -997,27 +1130,27 @@ scadabridge --url security role-mapping delete --id #### `security scope-rule list` -List all site scope rules for role mappings. +List all site scope rules for a role mapping. ```sh -scadabridge --url security scope-rule list [--role-mapping-id ] +scadabridge --url security scope-rule list --mapping-id ``` | Option | Required | Description | |--------|----------|-------------| -| `--role-mapping-id` | no | Filter by role mapping ID | +| `--mapping-id` | yes | Role mapping ID | #### `security scope-rule add` Add a site scope rule to a role mapping, restricting it to a specific site. ```sh -scadabridge --url security scope-rule add --role-mapping-id --site-id +scadabridge --url security scope-rule add --mapping-id --site-id ``` | Option | Required | Description | |--------|----------|-------------| -| `--role-mapping-id` | yes | Role mapping ID | +| `--mapping-id` | yes | Role mapping ID | | `--site-id` | yes | Site ID to scope the mapping to | #### `security scope-rule delete` @@ -1061,29 +1194,32 @@ scadabridge --url health site --identifier Query the site event log for a specific site. Events are fetched remotely from the site's local SQLite store. ```sh -scadabridge --url health event-log --site-identifier [--from ] [--to ] [--search ] [--page ] [--page-size ] +scadabridge --url health event-log --site [--event-type ] [--severity ] [--keyword ] [--from ] [--to ] [--page ] [--page-size ] [--instance-name ] ``` | Option | Required | Default | Description | |--------|----------|---------|-------------| -| `--site-identifier` | yes | — | Site identifier | +| `--site` | yes | — | Site identifier | +| `--event-type` | no | — | Filter by event type | +| `--severity` | no | — | Filter by severity | +| `--keyword` | no | — | Keyword search term | | `--from` | no | — | Start timestamp in ISO 8601 format | | `--to` | no | — | End timestamp in ISO 8601 format | -| `--search` | no | — | Keyword search term | | `--page` | no | `1` | Page number | | `--page-size` | no | `50` | Results per page | +| `--instance-name` | no | — | Filter by instance name | #### `health parked-messages` Query parked (dead-letter) messages at a specific site. ```sh -scadabridge --url health parked-messages --site-identifier [--page ] [--page-size ] +scadabridge --url health parked-messages --site [--page ] [--page-size ] ``` | Option | Required | Default | Description | |--------|----------|---------|-------------| -| `--site-identifier` | yes | — | Site identifier | +| `--site` | yes | — | Site identifier | | `--page` | no | `1` | Page number | | `--page-size` | no | `50` | Results per page | @@ -1162,6 +1298,8 @@ scadabridge --url audit query [options] | `--target` | no | — | Filter by target (external system, DB connection, notification list) | | `--actor` | no | — | Filter by actor | | `--correlation-id` | no | — | Filter by correlation ID | +| `--execution-id` | no | — | Filter by execution ID | +| `--parent-execution-id` | no | — | Filter by parent execution ID | | `--errors-only` | no | `false` | Show only failed events (`status=Failed`; overrides `--status`) | | `--page-size` | no | `100` | Events per page (1–1000) | | `--all` | no | `false` | Fetch every page, following the keyset cursor | @@ -1350,14 +1488,13 @@ scadabridge --url db-connection get --id Create a new database connection definition. ```sh -scadabridge --url db-connection create --name --connection-string [--provider ] +scadabridge --url db-connection create --name --connection-string ``` | Option | Required | Description | |--------|----------|-------------| | `--name` | yes | Connection name | | `--connection-string` | yes | Database connection string | -| `--provider` | no | Database provider (default: `SqlServer`) | #### `db-connection update` @@ -1415,14 +1552,16 @@ scadabridge --url api-method get --id Create a new inbound API method. ```sh -scadabridge --url api-method create --name --code [--description ] +scadabridge --url api-method create --name --script [--timeout ] [--parameters ] [--return-def ] ``` -| Option | Required | Description | -|--------|----------|-------------| -| `--name` | yes | Method name (used as the URL path segment in `POST /api/{methodName}`) | -| `--code` | yes | Script source code implementing the method (or `@filepath` to read from file) | -| `--description` | no | Method description | +| Option | Required | Default | Description | +|--------|----------|---------|-------------| +| `--name` | yes | — | Method name (used as the URL path segment in `POST /api/{methodName}`) | +| `--script` | yes | — | Script source code implementing the method | +| `--timeout` | no | `30` | Timeout in seconds | +| `--parameters` | no | — | Parameter definitions JSON | +| `--return-def` | no | — | Return type definition JSON | #### `api-method update` @@ -1457,6 +1596,74 @@ scadabridge --url api-method delete --id --- +### `bundle` — Transport bundle export / preview / import + +Export, preview, and import Transport (#24) bundles. Bundles carry templates, shared +scripts, external systems, database connections, notification lists, SMTP configurations, +and API methods between environments. Inbound API keys are **not** transported — recreate +them on the destination via the CLI or UI. + +Bundle commands use a 5-minute timeout (larger payloads may be slow over WAN). + +#### `bundle export` + +Export selected entities to a `.scadabundle` file. + +```sh +scadabridge --url bundle export --output [--passphrase ] [--all] [--include-dependencies] [entity-selectors] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--output` | yes | Output file path (e.g. `env-baseline.scadabundle`) | +| `--passphrase` | no | Encryption passphrase; omit to produce an unencrypted bundle | +| `--all` | no | Export every entity of every supported type (ignores per-type name flags) | +| `--include-dependencies` | no | Pull transitive dependencies (referenced shared scripts, parents, composed members) into the bundle | +| `--templates` | no | Comma-separated template names to include | +| `--shared-scripts` | no | Comma-separated shared-script names to include | +| `--external-systems` | no | Comma-separated external-system names to include | +| `--db-connections` | no | Comma-separated database-connection names to include | +| `--notification-lists` | no | Comma-separated notification-list names to include | +| `--smtp-configs` | no | Comma-separated SMTP host names to include | +| `--api-methods` | no | Comma-separated API-method names to include | +| `--source-environment` | no | `SourceEnvironment` value stamped into the bundle manifest (default: `cli`) | + +**Example** — export two templates and all their dependencies: + +```sh +scadabridge --url bundle export --output baseline.scadabundle \ + --templates "PumpTemplate,TankTemplate" --include-dependencies +``` + +#### `bundle preview` + +Load a bundle and print the diff preview (Added / Modified / Unchanged per entity) without applying any changes. + +```sh +scadabridge --url bundle preview --input [--passphrase ] +``` + +| Option | Required | Description | +|--------|----------|-------------| +| `--input` | yes | Bundle file path (`.scadabundle`) | +| `--passphrase` | no | Passphrase for encrypted bundles | + +#### `bundle import` + +Load and apply a bundle with a single global conflict policy. Preview first with `bundle preview` to review the diff. + +```sh +scadabridge --url bundle import --input [--passphrase ] [--on-conflict ] +``` + +| Option | Required | Default | Description | +|--------|----------|---------|-------------| +| `--input` | yes | — | Bundle file path (`.scadabundle`) | +| `--passphrase` | no | — | Passphrase for encrypted bundles | +| `--on-conflict` | no | `overwrite` | Resolution policy for `Modified` rows: `skip`, `overwrite`, or `rename` | + +--- + ## Architecture Notes The CLI connects to the Central cluster using Akka.NET's `ClusterClient`. It does not join the cluster — it contacts the `ClusterClientReceptionist` on one of the configured Central nodes and sends commands to the `ManagementActor` at path `/user/management`.