Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions cloud-controlplane/cloud-controlplane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2729,6 +2729,16 @@ components:
created:
$ref: '#/components/schemas/Created'
type: object
NetworkUpdate:
description: Resource describing an Update Network.
properties:
id:
description: ID of the network.
type: string
required:
- id
title: NetworkUpdate
type: object
NullValue:
description: |-
`NullValue` is a singleton enumeration to represent the null value for the
Expand Down Expand Up @@ -2759,6 +2769,7 @@ components:
- TYPE_DELETE_SERVERLESS_PRIVATE_LINK
- TYPE_CREATE_NETWORK_PEERING
- TYPE_DELETE_NETWORK_PEERING
- TYPE_UPDATE_NETWORK
- TYPE_CREATE_SHADOW_LINK
- TYPE_UPDATE_SHADOW_LINK
- TYPE_DELETE_SHADOW_LINK
Expand Down Expand Up @@ -4342,6 +4353,16 @@ components:
group:
$ref: '#/components/schemas/Group'
type: object
UpdateNetworkMetadata:
description: Resource describing an in-progress UpdateNetwork Operation.
title: UpdateNetworkMetadata
type: object
UpdateNetworkOperation:
description: UpdateNetworkOperation is the response of the update network rpc.
properties:
operation:
$ref: '#/components/schemas/v1.Operation'
type: object
Comment on lines +4356 to +4365
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wire update-network into the generic operation unions.

UpdateNetworkMetadata and UpdateNetworkOperation are added here, but v1.Operation still cannot represent a TYPE_UPDATE_NETWORK operation in the generic operations endpoints because OperationMetadata lacks the UpdateNetworkMetadata branch and OperationResponse has no UpdateNetworkResponse branch at all.

Minimal wiring to add
     OperationMetadata:
       oneOf:
+        - allOf:
+            - properties:
+                '`@type`':
+                  description: Fully qualified protobuf type name of the underlying response, prefixed with `type.googleapis.com/`.
+                  enum:
+                    - type.googleapis.com/redpanda.api.controlplane.v1.UpdateNetworkMetadata
+                  type: string
+            - $ref: '`#/components/schemas/UpdateNetworkMetadata`'

+    UpdateNetworkResponse:
+      properties:
+        network:
+          $ref: '`#/components/schemas/Network`'
+      type: object
+
     OperationResponse:
       oneOf:
+        - allOf:
+            - properties:
+                '`@type`':
+                  description: Fully qualified protobuf type name of the underlying response, prefixed with `type.googleapis.com/`.
+                  enum:
+                    - type.googleapis.com/redpanda.api.controlplane.v1.UpdateNetworkResponse
+                  type: string
+            - $ref: '`#/components/schemas/UpdateNetworkResponse`'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloud-controlplane/cloud-controlplane.yaml` around lines 4356 - 4365, The new
UpdateNetworkMetadata and UpdateNetworkOperation types were added but not wired
into the generic operation unions; update the union types so v1.Operation can
carry TYPE_UPDATE_NETWORK: add an UpdateNetworkMetadata branch to
OperationMetadata (or the equivalent metadata union) and add an
UpdateNetworkResponse/UpdateNetworkOperation branch to OperationResponse (or the
equivalent response union) so the generic operations endpoints can represent
TYPE_UPDATE_NETWORK using UpdateNetworkMetadata and UpdateNetworkOperation.

UpdateOrganizationResponse:
properties:
organization:
Expand Down Expand Up @@ -6332,6 +6353,60 @@ paths:
summary: Get network
tags:
- Networks
/v1/networks/{network.id}:
patch:
description: Update a Redpanda network.
operationId: NetworkService_UpdateNetwork
parameters:
- description: ID of the network.
in: path
name: network.id
required: true
schema:
type: string
Comment on lines +6356 to +6366
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
import re
from collections import defaultdict
from pathlib import Path

text = Path("cloud-controlplane/cloud-controlplane.yaml").read_text()

in_paths = False
paths = []
for line in text.splitlines():
    if line.strip() == "paths:":
        in_paths = True
        continue
    if in_paths and re.match(r'^\S', line):
        break
    m = re.match(r'^  (/[^:]+):\s*$', line)
    if in_paths and m:
        paths.append(m.group(1))

normalized = defaultdict(list)
for path in paths:
    normalized[re.sub(r'\{[^}]+\}', '{}', path)].append(path)

for key, variants in sorted(normalized.items()):
    if len(variants) > 1:
        print(key)
        for variant in variants:
            print(f"  - {variant}")
PY

Repository: redpanda-data/api-docs

Length of output: 522


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="cloud-controlplane/cloud-controlplane.yaml"

echo "=== Find /v1/networks/{id} path block ==="
rg -n --fixed-string '  /v1/networks/{id}:' "$FILE" -n || true
python - <<'PY'
from pathlib import Path
import re

p=Path("cloud-controlplane/cloud-controlplane.yaml")
lines=p.read_text().splitlines()

# find indices for the two path keys
targets=["  /v1/networks/{id}:","  /v1/networks/{network.id}:"]
for t in targets:
    idx=[i for i,l in enumerate(lines) if l.strip()==t.strip()]
    print(t, "count", len(idx), "indices", idx[:5])
    if idx:
        i=idx[0]
        # print from a bit before to a bit after
        start=max(0,i-5); end=min(len(lines), i+60)
        print("\n--- Context for", t, "lines", start+1, "-", end, "---")
        for k in range(start,end):
            print(f"{k+1:>6} {lines[k]}")
PY

echo "=== Find all operations directly under those two path keys (method lines) ==="
python - <<'PY'
from pathlib import Path
import re

FILE=Path("cloud-controlplane/cloud-controlplane.yaml")
lines=FILE.read_text().splitlines()

def collect_methods(path_key):
    methods=[]
    # find line with exact key
    idx=None
    for i,l in enumerate(lines):
        if l.strip()==path_key.strip():
            idx=i
            break
    if idx is None:
        return methods
    # scan until next top-level path key (2 spaces indent, starts with /)
    for j in range(idx+1,len(lines)):
        l=lines[j]
        if re.match(r'^  /[^:]+:\s*$', l.strip()):
            break
        m=re.match(r'^\s{4}([a-z]+):\s*$', l)  # 4 spaces then http method
        if m:
            methods.append(m.group(1))
    return methods

print("methods for /v1/networks/{id}:", collect_methods("  /v1/networks/{id}:"))
print("methods for /v1/networks/{network.id}:", collect_methods("  /v1/networks/{network.id}:"))
PY

Repository: redpanda-data/api-docs

Length of output: 6784


🌐 Web query:

OpenAPI 3 duplicate/conflicting path templates different parameter names {id} vs {network.id} validator behavior

💡 Result:

In the OpenAPI 3 specification, paths that share the same hierarchy but use different parameter names in their templates (such as /users/{id} and /users/{network.id}) are considered identical and are strictly invalid [1][2][3]. The OpenAPI Specification explicitly states: "Templated paths with the same hierarchy but different templated names MUST NOT exist as they are identical" [1][3]. Because OpenAPI tooling normalizes these templates by treating the placeholder (the text inside the braces) as a generic segment, both {id} and {network.id} are effectively reduced to the same internal signature (e.g., /users/{}). Validator behavior typically includes the following: 1. Invalid Specification: Most linters and schema validators will flag this as an error because the structure is ambiguous and violates the specification's uniqueness requirements [4]. 2. Tooling Failure: Code generators and diffing tools often fail when they encounter these paths because they cannot distinguish between the two templates, leading to errors like "Two path items have the same signature" [4]. 3. Ambiguous Routing: If a validator fails to catch this, actual API routing becomes ambiguous. Since the specification considers them identical, there is no standardized behavior for how an API server or client should resolve which path to use, and it is left to the individual implementation [1][2]. To resolve this issue, you must use consistent parameter names across identical path structures or restructure your API to ensure the paths themselves are distinct (e.g., /users/{id} vs /networks/{network.id}/users/{id}) [5][4].

Citations:


🌐 Web query:

OpenAPI path parameter name constraints allow dots '.' in {parameterName}

💡 Result:

In OpenAPI, dots '.' are allowed in the path parameter name (the identifier inside { }), as the spec does not restrict the parameter-name characters to exclude '.'. [1] What OpenAPI does restrict is the content/value of a path parameter: the path parameter value MUST NOT contain any unescaped “generic syntax” characters described by RFC3986: forward slashes (/), question marks (?), or hashes (#). This restriction is about the parameter value at runtime, not the name/identifier inside the curly braces. [2][3] So {user.name} as a template name is permitted by the OpenAPI rules, but the actual value substituted for {user.name} cannot include unescaped '/', '?', or '#'. [1][2]

Citations:


Merge /v1/networks/{network.id} into the existing /v1/networks/{id} path item (remove duplicate templated path)

/v1/networks/{network.id} conflicts with /v1/networks/{id}: OpenAPI does not allow two path items with the same hierarchy but different templated names ({network.id} vs {id}), since they’re treated as the same templated path signature by validators/generators. Move the patch operation under /v1/networks/{id} and rename the path parameter to name: id.

  /v1/networks/{network.id}:
    patch:
      description: Update a Redpanda network.
      operationId: NetworkService_UpdateNetwork
      parameters:
        - description: ID of the network.
          in: path
          name: network.id
          required: true
          schema:
            type: string
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloud-controlplane/cloud-controlplane.yaml` around lines 6356 - 6366, Remove
the duplicate path item /v1/networks/{network.id} by moving its patch operation
(operationId: NetworkService_UpdateNetwork) under the existing /v1/networks/{id}
path and delete the /v1/networks/{network.id} entry; also rename the path
parameter from name: network.id to name: id and ensure the parameter remains in:
path, required: true with schema type: string so the merged /v1/networks/{id}
contains the patch operation and a single canonical path parameter.

