Address code review feedback for domain ports PR#259
Conversation
- Add schema constraints to UserSchema matching domain invariants: - id: format=uuid - display_name: minLength=3, maxLength=32, pattern for allowed chars - Add ErrorCode sync test verifying domain serialization matches schema - Consolidate OpenAPI tests: remove duplicates from doc.rs covered by BDD - Refactor remaining doc.rs tests to use structured Schema inspection - Define OpenAPI acronym on first use in exec plan documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reviewer's GuideRefines OpenAPI-related schemas and tests to better align HTTP layer constraints with domain invariants, consolidates redundant OpenAPI tests in favor of BDD coverage, and tightens documentation wording around OpenAPI usage. Class diagram for updated OpenAPI HTTP schemas and ErrorCode enumclassDiagram
class UserSchema {
+String id
+String display_name
}
class ErrorSchema {
+String code
+String message
}
class ErrorCode {
<<enum>>
InvalidRequest
Unauthorized
Forbidden
NotFound
InternalError
}
ErrorSchema --> ErrorCode : uses
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Summary by CodeRabbitRelease Notes
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughRefactors test assertions within the documentation module to validate schema fields directly rather than inspecting serialised JSON. Enriches user schema definitions with UUID formatting and display name validation constraints (length and pattern). Adds a new test verifying error code serialisation consistency. Updates planning documentation with clarified OpenAPI terminology. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (6)**/*.{rs,ts,tsx,js,jsx,py,md}📄 CodeRabbit inference engine (AGENTS.md)
Files:
docs/**/*.md📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.md📄 CodeRabbit inference engine (AGENTS.md)
Files:
⚙️ CodeRabbit configuration file
Files:
**/*.{rs,ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{rs,ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.rs📄 CodeRabbit inference engine (AGENTS.md)
Files:
⚙️ CodeRabbit configuration file
Files:
🧠 Learnings (2)📚 Learning: 2025-12-14T12:57:20.659ZApplied to files:
📚 Learning: 2025-12-14T12:57:30.806ZApplied to files:
🔍 Remote MCP RefNow let me search for more information about the test refactoring pattern and domain-driven design related to the PR:Now I have gathered sufficient context. Let me compile the findings into a focused summary for the PR review. Summary of Additional Context for PR #259 ReviewBased on comprehensive research of the relevant technologies and patterns, here is the additional context that would help in reviewing this PR: 1. Utoipa Schema Constraints ImplementationUtoipa supports Key validation point: The maximum length of a schema cannot be less than the minimum length—if a minimum length is specified, the maximum length must be greater than or equal to that minimum length. The PR sets min_length=3 and max_length=32 for display_name, which satisfies this requirement. 2. UUID Format in OpenAPIThe uuid format represents a Universally Unique IDentifier as defined in RFC4122. OpenAPI supports formats like "uuid" even though they may be undefined by the specification, and tools can use these formats for documentation purposes. Using 3. Domain-Driven Design with Ports & Adapters ContextThe PR title references "domain ports," which aligns with hexagonal architecture principles. Hexagonal architecture isolates business logic from infrastructure code, with the application communicating with external components through interfaces called ports, using adapters to translate technical exchanges. Creating stronger types (like domain objects) for validation can introduce a place for validation and improves expressiveness of ports. The PR's schema constraints directly support this pattern by ensuring OpenAPI adapters accurately reflect domain invariants (3-32 char display names, UUID IDs). 4. Test Refactoring ApproachThe PR consolidates tests by removing duplicates covered by external BDD tests and refactoring 5. ErrorCode Serialization SyncThe new test ⏰ 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)
🔇 Additional comments (7)
Comment |
There was a problem hiding this comment.
Hey there - I've reviewed your changes - here's some feedback:
- The
display_nameschema comment says the value is trimmed but the regex^[A-Za-z0-9_ ]+$still allows leading/trailing and multiple spaces; either tighten the pattern (e.g., disallow leading/trailing spaces) or relax the comment so it matches what the schema actually enforces. - The
error_code_schema_matches_domain_serializationtest won’t fail automatically when newErrorCodevariants are added (the array is non-exhaustive and doesn’t use pattern matching), so consider restructuring it with amatchonErrorCodeto get compile-time exhaustiveness or at least adding a comment that this test must be updated whenever variants change.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `display_name` schema comment says the value is trimmed but the regex `^[A-Za-z0-9_ ]+$` still allows leading/trailing and multiple spaces; either tighten the pattern (e.g., disallow leading/trailing spaces) or relax the comment so it matches what the schema actually enforces.
- The `error_code_schema_matches_domain_serialization` test won’t fail automatically when new `ErrorCode` variants are added (the array is non-exhaustive and doesn’t use pattern matching), so consider restructuring it with a `match` on `ErrorCode` to get compile-time exhaustiveness or at least adding a comment that this test must be updated whenever variants change.
## Individual Comments
### Comment 1
<location> `backend/src/doc.rs:85-94` </location>
<code_context>
- json.contains(&format!("#/components/schemas/{USER_SCHEMA_NAME}")),
- "Responses should reference User schema"
- );
+ /// Assert that an Object schema contains a field with the given name.
+ fn assert_object_schema_has_field(schema: &RefOr<Schema>, field: &str) {
+ match schema {
+ RefOr::T(Schema::Object(obj)) => {
+ assert!(
+ obj.properties.contains_key(field),
+ "schema should have field '{field}'"
+ );
+ }
+ _ => panic!("expected Object schema"),
+ }
}
</code_context>
<issue_to_address>
**issue:** Handle referenced or composed schemas more defensively in the helper.
This helper will panic whenever the schema is a `$ref` or wrapped in a combinator (e.g., `AllOf`), which is a common pattern in `utoipa`. If `Error` or `User` are ever referenced or composed instead of inlined, these tests will fail despite a valid schema. Consider resolving `RefOr::Ref` (and other relevant variants) to an `Object` before checking `properties`, or at least include the schema name in the failure message so changes in representation are easier to diagnose.
</issue_to_address>
### Comment 2
<location> `backend/src/inbound/http/schemas.rs:78-88` </location>
<code_context>
/// Display name shown to other users.
- #[schema(value_type = String, example = "Ada Lovelace")]
+ ///
+ /// Matches the domain `DisplayName` invariant: trimmed, non-empty,
+ /// 3–32 characters, alphanumeric plus spaces and underscores.
+ #[schema(
+ value_type = String,
+ min_length = 3,
+ max_length = 32,
+ pattern = "^[A-Za-z0-9_ ]+$",
+ example = "Ada Lovelace"
+ )]
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The display_name pattern does not fully reflect the "trimmed" invariant.
The schema currently accepts values (e.g. leading/trailing or multiple consecutive spaces) that violate the `DisplayName` “trimmed” invariant. To keep the OpenAPI contract aligned with the domain, either tighten the regex to exclude those cases or adjust the comment to state that trimming is enforced in the domain layer, not by the schema itself.
```suggestion
/// Display name shown to other users.
///
/// Matches the domain `DisplayName` invariant: trimmed (no leading,
/// trailing, or consecutive spaces), non-empty, 3–32 characters,
/// alphanumeric plus spaces and underscores.
#[schema(
value_type = String,
min_length = 3,
max_length = 32,
// One or more groups of `[A-Za-z0-9_]+` separated by single spaces:
// - no leading/trailing spaces
// - no consecutive spaces
pattern = "^[A-Za-z0-9_]+(?: [A-Za-z0-9_]+)*$",
example = "Ada Lovelace"
)]
```
</issue_to_address>
### Comment 3
<location> `docs/execplans/phase-0-update-modules-to-use-domain-ports.md:13` </location>
<code_context>
from `middleware/trace.rs`
-2. **OpenAPI/Utoipa framework types in domain**: Domain types derive `ToSchema`
- from the `utoipa` crate
+2. **OpenAPI (Open API Specification) / Utoipa framework types in domain**: Domain
+ types derive `ToSchema` from the `utoipa` crate
</code_context>
<issue_to_address>
**suggestion (typo):** Use the correct, consistent spelling "OpenAPI Specification" in the parenthetical.
This parenthetical is the only place that uses "Open API" with a space. Please update it to "OpenAPI Specification" to match the official name and the rest of the document.
```suggestion
2. **OpenAPI (OpenAPI Specification) / Utoipa framework types in domain**: Domain
```
</issue_to_address>
### Comment 4
<location> `backend/src/inbound/http/schemas.rs:72` </location>
<code_context>
- #[schema(value_type = String, example = "3fa85f64-5717-4562-b3fc-2c963f66afa6")]
+ ///
+ /// Matches the domain `User` invariant of being a UUID.
+ #[schema(
+ value_type = String,
+ format = "uuid",
</code_context>
<issue_to_address>
**issue (review_instructions):** Add tests that verify the new OpenAPI constraints on `UserSchema.id` and `UserSchema.display_name`, covering both behavioural and unit aspects.
You change the OpenAPI contract by adding `format = "uuid"`, `min_length`, `max_length`, and `pattern` to `UserSchema`, but you do not add tests that assert these constraints in the generated schema or at the behavioural level.
Add unit tests (e.g. alongside `openapi_user_schema_has_required_fields` in `backend/src/doc.rs`) that inspect the generated schema and assert:
- `id` has `format = "uuid"`.
- `display_name` has the configured `min_length`, `max_length`, and `pattern`.
Also add (or extend existing) behavioural/BDD tests to ensure the exposed OpenAPI document used by clients actually includes these constraints, so both the unit and behavioural test requirements are satisfied for this change in feature behaviour.
<details>
<summary>Review instructions:</summary>
**Path patterns:** `**/*`
**Instructions:**
For any new feature or change to an existing feature, both behavioural *and* unit tests are required.
</details>
</issue_to_address>
### Comment 5
<location> `backend/src/inbound/http/schemas.rs:158` </location>
<code_context>
);
}
+
+ /// Verify domain ErrorCode serialization matches schema renames.
+ ///
+ /// This test fails if a new domain variant is added without updating
</code_context>
<issue_to_address>
**nitpick (review_instructions):** Comment uses US spelling for “serialisation/serialise”; please switch to en-GB-oxendict forms in the doc and inline comments.
The new comments around `error_code_schema_matches_domain_serialization` use US-style forms:
- `serialization` in the doc comment
- `serialize` in the inline `//` comment
Per the guidelines, these should use en-GB-oxendict spelling, e.g. `serialisation` / `serialise`.
Please update both comments accordingly while keeping the identifiers and string literals (which don’t affect the spelling requirement) as they are.
<details>
<summary>Review instructions:</summary>
**Path patterns:** `**/*.rs`
**Instructions:**
Comments must use en-GB-oxendict (-ize / -yse / -our) spelling and grammar.
</details>
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| /// Assert that an Object schema contains a field with the given name. | ||
| fn assert_object_schema_has_field(schema: &RefOr<Schema>, field: &str) { | ||
| match schema { | ||
| RefOr::T(Schema::Object(obj)) => { | ||
| assert!( | ||
| obj.properties.contains_key(field), | ||
| "schema should have field '{field}'" | ||
| ); | ||
| } | ||
| _ => panic!("expected Object schema"), |
There was a problem hiding this comment.
issue: Handle referenced or composed schemas more defensively in the helper.
This helper will panic whenever the schema is a $ref or wrapped in a combinator (e.g., AllOf), which is a common pattern in utoipa. If Error or User are ever referenced or composed instead of inlined, these tests will fail despite a valid schema. Consider resolving RefOr::Ref (and other relevant variants) to an Object before checking properties, or at least include the schema name in the failure message so changes in representation are easier to diagnose.
| /// Display name shown to other users. | ||
| #[schema(value_type = String, example = "Ada Lovelace")] | ||
| /// | ||
| /// Matches the domain `DisplayName` invariant: trimmed, non-empty, | ||
| /// 3–32 characters, alphanumeric plus spaces and underscores. | ||
| #[schema( | ||
| value_type = String, | ||
| min_length = 3, | ||
| max_length = 32, | ||
| pattern = "^[A-Za-z0-9_ ]+$", | ||
| example = "Ada Lovelace" | ||
| )] |
There was a problem hiding this comment.
suggestion (bug_risk): The display_name pattern does not fully reflect the "trimmed" invariant.
The schema currently accepts values (e.g. leading/trailing or multiple consecutive spaces) that violate the DisplayName “trimmed” invariant. To keep the OpenAPI contract aligned with the domain, either tighten the regex to exclude those cases or adjust the comment to state that trimming is enforced in the domain layer, not by the schema itself.
| /// Display name shown to other users. | |
| #[schema(value_type = String, example = "Ada Lovelace")] | |
| /// | |
| /// Matches the domain `DisplayName` invariant: trimmed, non-empty, | |
| /// 3–32 characters, alphanumeric plus spaces and underscores. | |
| #[schema( | |
| value_type = String, | |
| min_length = 3, | |
| max_length = 32, | |
| pattern = "^[A-Za-z0-9_ ]+$", | |
| example = "Ada Lovelace" | |
| )] | |
| /// Display name shown to other users. | |
| /// | |
| /// Matches the domain `DisplayName` invariant: trimmed (no leading, | |
| /// trailing, or consecutive spaces), non-empty, 3–32 characters, | |
| /// alphanumeric plus spaces and underscores. | |
| #[schema( | |
| value_type = String, | |
| min_length = 3, | |
| max_length = 32, | |
| // One or more groups of `[A-Za-z0-9_]+` separated by single spaces: | |
| // - no leading/trailing spaces | |
| // - no consecutive spaces | |
| pattern = "^[A-Za-z0-9_]+(?: [A-Za-z0-9_]+)*$", | |
| example = "Ada Lovelace" | |
| )] |
| from `middleware/trace.rs` | ||
| 2. **OpenAPI/Utoipa framework types in domain**: Domain types derive `ToSchema` | ||
| from the `utoipa` crate | ||
| 2. **OpenAPI (Open API Specification) / Utoipa framework types in domain**: Domain |
There was a problem hiding this comment.
suggestion (typo): Use the correct, consistent spelling "OpenAPI Specification" in the parenthetical.
This parenthetical is the only place that uses "Open API" with a space. Please update it to "OpenAPI Specification" to match the official name and the rest of the document.
| 2. **OpenAPI (Open API Specification) / Utoipa framework types in domain**: Domain | |
| 2. **OpenAPI (OpenAPI Specification) / Utoipa framework types in domain**: Domain |
| ); | ||
| } | ||
|
|
||
| /// Verify domain ErrorCode serialization matches schema renames. |
There was a problem hiding this comment.
nitpick (review_instructions): Comment uses US spelling for “serialisation/serialise”; please switch to en-GB-oxendict forms in the doc and inline comments.
The new comments around error_code_schema_matches_domain_serialization use US-style forms:
serializationin the doc commentserializein the inline//comment
Per the guidelines, these should use en-GB-oxendict spelling, e.g. serialisation / serialise.
Please update both comments accordingly while keeping the identifiers and string literals (which don’t affect the spelling requirement) as they are.
Review instructions:
Path patterns: **/*.rs
Instructions:
Comments must use en-GB-oxendict (-ize / -yse / -our) spelling and grammar.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/src/inbound/http/schemas.rs (1)
98-98: Fix spelling inconsistency to en-GB-oxendict.Use "serializes" (with -ize) instead of "serialises" (with -ise) to match en-GB-oxendict spelling requirements and maintain consistency with lines 176 and 182.
🔎 Proposed fix
- serde_json::to_string(&T::schema()).expect("schema serialises to JSON") + serde_json::to_string(&T::schema()).expect("schema serializes to JSON")
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
backend/src/doc.rs(1 hunks)backend/src/inbound/http/schemas.rs(2 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.mdbackend/src/doc.rsbackend/src/inbound/http/schemas.rs
docs/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*.md: Use the markdown files within thedocs/directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update documentation indocs/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 usingmake markdownlint.
Runmake fmtafter any documentation changes to format Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by runningmake 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 withis,has, orshould.
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/doc.rsbackend/src/inbound/http/schemas.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/doc.rsbackend/src/inbound/http/schemas.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Runmake fmt,make lint, andmake testbefore committing Rust code; these wrapcargo fmt,cargo clippy, andcargo 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 usingArcto 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 withcargo doc.
Prefer immutable data and avoid unnecessarymutbindings.
Handle errors with theResulttype instead of panicking where feasible.
Avoidunsafecode unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments, not before.
Do not usereturnin 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.
Preferexpectoverallowwhen suppressing warnings.
Where a function is unused with specific features selected, use conditional compilation with#[cfg]or#[cfg_attr].
Prefer.expect()over.unwrap().
Useconcat!()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.
Userstestfixtures for shared setup in Rust tests.
Replace duplicated tests with#[rstest(...)]parameterised cases in Rust.
Prefermockallfor mocks/stubs...
Files:
backend/src/doc.rsbackend/src/inbound/http/schemas.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
returnin single-line functions.- Move conditionals with >2 branches into a predicate function.
- Avoid
unsafeunless 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
rstestfixtures for shared setup and to avoid repetition between tests.- Replace duplicated tests with
#[rstest(...)]parameterised cases.- Prefer
mockallfor 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/doc.rsbackend/src/inbound/http/schemas.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
🔍 Remote MCP Ref
Now let me search for more information about the test refactoring pattern and domain-driven design related to the PR:Now I have gathered sufficient context. Let me compile the findings into a focused summary for the PR review.
Summary of Additional Context for PR #259 Review
Based on comprehensive research of the relevant technologies and patterns, here is the additional context that would help in reviewing this PR:
1. Utoipa Schema Constraints Implementation
Utoipa supports max_length, min_length, and pattern attributes to define validation constraints for string types. The PR's changes align with Utoipa's standard practices: Examples show using #[schema(format = "base64", example = "cri4", min_length = 4, max_length = 6)] to specify constraints and formats.
Key validation point: The maximum length of a schema cannot be less than the minimum length—if a minimum length is specified, the maximum length must be greater than or equal to that minimum length. The PR sets min_length=3 and max_length=32 for display_name, which satisfies this requirement.
2. UUID Format in OpenAPI
The uuid format represents a Universally Unique IDentifier as defined in RFC4122. OpenAPI supports formats like "uuid" even though they may be undefined by the specification, and tools can use these formats for documentation purposes. Using format = "uuid" on the id field follows industry best practices for REST API documentation and enables better OpenAPI tooling support.
3. Domain-Driven Design with Ports & Adapters Context
The PR title references "domain ports," which aligns with hexagonal architecture principles. Hexagonal architecture isolates business logic from infrastructure code, with the application communicating with external components through interfaces called ports, using adapters to translate technical exchanges. Creating stronger types (like domain objects) for validation can introduce a place for validation and improves expressiveness of ports. The PR's schema constraints directly support this pattern by ensuring OpenAPI adapters accurately reflect domain invariants (3-32 char display names, UUID IDs).
4. Test Refactoring Approach
The PR consolidates tests by removing duplicates covered by external BDD tests and refactoring doc.rs tests to use structured schema inspection (assert_object_schema_has_field). This approach reduces brittle string-matching assertions in favor of targeted field validation, improving test maintainability.
5. ErrorCode Serialization Sync
The new test error_code_schema_matches_domain_serialization ensures that domain ErrorCode enum variants correctly serialize to their OpenAPI schema representations (e.g., "invalid_request"). This maintains consistency between the domain model and the OpenAPI contract adapter.,,,,
⏰ 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 - clear acronym definition.Expanding "OpenAPI" on first use improves documentation clarity and follows best practices.
backend/src/doc.rs (3)
71-74: Good context for test scope boundaries.The comment clarifies that registration and endpoint reference tests are handled by BDD tests, helping maintainers understand the test distribution.
85-96: Excellent refactoring to structured assertions.The helper function replaces brittle JSON string matching with direct schema inspection. This improves test maintainability and provides clearer failure messages.
98-116: LGTM - focused field validation.The refactored tests use the new helper to verify schema structure directly, which is more robust than string-based assertions.
backend/src/inbound/http/schemas.rs (3)
70-76: LGTM - UUID format correctly specified.The schema now documents that
idis a UUID with proper format annotation and a valid example, matching the domain invariant.
79-88: Verify pattern enforcement of "trimmed" invariant.The comment states the domain invariant includes "trimmed", but the pattern
^[A-Za-z0-9_ ]+$permits leading and trailing spaces (e.g., " Ada " would match). This could be intentional if:
- The schema documents permissive input and the domain normalizes by trimming, or
- An inconsistency where the pattern should enforce
^[A-Za-z0-9_]([A-Za-z0-9_ ]*[A-Za-z0-9_])?$to match the trimmed invariant exactly.Clarify whether the schema should enforce trimming or whether the comment should indicate that trimming is a domain-layer concern.
#!/bin/bash # Verify how the domain DisplayName type handles whitespace # Search for DisplayName validation or construction logic ast-grep --pattern $'impl DisplayName { $$$ }' # Search for display_name validation patterns rg -nP -C5 'display.*name|DisplayName' --type=rust -g '!**/test/**' -g 'backend/src/domain/**'
158-184: Excellent synchronization test.This test ensures domain
ErrorCodeserialization remains consistent with schema renames. The explicit mapping forces updates when new variants are added, preventing drift between domain and OpenAPI contract.
🤖 Generated with Claude Code
Summary by Sourcery
Refine OpenAPI schema definitions and tests to better align with domain invariants and documentation.
New Features:
Enhancements:
Tests: