Skip to content

Make the MiniLcm validation wrapper validate writes by construction#2363

Closed
myieye wants to merge 4 commits into
developfrom
fix-createentry-validation-gap
Closed

Make the MiniLcm validation wrapper validate writes by construction#2363
myieye wants to merge 4 commits into
developfrom
fix-createentry-validation-gap

Conversation

@myieye

@myieye myieye commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2362. Companion to the open decision in #2359.

The validation wrapper let BeaKona auto-forward the whole IMiniLcmApi, so any write without a hand-written override forwarded straight through unvalidated. That's how CreateEntry quietly stopped validating — its override was CreateEntry(Entry) but the interface had grown a CreateEntryOptions? parameter, so callers bound to the generated 2-arg forwarder and skipped it.

This does what the write-normalization wrapper already does: BeaKona forwards only the read interface, and every write is hand-written — so a new or renamed write won't compile until someone decides how it validates, instead of silently slipping through. Plus wrapper tests that exercise the seam through IMiniLcmApi (reusing #2360's TestMiniLcmWrappers).

This PR preserves current behavior — same methods validate, same ones pass through. CreateEntry, CreatePublication, CreateMorphType and the JsonPatch updates stay pass-through on purpose: sync/import wraps the API here and writes empty FLEx MultiStrings the validators reject, so validating would break import. Whether we should change that (actually validate user-facing creates) is tracked separately in #2359.

Stacked on #2360, so the diff includes its commits until that merges.

🤖 Generated with Claude Code

The shared MiniLcm test bases now wrap their Api in the same
validation/normalization stack production uses, so the tests hit the API the
way the app actually does instead of more loosely. Reuses the production
AddMiniLcmValidators wiring so new validators flow into tests automatically.

One test that deliberately stores an empty value now talks to the raw BaseApi
(it checks storage round-tripping, not a real user call, and validation
correctly rejects empty values).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label Jun 18, 2026
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

MiniLcmApiValidationWrapper is rewritten to retarget BeaKona.AutoInterface from the _api field to a new ReadApi property, so only read-interface members are auto-generated. All write methods across every API region (writing system, part of speech, entry, sense, example sentence, custom view, bulk/file) are now implemented as explicit _api pass-through forwarders. CreateEntry gains the missing CreateEntryOptions? parameter to fix the signature drift that caused the validating override to be dead code.

Changes

Validation Wrapper Restructure

Layer / File(s) Summary
Auto-forward wiring and class documentation
backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs
Adds using MiniLcm.Media;, replaces the BeaKona.AutoInterface annotation on the _api field with a ReadApi property bearing the attribute, and adds a doc block explaining the hand-written-writes / auto-forwarded-reads design intent.
Non-validating write forwarders: WritingSystem through MorphType
backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs
MoveWritingSystem and all CRUD/relationship write methods for PartOfSpeech, Publication, SemanticDomain, ComplexFormType, and MorphType are implemented as direct _api pass-through Task forwarders without calling validators.ValidateAndThrow.
Entry and Sense write methods: signature fix and non-validating forwarders
backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs
CreateEntry gains CreateEntryOptions? options = null to match the interface signature and forwards to _api; UpdateEntry(Guid, UpdateObjectInput<Entry>) is a non-validating forwarder. Entry and Sense ID-based operations are converted to direct _api forwarders while CreateSense retains validation.
ExampleSentence, CustomView, Bulk, and File forwarders
backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs
Adds the UpdateExampleSentence(Guid, Guid, Guid, UpdateObjectInput<ExampleSentence>) overload and implements all remaining ExampleSentence, CustomView, bulk import/create, and SaveFile methods as non-validating direct _api forwarders.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

💻 FW Lite

Suggested reviewers

  • hahn-kev

Poem

🐇 Hop, hop — the wrapper's set aright,
No silent bypass slipping past the night.
ReadApi takes the auto-forge alone,
While write paths hand-craft every stepping stone.
The validation gap at last is sealed,
And drift in CreateEntry is revealed! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: refactoring the validation wrapper to enforce validation through construction via hand-written methods rather than auto-forwarding.
Linked Issues check ✅ Passed The changes address issue #2362 by re-targeting BeaKona to forward only IMiniLcmReadApi and hand-writing all write methods, which resolves the CreateEntry override bypass problem and forces compile-time checks for write method coverage.
Out of Scope Changes check ✅ Passed All changes are scoped to the MiniLcmApiValidationWrapper file and directly address the validation wrapper's architecture and write method forwarding behavior as specified in issue #2362.
Description check ✅ Passed The pull request description clearly explains the fix for #2362, detailing the validation wrapper issue with CreateEntry signature mismatch and the solution of hand-writing all write methods.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-createentry-validation-gap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

UI unit Tests

  1 files  ±0   62 suites  ±0   31s ⏱️ ±0s
186 tests ±0  186 ✅ ±0  0 💤 ±0  0 ❌ ±0 
258 runs  ±0  258 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 202d5f0. ± Comparison against base commit f58948e.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

C# FwHeadless Unit Tests

48 tests  ±0   48 ✅ ±0   17s ⏱️ -1s
 5 suites ±0    0 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 202d5f0. ± Comparison against base commit f58948e.

♻️ This comment has been updated with latest results.

@argos-ci

argos-ci Bot commented Jun 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jun 18, 2026, 2:35 PM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs`:
- Around line 106-109: The UpdatePublication method passes the api parameter
directly to _api.UpdatePublication instead of using the null-coalescing operator
pattern used by other Update methods in this class. Change the method call from
_api.UpdatePublication(before, after, api) to _api.UpdatePublication(before,
after, api ?? this) to ensure that when api is null, the request routes through
this validation wrapper instead of bypassing it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bddf2441-0e42-4cff-9d00-c12eb7305e7e

📥 Commits

Reviewing files that changed from the base of the PR and between f58948e and 7e413ca.

📒 Files selected for processing (1)
  • backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs

Comment on lines +106 to +109
public Task<Publication> UpdatePublication(Publication before, Publication after, IMiniLcmApi? api = null)
{
return _api.UpdatePublication(before, after, api);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent api parameter: should be api ?? this.

All other Update*(..., before, after, api) overloads pass api ?? this to ensure callbacks from the inner API route through this validation wrapper. This method passes api directly, which could skip validation for related operations if api is null.

Proposed fix
     public Task<Publication> UpdatePublication(Publication before, Publication after, IMiniLcmApi? api = null)
     {
-        return _api.UpdatePublication(before, after, api);
+        return _api.UpdatePublication(before, after, api ?? this);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public Task<Publication> UpdatePublication(Publication before, Publication after, IMiniLcmApi? api = null)
{
return _api.UpdatePublication(before, after, api);
}
public Task<Publication> UpdatePublication(Publication before, Publication after, IMiniLcmApi? api = null)
{
return _api.UpdatePublication(before, after, api ?? this);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs` around
lines 106 - 109, The UpdatePublication method passes the api parameter directly
to _api.UpdatePublication instead of using the null-coalescing operator pattern
used by other Update methods in this class. Change the method call from
_api.UpdatePublication(before, after, api) to _api.UpdatePublication(before,
after, api ?? this) to ensure that when api is null, the request routes through
this validation wrapper instead of bypassing it.

myieye and others added 2 commits June 18, 2026 15:42
…apper

The validation wrapper auto-forwarded the whole IMiniLcmApi via BeaKona, so any
write method without a matching hand-written override silently forwarded
unvalidated. That is how CreateEntry drifted out of validation: its override took
(Entry) while the interface member is (Entry, CreateEntryOptions?), so the
generated 2-arg forwarder bypassed it entirely (#2362).

Re-target BeaKona at IMiniLcmReadApi only (like the write-normalization wrapper)
and hand-write every write method, so a new/renamed write becomes a compile error
instead of a silent unvalidated forward. Behavior is unchanged: the same methods
validate as before, and the sync-write surface (CreateEntry, CreatePublication,
CreateMorphType and all JsonPatch updates) deliberately stays pass-through because
sync/import writes empty FLEx MultiStrings the validators would reject.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The validator classes have unit tests, but nothing tested the seam where they meet
the API - which is exactly where #2362 hid (a dead CreateEntry override). These pin
the two things that matter at that seam: methods we expect to validate actually do,
and the ones that deliberately don't (CreateEntry, CreatePublication, CreateMorphType)
keep passing through, so a future "fix" that breaks sync of empty FLEx values goes red.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@myieye myieye force-pushed the fix-createentry-validation-gap branch from 7e413ca to 256b8c6 Compare June 18, 2026 13:47
…updates

UpdatePublication(before, after) forwarded `api` directly while every other
before/after update passes `api ?? this`, so nested callbacks bypassed the wrapper.
No behavior change today (Publication writes pass through anyway), but it matches
the established pattern and avoids a latent gap if Publication validation is added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@myieye

myieye commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

Want to talk about this

@myieye myieye closed this Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validation wrapper's CreateEntry override is never reached through IMiniLcmApi

1 participant