Synchronize CLI documentation with management command parity

This commit is contained in:
Joseph Doherty
2026-09-10 01:20:12 -04:00
parent 0cc9db9e94
commit 2b9a7c3ca0
4 changed files with 376 additions and 169 deletions
+259 -105
View File
@@ -22,13 +22,13 @@ Every command requires a connection to a running Central node. The management UR
scadabridge --url http://central-host:5000 <command>
```
**Docker:** With the Docker setup, the Central UI (and management API) is available at `http://localhost:9001`:
**Docker:** Use Traefik at `http://localhost:9000` to reach the active central node:
```sh
scadabridge --url http://localhost:9001 <command>
scadabridge --url http://localhost:9000 <command>
```
For HA failover, use a load balancer URL. The management API is stateless (Basic Auth per request), so any central node can handle any request without sticky sessions.
The management API is stateless (Basic Auth per request), so sticky sessions are unnecessary. Direct node URLs (`9001`/`9002`) are useful for diagnostics; use Traefik for active-node routing and failover.
## Global Options
@@ -107,6 +107,24 @@ scadabridge --url <url> --format json template list # unmodified JS
| `--skip` | no | Offset paging: number of items to skip (default 0) |
| `--take` | no | Offset paging: max items to return (clamped 1..1000; omit for unlimited) |
#### `template resolved-members`
Inspect effective template members, including inheritance. This does not apply composition or instance overrides.
```sh
scadabridge template resolved-members --id <template-id>
```
#### `template move`
Move a template into a folder, or to the root when `--folder-id` is omitted.
```sh
scadabridge template move --id <template-id> [--folder-id <folder-id>]
```
Requires Designer access; server-side folder and dependency checks apply.
#### `template get`
Get a single template by ID. Unlike `template list`, this returns the **full** template
@@ -333,6 +351,16 @@ List the native alarm source bindings on a template.
scadabridge --url <url> template native-alarm-source list --template-id <int>
```
#### `template native-alarm-source update`
Replace the fields of an existing native alarm source binding.
```sh
scadabridge template native-alarm-source update --id <source-id> --name <name> --connection <name> --source-ref <reference> [--filter <expression>] [--description <text>] [--locked]
```
The ID, name, connection, and source reference are required. Omitted filter and description clear those values; omitted `--locked` means unlocked. Requires Designer access; the server enforces locking rules.
#### `template native-alarm-source remove`
Remove a native alarm source binding from a template (by its ID).
@@ -566,6 +594,24 @@ Create Instance page can bind the module groups at creation time (design
2026-08-21); the CLI equivalent is a follow-up `instance set-bindings` /
`instance bind-module` against the new instance id.
#### `instance native-alarm-source list`
List the native alarm source overrides for an instance.
```sh
scadabridge instance native-alarm-source list --instance-id <id>
```
#### `instance attribute-override delete`
Delete one attribute override while preserving other overrides.
```sh
scadabridge instance attribute-override delete --instance-id <id> --attribute <canonical-name>
```
Use a composed name such as `Module.Speed` where applicable. Requires Deployer access and passes through server-side site-scope checks.
#### `instance native-alarm-source set`
Override an inherited native alarm source binding for a single instance (upsert). Blank
@@ -1143,6 +1189,16 @@ scadabridge --url <url> data-connection update --id <int> --name <string> --prot
| `--backup-config` | no | Backup protocol-specific configuration as a JSON string |
| `--failover-retry-count` | no | Retries before failover to the backup configuration (default: `3`) |
#### `data-connection move`
Move a data connection to a destination site.
```sh
scadabridge data-connection move --id <connection-id> --site-id <destination-site-id>
```
Both IDs are required. Requires Designer access; the server validates the destination and any dependency restrictions.
#### `data-connection delete`
Delete a data connection.
@@ -1326,6 +1382,48 @@ scadabridge --url <url> external-system delete --id <int>
---
#### `external-system method list`
List the methods belonging to an external system.
```sh
scadabridge external-system method list --external-system-id <id>
```
#### `external-system method get`
Read one method definition.
```sh
scadabridge external-system method get --id <id>
```
#### `external-system method create`
Create an external HTTP method. Requires Designer access.
```sh
scadabridge external-system method create --external-system-id <id> --name <name> --http-method <verb> --path <path> [--params <json>] [--return <json>]
```
#### `external-system method update`
Update an external HTTP method. Requires Designer access.
```sh
scadabridge external-system method update --id <id> [--name <name>] [--http-method <verb>] [--path <path>] [--params <json>] [--return <json>]
```
#### `external-system method delete`
Delete a method by ID. Requires Designer access.
```sh
scadabridge external-system method delete --id <id>
```
---
### `notification` — Manage notification lists
#### `notification get`
@@ -1392,6 +1490,36 @@ scadabridge --url <url> notification update --id <int> --name <string> --type sm
| `--emails` | conditional | Comma-separated recipient email addresses. **Required for `--type email`; rejected for `--type sms`.** |
| `--phones` | conditional | Comma-separated recipient phone numbers in E.164. **Required for `--type sms`; rejected for `--type email`.** |
#### `notification rename`
Rename a list without replacing its recipients.
```sh
scadabridge notification rename --id <list-id> --name <name>
```
Requires Designer access. Unrelated recipient IDs, names, and contacts are preserved.
#### `notification recipient add`
Add an individual named recipient to an existing list.
```sh
scadabridge notification recipient add --list-id <id> --name <name> [--email <email>] [--phone <E.164-number>]
```
Provide at least one of `--email` or `--phone`. The server checks the contact against the owning list channel. Requires Designer access; other recipients remain unchanged.
#### `notification recipient delete`
Delete one recipient by recipient ID.
```sh
scadabridge notification recipient delete --id <recipient-id>
```
Requires Designer access. Only the specified recipient is removed.
#### `notification delete`
Delete a notification list.
@@ -1412,6 +1540,16 @@ Show the current SMTP configuration.
scadabridge --url <url> notification smtp list
```
#### `notification smtp create`
Create a new SMTP configuration. Requires Administrator access.
```sh
scadabridge notification smtp create --server <host> --port <int> --auth-mode <mode> --from-address <email> [--tls-mode <mode>] [--credentials <value>] [--oauth2-authority <url>] [--oauth2-scope <scope>] [--transport <Smtp|Ews>]
```
Uses the same settings as `smtp update`, without `--id`. This sends the distinct create contract; update with ID zero is not a creation operation. The server validates transport/authentication compatibility.
#### `notification smtp update`
Update the SMTP configuration.
@@ -1445,22 +1583,35 @@ Show the current SMS (Twilio) configuration. The Twilio **Auth Token is never re
scadabridge --url <url> notification sms list
```
#### `notification sms create`
Create a new Twilio configuration. Requires Administrator access.
```sh
scadabridge notification sms create --account-sid <sid> --auth-token <token> [--from-number <E.164-number>] [--messaging-service-sid <sid>] [--api-base-url <url>] [--connection-timeout-seconds <n>] [--max-retries <n>] [--retry-delay-seconds <n>]
```
Account SID and auth token are required. Supply at least one sender: `--from-number` or `--messaging-service-sid`. Timeout must be positive; retries/delay must be nonnegative. Omitted policy settings use creation defaults. Explicit zero retry settings retain the outbox fallback semantics; they do not disable retries.
#### `notification sms update`
Update the SMS (Twilio) configuration.
```sh
scadabridge --url <url> notification sms update --id <int> --account-sid <string> --from-number <string> [--messaging-service-sid <string>] [--api-base-url <string>] [--auth-token <string>]
scadabridge --url <url> notification sms update --id <int> --account-sid <string> [--from-number <string>] [--messaging-service-sid <string>] [--api-base-url <string>] [--auth-token <string>] [--connection-timeout-seconds <n>] [--max-retries <n>] [--retry-delay-seconds <n>]
```
| Option | Required | Description |
|--------|----------|-------------|
| `--id` | yes | SMS config ID |
| `--account-sid` | yes | Twilio Account SID |
| `--from-number` | yes | Sender phone number (E.164) |
| `--from-number` | conditional | Sender phone number (E.164); provide this and/or `--messaging-service-sid` |
| `--messaging-service-sid` | no | Twilio Messaging Service SID. **Omitting it CLEARS the stored value** (the update overwrites it). |
| `--api-base-url` | no | API base URL override (preserves existing if omitted) |
| `--auth-token` | no | Twilio Auth Token. **Omitting it PRESERVES the stored token.** Never printed back. |
| `--connection-timeout-seconds` | no | Positive timeout; omission preserves the existing value |
| `--max-retries` | no | Nonnegative retry setting; omission preserves it; zero retains outbox fallback semantics |
| `--retry-delay-seconds` | no | Nonnegative delay; omission preserves it; zero retains outbox fallback semantics |
---
@@ -1952,6 +2103,56 @@ single `Property`/`Value` cell (deferred-work register row 57).
---
### `shared-schema` — Manage the shared JSON schema library
Reads require authentication; create/update/delete require Designer access.
#### `shared-schema list`
List all shared schemas.
```sh
scadabridge shared-schema list
```
#### `shared-schema get`
Get one shared schema by ID.
```sh
scadabridge shared-schema get --id <id>
```
#### `shared-schema create`
Create a schema from a UTF-8 JSON file.
```sh
scadabridge shared-schema create --name <name> --schema-file <path.json> [--scope <scope>]
```
The CLI validates file readability and JSON syntax; the server validates schema structure and uniqueness.
#### `shared-schema update`
Replace a schema's name, scope, and document.
```sh
scadabridge shared-schema update --id <id> --name <name> --schema-file <path.json> [--scope <scope>]
```
The CLI validates file readability and JSON syntax; the server validates schema structure and uniqueness. Omit `--scope` to clear it on update.
#### `shared-schema delete`
Delete a shared schema by ID.
```sh
scadabridge shared-schema delete --id <id>
```
---
### `shared-script` — Manage shared scripts
#### `shared-script list`
@@ -2270,9 +2471,9 @@ scadabridge --url <url> cached-call discard --site-id <string> --tracked-operati
---
### `secured-write` — Query two-person write requests
### `secured-write` — Manage two-person write requests
`secured-write list` reads the MxGateway secured-write queue and terminal history. It requires any of Operator, Verifier or Administrator and applies the caller's site scope. This group also exposes `submit`, `approve`, and `reject` through the same server-side authorization and separation-of-duties checks as the UI; see the parity additions below.
`secured-write list` reads the MxGateway secured-write queue and terminal history. It requires any of Operator, Verifier or Administrator and applies the caller's site scope. This group also exposes `submit`, `approve`, and `reject` through the same server-side authorization and separation-of-duties checks as the UI.
```sh
scadabridge secured-write list --status Pending --site site-a --skip 0 --take 50
@@ -2280,6 +2481,38 @@ scadabridge secured-write list --status Pending --site site-a --skip 0 --take 50
`--status` and `--site` are optional filters. `--skip` defaults to 0; `--take` defaults to 200 and is clamped server-side to 1–500. Global connection, authentication and output-format options apply.
#### `secured-write submit`
Submit a pending MxGateway write as an Operator. A distinct Verifier must approve or reject it.
```sh
scadabridge secured-write submit --site <identifier> --connection <name> --tag-path <path> --value-json <json> --value-type <type> [--comment <text>]
```
The first five options are required. JSON strings must include JSON quotes, for example `--value-json '"Auto"' --value-type String`. The server validates the type/value pairing and site scope and derives identity from authentication.
#### `secured-write approve`
Approve and execute a pending write as a Verifier. This can write to the real device.
```sh
scadabridge secured-write approve --id <long> [--comment <text>]
```
The 64-bit request ID is required. The server enforces a different principal from the submitter, expiry, site scope, and concurrent decision handling. Exit 0 requires `status: Executed`; a failed execution or invalid response exits 1, preserving response details. Authorization denial exits 2.
#### `secured-write reject`
Reject a pending write as a Verifier.
```sh
scadabridge secured-write reject --id <long> [--comment <text>]
```
The 64-bit request ID is required. The server enforces separation of duties and site scope. A rejection does not execute the device write.
---
### `flow-debug` — Trace an inbound API, script, or value-change flow end to end
The CLI face of the **Flow Debugger** (design `docs/plans/2026-09-05-flow-debugger-design.md`,
@@ -2411,6 +2644,15 @@ run's outbound API / DB / notification rows, which are always audited.
---
## Deployment deadlines
`deploy instance`, `instance deploy`, `deploy artifacts`, `site deploy-artifacts`,
and `deploy site` defer the overall deadline to the Management API. They keep the
bounded socket-connect timeout but do not impose the ordinary 30-second client
request deadline on a deployment that may still be applying. The API's configured
long-running timeout remains authoritative. Ordinary commands retain a 30-second
client deadline; explicit bundle/Flow Debugger timeouts retain their own policies.
## Architecture Notes
The CLI connects to the Central cluster over **HTTP** (`ManagementHttpClient`), posting to the `/management` endpoints at the configured `managementUrl` — normally the Traefik load balancer, which routes to the active central node. It carries HTTP **Basic** credentials from `--username`/`--password`. Central's endpoint handler asks the `ManagementActor` in-process via `ManagementActorHolder`.
@@ -2419,109 +2661,21 @@ There is no Akka dependency in the CLI at all: it does not join the cluster, doe
An `HttpClient` is created per command invocation and disposed when the command completes.
Role enforcement is applied by the ManagementActor on the server side. The CLI authenticates against LDAP using `--username` / `--password`, resolves LDAP group memberships, then maps groups to ScadaBridge roles (Admin, Design, Deployment) via role mappings configured in the security settings. Operations require the appropriate role — for example, creating templates requires `Design`, deploying requires `Deployment`. In the test environment, use the `multi-role` user (password: `password`) which has all three roles.
Role enforcement is applied by the ManagementActor on the server side. The CLI sends `--username` / `--password` as HTTP Basic credentials. The server performs LDAP authentication, resolves group memberships, and maps them to roles such as Administrator, Designer, and Deployer. Operations require the appropriate role — for example, creating templates requires `Designer`, deploying requires `Deployer`. In the test environment, use the `multi-role` user (password: `password`) which has all three roles.
## Issues & Missing Features
If you encounter bugs, unexpected behavior, or missing features in the CLI, log them in [`cli_issues.md`](../../cli_issues.md) in the project root. Include a brief description, the command involved, and any relevant error output.
## Management parity additions (2026-09-10)
The production CLI exposes all 149 HTTP-eligible management contracts across 20
command groups. `CliApplication.BuildRoot()` is used both by the executable and
by the HTTP-dispatch parity test. Site-only `ReadTagValues` and the retired
`ResolveRoles` flow are not accepted by `POST /management`; binding tests continue
using the site's existing transport.
All 149 HTTP-eligible management contracts are exposed across 20 command groups.
The new operations are documented in their main command sections above, including
[shared schemas](#shared-schema--manage-the-shared-json-schema-library),
[notifications](#notification--manage-notification-lists), and
[secured writes](#secured-write--manage-two-person-write-requests).
[Deployment deadlines](#deployment-deadlines) apply to all deployment aliases.
### Shared schema library
```sh
scadabridge shared-schema list
scadabridge shared-schema get --id 7
scadabridge shared-schema create --name PumpPayload --schema-file ./pump.schema.json --scope Pump
scadabridge shared-schema update --id 7 --name PumpPayload --schema-file ./pump.schema.json
scadabridge shared-schema delete --id 7
```
Create/update read UTF-8 JSON from `--schema-file`; the server validates schema
structure and uniqueness. Update replaces the name, schema, and scope; omitting
`--scope` clears it. Mutations require Designer access.
### Individual notification edits and provider creation
```sh
scadabridge notification rename --id 4 --name "Shift engineers"
scadabridge notification recipient add --list-id 4 --name "On-call engineer" --email engineer@example.com
scadabridge notification recipient delete --id 18
scadabridge notification smtp create --server smtp.example.com --port 587 --auth-mode None --from-address alerts@example.com
scadabridge notification sms create --account-sid AC0123456789abcdef0123456789abcdef --from-number +15551234567 --auth-token "<token>"
```
Rename and individual recipient edits preserve unrelated recipient IDs and names.
Recipient add accepts `--email` and/or `--phone`; the server checks them against
its owning list's channel. Existing `notification update` retains its whole-list
recipient replacement semantics.
SMTP/SMS create accept their update options except `--id` and send distinct create
contracts. SMS create requires an auth token and a sender (`--from-number` and/or
`--messaging-service-sid`). Provider creation/update requires Administrator access.
SMS create and update also accept:
| Option | Meaning |
|---|---|
| `--connection-timeout-seconds` | Positive connection timeout |
| `--max-retries` | Nonnegative retry setting |
| `--retry-delay-seconds` | Nonnegative retry delay |
Omission preserves existing update values or uses creation defaults. Explicit
zero retry settings retain the existing outbox fallback semantics; they do not
promise that delivery will never retry. Existing secret-preservation and
messaging-service-ID clearing behavior on update is unchanged.
### Template, instance, and connection edits
```sh
scadabridge template resolved-members --id 3
scadabridge template move --id 3 --folder-id 8
scadabridge template native-alarm-source update --id 5 --name Pressure --connection Plc --source-ref Pressure --locked
scadabridge instance attribute-override delete --instance-id 7 --attribute Module.Speed
scadabridge instance native-alarm-source list --instance-id 7
scadabridge data-connection move --id 9 --site-id 2
```
`resolved-members` inspects effective inherited template members, without applying
composition or instance overrides. Omit `--folder-id` to move a template to the
root. Native-alarm-source update replaces all contract fields: optional `--filter`
and `--description` clear when omitted, and omitted `--locked` means false.
Individual attribute-override deletion preserves other overrides. Server-side
role, site-scope, locking, and dependency checks remain authoritative.
### Secured-write lifecycle
```sh
scadabridge secured-write submit --site site-a --connection Plc --tag-path Pump.Setpoint --value-json 42 --value-type Int32 --comment "Approved operating procedure"
scadabridge secured-write approve --id 123 --comment "Verified setpoint"
scadabridge secured-write reject --id 124 --comment "Incorrect target"
```
Submit requires Operator access; approve/reject require Verifier access. The
server derives identity from authentication and enforces a different principal
for the verification decision. Approval can execute a real device write.
`--value-json` must be valid JSON; the server validates the value/type pairing.
IDs for approve/reject are 64-bit integers; `--comment` is optional.
Approval exits zero only for an `Executed` response. A server-reported execution
failure exits one while retaining the response details; malformed or unexpected
approval responses also fail. Authorization denial exits two. JSON/table output
continues to use the standard formatter.
### Deployment deadline policy
`deploy instance`, `instance deploy`, `deploy artifacts`, `site deploy-artifacts`,
and `deploy site` defer the overall deadline to the Management API. They keep the
bounded socket-connect timeout but do not impose the ordinary 30-second client
request deadline on a deployment that may still be applying. The API's configured
long-running timeout remains authoritative. Ordinary commands retain a 30-second
client deadline; explicit bundle/Flow Debugger timeouts retain their own policies.
`CliApplication.BuildRoot()` constructs the executable command tree and the tree
used by the HTTP parity test. Site-only `ReadTagValues` and retired `ResolveRoles`
are excluded from `POST /management`; site binding tests retain their transport.