requestBody:
content:
application/json:
schema:
description: Resource describing an Update Network.
required:
- network
title: NetworkUpdate
type: object
description: |-
NetworkUpdate

Resource describing an Update Network.
required: true
Comment on lines +6367 to +6380
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Define the PATCH payload instead of requiring an undeclared field.

The request schema marks network as required, but it defines neither properties.network nor a $ref. That leaves clients/codegen with a required key of unspecified shape. Either reference a real update schema here or drop the body requirement if this operation is path-only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloud-controlplane/cloud-controlplane.yaml` around lines 6367 - 6380, The
OpenAPI requestBody schema for NetworkUpdate declares a required field "network"
but does not define properties or a $ref; update the NetworkUpdate schema used
in the requestBody to either (a) include a properties object that defines
"network" (with its correct type or object schema) or (b) replace the inline
schema with a $ref to the existing Network update model, ensuring "network" is
properly declared, or (c) if this PATCH only uses path parameters, remove the
requestBody.required and the "network" requirement entirely; look for the
NetworkUpdate schema block and the requestBody definition to apply the change.

x-originalParamName: network
responses:
"202":
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateNetworkOperation'
description: Accepted
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/rpc.Status'
description: Not Found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/rpc.Status'
description: Internal Server Error. Please reach out to support.
default:
content:
application/json:
schema:
$ref: '#/components/schemas/rpc.Status'
description: An unexpected error response.
summary: Update network
tags:
- Networks
/v1/operations:
get:
description: List operations. This is a generic endpoint and can be used to list any type of operation.
Expand All @@ -6356,6 +6431,7 @@ paths:
- TYPE_DELETE_SERVERLESS_PRIVATE_LINK
- TYPE_CREATE_NETWORK_PEERING
- TYPE_DELETE_NETWORK_PEERING
- TYPE_UPDATE_NETWORK
- TYPE_CREATE_SHADOW_LINK
- TYPE_UPDATE_SHADOW_LINK
- TYPE_DELETE_SHADOW_LINK
Expand Down
2 changes: 1 addition & 1 deletion cloud-dataplane/cloud-dataplane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7856,7 +7856,7 @@ paths:
schema:
$ref: '#/components/schemas/TransformMetadata'
description: Created
summary: Deploy transform
summary: Deploy Transform
tags:
- Wasm Transforms
/v1/transforms/{name}:
Expand Down
Loading