From 62cdb9b3db6ad918aa1c4de4712c8dee3928d88f Mon Sep 17 00:00:00 2001 From: Ygal Blum Date: Tue, 24 Mar 2026 14:32:59 -0400 Subject: [PATCH] Add SP Resource Manager (Topic 9) to spec and test plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add read-only `dcm sp resource list/get` commands for the Service Provider Resource Manager backend. Updates include new Topic 9 with 5 requirements (REQ-SPR-010–050), 8 acceptance criteria, 10 test cases (TC-U121–TC-U131), and cross-cutting generated client requirement REQ-XC-CLI-025. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Ygal Blum --- .ai/specs/dcm-cli.spec.md | 135 ++++++++++++++++++++-- .ai/test-plans/dcm-cli-unit.test-plan.md | 137 +++++++++++++++++++++-- 2 files changed, 250 insertions(+), 22 deletions(-) diff --git a/.ai/specs/dcm-cli.spec.md b/.ai/specs/dcm-cli.spec.md index 2b2741f..01ba2ca 100644 --- a/.ai/specs/dcm-cli.spec.md +++ b/.ai/specs/dcm-cli.spec.md @@ -4,9 +4,10 @@ The DCM CLI (`dcm`) is a Go-based command-line tool for interacting with the DCM (Data Center Management) control plane. It communicates exclusively through -the API Gateway (KrakenD on port 9080) to reach the Policy Manager and Catalog -Manager backends. The CLI uses generated clients from `policy-manager/pkg/client` -and `catalog-manager/pkg/client` (oapi-codegen generated) as Go module +the API Gateway (KrakenD on port 9080) to reach the Policy Manager, Catalog +Manager, and Service Provider Resource Manager backends. The CLI uses generated +clients from `policy-manager/pkg/client`, `catalog-manager/pkg/client`, and +`service-provider-manager/pkg/client` (oapi-codegen generated) as Go module dependencies. **Version scope (v1alpha1):** @@ -15,6 +16,7 @@ dependencies. - Service type read operations (list, get) - Catalog item operations (create, list, get, delete) - Catalog item instance operations (create, list, get, delete) +- SP resource read operations (list, get) via Service Provider Resource Manager - Version display - Output formatting (table, JSON, YAML) - Configuration via file, environment variables, and flags @@ -54,6 +56,10 @@ dependencies. │ CLI │ HTTP / HTTPS │ (KrakenD 9080) │ └──────────────────┘ │ │ │ │ ┌──────────────────┐ └─────────┘ │ │──────▶│ Catalog Manager │ + │ │ │ (port 8080) │ + │ │ └──────────────────┘ + │ │ ┌──────────────────┐ + │ │──────▶│ SP Resource Mgr │ └──────────────────┘ │ (port 8080) │ └──────────────────┘ ``` @@ -70,7 +76,8 @@ dcm-cli/ │ │ ├── policy.go ← Policy command group │ │ ├── catalog_service_type.go ← Service-type command group │ │ ├── catalog_item.go ← Catalog item command group -│ │ └── catalog_instance.go ← Catalog instance command group +│ │ ├── catalog_instance.go ← Catalog instance command group +│ │ └── sp_resource.go ← SP resource command group │ └── version/ ← Build-time version info ├── test/e2e/ ← E2E tests (build tag: e2e) ├── Makefile @@ -93,6 +100,7 @@ dcm-cli/ | 6 | Catalog Item Commands | CIT | 1, 2, 3 | | 7 | Catalog Instance Commands | CIN | 1, 2, 3 | | 8 | Version Command | VER | 1 | +| 9 | SP Resource Commands | SPR | 1, 2, 3 | ``` Topic 1: CLI Framework (independent) @@ -103,6 +111,7 @@ Topic 3: Output Formatting (independent) +---------+---------+---> Topic 5: Service-Type Commands (depends on 1, 2, 3) +---------+---------+---> Topic 6: Catalog Item Commands (depends on 1, 2, 3) +---------+---------+---> Topic 7: Catalog Instance Cmds (depends on 1, 2, 3) + +---------+---------+---> Topic 9: SP Resource Commands (depends on 1, 2, 3) | +-----------------------> Topic 8: Version Command (depends on 1) ``` @@ -132,7 +141,7 @@ Out of scope: shell autocompletion, plugin system, interactive prompts. | ID | Requirement | Priority | Notes | |----|-------------|----------|-------| | REQ-CLI-020 | The CLI MUST define a root command `dcm` with global flags | MUST | | -| REQ-CLI-030 | The root command MUST register all subcommand groups: `policy`, `catalog`, `version` | MUST | | +| REQ-CLI-030 | The root command MUST register all subcommand groups: `policy`, `catalog`, `sp`, `version` | MUST | | | REQ-CLI-040 | The `catalog` command MUST register subcommand groups: `service-type`, `item`, `instance` | MUST | | | REQ-CLI-050 | Global flags MUST include `--api-gateway-url`, `--output`/`-o`, `--timeout`, `--config`, `--tls-ca-cert`, `--tls-client-cert`, `--tls-client-key`, `--tls-skip-verify` | MUST | | | REQ-CLI-060 | The CLI MUST exit with code 0 on success, 1 on runtime errors, 2 on usage errors | MUST | | @@ -152,8 +161,9 @@ Out of scope: shell autocompletion, plugin system, interactive prompts. - **Validates:** REQ-CLI-030, REQ-CLI-040 - **Given** the CLI is invoked - **When** `dcm --help` is run -- **Then** subcommands `policy`, `catalog`, and `version` MUST be listed +- **Then** subcommands `policy`, `catalog`, `sp`, and `version` MUST be listed - **And** `dcm catalog --help` MUST list `service-type`, `item`, and `instance` +- **And** `dcm sp --help` MUST list `resource` ##### AC-CLI-040: Exit code on success @@ -958,6 +968,104 @@ Depends on Topic 1 (CLI Framework). --- +### 4.9 SP Resource Commands + +#### Overview + +Implement the `dcm sp resource` command group with read-only subcommands: `list` +and `get`. SP resources are service type instances managed by the Service +Provider Resource Manager (SPRM). The CLI provides read-only access to these +resources. + +Out of scope: SP resource create/update/delete (managed via other flows), +SP health check. + +#### Requirements + +| ID | Requirement | Priority | Notes | +|----|-------------|----------|-------| +| REQ-SPR-010 | `dcm sp resource list` MUST list SP resources (service type instances) with optional `--provider`, `--page-size`, `--page-token` flags | MUST | | +| REQ-SPR-020 | `dcm sp resource list` MUST display SP resources in the configured output format | MUST | | +| REQ-SPR-030 | `dcm sp resource get` MUST accept an `INSTANCE_ID` positional argument and display the SP resource | MUST | | +| REQ-SPR-040 | Missing `INSTANCE_ID` argument for `get` MUST result in a usage error (exit code 2) | MUST | | +| REQ-SPR-050 | All SP resource commands MUST use the generated SP Resource Manager client | MUST | | + +#### Table Output Columns + +``` +ID PROVIDER STATUS CREATED +my-instance kubevirt-123 READY 2026-03-09T10:00:00Z +``` + +#### Acceptance Criteria + +##### AC-SPR-010: List SP resources + +- **Validates:** REQ-SPR-010, REQ-SPR-020 +- **Given** SP resources exist in the system +- **When** `dcm sp resource list` is invoked +- **Then** a GET request MUST be sent to `/api/v1alpha1/service-type-instances` +- **And** the SP resources MUST be displayed in the configured output format + +##### AC-SPR-020: List SP resources with pagination + +- **Validates:** REQ-SPR-010 +- **Given** SP resources exist in the system +- **When** `dcm sp resource list --page-size 5` is invoked +- **Then** the GET request MUST include `max_page_size=5` as a query parameter + +##### AC-SPR-030: List SP resources with provider filter + +- **Validates:** REQ-SPR-010 +- **Given** SP resources exist in the system +- **When** `dcm sp resource list --provider kubevirt-123` is invoked +- **Then** the GET request MUST include `provider=kubevirt-123` as a query parameter + +##### AC-SPR-040: Get SP resource + +- **Validates:** REQ-SPR-030 +- **Given** an SP resource with ID `my-instance` exists +- **When** `dcm sp resource get my-instance` is invoked +- **Then** a GET request MUST be sent to `/api/v1alpha1/service-type-instances/my-instance` +- **And** the SP resource MUST be displayed in the configured output format + +##### AC-SPR-050: Get without INSTANCE_ID + +- **Validates:** REQ-SPR-040 +- **Given** no positional argument is provided +- **When** `dcm sp resource get` is invoked +- **Then** the CLI MUST exit with code 2 and display a usage error + +##### AC-SPR-060: List SP resources returns empty list + +- **Validates:** REQ-SPR-010, REQ-SPR-020 +- **Given** no SP resources exist in the system +- **When** `dcm sp resource list` is invoked +- **Then** a GET request MUST be sent to `/api/v1alpha1/service-type-instances` +- **And** an empty result MUST be displayed (empty table with headers only, or empty JSON array/YAML list) + +##### AC-SPR-070: Get non-existent SP resource + +- **Validates:** REQ-SPR-030, REQ-XC-ERR-010 +- **Given** no SP resource with ID `nonexistent` exists +- **When** `dcm sp resource get nonexistent` is invoked +- **Then** the API returns a 404 with RFC 7807 body +- **And** the CLI MUST display the error in the configured output format and exit with code 1 + +##### AC-SPR-080: Generated client usage + +- **Validates:** REQ-SPR-050 +- **Given** any SP resource command is invoked +- **When** the command communicates with the API +- **Then** the generated SP Resource Manager client MUST be used + +#### Dependencies + +Depends on Topic 1 (CLI Framework), Topic 2 (Configuration), Topic 3 (Output +Formatting). + +--- + ## 5. Cross-Cutting Concerns ### 5.1 Error Handling @@ -1061,9 +1169,10 @@ Depends on Topic 1 (CLI Framework). |----|-------------|----------|-------| | REQ-XC-CLI-010 | The CLI MUST use the generated Policy Manager client (`github.com/dcm-project/policy-manager/pkg/client`) for all policy operations | MUST | | | REQ-XC-CLI-020 | The CLI MUST use the generated Catalog Manager client (`github.com/dcm-project/catalog-manager/pkg/client`) for all catalog operations | MUST | | -| REQ-XC-CLI-030 | Both clients MUST be instantiated with the API Gateway URL appended with `/api/v1alpha1` | MUST | | -| REQ-XC-CLI-040 | Both clients MUST respect the configured request timeout. The timeout applies to the HTTP request deadline (context timeout) only; file I/O and output formatting are not subject to the timeout. | MUST | | -| REQ-XC-CLI-050 | Both clients MUST use a custom HTTP client with TLS transport when the API Gateway URL uses `https://` | MUST | | +| REQ-XC-CLI-025 | The CLI MUST use the generated SP Resource Manager client (`github.com/dcm-project/service-provider-manager/pkg/client`) for all SP resource operations | MUST | | +| REQ-XC-CLI-030 | All clients MUST be instantiated with the API Gateway URL appended with `/api/v1alpha1` | MUST | | +| REQ-XC-CLI-040 | All clients MUST respect the configured request timeout. The timeout applies to the HTTP request deadline (context timeout) only; file I/O and output formatting are not subject to the timeout. | MUST | | +| REQ-XC-CLI-050 | All clients MUST use a custom HTTP client with TLS transport when the API Gateway URL uses `https://` | MUST | | #### Acceptance Criteria @@ -1074,6 +1183,7 @@ Depends on Topic 1 (CLI Framework). - **When** the generated clients are created - **Then** the Policy Manager client MUST be created with `http://localhost:9080/api/v1alpha1` - **And** the Catalog Manager client MUST be created with `http://localhost:9080/api/v1alpha1` +- **And** the SP Resource Manager client MUST be created with `http://localhost:9080/api/v1alpha1` ##### AC-XC-CLI-020: Request timeout @@ -1214,7 +1324,7 @@ and `catalog-manager/pkg/client` instead of hand-writing HTTP client code. boilerplate, and evolve with the OpenAPI specs. The CLI is a thin wrapper around these clients. -**Related requirements:** REQ-XC-CLI-010, REQ-XC-CLI-020 +**Related requirements:** REQ-XC-CLI-010, REQ-XC-CLI-020, REQ-XC-CLI-025 ### DD-020: Cobra + Viper for CLI framework @@ -1329,8 +1439,9 @@ REQ-OUT-090, REQ-OUT-110, REQ-OUT-120 | REQ-CIT-NNN | 4.6: Catalog Item Commands | 11 | | REQ-CIN-NNN | 4.7: Catalog Instance Commands | 11 | | REQ-VER-NNN | 4.8: Version Command | 3 | +| REQ-SPR-NNN | 4.9: SP Resource Commands | 5 | | REQ-XC-ERR-NNN | 5.1: Error Handling | 7 | | REQ-XC-INP-NNN | 5.2: Input File Parsing | 3 | -| REQ-XC-CLI-NNN | 5.3: Generated Client Usage | 4 | +| REQ-XC-CLI-NNN | 5.3: Generated Client Usage | 5 | | REQ-XC-PAG-NNN | 5.4: Pagination | 3 | -| **Total** | | **88** | +| **Total** | | **94** | diff --git a/.ai/test-plans/dcm-cli-unit.test-plan.md b/.ai/test-plans/dcm-cli-unit.test-plan.md index 9a0045d..4593b62 100644 --- a/.ai/test-plans/dcm-cli-unit.test-plan.md +++ b/.ai/test-plans/dcm-cli-unit.test-plan.md @@ -4,7 +4,7 @@ - **Related Spec:** .ai/specs/dcm-cli.spec.md - **Related Plan:** .ai/plan/dcm-cli.plan.md -- **Related Requirements:** REQ-CLI-010–070, REQ-CFG-010–070, REQ-OUT-010–120, REQ-POL-010–130, REQ-CST-010–050, REQ-CIT-010–130, REQ-CIN-010–110, REQ-VER-010–030, REQ-XC-ERR-010–070, REQ-XC-INP-010–030, REQ-XC-CLI-010–050, REQ-XC-PAG-010–030, REQ-XC-TLS-010–080 +- **Related Requirements:** REQ-CLI-010–070, REQ-CFG-010–070, REQ-OUT-010–120, REQ-POL-010–130, REQ-CST-010–050, REQ-CIT-010–130, REQ-CIN-010–110, REQ-SPR-010–050, REQ-VER-010–030, REQ-XC-ERR-010–070, REQ-XC-INP-010–030, REQ-XC-CLI-010–050, REQ-XC-PAG-010–030, REQ-XC-TLS-010–080 - **Framework:** Ginkgo v2 + Gomega - **Created:** 2026-03-09 @@ -262,7 +262,7 @@ test classes. Instead: - **Type:** Unit - **Given:** The root command is created via `NewRootCommand()` - **When:** `dcm --help` is executed -- **Then:** Subcommands `policy`, `catalog`, and `version` are listed in the help output +- **Then:** Subcommands `policy`, `catalog`, `sp`, and `version` are listed in the help output ### TC-U020: Catalog command registers subcommand groups @@ -273,6 +273,15 @@ test classes. Instead: - **When:** `dcm catalog --help` is executed - **Then:** Subcommands `service-type`, `item`, and `instance` are listed +### TC-U129: SP command registers subcommand groups + +- **Requirement:** REQ-CLI-030 +- **Acceptance Criteria:** AC-CLI-030 +- **Type:** Unit +- **Given:** The root command is created +- **When:** `dcm sp --help` is executed +- **Then:** Subcommand `resource` is listed + ### TC-U021: Global flags are registered - **Requirement:** REQ-CLI-050 @@ -863,7 +872,89 @@ test classes. Instead: --- -## 9 · TLS Configuration +## 9 · SP Resource Commands + +> **Suggested Ginkgo structure:** `Describe("SP Resource Commands")` with +> nested `Describe` per subcommand. All tests use `net/http/httptest` to mock +> the generated client's HTTP calls. + +### TC-U121: List SP resources + +- **Requirement:** REQ-SPR-010, REQ-SPR-020 +- **Acceptance Criteria:** AC-SPR-010 +- **Type:** Unit +- **Transitively covers:** TC-U131 (generated SP Resource Manager client usage) +- **Given:** A mock server returning 200 with a list of SP resources +- **When:** `dcm sp resource list` is executed +- **Then:** A GET request is sent to `/api/v1alpha1/service-type-instances` AND the SP resources are displayed in the configured output format + +### TC-U122: List SP resources with pagination + +- **Requirement:** REQ-SPR-010 +- **Acceptance Criteria:** AC-SPR-020 +- **Type:** Unit +- **Transitively covers:** TC-U069 (pagination flags present) +- **Given:** A mock server +- **When:** `dcm sp resource list --page-size 5` is executed +- **Then:** The GET request includes `max_page_size=5` as a query parameter + +### TC-U123: List SP resources with provider filter + +- **Requirement:** REQ-SPR-010 +- **Acceptance Criteria:** AC-SPR-030 +- **Type:** Unit +- **Given:** A mock server +- **When:** `dcm sp resource list --provider kubevirt-123` is executed +- **Then:** The GET request includes `provider=kubevirt-123` as a query parameter + +### TC-U124: Get SP resource + +- **Requirement:** REQ-SPR-030 +- **Acceptance Criteria:** AC-SPR-040 +- **Type:** Unit +- **Given:** A mock server returning 200 with an SP resource +- **When:** `dcm sp resource get my-instance` is executed +- **Then:** A GET request is sent to `/api/v1alpha1/service-type-instances/my-instance` AND the SP resource is displayed + +### TC-U125: Get SP resource without INSTANCE_ID fails + +- **Requirement:** REQ-SPR-040 +- **Acceptance Criteria:** AC-SPR-050 +- **Type:** Unit +- **Given:** No positional argument is provided +- **When:** `dcm sp resource get` is executed +- **Then:** The CLI exits with code 2 and displays a usage error + +### TC-U126: List SP resources returns empty list + +- **Requirement:** REQ-SPR-010, REQ-SPR-020 +- **Acceptance Criteria:** AC-SPR-060 +- **Type:** Unit +- **Given:** A mock server returning 200 with an empty SP resource list (`{"instances":[],"next_page_token":""}`) +- **When:** `dcm sp resource list` is executed +- **Then:** An empty result is displayed (empty table with headers only for table format, empty array for JSON, empty list for YAML) + +### TC-U127: Get non-existent SP resource + +- **Requirement:** REQ-SPR-030, REQ-XC-ERR-010 +- **Acceptance Criteria:** AC-SPR-070, AC-XC-ERR-010 +- **Type:** Unit +- **Given:** A mock server returning 404 with RFC 7807 body for instance ID `nonexistent` +- **When:** `dcm sp resource get nonexistent` is executed +- **Then:** The CLI displays the error in the configured output format AND exits with code 1 + +### TC-U128: SP resource table output columns + +- **Requirement:** REQ-OUT-050 +- **Acceptance Criteria:** AC-OUT-010 +- **Type:** Unit +- **Given:** A mock server returning an SP resource with all fields populated +- **When:** `dcm sp resource get my-instance` is executed with `--output table` +- **Then:** The table output includes columns: ID, PROVIDER, STATUS, CREATED + +--- + +## 10 · TLS Configuration > **Suggested Ginkgo structure:** `Describe("TLS Configuration")` with `Context` > per scenario. Tests use `net/http/httptest` with TLS-enabled servers where @@ -979,7 +1070,7 @@ test classes. Instead: --- -## 10 · Error Handling +## 11 · Error Handling > **Suggested Ginkgo structure:** `Describe("Error Handling")` with `Context` > per error type. Tests exercise error paths through command execution with @@ -1148,6 +1239,26 @@ dedicated test class or `Describe` block. - **Then:** The generated Catalog Manager client is used (verified by mock server receiving correctly structured requests) - **Referenced by:** TC-U042 (service-type list), TC-U044 (service-type get), TC-U046 (item create), TC-U058 (instance create) +#### TC-U130: SP Resource Manager client instantiated with correct URL + +- **Requirement:** REQ-XC-CLI-025, REQ-XC-CLI-030 +- **Acceptance Criteria:** AC-XC-CLI-010 +- **Type:** Unit +- **Given:** The API Gateway URL is `http://localhost:9080` +- **When:** The SP Resource Manager client is created +- **Then:** The client base URL is `http://localhost:9080/api/v1alpha1` +- **Referenced by:** TC-U121 (list SP resources verifies request goes to correct URL path) + +#### TC-U131: SP Resource Manager generated client used for SP resource operations + +- **Requirement:** REQ-XC-CLI-025, REQ-SPR-050 +- **Acceptance Criteria:** AC-SPR-080 +- **Type:** Unit (structural) +- **Given:** Any SP resource command is invoked +- **When:** The command communicates with the API +- **Then:** The generated SP Resource Manager client is used (verified by mock server receiving correctly structured requests) +- **Referenced by:** TC-U121 (list), TC-U124 (get) + #### TC-U068: Request timeout applied to HTTP requests - **Requirement:** REQ-XC-CLI-040 @@ -1165,10 +1276,10 @@ dedicated test class or `Describe` block. - **Requirement:** REQ-XC-PAG-010 - **Acceptance Criteria:** AC-XC-PAG-010 - **Type:** Unit -- **Given:** Any list command (`policy list`, `catalog service-type list`, `catalog item list`, `catalog instance list`) +- **Given:** Any list command (`policy list`, `catalog service-type list`, `catalog item list`, `catalog instance list`, `sp resource list`) - **When:** `--help` is displayed - **Then:** `--page-size` and `--page-token` flags are listed -- **Referenced by:** TC-U033 (policy list pagination), TC-U043 (service-type list pagination), TC-U074 (instance list pagination) +- **Referenced by:** TC-U033 (policy list pagination), TC-U043 (service-type list pagination), TC-U074 (instance list pagination), TC-U122 (SP resource list pagination) #### TC-U070: Pagination parameters passed as query parameters @@ -1236,7 +1347,7 @@ dedicated test class or `Describe` block. | REQ-OUT-020 | TC-U009 (table is default) | Covered | | REQ-OUT-030 | TC-U017 | Covered | | REQ-OUT-040 | TC-U009, TC-U010, TC-U018 | Covered | -| REQ-OUT-050 | TC-U009, TC-U010, TC-U041, TC-U057, TC-U079 | Covered | +| REQ-OUT-050 | TC-U009, TC-U010, TC-U041, TC-U057, TC-U079, TC-U128 | Covered | | REQ-OUT-060 | TC-U011 | Covered | | REQ-OUT-070 | TC-U012 | Covered | | REQ-OUT-080 | TC-U014, TC-U015 | Covered | @@ -1284,6 +1395,11 @@ dedicated test class or `Describe` block. | REQ-CIN-090 | TC-U067 (via TC-U058, TC-U073, TC-U075, TC-U077) | Covered | | REQ-CIN-100 | TC-U072 | Covered | | REQ-CIN-110 | TC-U076, TC-U078 | Covered | +| REQ-SPR-010 | TC-U121, TC-U122, TC-U123 | Covered | +| REQ-SPR-020 | TC-U121 | Covered | +| REQ-SPR-030 | TC-U124 | Covered | +| REQ-SPR-040 | TC-U125 | Covered | +| REQ-SPR-050 | TC-U131 (via TC-U121, TC-U124) | Covered | | REQ-VER-010 | TC-U024 | Covered | | REQ-VER-020 | TC-U024 | Covered | | REQ-VER-030 | TC-U025 | Covered | @@ -1299,10 +1415,11 @@ dedicated test class or `Describe` block. | REQ-XC-INP-030 | TC-U062 (via TC-U026), TC-U063 (via TC-U026) | Covered | | REQ-XC-CLI-010 | TC-U064 (via TC-U026), TC-U066 (via TC-U026/U030/U034/U036/U039) | Covered | | REQ-XC-CLI-020 | TC-U065 (via TC-U042), TC-U067 (via TC-U042/U044/U046/U058) | Covered | -| REQ-XC-CLI-030 | TC-U064 (via TC-U026), TC-U065 (via TC-U042) | Covered | +| REQ-XC-CLI-025 | TC-U130 (via TC-U121), TC-U131 (via TC-U121/U124) | Covered | +| REQ-XC-CLI-030 | TC-U064 (via TC-U026), TC-U065 (via TC-U042), TC-U130 (via TC-U121) | Covered | | REQ-XC-CLI-040 | TC-U068 (via TC-U084) | Covered | | REQ-XC-CLI-050 | TC-U088, TC-U090, TC-U091 | Covered | -| REQ-XC-PAG-010 | TC-U069 (via TC-U033, TC-U043, TC-U074) | Covered | +| REQ-XC-PAG-010 | TC-U069 (via TC-U033, TC-U043, TC-U074, TC-U122) | Covered | | REQ-XC-PAG-020 | TC-U070 (via TC-U033) | Covered | | REQ-XC-PAG-030 | TC-U071 (via TC-U013, TC-U014, TC-U015) | Covered | | REQ-XC-TLS-010 | TC-U088 | Covered | @@ -1314,7 +1431,7 @@ dedicated test class or `Describe` block. | REQ-XC-TLS-070 | TC-U095, TC-U096 | Covered | | REQ-XC-TLS-080 | TC-U090, TC-U097 | Covered | -**Total:** 85 test case IDs — 63 in behavioural test classes, 22 in the utility +**Total:** 95 test case IDs — 71 in behavioural test classes, 24 in the utility index (tested transitively through higher-level behavioural tests). ---