Skip to content

Conversation

@HenrikHL
Copy link
Contributor

@HenrikHL HenrikHL commented Jan 20, 2026

User description

Adding the GET terminal timestamps endPoint to OVS Hub


PR Type

Enhancement


Description

  • Add GET endpoint for terminal schedules with comprehensive filtering

  • Introduce new ServiceSchedule schema with vessel and transport call details

  • Add support for date range, service code, and pagination parameters

  • Define Timestamp, Address, VesselSchedule, and TransportCall schemas


Diagram Walkthrough

flowchart LR
  A["GET /v1/terminal-schedules"] -->|Query Parameters| B["carrierServiceCode<br/>startDate<br/>endDate<br/>limit<br/>cursor"]
  B --> C["ServiceSchedule<br/>Response"]
  C --> D["VesselSchedule"]
  D --> E["TransportCall"]
  E --> F["Timestamp"]
Loading

File Walkthrough

Relevant files
Enhancement
OVS_HUB_TER_v1.0.0.yaml
Add GET terminal schedules endpoint with schemas                 

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml

  • Added new "Terminal Schedules" tag and GET /v1/terminal-schedules
    endpoint with query parameters for filtering by service code, date
    range, and pagination
  • Introduced ServiceSchedule schema containing carrier service details
    and vessel schedules
  • Added VesselSchedule schema with vessel information and transport
    calls
  • Added TransportCall schema with voyage references, location, and
    timestamps
  • Added Timestamp schema for arrival/departure event data
  • Added Address schema for location address details
+443/-1 

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 20, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unbounded pagination limit

Description: The new GET /v1/terminal-schedules query parameter limit has no documented/enforced
maximum (only minimum: 0), which can enable resource-exhaustion (DoS) if clients request
extremely large pages that trigger heavy backend queries and large responses.
OVS_HUB_TER_v1.0.0.yaml [233-243]

Referred Code
- name: limit
  in: query
  description: |
    Specifies the maximum number of `Terminal Schedule` objects to return.
  schema:
    type: number
    format: int32
    minimum: 0
    default: 100
    example: 100
-  name: cursor
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Weak parameter validation: The new query parameter schema for pagination and limits is under-specified/inconsistent
(e.g., limit uses type: number with format: int32 and allows minimum: 0, and the spec text
mandates cursor-only pagination without enforcing mutual exclusivity with other query
parameters), which can lead to ambiguous or insecure request handling.

Referred Code
- name: limit
  in: query
  description: |
    Specifies the maximum number of `Terminal Schedule` objects to return.
  schema:
    type: number
    format: int32
    minimum: 0
    default: 100
    example: 100
-  name: cursor
   in: query
   description: |
     A server generated value to specify a specific point in a collection result, used for pagination.
   schema:
     type: string
     maxLength: 1024
     example: fE9mZnNldHw9MTAmbGltaXQ9MTA
