Skip to content

Address second round of code review feedback#261

Merged
leynos merged 5 commits intomainfrom
domain-ports-feedback
Dec 19, 2025
Merged

Address second round of code review feedback#261
leynos merged 5 commits intomainfrom
domain-ports-feedback

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Dec 19, 2025

  • Clarify display_name schema comment: document that schema constraints and domain validation are separate (schema allows spaces, domain checks non-empty when trimmed)
  • Restructure ErrorCode sync test with pattern matching for compile-time exhaustiveness; adding new variants now causes build errors
  • Make assert_object_schema_has_field more defensive: handle $ref, AllOf, OneOf, AnyOf, Array with diagnostic messages
  • Add unit tests for UserSchema constraints (uuid format, min/max length, pattern)
  • Add BDD scenario for User schema validation constraints
  • Fix "Open API" typo to "OpenAPI Specification"
  • Fix "serialises" spelling to "serializes" (en-GB-oxendict)

🤖 Generated with Claude Code

Summary by Sourcery

Strengthen OpenAPI schema validation around the User and ErrorCode types, and clarify associated documentation and comments.

New Features:

  • Add unit tests to verify OpenAPI UserSchema constraints for id format and display_name length/pattern.
  • Add BDD scenarios to assert User schema validation constraints in the generated OpenAPI document.

Enhancements:

  • Make object schema assertion helpers more defensive with detailed diagnostics for non-object and combinator schemas.
  • Refine the ErrorCode schema synchronization test to use exhaustive pattern matching for compile-time coverage of enum variants.
  • Clarify UserSchema display_name documentation to distinguish schema-level constraints from domain-layer validation.
  • Fix minor spelling and terminology issues in schema tests and architecture documentation.

- Clarify display_name schema comment: document that schema constraints
  and domain validation are separate (schema allows spaces, domain
  checks non-empty when trimmed)
- Restructure ErrorCode sync test with pattern matching for compile-time
  exhaustiveness; adding new variants now causes build errors
- Make assert_object_schema_has_field more defensive: handle $ref,
  AllOf, OneOf, AnyOf, Array with diagnostic messages
- Add unit tests for UserSchema constraints (uuid format, min/max
  length, pattern)
- Add BDD scenario for User schema validation constraints
- Fix "Open API" typo to "OpenAPI Specification"
- Fix "serialises" spelling to "serializes" (en-GB-oxendict)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Dec 19, 2025

Reviewer's Guide

Strengthens OpenAPI schema verification for User and ErrorCode types by making schema inspection helpers more defensive, adding focused unit and BDD tests for UserSchema constraints, and performing minor documentation and spelling cleanups.

Sequence diagram for ErrorCode schema serialization verification

sequenceDiagram
    participant T as error_code_schema_matches_domain_serialization_test
    participant H as expected_serialization
    participant S as serde_json

    T->>T: define variants = [InvalidRequest, Unauthorized,
    T->>T: Forbidden, NotFound, InternalError]

    loop for each code in variants
        T->>S: to_string(code)
        S-->>T: serialized_json_string

        T->>H: expected_serialization(code)
        H-->>T: expected_string

        T->>T: assert serialized_json_string == "\"expected_string\""
    end

    note over T: Pattern matching in expected_serialization
    note over T: causes compile-time failure if
    note over T: a new ErrorCode variant is added without
    note over T: updating the match arms
Loading

Updated class diagram for OpenAPI schema test helpers and related types

classDiagram
    class ApiDoc {
        +openapi() OpenApi
    }

    class OpenApi {
        +components ComponentsOption
    }

    class ComponentsOption {
        +schemas Map~String,RefOr_Schema_~
    }

    class RefOr_Schema_ {
    }

    class Schema {
    }

    class ObjectSchema {
        +properties Map~String,RefOr_Schema_~
        +min_length Option~u32~
        +max_length Option~u32~
        +pattern Option~String~
        +format Option~SchemaFormat~
    }

    class SchemaFormat {
        <<enumeration>>
        +Custom(String)
    }

    class UserSchema {
        -id String
        -display_name String
    }

    class ErrorCode {
        <<enumeration>>
        +InvalidRequest
        +Unauthorized
        +Forbidden
        +NotFound
        +InternalError
    }

    class TestHelpers {
        +assert_object_schema_has_field(schema RefOr_Schema_, schema_name String, field String) void
        +unwrap_object_schema(schema RefOr_Schema_, name String) ObjectSchema
        +expected_serialization(code ErrorCode) String
    }

    ApiDoc --> OpenApi : produces
    OpenApi --> ComponentsOption : has
    ComponentsOption --> RefOr_Schema_ : contains

    RefOr_Schema_ --> Schema : wraps
    Schema <|-- ObjectSchema : variant

    ObjectSchema --> SchemaFormat : uses

    UserSchema --> ObjectSchema : generates_schema
    UserSchema --> ApiDoc : included_in

    ErrorCode ..> TestHelpers : passed_to
    TestHelpers ..> ObjectSchema : inspects
    TestHelpers ..> RefOr_Schema_ : inspects
    TestHelpers ..> ErrorCode : matches_variants
Loading

File-Level Changes

Change Details Files
Harden OpenAPI schema inspection helpers and add unit tests for UserSchema constraints.
  • Extend assert_object_schema_has_field to accept schema_name and emit detailed diagnostics for $ref, combinators, arrays, and unexpected schema variants instead of a generic panic.
  • Introduce unwrap_object_schema helper to centralize extraction of Object schemas and reuse it in new tests.
  • Add unit tests that verify the OpenAPI User schema enforces UUID format on id and length/pattern constraints on display_name.
backend/src/doc.rs
Add BDD coverage for User schema validation details in the generated OpenAPI document.
  • Add step definitions that assert User.id has format=uuid and User.display_name has min/max length and pattern constraints.
  • Extend the openapi_schemas.feature with a new scenario that exercises the User schema validation constraints via the OpenAPI document.
backend/tests/openapi_schemas_bdd.rs
backend/tests/features/openapi_schemas.feature
Improve ErrorCode schema sync test robustness and clarify docs/comments.
  • Refactor the ErrorCode serialization/schema sync test to use an exhaustive match-based expected_serialization helper and a variants list, ensuring compile-time failure when new ErrorCode variants are added.
  • Clarify the UserSchema.display_name doc comment to distinguish schema-level constraints from domain-level trimmed non-empty validation.
  • Fix spelling and terminology: change 'serialises' to 'serializes' in schema_to_json test and correct 'Open API' to 'OpenAPI Specification' in execution plan docs.
backend/src/inbound/http/schemas.rs
docs/execplans/phase-0-update-modules-to-use-domain-ports.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 19, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation error messages with clearer diagnostics for schema validation issues.
  • Tests

    • Added BDD and unit tests verifying user ID format (UUID-like) and display name constraints (length and pattern).
  • Documentation

    • Minor clarifications in schema documentation and example serialization wording.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Summarise added test-support OpenAPI helpers and richer schema assertions: introduce test_support::openapi helpers to unwrap object schemas and fetch properties; extend assert_object_schema_has_field to accept schema_name and produce diagnostic panics for non-Object schema shapes; update tests and BDD to assert User.id uuid format and User.display_name length/pattern constraints; refactor an error-code serialisation test.

Changes

Cohort / File(s) Change Summary
Doc & assertion helpers
backend/src/doc.rs
Add schema_name parameter to assert_object_schema_has_field; extend match arms to panic with diagnostic messages for non-Object schema variants ($ref, AllOf, OneOf, AnyOf, Array, others).
Test support module
backend/src/test_support.rs, backend/src/lib.rs
Add new public test_support module and pub mod openapi containing unwrap_object_schema<'a>(schema: &'a RefOr<Schema>, name: &str) -> &'a Object and get_property<'a>(obj: &'a Object, field: &str) -> &'a RefOr<Schema> with descriptive panic diagnostics; export via conditional pub mod test_support;.
Schema constraints, docs & tests
backend/src/inbound/http/schemas.rs
Clarify UserSchema.display_name docs: separate domain-level invariant from schema-level constraints (min/max length, allowed chars). Refactor error-code serialisation test to use an inner helper mapping variants to expected strings for compile-time exhaustiveness and iterate over variants.
BDD scenarios and test steps
backend/tests/features/openapi_schemas.feature, backend/tests/openapi_schemas_bdd.rs
Add BDD scenario "User schema has validation constraints". Add steps asserting User.id format=uuid, User.display_name min_length=3, max_length=32, and pattern="^[A-Za-z0-9_ ]+$". Import and use unwrap_object_schema and get_property helpers in tests.
Docs formatting
docs/execplans/phase-0-update-modules-to-use-domain-ports.md
Apply minor line-break/formatting adjustment within a bullet; no semantic change.
Cargo / features
backend/Cargo.toml
Add test-support feature and declare backend as a dev-dependency with the test-support feature enabled for tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify all call sites updated to the new assert_object_schema_has_field signature and that schema_name values are meaningful.
  • Inspect unwrap_object_schema match arms to ensure all non-Object schema variants produce clear, actionable diagnostics.
  • Confirm get_property panics have informative messages and that tests using it expect the shape asserted.
  • Review the error-code serialisation test inner helper for exhaustiveness and readability.
  • Validate BDD steps correctly unwrap nested schemas and assert the exact format, min_length, max_length, and pattern values.

Possibly related PRs

Poem

🧭 Schemas unwrapped with a careful pry,
Panic notes point where the shapes defy,
UUIDs checked and patterns held tight,
Lengths and bounds set clean and bright,
Tests sing true beneath the CI sky.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and generic, using a non-descriptive term 'second round of code review feedback' that doesn't convey the specific changes or main objectives of the changeset. Revise the title to highlight the primary change, e.g., 'Strengthen OpenAPI schema validation and add comprehensive tests' or 'Refactor error code test with exhaustive pattern matching and improve schema helpers'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly relates to the changeset, detailing schema validation improvements, test restructuring, documentation clarifications, and spelling fixes that all appear in the file summaries.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch domain-ports-feedback

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28e89c6 and 07a328d.

📒 Files selected for processing (1)
  • backend/tests/openapi_schemas_bdd.rs (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rs,ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,ts,tsx,js,jsx,py}: Comment why, not what—explain assumptions, edge cases, trade-offs, or complexity; do not echo the obvious.
Favour clarity over cleverness—be concise but prefer explicit over terse or obscure idioms; prioritise code that is easy to follow.
Use functions and composition to avoid repetition; prefer generators or comprehensions and declarative code to imperative repetition when readable.
Keep functions small and meaningful—single responsibility, clear purpose, and obey command/query segregation.
Name things precisely—use clear, descriptive variable and function names; for booleans, prefer names with is, has, or should.
Structure logically—each file should encapsulate a coherent module; group related code close together.
Illustrate with clear examples in function documentation demonstrating usage and outcome; for tests, omit examples where the example only reiterates test logic.
Keep file size manageable—no single code file may exceed 400 lines; break up long switch statements and move large test data blocks to external files.
New functionality or changes in behaviour must be fully validated by relevant unittests and behavioural tests before committing.
When fixing a bug, provide a unittest demonstrating the corrected behaviour to validate the fix and guard against regression.

Files:

  • backend/tests/openapi_schemas_bdd.rs
**/*.{rs,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Group by feature, not layer—colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.

Files:

  • backend/tests/openapi_schemas_bdd.rs
**/*.{rs,ts,tsx,js,jsx,py,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use consistent spelling and grammar with en-GB-oxendict ("-ize" / "-yse" / "-our") spelling and grammar, except for references to external APIs.

Files:

  • backend/tests/openapi_schemas_bdd.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Run make fmt, make lint, and make test before committing Rust code; these wrap cargo fmt, cargo clippy, and cargo test.
Clippy warnings must be disallowed; fix any warnings emitted during tests in the code itself rather than silencing them.
For excessively long functions, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
For functions with too many parameters, group related parameters in meaningfully named structs.
Where a function returns a large error, consider using Arc to reduce the amount of data returned.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments, not before.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort; lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow when suppressing warnings.
Where a function is unused with specific features selected, use conditional compilation with #[cfg] or #[cfg_attr].
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single-line versions of functions where appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) }).
Write unit and behavioural tests for new Rust functionality; run both before and after making any change.
Use rstest fixtures for shared setup in Rust tests.
Replace duplicated tests with #[rstest(...)] parameterised cases in Rust.
Prefer mockall for mocks/stubs...

Files:

  • backend/tests/openapi_schemas_bdd.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • Adhere to single responsibility and CQRS
  • Place function attributes after doc comments.
  • Do not use return in single-line functions.
  • Move conditionals with >2 branches into a predicate function.
  • Avoid unsafe unless absolutely necessary.
  • Every module must begin with a //! doc comment that explains the module's purpose and utility.
  • Comments and docs must follow en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Lints must not be silenced except as a last resort.
    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.
  • Replace duplicated tests with #[rstest(...)] parameterised cases.
  • Prefer mockall for mocks/stubs.
  • Prefer .expect() over .unwrap() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • Ensure that any API or behavioural changes are reflected in the documentation in docs/
  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • backend/tests/openapi_schemas_bdd.rs
🧬 Code graph analysis (1)
backend/tests/openapi_schemas_bdd.rs (1)
backend/src/test_support.rs (2)
  • get_property (47-51)
  • unwrap_object_schema (19-42)
🔍 Remote MCP

The Ref tool is not properly configured. Let me try using web search to gather relevant technical context:Based on my search of relevant documentation, here is a summary of contextual information helpful for reviewing this PR:

Technical Context

Utoipa OpenAPI Schema Validation Framework

The utoipa crate provides auto-generated OpenAPI documentation for Rust REST APIs using a code-first approach with simple macros, and also contains Rust types of the OpenAPI spec allowing you to write the OpenAPI spec using Rust. This is the framework being enhanced in this PR.

Schema Constraint Support: Utoipa's ToSchema derive macro supports validation attributes including max_length, min_length, and pattern constraints on fields. This directly relates to the PR's changes adding constraints for display_name (min_length: 3, max_length: 32, pattern: "^[A-Za-z0-9_ ]+$").

Schema Format Types: Utoipa's KnownFormat enum includes a Uuid variant used with String values to indicate value is in UUID format, which aligns with the PR's addition of uuid format validation for the id field via SchemaFormat::Custom("uuid").

RefOr Pattern: Utoipa uses a RefOr pattern representing either a Ref or some other type T, which is the core pattern the PR's helper functions (unwrap_object_schema and get_property) work with to traverse schema definitions.

Cucumber BDD Testing Framework for Rust

Cucumber is a specification for running tests in a BDD (behavior-driven development) style workflow using Gherkin language for human-readable test syntax. Cucumber tests are more likely to take the form of integration, functional or E2E testing.

World Pattern: The World object holds the state of Cucumber tests during execution, which is the pattern the PR uses with OpenApiWorld to maintain test state for schema validation assertions.

Code Quality Context

Helper Function Consolidation: The PR's proposed refactoring with with_user_property_object_schema addresses identified code duplication in BDD step functions, which aligns with established testing best practices for eliminating repeated schema traversal logic.

Defensive Schema Handling: The enhancements to assert_object_schema_has_field to handle schema combinator types ($ref, AllOf, OneOf, AnyOf, Array) reflects best practices for robust schema inspection, preventing silent failures when schema structures don't match expectations.

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: build
🔇 Additional comments (4)
backend/tests/openapi_schemas_bdd.rs (4)

9-9: LGTM: Helper imports are correct.

The import of both get_property and unwrap_object_schema from test_support correctly addresses the past review feedback and provides the necessary helpers for the with_user_property_object_schema function.


54-98: LGTM: Excellent documentation and implementation.

The comprehensive doc comment and helper function successfully eliminate duplication whilst maintaining clarity. The generic closure pattern is idiomatic, the error messages are actionable, and the delegation to test_support helpers (lines 93-95) correctly centralises schema traversal logic.

Optional: If similar patterns emerge for Error or ErrorCode schema properties, extract a more generic with_schema_property_object_schema(schema_name, property_name, f) helper. However, the current specific implementation appropriately follows YAGNI until proven need arises.


172-182: LGTM: UUID format validation is correct.

The test properly validates the uuid format constraint using matches! with a guard pattern, which is idiomatic for checking both the enum variant and inner value. The helper function eliminates boilerplate whilst maintaining test clarity.


184-209: LGTM: Display name validation tests are correct and well-structured.

Both tests properly validate the schema constraints:

  • Length test (lines 184-198) asserts min_length=3 and max_length=32 with clear messages
  • Pattern test (lines 200-209) correctly uses .as_deref() for Option comparison

The consistent use of the helper function eliminates duplication whilst maintaining test clarity and focus.


Comment @coderabbitai help to get the list of available commands and usage tips.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • The OpenAPI User schema traversal logic is duplicated in multiple places (e.g. unwrap_object_schema in doc.rs tests and the BDD step definitions in openapi_schemas_bdd.rs); consider extracting a shared helper for resolving RefOr<Schema> to Object to keep the assertions DRY and easier to update if the schema shape changes.
  • assert_object_schema_has_field provides detailed diagnostics for non-Object schemas, while unwrap_object_schema and the BDD steps use simpler panic! messages; aligning these helpers (or reusing one in terms of the other) would give more consistent and descriptive failures when the schema is not an Object.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The OpenAPI User schema traversal logic is duplicated in multiple places (e.g. `unwrap_object_schema` in `doc.rs` tests and the BDD step definitions in `openapi_schemas_bdd.rs`); consider extracting a shared helper for resolving `RefOr<Schema>` to `Object` to keep the assertions DRY and easier to update if the schema shape changes.
- `assert_object_schema_has_field` provides detailed diagnostics for non-`Object` schemas, while `unwrap_object_schema` and the BDD steps use simpler `panic!` messages; aligning these helpers (or reusing one in terms of the other) would give more consistent and descriptive failures when the schema is not an `Object`.

## Individual Comments

### Comment 1
<location> `backend/src/doc.rs:162-179` </location>
<code_context>
+    }
+
+    #[test]
+    fn openapi_user_id_has_uuid_format() {
+        use utoipa::openapi::schema::SchemaFormat;
+
+        let doc = ApiDoc::openapi();
+        let schemas = &doc.components.as_ref().expect("components").schemas;
+        let user_schema = schemas.get(USER_SCHEMA_NAME).expect("User schema");
+        let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
+
+        let id_prop = obj.properties.get("id").expect("id property exists");
+        let id_obj = unwrap_object_schema(id_prop, "id");
+
+        // Schema format is set via #[schema(format = "uuid")] which produces Custom variant
</code_context>

<issue_to_address>
**suggestion (testing):** The UUID format assertion should likely target a string schema instead of unwrapping to an object.

Here you unwrap `id_prop` as an object and then read `id_obj.format`, but in utoipa a UUID `format` is attached to `Schema::String`, not `Object`. Instead, match on `RefOr::T(Schema::String(s))` (or use a small helper for string schemas) and assert on `s.format` so the test matches utoipa’s schema shape and avoids panics on non-object fields.

```suggestion
    #[test]
    fn openapi_user_id_has_uuid_format() {
        use utoipa::openapi::schema::{Schema, SchemaFormat};

        let doc = ApiDoc::openapi();
        let schemas = &doc.components.as_ref().expect("components").schemas;
        let user_schema = schemas.get(USER_SCHEMA_NAME).expect("User schema");
        let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);

        let id_prop = obj.properties.get("id").expect("id property exists");
        let id_schema = match id_prop {
            RefOr::T(Schema::String(s)) => s,
            _ => panic!("schema 'id' is not a String"),
        };

        // Schema format is set via #[schema(format = "uuid")] which produces Custom variant
        assert!(
            matches!(&id_schema.format, Some(SchemaFormat::Custom(s)) if s == "uuid"),
            "id should have format=uuid"
        );
    }
```
</issue_to_address>

### Comment 2
<location> `backend/src/doc.rs:182-191` </location>
<code_context>
+    }
+
+    #[test]
+    fn openapi_user_display_name_has_constraints() {
+        let doc = ApiDoc::openapi();
+        let schemas = &doc.components.as_ref().expect("components").schemas;
+        let user_schema = schemas.get(USER_SCHEMA_NAME).expect("User schema");
+        let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
+
+        let display_name_prop = obj
+            .properties
+            .get("display_name")
+            .expect("display_name property exists");
+        let display_name_obj = unwrap_object_schema(display_name_prop, "display_name");
+
+        assert_eq!(
</code_context>

<issue_to_address>
**suggestion (testing):** Length and pattern checks on `display_name` should probably use the string schema variant rather than forcing an object.

Because `display_name` is a `String` with schema attributes, utoipa will typically produce a `Schema::String` with `min_length`, `max_length`, and `pattern` set directly, not an `Object`. Forcing an object here could panic if the schema shape changes. Consider either:
- a helper that matches `Schema::String` and asserts `min_length`/`max_length`/`pattern`, or
- a helper that can handle both string and object schemas.

That way the test remains robust to the actual schema representation of this field.

Suggested implementation:

```rust
        let display_name_prop = obj
            .properties
            .get("display_name")
            .expect("display_name property exists");

        match display_name_prop {
            utoipa::openapi::schema::Schema::String(string_schema) => {
                assert_eq!(
                    string_schema.min_length,
                    Some(3),
                    "display_name should have min_length=3"
                );
                assert_eq!(
                    string_schema.max_length,
                    Some(32),
                    "display_name should have max_length=32"
                );
                assert!(
                    string_schema.pattern.is_some(),
                    "display_name should have a pattern constraint"
                );
            }
            utoipa::openapi::schema::Schema::Object(obj_schema) => {
                assert_eq!(
                    obj_schema.min_length,
                    Some(3),
                    "display_name should have min_length=3"
                );
                assert_eq!(
                    obj_schema.max_length,
                    Some(32),
                    "display_name should have max_length=32"
                );
                assert!(
                    obj_schema.pattern.is_some(),
                    "display_name should have a pattern constraint"
                );
            }
            other => panic!(
                "display_name should be represented as a string or object schema; got {:?}",
                other
            ),
        }

```

1. If there are any remaining assertions below this snippet that still reference `display_name_obj` or assume an object schema, update them to:
   - either be removed (if redundant with the new checks), or
   - be moved into the `match` arms, using `string_schema` / `obj_schema` as appropriate.
2. If you want to assert the exact pattern rather than just "some pattern", replace the `pattern.is_some()` assertions with `assert_eq!(..., Some("your-regex-here".to_string()), "...")` in both match arms.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread backend/src/doc.rs
Comment thread backend/src/doc.rs
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread backend/src/doc.rs
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Dec 19, 2025

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

backend/tests/openapi_schemas_bdd.rs

Comment on lines +157 to +193

fn user_display_name_has_length_constraints(world: &Mutex<OpenApiWorld>) {
    use utoipa::openapi::schema::Schema;
    use utoipa::openapi::RefOr;

    let world = world.lock().expect("world lock");
    let doc = world.document.as_ref().expect("document generated");
    let components = doc.components.as_ref().expect("components present");
    let user_schema = components
        .schemas
        .get(USER_SCHEMA_NAME)
        .expect("User schema");

    let obj = match user_schema {
        RefOr::T(Schema::Object(obj)) => obj,
        _ => panic!("User schema is not an Object"),
    };

    let display_name_prop = obj
        .properties
        .get("display_name")
        .expect("display_name property");
    let display_name_obj = match display_name_prop {
        RefOr::T(Schema::Object(obj)) => obj,
        _ => panic!("display_name property is not an Object"),
    };

    assert_eq!(
        display_name_obj.min_length,
        Some(3),
        "User.display_name should have min_length=3"
    );
    assert_eq!(
        display_name_obj.max_length,
        Some(32),
        "User.display_name should have max_length=32"
    );
}

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: user_display_name_has_length_constraints,user_display_name_has_pattern_constraint

@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos force-pushed the domain-ports-feedback branch from bf09afb to c494182 Compare December 19, 2025 15:24
codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
backend/tests/openapi_schemas_bdd.rs (2)

129-196: Verify that string properties are correctly handled as Object schemas.

Past reviewers raised concerns that UserSchema defines id and display_name as String fields (lines 77, 90 in backend/src/inbound/http/schemas.rs), and utoipa should emit Schema::String for these properties, not Schema::Object. If that's the case, unwrap_object_schema will panic on every test run.

Confirm that the tests pass and that utoipa v5.0.0 generates Object schemas (with format, min_length, max_length, pattern fields) for string properties with validation constraints. If the tests panic, refactor to match Schema::String instead.

Run the following to verify test behaviour:

#!/bin/bash
# Verify the new OpenAPI schema validation tests execute without panicking
cd backend
cargo test --test openapi_schemas_bdd -- --nocapture

151-196: Extract shared schema traversal logic.

The two functions user_display_name_has_length_constraints and user_display_name_has_pattern_constraint share nearly identical structure (lock world, retrieve document, get User schema, unwrap to object, get display_name property). Extract a helper function that accepts a closure to eliminate duplication and reduce maintenance burden.

Proposed refactor with helper function

Add this helper after line 56:

+/// Invoke closure with User display_name Object schema.
+fn with_user_property_object_schema<F>(
+    world: &Mutex<OpenApiWorld>,
+    property_name: &str,
+    f: F,
+) where
+    F: FnOnce(&utoipa::openapi::schema::Object),
+{
+    let world = world.lock().expect("world lock");
+    let doc = world.document.as_ref().expect("document generated");
+    let components = doc.components.as_ref().expect("components present");
+    let user_schema = components
+        .schemas
+        .get(USER_SCHEMA_NAME)
+        .expect("User schema");
+    let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
+    let property_obj = unwrap_object_schema(get_property(obj, property_name), property_name);
+    f(property_obj);
+}

Refactor the three test functions:

 #[then("the User id field has uuid format")]
 fn user_id_has_uuid_format(world: &Mutex<OpenApiWorld>) {
     use utoipa::openapi::schema::SchemaFormat;
-
-    let world = world.lock().expect("world lock");
-    let doc = world.document.as_ref().expect("document generated");
-    let components = doc.components.as_ref().expect("components present");
-    let user_schema = components
-        .schemas
-        .get(USER_SCHEMA_NAME)
-        .expect("User schema");
-
-    let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
-    let id_obj = unwrap_object_schema(get_property(obj, "id"), "User.id");
-
-    // Schema format is set via #[schema(format = "uuid")] which produces Custom variant
-    assert!(
-        matches!(&id_obj.format, Some(SchemaFormat::Custom(s)) if s == "uuid"),
-        "User.id should have format=uuid"
-    );
+    with_user_property_object_schema(world, "id", |id_obj| {
+        assert!(
+            matches!(&id_obj.format, Some(SchemaFormat::Custom(s)) if s == "uuid"),
+            "User.id should have format=uuid"
+        );
+    });
 }

 #[then("the User display_name field has length constraints")]
 fn user_display_name_has_length_constraints(world: &Mutex<OpenApiWorld>) {
-    let world = world.lock().expect("world lock");
-    let doc = world.document.as_ref().expect("document generated");
-    let components = doc.components.as_ref().expect("components present");
-    let user_schema = components
-        .schemas
-        .get(USER_SCHEMA_NAME)
-        .expect("User schema");
-
-    let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
-    let display_name_obj =
-        unwrap_object_schema(get_property(obj, "display_name"), "User.display_name");
-
-    assert_eq!(
-        display_name_obj.min_length,
-        Some(3),
-        "User.display_name should have min_length=3"
-    );
-    assert_eq!(
-        display_name_obj.max_length,
-        Some(32),
-        "User.display_name should have max_length=32"
-    );
+    with_user_property_object_schema(world, "display_name", |display_name_obj| {
+        assert_eq!(
+            display_name_obj.min_length,
+            Some(3),
+            "User.display_name should have min_length=3"
+        );
+        assert_eq!(
+            display_name_obj.max_length,
+            Some(32),
+            "User.display_name should have max_length=32"
+        );
+    });
 }

 #[then("the User display_name field has pattern constraint")]
 fn user_display_name_has_pattern_constraint(world: &Mutex<OpenApiWorld>) {
-    let world = world.lock().expect("world lock");
-    let doc = world.document.as_ref().expect("document generated");
-    let components = doc.components.as_ref().expect("components present");
-    let user_schema = components
-        .schemas
-        .get(USER_SCHEMA_NAME)
-        .expect("User schema");
-
-    let obj = unwrap_object_schema(user_schema, USER_SCHEMA_NAME);
-    let display_name_obj =
-        unwrap_object_schema(get_property(obj, "display_name"), "User.display_name");
-
-    assert_eq!(
-        display_name_obj.pattern.as_deref(),
-        Some("^[A-Za-z0-9_ ]+$"),
-        "User.display_name should have pattern constraint"
-    );
+    with_user_property_object_schema(world, "display_name", |display_name_obj| {
+        assert_eq!(
+            display_name_obj.pattern.as_deref(),
+            Some("^[A-Za-z0-9_ ]+$"),
+            "User.display_name should have pattern constraint"
+        );
+    });
 }
backend/src/doc.rs (1)

182-229: Verify that string properties are correctly handled as Object schemas.

Past reviewers flagged that UserSchema defines id and display_name as String fields with value_type = String (backend/src/inbound/http/schemas.rs lines 73-74, 84), and utoipa should emit Schema::String for these properties. If that's the case, unwrap_object_schema will panic when called on these properties.

Confirm that the tests pass and that utoipa v5.0.0 generates Object schemas (with format, min_length, max_length, pattern fields) for string properties with validation constraints. If the tests panic, refactor to match Schema::String and read from string_schema.format, string_schema.min_length, etc.

Run the following to verify test behaviour:

#!/bin/bash
# Verify the new OpenAPI schema validation tests execute without panicking
cd backend
cargo test --lib doc::tests::openapi_user_id_has_uuid_format -- --nocapture
cargo test --lib doc::tests::openapi_user_display_name_has_constraints -- --nocapture
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a437a9 and c494182.

📒 Files selected for processing (6)
  • backend/src/doc.rs (3 hunks)
  • backend/src/inbound/http/schemas.rs (3 hunks)
  • backend/tests/features/openapi_schemas.feature (1 hunks)
  • backend/tests/openapi_schemas_bdd.rs (2 hunks)
  • backend/tests/openapi_support.rs (1 hunks)
  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{rs,ts,tsx,js,jsx,py,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use consistent spelling and grammar with en-GB-oxendict ("-ize" / "-yse" / "-our") spelling and grammar, except for references to external APIs.

Files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md
  • backend/src/inbound/http/schemas.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/tests/openapi_support.rs
  • backend/src/doc.rs
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/**/*.md: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update documentation in docs/ when new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve to ensure accuracy and currency.
Documentation must use en-GB-oxendict ("-ize" / "-yse" / "-our") spelling and grammar, with the exception of the "LICENSE" file which should remain unchanged.

Follow the Documentation style guide for clear, consistent documentation conventions

Files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns; code blocks at 120 columns; tables and headings must not be wrapped.
Use dashes (-) for list bullets in Markdown.
Use GitHub-flavoured Markdown footnotes ([^1]) for references and footnotes.

Files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md

⚙️ CodeRabbit configuration file

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md
**/*.{rs,ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,ts,tsx,js,jsx,py}: Comment why, not what—explain assumptions, edge cases, trade-offs, or complexity; do not echo the obvious.
Favour clarity over cleverness—be concise but prefer explicit over terse or obscure idioms; prioritise code that is easy to follow.
Use functions and composition to avoid repetition; prefer generators or comprehensions and declarative code to imperative repetition when readable.
Keep functions small and meaningful—single responsibility, clear purpose, and obey command/query segregation.
Name things precisely—use clear, descriptive variable and function names; for booleans, prefer names with is, has, or should.
Structure logically—each file should encapsulate a coherent module; group related code close together.
Illustrate with clear examples in function documentation demonstrating usage and outcome; for tests, omit examples where the example only reiterates test logic.
Keep file size manageable—no single code file may exceed 400 lines; break up long switch statements and move large test data blocks to external files.
New functionality or changes in behaviour must be fully validated by relevant unittests and behavioural tests before committing.
When fixing a bug, provide a unittest demonstrating the corrected behaviour to validate the fix and guard against regression.

Files:

  • backend/src/inbound/http/schemas.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/tests/openapi_support.rs
  • backend/src/doc.rs
**/*.{rs,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Group by feature, not layer—colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.

Files:

  • backend/src/inbound/http/schemas.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/tests/openapi_support.rs
  • backend/src/doc.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Run make fmt, make lint, and make test before committing Rust code; these wrap cargo fmt, cargo clippy, and cargo test.
Clippy warnings must be disallowed; fix any warnings emitted during tests in the code itself rather than silencing them.
For excessively long functions, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
For functions with too many parameters, group related parameters in meaningfully named structs.
Where a function returns a large error, consider using Arc to reduce the amount of data returned.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments, not before.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort; lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow when suppressing warnings.
Where a function is unused with specific features selected, use conditional compilation with #[cfg] or #[cfg_attr].
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single-line versions of functions where appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) }).
Write unit and behavioural tests for new Rust functionality; run both before and after making any change.
Use rstest fixtures for shared setup in Rust tests.
Replace duplicated tests with #[rstest(...)] parameterised cases in Rust.
Prefer mockall for mocks/stubs...

Files:

  • backend/src/inbound/http/schemas.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/tests/openapi_support.rs
  • backend/src/doc.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • Adhere to single responsibility and CQRS
  • Place function attributes after doc comments.
  • Do not use return in single-line functions.
  • Move conditionals with >2 branches into a predicate function.
  • Avoid unsafe unless absolutely necessary.
  • Every module must begin with a //! doc comment that explains the module's purpose and utility.
  • Comments and docs must follow en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Lints must not be silenced except as a last resort.
    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.
  • Replace duplicated tests with #[rstest(...)] parameterised cases.
  • Prefer mockall for mocks/stubs.
  • Prefer .expect() over .unwrap() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • Ensure that any API or behavioural changes are reflected in the documentation in docs/
  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • backend/src/inbound/http/schemas.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/tests/openapi_support.rs
  • backend/src/doc.rs
🧠 Learnings (2)
📚 Learning: 2025-12-14T12:57:20.659Z
Learnt from: leynos
Repo: leynos/wildside PR: 253
File: docs/wildside-pwa-design.md:28-30
Timestamp: 2025-12-14T12:57:20.659Z
Learning: In the leynos/wildside repository, documentation should follow en-GB-oxendict spelling standards that require -ize endings for localization-related terms: use 'localization', 'localizability', and 'localizable' (not -ise variants). Apply this guideline to all Markdown documentation files under the docs/ directory and any future docs as they are added.

Applied to files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md
📚 Learning: 2025-12-14T12:57:30.806Z
Learnt from: leynos
Repo: leynos/wildside PR: 253
File: docs/wildside-pwa-data-model.md:156-158
Timestamp: 2025-12-14T12:57:30.806Z
Learning: Adopt en-GB-oxendict spelling in all Wildside documentation. Use -ize endings (e.g., localize, localization, localized) instead of -ise endings (e.g., localise) wherever the en-GB-oxendict style guide applies. Apply this consistently across all docs under the docs directory.

Applied to files:

  • docs/execplans/phase-0-update-modules-to-use-domain-ports.md
🧬 Code graph analysis (4)
backend/src/inbound/http/schemas.rs (2)
backend/src/domain/error.rs (1)
  • code (105-107)
backend/src/domain/user_events.rs (1)
  • code (40-45)
backend/tests/openapi_schemas_bdd.rs (1)
backend/tests/openapi_support.rs (2)
  • get_property (42-46)
  • unwrap_object_schema (14-37)
backend/tests/openapi_support.rs (1)
backend/src/doc.rs (1)
  • unwrap_object_schema (154-180)
backend/src/doc.rs (2)
backend/src/domain/user_events.rs (1)
  • field (34-36)
backend/tests/openapi_support.rs (1)
  • unwrap_object_schema (14-37)
🔍 Remote MCP

Based on the search results, I've found helpful context about Utoipa and OpenAPI schema validation. Let me gather additional information specific to this codebase's testing patterns.## Summary of Key Context Found

Utoipa Framework & OpenAPI Schema Validation

Utoipa provides auto-generated OpenAPI documentation for Rust REST APIs and treats code-first approach as a first class citizen, simplifying API documentation by providing simple macros for generating documentation from code. Utoipa supports validation attributes on schema fields, allowing you to define constraints like maximum/minimum values, max_length/min_length, and pattern matching, which aligns directly with this PR's testing of UserSchema constraints.

Utoipa has specific support for uuid format—Uuid type will be presented as String with format uuid in OpenAPI spec. This is directly relevant to the PR's test openapi_user_id_has_uuid_format that validates the id property has uuid-like custom format.

BDD Testing with Cucumber-rs

Cucumber is a tool for behavior-driven development (BDD) that uses Gherkin language to specify test scenarios with syntax close to natural language, using keywords such as When and Then. This context is useful for understanding the BDD scenario added in backend/tests/features/openapi_schemas.feature. The PR's use of Cucumber tests to validate OpenAPI schema constraints follows standard BDD practices.

Exhaustive Pattern Matching & Compile-time Guarantees

Exhaustive checking via match in Rust ensures all possible variants are handled, reducing bugs, and adding a new variant to an enum will cause a compile-time error if not handled, prompting methodical updates. This directly supports the PR's refactoring of the ErrorCode serialization test to use exhaustive pattern matching over a compile-time-exhaustive variants array—a key safety improvement that ensures developers won't accidentally miss new ErrorCode variants when they're added.

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: build
🔇 Additional comments (7)
docs/execplans/phase-0-update-modules-to-use-domain-ports.md (1)

13-14: LGTM: Corrected terminology.

The fix from "Open API Specification" to "OpenAPI Specification" aligns with official naming conventions.

backend/src/inbound/http/schemas.rs (3)

80-82: LGTM: Clarified validation layer separation.

The updated documentation correctly distinguishes schema-level constraints from domain-level validation, making it clear that non-empty-when-trimmed is a domain concern separate from the 3–32 character schema constraint.


99-99: LGTM: Corrected spelling.

Changed "serialises" to "serializes" per en-GB-oxendict standards.


167-198: LGTM: Exhaustive pattern matching strengthens compile-time guarantees.

The refactored test now uses a helper function with exhaustive pattern matching, ensuring that adding a new ErrorCode variant will trigger a build error until the test is updated. This is a significant improvement over the previous static array approach.

backend/tests/features/openapi_schemas.feature (1)

23-28: LGTM: Added comprehensive validation constraint scenario.

The new scenario exercises User schema constraints (uuid format for id, length and pattern for display_name) via BDD steps, improving test coverage.

backend/src/doc.rs (1)

86-128: LGTM: Improved diagnostic messages for schema type mismatches.

The updated assert_object_schema_has_field now handles $ref, AllOf, OneOf, AnyOf, and Array cases with clear diagnostic messages, making test failures easier to diagnose and fix.

backend/tests/openapi_support.rs (1)

14-46: LGTM: Clear diagnostic helpers for schema traversal.

The unwrap_object_schema and get_property helpers provide helpful diagnostic messages for schema type mismatches. However, verify that utoipa v5.0.0 generates Object schemas (rather than String schemas) for string properties with validation constraints, as flagged in the reviews for backend/src/doc.rs and backend/tests/openapi_schemas_bdd.rs.

Comment thread backend/src/doc.rs Outdated
Replace separate openapi_support module with inline with_user_property_object_schema
helper that accepts a closure. This eliminates code duplication while keeping the
navigation logic self-contained in the test file.

Also align unwrap_object_schema in doc.rs to have detailed diagnostics matching
assert_object_schema_has_field for consistent failure messages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@leynos leynos force-pushed the domain-ports-feedback branch from c494182 to d3de032 Compare December 19, 2025 15:31
Creates backend/src/test_support.rs with unwrap_object_schema helper
that can be used by both unit tests in doc.rs and integration tests.
Eliminates duplicate implementations across test files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3de032 and aad6327.

📒 Files selected for processing (4)
  • backend/src/doc.rs (4 hunks)
  • backend/src/lib.rs (1 hunks)
  • backend/src/test_support.rs (1 hunks)
  • backend/tests/openapi_schemas_bdd.rs (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rs,ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,ts,tsx,js,jsx,py}: Comment why, not what—explain assumptions, edge cases, trade-offs, or complexity; do not echo the obvious.
Favour clarity over cleverness—be concise but prefer explicit over terse or obscure idioms; prioritise code that is easy to follow.
Use functions and composition to avoid repetition; prefer generators or comprehensions and declarative code to imperative repetition when readable.
Keep functions small and meaningful—single responsibility, clear purpose, and obey command/query segregation.
Name things precisely—use clear, descriptive variable and function names; for booleans, prefer names with is, has, or should.
Structure logically—each file should encapsulate a coherent module; group related code close together.
Illustrate with clear examples in function documentation demonstrating usage and outcome; for tests, omit examples where the example only reiterates test logic.
Keep file size manageable—no single code file may exceed 400 lines; break up long switch statements and move large test data blocks to external files.
New functionality or changes in behaviour must be fully validated by relevant unittests and behavioural tests before committing.
When fixing a bug, provide a unittest demonstrating the corrected behaviour to validate the fix and guard against regression.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs
**/*.{rs,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Group by feature, not layer—colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs
**/*.{rs,ts,tsx,js,jsx,py,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use consistent spelling and grammar with en-GB-oxendict ("-ize" / "-yse" / "-our") spelling and grammar, except for references to external APIs.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Run make fmt, make lint, and make test before committing Rust code; these wrap cargo fmt, cargo clippy, and cargo test.
Clippy warnings must be disallowed; fix any warnings emitted during tests in the code itself rather than silencing them.
For excessively long functions, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
For functions with too many parameters, group related parameters in meaningfully named structs.
Where a function returns a large error, consider using Arc to reduce the amount of data returned.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments, not before.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort; lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow when suppressing warnings.
Where a function is unused with specific features selected, use conditional compilation with #[cfg] or #[cfg_attr].
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single-line versions of functions where appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) }).
Write unit and behavioural tests for new Rust functionality; run both before and after making any change.
Use rstest fixtures for shared setup in Rust tests.
Replace duplicated tests with #[rstest(...)] parameterised cases in Rust.
Prefer mockall for mocks/stubs...

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • Adhere to single responsibility and CQRS
  • Place function attributes after doc comments.
  • Do not use return in single-line functions.
  • Move conditionals with >2 branches into a predicate function.
  • Avoid unsafe unless absolutely necessary.
  • Every module must begin with a //! doc comment that explains the module's purpose and utility.
  • Comments and docs must follow en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Lints must not be silenced except as a last resort.
    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.
  • Replace duplicated tests with #[rstest(...)] parameterised cases.
  • Prefer mockall for mocks/stubs.
  • Prefer .expect() over .unwrap() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • Ensure that any API or behavioural changes are reflected in the documentation in docs/
  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs
🧠 Learnings (1)
📚 Learning: 2025-12-19T16:24:57.331Z
Learnt from: leynos
Repo: leynos/wildside PR: 261
File: backend/src/doc.rs:191-193
Timestamp: 2025-12-19T16:24:57.331Z
Learning: In utoipa 5.x, there is no Schema::String variant. All primitive types, including strings, are represented as Schema::Object with a schema_type field (e.g., SchemaType::String). String constraints like format, min_length, max_length, and pattern are fields on the Object struct itself. When reviewing Rust code that uses utoipa, verify that string fields are modeled as Schema::Object with schema_type = String and that constraints are applied on the Object, not on a non-existent Schema::String variant.

Applied to files:

  • backend/src/lib.rs
  • backend/src/doc.rs
  • backend/src/test_support.rs
🧬 Code graph analysis (2)
backend/tests/openapi_schemas_bdd.rs (1)
backend/src/test_support.rs (1)
  • unwrap_object_schema (19-42)
backend/src/doc.rs (1)
backend/src/test_support.rs (1)
  • unwrap_object_schema (19-42)
🔍 Remote MCP

Based on my research, I've found valuable context about OpenAPI schema validation patterns in Rust. Let me summarize the relevant findings for reviewing this PR:

Summary of Additional Context for PR #261 Review

OpenAPI Schema Testing and Validation Patterns

Utoipa provides auto-generated OpenAPI documentation for Rust REST APIs by treating a code-first approach as a first-class citizen and simplifying API documentation through simple macros. It also contains Rust types of the OpenAPI spec, allowing you to write the OpenAPI spec using Rust if auto generation is not appropriate.

Schema Validation Attributes in Utoipa

The PR's focus on adding validation constraints to the User schema aligns with Utoipa's built-in support for schema validation. Utoipa supports validation attributes such as max_length, min_length, and pattern constraints on string fields. For the User schema specifically:

  • Display name constraints: min_length (3) and max_length (32) constraints can be applied to string fields
  • ID format handling: Uuid type will be presented as String with format uuid in OpenAPI spec when uuid support is enabled

Test Helper Pattern Validation

The PR's approach of creating test-support helpers to unwrap and inspect OpenAPI schemas follows good practices for schema validation. Generating documentation from code alone doesn't guarantee correctness—despite Rust's strong type system, issues can arise such as mapping wrong request body types to endpoints or providing invalid example values, so validation of actual schema structure is needed.

Code Duplication Refactoring Context

The code review comment about duplicated navigation logic in BDD steps is valid—centralizing schema navigation patterns improves maintainability. The proposed helper function pattern with_user_property_object_schema(world, property_name, f) to extract shared traversal logic (accessing User schema → finding property → matching as Object → passing to closure) is a sound refactoring approach for BDD test code.

[::web_search::]

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: build
🔇 Additional comments (4)
backend/tests/openapi_schemas_bdd.rs (1)

151-188: LGTM—correct Schema::Object usage and clear assertions.

These Then step functions correctly:

  • Use unwrap_object_schema to extract Object schemas (no Schema::String assumption)
  • Assert UUID format via SchemaFormat::Custom("uuid") per utoipa 5.x
  • Validate min_length, max_length, and pattern constraints on the Object

The with_user_property_object_schema helper cleanly centralises navigation logic and the closures remain focused on assertions.

Based on learnings, utoipa 5.x represents all primitives as Schema::Object with constraints on the Object struct itself.

backend/src/doc.rs (2)

86-130: Enhanced diagnostics improve test maintainability.

Adding the schema_name parameter and expanding match arms for all Schema variants (Ref, AllOf, OneOf, AnyOf, Array) provides clear, actionable panic messages. The function now guides developers towards the correct inspection strategy for each schema type.

The repetitive structure of the combinator panic messages (lines 106-123) could be factored into a helper, but for test code the explicit patterns aid clarity.


152-199: New tests correctly validate OpenAPI constraints per utoipa 5.x.

Both tests appropriately:

  • Use unwrap_object_schema to extract nested Object schemas
  • Check constraints on the Object struct (format, min_length, max_length, pattern)
  • Use matches! for SchemaFormat::Custom("uuid") validation
  • Assert exact expected values with clear failure messages

This aligns with the learnings that utoipa 5.x represents all primitives as Schema::Object with a schema_type field, not as Schema::String variants.

Based on learnings, utoipa 5.x has no Schema::String variant; string constraints are fields on Schema::Object.

backend/src/test_support.rs (1)

1-52: Well-structured test utilities with clear diagnostics.

This module appropriately:

  • Documents its purpose and scope (unit and integration tests)
  • Provides focused helpers for OpenAPI schema traversal
  • Panics with actionable messages for refs, combinators, arrays, and unexpected types
  • Uses correct utoipa 5.x Schema enum variants (Object, Array, OneOf, AllOf, AnyOf)

The unwrap_object_schema function correctly returns &Object for Schema::Object, matching the learnings that utoipa 5.x has no Schema::String variant. The get_property helper encapsulates property access with clear diagnostics.

Both functions use .unwrap_or_else(|| panic!(...)) for custom messages, which is appropriate for test utilities where panics indicate test-author errors rather than runtime failures.

Based on learnings, the Schema enum handling is correct for utoipa 5.x (Object, Array, combinators only).

Comment thread backend/src/lib.rs
Comment thread backend/tests/openapi_schemas_bdd.rs Outdated
…helper

- Guard test_support module with #[cfg(any(test, feature = "test-support"))]
  to prevent test utilities from leaking into production builds
- Add test-support feature to backend/Cargo.toml
- Import and use get_property helper in BDD tests to simplify property access
  and provide consistent panic diagnostics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Dec 19, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Dec 19, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Dec 19, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 19, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aad6327 and 28e89c6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • backend/Cargo.toml (1 hunks)
  • backend/src/lib.rs (1 hunks)
  • backend/tests/openapi_schemas_bdd.rs (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rs,ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,ts,tsx,js,jsx,py}: Comment why, not what—explain assumptions, edge cases, trade-offs, or complexity; do not echo the obvious.
Favour clarity over cleverness—be concise but prefer explicit over terse or obscure idioms; prioritise code that is easy to follow.
Use functions and composition to avoid repetition; prefer generators or comprehensions and declarative code to imperative repetition when readable.
Keep functions small and meaningful—single responsibility, clear purpose, and obey command/query segregation.
Name things precisely—use clear, descriptive variable and function names; for booleans, prefer names with is, has, or should.
Structure logically—each file should encapsulate a coherent module; group related code close together.
Illustrate with clear examples in function documentation demonstrating usage and outcome; for tests, omit examples where the example only reiterates test logic.
Keep file size manageable—no single code file may exceed 400 lines; break up long switch statements and move large test data blocks to external files.
New functionality or changes in behaviour must be fully validated by relevant unittests and behavioural tests before committing.
When fixing a bug, provide a unittest demonstrating the corrected behaviour to validate the fix and guard against regression.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
**/*.{rs,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Group by feature, not layer—colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
**/*.{rs,ts,tsx,js,jsx,py,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use consistent spelling and grammar with en-GB-oxendict ("-ize" / "-yse" / "-our") spelling and grammar, except for references to external APIs.

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Run make fmt, make lint, and make test before committing Rust code; these wrap cargo fmt, cargo clippy, and cargo test.
Clippy warnings must be disallowed; fix any warnings emitted during tests in the code itself rather than silencing them.
For excessively long functions, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
For functions with too many parameters, group related parameters in meaningfully named structs.
Where a function returns a large error, consider using Arc to reduce the amount of data returned.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments, not before.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort; lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow when suppressing warnings.
Where a function is unused with specific features selected, use conditional compilation with #[cfg] or #[cfg_attr].
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single-line versions of functions where appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) }).
Write unit and behavioural tests for new Rust functionality; run both before and after making any change.
Use rstest fixtures for shared setup in Rust tests.
Replace duplicated tests with #[rstest(...)] parameterised cases in Rust.
Prefer mockall for mocks/stubs...

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • Adhere to single responsibility and CQRS
  • Place function attributes after doc comments.
  • Do not use return in single-line functions.
  • Move conditionals with >2 branches into a predicate function.
  • Avoid unsafe unless absolutely necessary.
  • Every module must begin with a //! doc comment that explains the module's purpose and utility.
  • Comments and docs must follow en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Lints must not be silenced except as a last resort.
    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.
  • Replace duplicated tests with #[rstest(...)] parameterised cases.
  • Prefer mockall for mocks/stubs.
  • Prefer .expect() over .unwrap() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • Ensure that any API or behavioural changes are reflected in the documentation in docs/
  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • backend/src/lib.rs
  • backend/tests/openapi_schemas_bdd.rs
🧠 Learnings (1)
📚 Learning: 2025-12-19T16:24:57.331Z
Learnt from: leynos
Repo: leynos/wildside PR: 261
File: backend/src/doc.rs:191-193
Timestamp: 2025-12-19T16:24:57.331Z
Learning: In utoipa 5.x, there is no Schema::String variant. All primitive types, including strings, are represented as Schema::Object with a schema_type field (e.g., SchemaType::String). String constraints like format, min_length, max_length, and pattern are fields on the Object struct itself. When reviewing Rust code that uses utoipa, verify that string fields are modeled as Schema::Object with schema_type = String and that constraints are applied on the Object, not on a non-existent Schema::String variant.

Applied to files:

  • backend/src/lib.rs
🧬 Code graph analysis (1)
backend/tests/openapi_schemas_bdd.rs (1)
backend/src/test_support.rs (2)
  • get_property (47-51)
  • unwrap_object_schema (19-42)
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (6)
backend/Cargo.toml (2)

53-54: LGTM: Standard feature flag pattern.

The test-support feature is correctly defined for conditional compilation of test utilities.


57-58: LGTM: Correct self-referential dev-dependency pattern.

Enabling the test-support feature in dev-dependencies allows integration tests to access test utilities whilst keeping them out of production builds.

backend/src/lib.rs (1)

13-14: LGTM: Correctly implements conditional compilation for test utilities.

The cfg gate ensures test_support is only available during tests or when the test-support feature is explicitly enabled, preventing test utilities from leaking into production builds whilst making them accessible to integration tests.

backend/tests/openapi_schemas_bdd.rs (3)

9-9: LGTM: Correct import of test utilities.

Both helpers are used by the with_user_property_object_schema function to simplify schema navigation.


146-156: LGTM: UUID format validation is correct.

The test correctly validates that User.id has format=uuid using matches! with a pattern guard, aligning with utoipa 5.x schema representation.


158-183: LGTM: Length and pattern constraints correctly validated.

Both test steps properly validate User.display_name schema constraints:

  • min_length=3 and max_length=32 are correctly asserted
  • Pattern constraint "^[A-Za-z0-9_ ]+$" is correctly validated using as_deref()

The tests align with the domain validation rules and provide clear assertion messages.

Comment thread backend/tests/openapi_schemas_bdd.rs Outdated
Documents the helper's purpose, parameters, usage pattern, and includes
an example to guide future contributors on when and how to use it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@leynos leynos merged commit 0e40e2a into main Dec 19, 2025
4 checks passed
@leynos leynos deleted the domain-ports-feedback branch December 19, 2025 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant