Complete management API and CLI command parity
This commit is contained in:
+33
-5
@@ -44,7 +44,7 @@ Every command accepts `--format json` (default) or `--format table`. For JSON ou
|
||||
|
||||
## Architecture
|
||||
|
||||
`Program.cs` builds the `RootCommand` tree, attaches the four global options (`--url`, `--username`, `--password`, `--format`), and registers each command group:
|
||||
`Program.cs` invokes `CliApplication.BuildRoot()`, which builds the `RootCommand` tree, attaches the four global options (`--url`, `--username`, `--password`, `--format`), and registers each command group:
|
||||
|
||||
```csharp
|
||||
rootCommand.Add(TemplateCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
@@ -59,10 +59,14 @@ rootCommand.Add(AuditLogCommands.Build(urlOption, formatOption, usernameOption,
|
||||
rootCommand.Add(AuditCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(HealthCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(DebugCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(SharedSchemaCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(SharedScriptCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(DbConnectionCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(ApiMethodCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(BundleCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(CachedCallCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(SecuredWriteCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
rootCommand.Add(FlowDebugCommands.Build(urlOption, formatOption, usernameOption, passwordOption));
|
||||
```
|
||||
|
||||
Every command's action delegates to `CommandHelpers.ExecuteCommandAsync`, which owns the URL/credential resolution, `ManagementHttpClient` lifetime, and exit-code mapping. This consolidation means the authorization-failure exit code (`2`) is enforced uniformly — including for the `bundle` group, which uses `ExecuteCommandAsync` with a longer 5-minute timeout and a per-command `onSuccess` handler rather than a separate HTTP path.
|
||||
@@ -105,14 +109,18 @@ scadabridge instance deploy --id 7
|
||||
|
||||
| Group | Subcommands | Role required |
|
||||
|-------|-------------|---------------|
|
||||
| `template` | `list`, `get`, `create`, `update`, `delete`, `validate`; `attribute add/update/delete`; `alarm add/update/delete`; `script add/update/delete`; `composition add/delete`; `native-alarm-source add/list/remove` | `Design` |
|
||||
| `instance` | `list`, `get`, `create`, `set-bindings`, `set-overrides`, `alarm-override set/delete/list`, `native-alarm-source set/clear`, `set-area`, `diff`, `deploy`, `enable`, `disable`, `delete` | `Deployment` |
|
||||
| `template` | `list`, `get`, `create`, `update`, `delete`, `validate`, `resolved-members`, `move`; `attribute add/update/delete`; `alarm add/update/delete`; `script add/update/delete`; `composition add/delete`; `native-alarm-source add/list/update/remove` | `Design` |
|
||||
| `instance` | `list`, `get`, `create`, `set-bindings`, `set-overrides`, `alarm-override set/delete/list`, `native-alarm-source set/clear/list/import`, `attribute-override delete`, `set-area`, `diff`, `deploy`, `enable`, `disable`, `delete` | `Deployment` |
|
||||
| `site` | `list`, `get`, `create`, `delete`, `deploy-artifacts`; `area list/create/update/delete` | `Admin` |
|
||||
| `deploy` | `instance`, `artifacts`, `status` | `Deployment` |
|
||||
| `data-connection` | `list`, `get`, `create`, `update`, `delete` | `Design` / `Deployment` |
|
||||
| `data-connection` | `list`, `get`, `create`, `update`, `delete`, `move`; `browse`, `search`, `verify-endpoint`, `certs` | `Design` / `Deployment` |
|
||||
| `external-system` | `list`, `get`, `create`, `update`, `delete` | `Design` |
|
||||
| `notification` | `list`, `get`, `create`, `update`, `delete`; `smtp list/update` | `Design` / `Admin` |
|
||||
| `notification` | `list`, `get`, `create`, `update`, `delete`, `rename`; `recipient add/delete`; `smtp list/create/update`; `sms list/create/update` | `Design` / `Admin` |
|
||||
| `security` | `api-key list/create/update/delete/set-methods`; `role-mapping list/create/update/delete`; `scope-rule list/add/delete` | `Admin` |
|
||||
| `shared-schema` | `list`, `get`, `create`, `update`, `delete` | Read: authenticated; mutations: Designer |
|
||||
| `secured-write` | `list`, `submit`, `approve`, `reject` | Operator / Verifier / Administrator, enforced per operation |
|
||||
| `cached-call` | `list`, `retry`, `discard` | Server-enforced operational roles and site scope |
|
||||
| `flow-debug` | `run-method`, `run-script`, `run-value-change`, `replay` | Deployer; replay also accepts OperationalAudit roles |
|
||||
| `shared-script` | `list`, `get`, `create`, `update`, `delete` | `Design` |
|
||||
| `db-connection` | `list`, `get`, `create`, `update`, `delete` | `Design` |
|
||||
| `api-method` | `list`, `get`, `create`, `update`, `delete` | `Design` |
|
||||
@@ -248,3 +256,23 @@ The `audit-log` command group was renamed to `audit-config` in M8 of Audit Log (
|
||||
- [Audit Log](./AuditLog.md)
|
||||
- [Security](./Security.md)
|
||||
- [Commons](./Commons.md)
|
||||
|
||||
|
||||
## Management parity and deadlines
|
||||
|
||||
All 149 HTTP-eligible management contracts are exposed across 20 production CLI
|
||||
groups, including the `shared-schema` library and the secured-write lifecycle.
|
||||
The [parity additions](../../src/ZB.MOM.WW.ScadaBridge.CLI/README.md#management-parity-additions-2026-09-10)
|
||||
document the individual notification edits, provider creation, template and
|
||||
instance operations, connection relocation, and SMS policy flags.
|
||||
|
||||
The production-root loopback test requires actual HTTP dispatch for every
|
||||
eligible contract. A separate actor test verifies every registered contract has
|
||||
a handler. `ReadTagValues` remains site-only and `ResolveRoles` remains retired;
|
||||
both are excluded from HTTP name resolution.
|
||||
|
||||
Every instance/artifact/site deployment alias lets the server own the overall
|
||||
deadline, while retaining a bounded connect timeout. This prevents the ordinary
|
||||
30-second client timer from abandoning a deployment still applying at the server.
|
||||
Secured-write approval interprets execution status as well as HTTP success:
|
||||
only `Executed` exits zero; failed execution or an invalid response exits one.
|
||||
|
||||
@@ -241,3 +241,14 @@ Any exception that is not a `ManagementCommandException` or `SiteScopeViolationE
|
||||
- [Security](./Security.md)
|
||||
- [Audit Log](./AuditLog.md)
|
||||
- [Host](./Host.md)
|
||||
|
||||
|
||||
## HTTP command eligibility
|
||||
|
||||
`ManagementCommandRegistry` includes 149 executable HTTP contracts. The site-only
|
||||
`ReadTagValuesCommand` and retired `ResolveRolesCommand` remain internal message
|
||||
types but are excluded from the HTTP registry, so `/management` rejects those
|
||||
names as unknown commands instead of accepting an undispatchable request. Site
|
||||
gRPC tag-read serialization and server-side LDAP role resolution are unchanged.
|
||||
The dispatch-coverage test now checks every HTTP-registered contract without
|
||||
exemptions, including create records inherited from update records.
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
**Date:** 2026-09-10
|
||||
**Reviewed revision:** `9ee402bb`
|
||||
**Status:** Findings recorded; remediation not started.
|
||||
**Status:** Remediation in progress on `codex/management-cli-parity`.
|
||||
|
||||
## Scope and method
|
||||
## Original review scope and method
|
||||
|
||||
Source-level comparison of management command records, automatic HTTP command
|
||||
registration, ManagementActor dispatch (including inherited record types), CLI
|
||||
command construction and registration, and management audit REST endpoints.
|
||||
No live mutations were performed and no tests were rerun for this review.
|
||||
|
||||
The CLI's 19 registered command groups and previously passing 475-test suite do
|
||||
not establish complete actor/API parity. The inventory found:
|
||||
At the reviewed revision, 19 registered command groups and the passing 475-test
|
||||
suite did not establish complete actor/API parity. The baseline inventory found:
|
||||
|
||||
| Inventory | Count |
|
||||
|---|---:|
|
||||
@@ -31,24 +31,24 @@ is not counted as a missing operator command.
|
||||
## Missing CLI operations
|
||||
|
||||
All 19 commands below are handled by the actor and reachable through the generic
|
||||
`POST /management` API, subject to server-side authorization. Each remains open;
|
||||
the secured-write limitation is already documented and may be retained as an
|
||||
explicit product decision rather than implemented.
|
||||
`POST /management` API, subject to server-side authorization. Remediation adds
|
||||
all 19, including the full secured-write lifecycle. The descriptions below retain
|
||||
the original findings; status cells and completion evidence track the fixes.
|
||||
|
||||
| ID | Capability | Missing command contracts | Status |
|
||||
|---|---|---|---|
|
||||
| GAP-01 | Shared-schema library (5) | `ListSharedSchemasCommand`, `GetSharedSchemaCommand`, `CreateSharedSchemaCommand`, `UpdateSharedSchemaCommand`, `DeleteSharedSchemaCommand` | Open |
|
||||
| GAP-02 | Secured-write lifecycle (3) | `SubmitSecuredWriteCommand`, `ApproveSecuredWriteCommand`, `RejectSecuredWriteCommand` | Open; documented listing-only CLI scope |
|
||||
| GAP-03 | Individual notification editing (3) | `RenameNotificationListCommand`, `AddNotificationRecipientCommand`, `DeleteNotificationRecipientCommand` | Open |
|
||||
| GAP-04 | Provider configuration creation (2) | `CreateSmtpConfigCommand`, `CreateSmsConfigCommand` | Open |
|
||||
| GAP-05 | Template inspection and editing (3) | `GetResolvedTemplateMembersCommand`, `MoveTemplateToFolderCommand`, `UpdateTemplateNativeAlarmSourceCommand` | Open |
|
||||
| GAP-06 | Instance override management (2) | `DeleteInstanceAttributeOverrideCommand`, `ListInstanceNativeAlarmSourceOverridesCommand` | Open |
|
||||
| GAP-07 | Data-connection relocation (1) | `MoveDataConnectionCommand` | Open |
|
||||
| GAP-01 | Shared-schema library (5) | `ListSharedSchemasCommand`, `GetSharedSchemaCommand`, `CreateSharedSchemaCommand`, `UpdateSharedSchemaCommand`, `DeleteSharedSchemaCommand` | Completed |
|
||||
| GAP-02 | Secured-write lifecycle (3) | `SubmitSecuredWriteCommand`, `ApproveSecuredWriteCommand`, `RejectSecuredWriteCommand` | Completed; full lifecycle exposed |
|
||||
| GAP-03 | Individual notification editing (3) | `RenameNotificationListCommand`, `AddNotificationRecipientCommand`, `DeleteNotificationRecipientCommand` | Completed |
|
||||
| GAP-04 | Provider configuration creation (2) | `CreateSmtpConfigCommand`, `CreateSmsConfigCommand` | Completed |
|
||||
| GAP-05 | Template inspection and editing (3) | `GetResolvedTemplateMembersCommand`, `MoveTemplateToFolderCommand`, `UpdateTemplateNativeAlarmSourceCommand` | Completed |
|
||||
| GAP-06 | Instance override management (2) | `DeleteInstanceAttributeOverrideCommand`, `ListInstanceNativeAlarmSourceOverridesCommand` | Completed |
|
||||
| GAP-07 | Data-connection relocation (1) | `MoveDataConnectionCommand` | Completed |
|
||||
|
||||
Evidence:
|
||||
|
||||
- [ManagementActor dispatch](../../src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs)
|
||||
- [CLI root registration](../../src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs)
|
||||
- [CLI root registration](../../src/ZB.MOM.WW.ScadaBridge.CLI/CliApplication.cs)
|
||||
- [CLI command implementations](../../src/ZB.MOM.WW.ScadaBridge.CLI/Commands/)
|
||||
- [Management command contracts](../../src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/)
|
||||
|
||||
@@ -57,14 +57,14 @@ contracts and are dispatched through the corresponding update handlers. They
|
||||
are not unhandled API contracts. The handlers distinguish the create subtype;
|
||||
sending an ordinary update with ID zero is not equivalent.
|
||||
|
||||
## Behavioral and contract findings
|
||||
## Original behavioral and contract findings
|
||||
|
||||
Severity is a review estimate. These findings overlap the operation inventory;
|
||||
do not add the row counts together as unique missing commands.
|
||||
|
||||
### PAR-01 — Deployment deadlines differ between API and CLI
|
||||
|
||||
**Severity:** Medium · **Status:** Open
|
||||
**Severity:** Medium · **Status:** Completed
|
||||
|
||||
`deploy instance`, `instance deploy`, `deploy artifacts`, and
|
||||
`site deploy-artifacts` use the default 30-second CLI request deadline. The API
|
||||
@@ -84,7 +84,7 @@ policy and add delayed-response regression coverage for every CLI alias.
|
||||
|
||||
### PAR-02 — Notification replacement is not equivalent to individual editing
|
||||
|
||||
**Severity:** Medium · **Status:** Open · **Related:** GAP-03
|
||||
**Severity:** Medium · **Status:** Completed · **Related:** GAP-03
|
||||
|
||||
The existing CLI whole-list update reaches `HandleUpdateNotificationList`, which
|
||||
deletes existing recipients and recreates them. It cannot faithfully replace
|
||||
@@ -99,7 +99,7 @@ verify unrelated recipients retain their identities and names.
|
||||
|
||||
### PAR-03 — SMS retry and timeout options are missing
|
||||
|
||||
**Severity:** Low · **Status:** Open
|
||||
**Severity:** Low · **Status:** Completed
|
||||
|
||||
The actor/API accept `ConnectionTimeoutSeconds`, `MaxRetries`, and `RetryDelay`
|
||||
on `UpdateSmsConfigCommand`. CLI payload construction supplies none of these
|
||||
@@ -116,7 +116,7 @@ explicit values and omission behavior against the API contract.
|
||||
|
||||
### PAR-04 — Registry accepts two contracts the actor cannot dispatch
|
||||
|
||||
**Severity:** Low · **Status:** Open
|
||||
**Severity:** Low · **Status:** Completed
|
||||
|
||||
The registry automatically includes every concrete `*Command` type in the
|
||||
management namespace. `ReadTagValuesCommand` and `ResolveRolesCommand` therefore
|
||||
@@ -140,7 +140,7 @@ flow's security restriction.
|
||||
|
||||
### PAR-05 — Tests do not enforce complete surface parity
|
||||
|
||||
**Severity:** Low · **Status:** Open
|
||||
**Severity:** Low · **Status:** Completed
|
||||
|
||||
Command-tree tests verify existing groups and selected operations, but do not
|
||||
require every supported actor command to map to a CLI command or an explicit
|
||||
@@ -163,3 +163,77 @@ inheritance, and test representative payload fields and deadline policies.
|
||||
|
||||
This is a bounded surface comparison, not an exhaustive security audit or a
|
||||
field-by-field review of all 130 CLI-referenced contracts.
|
||||
|
||||
|
||||
## Implementation plan and progress
|
||||
|
||||
The requested remediation implements all 19 CLI mappings, including secured-write
|
||||
submit/approve/reject through existing server authorization. The HTTP registry
|
||||
will exclude site-only ReadTagValues and retired ResolveRoles contracts; their
|
||||
internal types remain intact. Existing update semantics remain compatible.
|
||||
|
||||
| Work package | Files / scope | Verification | Status |
|
||||
|---|---|---|---|
|
||||
| Notifications | CLI NotificationCommands; focused notification tests; GAP-03/04, PAR-02/03 | Capture real command payloads, preserve named recipients, create and optional SMS settings | Completed |
|
||||
| Template/instance/connection commands | CLI TemplateCommands, InstanceCommands, DataConnectionCommands; GAP-05/06/07 | Parse and HTTP-envelope regressions for every added operation | Completed |
|
||||
| Schema and secured writes | New SharedSchemaCommands, SecuredWriteCommands; GAP-01/02 | Real command payloads, role enforcement remains server-side | Completed |
|
||||
| Deadline and registry policy | CommandHelpers, Commons registry, API tests; PAR-01/04 | Delayed responses for all deploy aliases; rejected HTTP-ineligible contracts | Completed |
|
||||
| Parity gate and integration | CLI root, command mapping tests, CLI docs; PAR-05 | Exhaustive registry/dispatch/CLI mapping with explicit internal exclusions | Completed |
|
||||
| Completion | Full solution build/tests, local deployment/read-only smoke, report updates, merge/commit/push | Fresh verification evidence recorded below | In progress |
|
||||
|
||||
Each package follows failing regression tests, minimal implementation, focused
|
||||
verification, and code review. Builds/tests use a shared lock in this worktree to
|
||||
avoid concurrent dotnet output races. The final merge and git operations are
|
||||
owned by the primary agent.
|
||||
|
||||
### Progress checkpoint
|
||||
|
||||
- Notification/Smtp/Sms focused suite: 52 passed, including 19 new parse/HTTP cases.
|
||||
- Editing parity: 15 passed, covering all six added operations and an existing alias.
|
||||
- Deployment deadline regression: all four aliases now accept the server's response
|
||||
after 31 seconds; the same test failed with the old 30-second client deadline.
|
||||
- HTTP registry regressions: 11 passed; ReadTagValues and ResolveRoles no longer resolve.
|
||||
- Production-root parity probe: all 149 HTTP-eligible contracts actually dispatched
|
||||
to a loopback recorder. Removing the schema group produces missing coverage.
|
||||
- Independent review approved the editing and notification mappings. Additional
|
||||
actor preservation coverage and secured-write execution-failure exit handling
|
||||
are being verified before final completion.
|
||||
|
||||
|
||||
### Independent review follow-ups
|
||||
|
||||
- Added email and SMS actor-dispatch preservation tests: rename, add, and delete
|
||||
leave the existing named recipient and ID untouched (2 passed).
|
||||
- Secured-write approval now treats HTTP 200 with `status: Failed` as CLI failure,
|
||||
and rejects malformed or unexpected approval outcomes. Schema/secured focused
|
||||
tests: 33 passed, including existing listing behavior and new outcome checks.
|
||||
- Fixed a pre-existing blind spot in the actor dispatch gate: its sentinel now
|
||||
passes through the configuration transaction before throwing on handler
|
||||
dependencies. A negative control detects an unsupported command (2 passed).
|
||||
- New CLI tests that invoke Console-writing actions share the Console collection
|
||||
to avoid racing tests that redirect process-global output.
|
||||
|
||||
All implementation packages are present. Final solution verification, canonical
|
||||
local deployment, and integration remain in progress.
|
||||
|
||||
|
||||
### Final pre-integration verification
|
||||
|
||||
- Full solution build: zero warnings and errors.
|
||||
- Full solution run (excluding deployed Playwright): 9,551 passed, one failure in
|
||||
the UI toast unobserved-exception test. Root cause was unrelated incomplete
|
||||
JavaScript success stubs in UI fixtures; no product UI behavior changed.
|
||||
- Fixed 15 successful void stubs across 11 fixtures to complete explicitly. Two
|
||||
direct regression tests failed before and passed after. Full CentralUI rerun:
|
||||
**1,418/1,418 passed**; the original toast assertion remains unchanged.
|
||||
- Replacing the initial UI result with the corrected full UI suite gives
|
||||
**9,554 passed, zero outstanding failures or skips** across 29 test suites.
|
||||
Key suites: CLI **543**, ManagementService **665**, Commons **852**,
|
||||
Communication **766**, Integration **118**, Host **598**.
|
||||
- Documentation links and `git diff --check` passed. All GAP-01 through GAP-07 and
|
||||
PAR-01 through PAR-05 are complete. Canonical deployment and final merge/push
|
||||
evidence will be added after integration.
|
||||
|
||||
Local verification logs: `/tmp/parity-full-build.log`, `/tmp/parity-full-tests.log`,
|
||||
`/tmp/parity-ui-red.log`, `/tmp/parity-ui-green.log`, `/tmp/parity-ui-full.log`.
|
||||
These logs are local evidence, not committed artifacts.
|
||||
|
||||
@@ -447,7 +447,7 @@ Configuration is resolved in the following priority order (highest wins):
|
||||
## Error Handling
|
||||
|
||||
- **Connection failure**: If the CLI cannot connect to the management URL (e.g., DNS failure, connection refused), it exits with code 1 and a descriptive error message.
|
||||
- **Command timeout**: If the server does not respond within 30 seconds, the command fails with a timeout error (HTTP 504).
|
||||
- **Command timeout**: Ordinary CLI commands use a 30-second client deadline. All instance/artifact/site deployment aliases defer the overall deadline to the server, retaining a bounded socket-connect timeout. Server Ask expiry returns HTTP 504; a client deadline is reported locally. Bundle and Flow Debugger commands retain their explicit timeout policies.
|
||||
- **Authentication failure**: If the server returns HTTP 401 (LDAP bind failed), the CLI exits with code 1.
|
||||
- **Authorization failure**: If the server returns HTTP 403, the CLI exits with code 2.
|
||||
|
||||
@@ -472,3 +472,24 @@ deploy site preserves the returned summary in JSON/table output and exits 1 when
|
||||
is nonzero or the summary is malformed, even when HTTP returned 2xx. A zero failure count exits
|
||||
0; HTTP authorization failures retain exit 2. The server owns the bounded bulk operation deadline;
|
||||
the client does not impose a shorter total timer on this command.
|
||||
|
||||
|
||||
## Management parity (2026-09-10)
|
||||
|
||||
The CLI exposes all 149 HTTP-eligible management contracts. The production root
|
||||
is constructed by `CliApplication.BuildRoot`; the test suite invokes that tree
|
||||
against a loopback HTTP recorder and requires every registered contract to be
|
||||
sent, with a negative control for a removed group. Actor dispatch coverage uses
|
||||
the same HTTP eligibility boundary with no unhandled-command exemptions.
|
||||
|
||||
Added operations include the five `shared-schema` CRUD commands, secured-write
|
||||
submit/approve/reject, notification rename and individual recipient add/delete,
|
||||
SMTP/SMS create, effective template member inspection, template folder moves,
|
||||
native alarm source updates, individual attribute-override deletion, native alarm
|
||||
override listing, and data-connection moves. SMS timeout/retry settings are also
|
||||
exposed. Their exact syntax and omission semantics are maintained in the
|
||||
[CLI command reference](../../src/ZB.MOM.WW.ScadaBridge.CLI/README.md#management-parity-additions-2026-09-10).
|
||||
|
||||
All additions retain server-owned roles, scope restrictions, validation, and audit
|
||||
handling. In particular, secured-write approval requires a different verifier
|
||||
identity and exits with failure when the returned device execution failed.
|
||||
|
||||
Reference in New Issue
Block a user