responses:
  '200':
    description: OK


 ... (clipped 21 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit info: The PR only updates the OpenAPI contract for GET /v1/terminal-schedules, so it is not
possible to verify whether reads are audit-logged with user context and outcomes.

Referred Code
/v1/terminal-schedules:
  get:
    tags:
    - Terminal Schedules
    summary: |
      Get a list of Terminal Schedules
    operationId: get-terminal-schedules
    description: |
      Get a list of terminal service schedules.
    parameters:
    - name: carrierServiceCode
      in: query
      description: |
        The carrier specific service code to filter by. The result will only return schedules including the service code.
      schema:
        type: string
        maxLength: 11
        example: FE1
    - name: startDate
      in: query
      description: |


 ... (clipped 110 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Edge cases unspecified: The new endpoint defines generic 400/500 responses but the contract does not specify
validation/error behavior for key edge cases such as invalid startDate/endDate ranges or
pagination misuse (e.g., providing cursor alongside other filters).

Referred Code
- name: startDate
  in: query
  description: |
    The start date of the period for which schedule information is requested. If a date of any Timestamp (ATA, ETA or PTA) inside a Schedule matches a date on or after (≥) the `startDate` the entire Voyage (import- and export-Voyage) matching the PortCall will be included in the result. All matching is done towards local Date at the place of the port call.
    If this filter is not provided, the default value is **3 months** prior to the request time.
  schema:
    type: string
    format: date
    example: 2020-04-06
- name: endDate
  in: query
  description: |
    The end date of the period for which schedule information is requested. If a date of any Timestamp (ATA, ETA or PTA) inside a Schedule matches a date on or before (≤) the `endDate` the entire Voyage(import- and export-Voyage) matching the PortCall will be included in the result. All matching is done towards local Date at the place of the port call.
    If this filter is not provided, the default value is **6 months** after the request time.
  schema:
    type: string
    format: date
    example: 2020-04-10
- name: limit
  in: query
  description: |


 ... (clipped 92 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Logging not verifiable: The PR changes an API specification only, so there is no visibility into whether
implementation logs are structured and free of sensitive information for this new
endpoint.

Referred Code
/v1/terminal-schedules:
  get:
    tags:
    - Terminal Schedules
    summary: |
      Get a list of Terminal Schedules
    operationId: get-terminal-schedules
    description: |
      Get a list of terminal service schedules.
    parameters:
    - name: carrierServiceCode
      in: query
      description: |
        The carrier specific service code to filter by. The result will only return schedules including the service code.
      schema:
        type: string
        maxLength: 11
        example: FE1
    - name: startDate
      in: query
      description: |


 ... (clipped 110 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 20, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix cursor parameter indentation
Suggestion Impact:The commit adjusted the indentation of the `cursor` parameter entry, removing the extra space after the dash and aligning subsequent keys, matching the suggested YAML fix.

code diff:

-      -  name: cursor
-         in: query
-         description: |
-           A server generated value to specify a specific point in a collection result, used for pagination.
-         schema:
-           type: string
-           maxLength: 1024
-           example: fE9mZnNldHw9MTAmbGltaXQ9MTA
+      - name: cursor
+        in: query
+        description: |
+          A server generated value to specify a specific point in a collection result, used for pagination.
+        schema:
+          type: string
+          maxLength: 1024
+          example: fE9mZnNldHw9MTAmbGltaXQ9MTA

Fix a YAML syntax error in the cursor parameter definition by removing an extra
space after the dash.

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml [243-244]

--  name: cursor
-   in: query
+- name: cursor
+  in: query

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a YAML syntax error (- name: cursor) that would cause parsing to fail, making it a critical fix for the API definition to be valid.

High
Add missing object type
Suggestion Impact:The commit added `type: object` to the `location` field schema (and also added a `title` plus other related schema text/field adjustments). This addresses the missing object type noted in the suggestion.

code diff:

         location:
+          type: object    
+          title: 'Location'      
           description: |
             An object to capture the location of the timestamp(s).
 
-            The location can be specified in **any** of the following ways: `UN Location Code`, `Facility SMDG Code` or an `Address`.
-
-            **Condition:** It is expected that if a location is specified in multiple ways (e.g. both as an `Address` and as a `Facility SMDG Code`) that both ways point to the same location.
+            The location can be specified in **any** of the following ways: `UN Location Code` or `Facility SMDG Code`.
+
+            **Condition:** It is expected that if a location is specified in multiple ways (e.g. both as an `UN Location Code` and as a `Facility SMDG Code`) that both ways point to the same location.
           example:
             locationName: Hamburg
             UNLocationCode: DEHAM
@@ -506,16 +508,12 @@

Add the missing type: object declaration to the location field schema to ensure
it is correctly interpreted as an object with properties.

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml [487-503]

 location:
+  type: object
   description: |
     An object to capture the location of the timestamp(s).
   example:
     locationName: Hamburg
     UNLocationCode: DEHAM
   properties:
     locationName:
       type: string
       ...

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that the location schema is missing the required type: object declaration, which is a significant schema validation error.

Medium
Clarify pagination documentation for correctness
Suggestion Impact:The commit updates the Next-Page-Cursor header description to state that subsequent page requests must preserve the original query parameters while only adding the cursor, and that the original limit is typically encoded in the cursor and should not be resent—resolving the earlier contradiction.

code diff:

               description: |
                 The Next-Page-Cursor header contains a cursor value that points to the next page of results in a paginated API response.
                 When an initial `GET` endpoint request includes the query parameter `limit=...` the API provider limits the number of items in the root array of the response to the specified limit. If the response would contain more items than the specified limit, the API provider includes only the first set of limit items and appends the following response header:
-                `Next-Page-Cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`, a string that acts as a reference for the next page of results. The cursor value is used in subsequent requests to retrieve the next page by passing it as a query parameter: `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`.
-
-                To retrieve the next page, the API consumer sends a `GET` request to the endpoint URL with only `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA` as query parameter. The limit of items per page and any other query parameters may not be altered and MUST be preserved when requesting subsequent pages.
+                `Next-Page-Cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`, a string that acts as a reference for the next page of results.
+
+                To retrieve the next page, the API consumer sends a `GET` request to the same endpoint URL with the `cursor` query parameter set to the value from the `Next-Page-Cursor` header (e.g., `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`). All other query parameters from the original request (such as `carrierServiceCode`, `startDate`, etc.) MUST be preserved when requesting subsequent pages. The `limit` parameter from the original request is typically encoded within the cursor and should not be sent again.

Clarify the Next-Page-Cursor header description to resolve a contradiction
regarding the preservation of query parameters during pagination.

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml [243-273]

 -  name: cursor
    in: query
    description: |
      A server generated value to specify a specific point in a collection result, used for pagination.
    schema:
      type: string
      maxLength: 1024
      example: fE9mZnNldHw9MTAmbGltaXQ9MTA
 responses:
   '200':
     description: OK
     content:
       application/json:
         schema:
           type: array
           items:
             $ref: '#/components/schemas/ServiceSchedule'
     headers:
       API-Version:
         $ref: '#/components/headers/API-Version'
       Next-Page-Cursor:
         schema:
           type: string
           maxLength: 1024
           example: fE9mZnNldHw9MTAmbGltaXQ9MTA
         description: |
           The Next-Page-Cursor header contains a cursor value that points to the next page of results in a paginated API response.
           When an initial `GET` endpoint request includes the query parameter `limit=...` the API provider limits the number of items in the root array of the response to the specified limit. If the response would contain more items than the specified limit, the API provider includes only the first set of limit items and appends the following response header:
-          `Next-Page-Cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`, a string that acts as a reference for the next page of results. The cursor value is used in subsequent requests to retrieve the next page by passing it as a query parameter: `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`.
+          `Next-Page-Cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`, a string that acts as a reference for the next page of results.
 
-          To retrieve the next page, the API consumer sends a `GET` request to the endpoint URL with only `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA` as query parameter. The limit of items per page and any other query parameters may not be altered and MUST be preserved when requesting subsequent pages.
+          To retrieve the next page, the API consumer sends a `GET` request to the same endpoint URL with the `cursor` query parameter set to the value from the `Next-Page-Cursor` header (e.g., `?cursor=fE9mZnNldHw9MTAmbGltaXQ9MTA`). All other query parameters from the original request (such as `carrierServiceCode`, `startDate`, etc.) MUST be preserved when requesting subsequent pages. The `limit` parameter from the original request is typically encoded within the cursor and should not be sent again.

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies a confusing and contradictory statement in the API documentation that could lead to incorrect client implementations, and the proposed change clarifies this ambiguity.

Low
General
Use integer type for limit parameter
Suggestion Impact:The commit updates the `limit` parameter schema type from `number` to `integer` as suggested. Other unrelated formatting and schema changes are also present.

code diff:

@@ -235,19 +235,19 @@
         description: |
           Specifies the maximum number of `Terminal Schedule` objects to return.
         schema:
-          type: number
+          type: integer
           format: int32
           minimum: 0
           default: 100
           example: 100

Change the limit parameter's type from number to integer for more precise schema
definition and stricter validation.

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml [233-242]

 limit:
   in: query
   description: |
     Specifies the maximum number of `Terminal Schedule` objects to return.
   schema:
-    type: number
+    type: integer
     format: int32
     minimum: 0
     default: 100
     example: 100

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 4

__

Why: The suggestion correctly proposes using the more specific integer type instead of number for the limit parameter, which improves schema precision and validation according to OpenAPI best practices.

Low
Remove redundant length constraints from schema

Remove the redundant minLength and maxLength attributes from the MMSINumber
field, as the pattern already enforces the length.

ovs_hub_ter/v1/OVS_HUB_TER_v1.0.0.yaml [400-407]

 MMSINumber:
   type: string
   pattern: ^\d{9}$
-  minLength: 9
-  maxLength: 9
   description: |
     Maritime Mobile Service Identities (MMSIs) are nine-digit numbers used by maritime digital selective calling (DSC), automatic identification systems (AIS) and certain other equipment to uniquely identify a ship or a coast radio station.
   example: '278111222'
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies and proposes removing redundant minLength and maxLength constraints, as they are already covered by the pattern, which simplifies the schema.

Low
  • Update

Co-authored-by: qodo-code-review[bot] <151058649+qodo-code-review[bot]@users.noreply.github.com>
@HenrikHL HenrikHL merged commit fc26b74 into master Jan 20, 2026
1 check passed
@HenrikHL HenrikHL deleted the Add-GET-endPoint-to-OVS_HUB_TER branch January 20, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants