Add RVO field synchronization package and import workflows#374
Conversation
…dm-app to connect to RVO and sync fields with fdm-core
…and also at the fields page of the farm
🦋 Changeset detectedLatest commit: 34f2452 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a new workspace package Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant Browser
participant AppServer
participant RVO_API
participant DB
User->>Browser: Click "Import from RVO"
Browser->>AppServer: POST /start_import (b_id_farm)
AppServer->>AppServer: createRvoState(farmId, returnUrl) / set-state cookie
AppServer->>RVO_API: generateAuthUrl(state, redirect_uri)
AppServer-->>Browser: 302 Redirect to RVO auth URL (Set-Cookie: rvo_state)
Browser->>RVO_API: User authenticates, RVO redirects back with ?code&state
Browser->>AppServer: GET /rvo?code=...&state=...
AppServer->>AppServer: verifyRvoState(cookie, state)
AppServer->>RVO_API: exchangeToken(code) => accessToken
AppServer->>RVO_API: fetchRvoFields(accessToken, year, kvk)
AppServer->>DB: loadLocalFields(farm)
AppServer->>AppServer: compareFields(local, rvo) => reviewData
AppServer-->>Browser: 200 Page with review UI (reviewData)
Browser->>AppServer: POST apply_changes (userChoices + reviewData)
AppServer->>DB: processRvoImport(...) (add/update/remove)
AppServer-->>Browser: Redirect to farm page (success)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Using 'strict' would break the CSRF verification as the user is redirected back from the RVO site |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsx (1)
99-144:⚠️ Potential issue | 🟡 MinorOAuth authorization code reuse on page refresh.
After the OAuth callback,
codeandstateremain in the URL. If the user refreshes,exchangeToken(rvoClient, code)will be called again with a single-use code that's already been consumed, causing aninvalid_granterror. While the error is caught and displayed, this creates a confusing UX.Consider persisting the review data in a session/flash store after successful token exchange, then redirecting to the same route without query params. This prevents accidental code resubmission.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx around lines 99 - 144, After successfully exchanging the OAuth code (exchangeToken called on the rvoClient created by createConfiguredRvoClient) and building RvoImportReviewData via compareFields, persist the review payload (or a flag indicating successful exchange) into the session/flash store tied to the current principal/farm and then perform a server-side redirect to the same route without query parameters to clear code/state; on subsequent loads read review data from the session/flash instead of re-calling exchangeToken (and clear the persisted data once consumed). Ensure verifyRvoState still runs before exchangeToken and use the session key to skip exchangeToken when present so refreshing the page won’t resend the single-use code.fdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsx (1)
109-170:⚠️ Potential issue | 🟡 MinorOAuth authorization code reuse on page refresh.
Same issue as the creation wizard route: after the OAuth callback, the
codeandstateremain in the URL. A page refresh will attempt to reuse the single-use authorization code, resulting in aninvalid_granterror.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx around lines 109 - 170, The OAuth authorization code and state are left in the URL so a page refresh re-uses the single-use code; after you successfully call exchangeToken(rvoClient, code) (and any further RVO calls like fetchRvoFields/compareFields), clear those query params by returning a redirect to the same route without code and state (i.e. rebuild the URL excluding code/state or use the framework's redirect helper) so the browser receives a 3xx and the URL no longer contains the one-time code; ensure this redirect happens only after a successful exchange and keep verifyRvoState, exchangeToken, createConfiguredRvoClient and subsequent logic intact before issuing the redirect.
🧹 Nitpick comments (3)
fdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsx (1)
224-250: Useless initial assignment todefaultAction.Line 228 assigns
"NO_ACTION"todefaultAction, but the switch statement on lines 230-246 covers all cases and always assigns a value before use. Remove the initial assignment to fix the CodeQL warning.♻️ Suggested fix
- let defaultAction: ImportReviewAction = "NO_ACTION" + let defaultAction: ImportReviewActionNote: The switch comprehensively handles all five
RvoImportReviewStatusvalues (NEW_REMOTE,NEW_LOCAL,EXPIRED_LOCAL,CONFLICT,MATCH), so the initial assignment is never used.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx around lines 224 - 250, Remove the unnecessary initialization of defaultAction in the useEffect: declare let defaultAction: ImportReviewAction; (no initial value) inside the loop that processes rvoImportReviewData, keep the existing switch on RvoImportReviewStatus to assign the value, and then use initialChoices[id] = defaultAction before calling setUserChoices; reference symbols: useEffect, initialChoices, defaultAction, rvoImportReviewData, RvoImportReviewStatus, getItemId, setUserChoices.fdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsx (1)
495-496: Consider returning an error for unrecognized intents.Returning an empty object for unrecognized intent values could mask form submission errors. While intents are controlled via hidden fields, explicit error handling would improve debuggability.
♻️ Suggested improvement
- return {} + return { + success: false, + message: `Unknown intent: ${intent}`, + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx around lines 495 - 496, The handler currently returns an empty object for unknown "intent" cases (the line with "return {}"); replace that silent fallback with an explicit error response: locate the branch handling unrecognized intent values and either throw a Response or return a JSON error payload with a 4xx status (e.g., 400) and a clear message like "Unrecognized intent" so form submission errors are surfaced and debuggable; keep the check that reads the "intent" hidden field and ensure the error path is hit when no known intent matches.fdm-app/app/routes/farm.create.$b_id_farm.$calendar._index.tsx (1)
88-92: Simplify conditional rendering.The RVO card uses a
hiddenclass when!isRvoConfigured, but it would be cleaner to conditionally render the card only when needed, consistent with how the grid column count is already conditionally set.♻️ Suggested simplification
- <Card - className={cn( - "flex flex-col", - isRvoConfigured ? "" : "hidden", - )} - > + {isRvoConfigured && ( + <Card className="flex flex-col">And close with
</Card>)}instead of just</Card>.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar._index.tsx around lines 88 - 92, The Card currently toggles visibility by adding a "hidden" class via cn; instead, render it only when needed by wrapping the Card JSX with a conditional expression (e.g. {isRvoConfigured && ( ... )}) and remove the isRvoConfigured ? "" : "hidden" branch from the cn call; ensure the wrapper closes with </Card>)} so the component returns the Card only when isRvoConfigured.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx:
- Line 530: The action handler currently does const year = Number(yearString)
without validation, which can produce NaN and lead to bad input being passed to
processRvoImport; update the action to validate yearString the same way as the
loader: parse the value (e.g., parseInt or Number), check Number.isInteger(year)
and that it is within any expected range, and if invalid return or throw an
appropriate response (mirror the loader's error handling) before calling
processRvoImport; specifically adjust the code around the yearString -> const
year = Number(yearString) conversion in the action handler to include these
checks and early-return on invalid input.
---
Duplicate comments:
In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx:
- Around line 109-170: The OAuth authorization code and state are left in the
URL so a page refresh re-uses the single-use code; after you successfully call
exchangeToken(rvoClient, code) (and any further RVO calls like
fetchRvoFields/compareFields), clear those query params by returning a redirect
to the same route without code and state (i.e. rebuild the URL excluding
code/state or use the framework's redirect helper) so the browser receives a 3xx
and the URL no longer contains the one-time code; ensure this redirect happens
only after a successful exchange and keep verifyRvoState, exchangeToken,
createConfiguredRvoClient and subsequent logic intact before issuing the
redirect.
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx:
- Around line 99-144: After successfully exchanging the OAuth code
(exchangeToken called on the rvoClient created by createConfiguredRvoClient) and
building RvoImportReviewData via compareFields, persist the review payload (or a
flag indicating successful exchange) into the session/flash store tied to the
current principal/farm and then perform a server-side redirect to the same route
without query parameters to clear code/state; on subsequent loads read review
data from the session/flash instead of re-calling exchangeToken (and clear the
persisted data once consumed). Ensure verifyRvoState still runs before
exchangeToken and use the session key to skip exchangeToken when present so
refreshing the page won’t resend the single-use code.
---
Nitpick comments:
In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx:
- Around line 224-250: Remove the unnecessary initialization of defaultAction in
the useEffect: declare let defaultAction: ImportReviewAction; (no initial value)
inside the loop that processes rvoImportReviewData, keep the existing switch on
RvoImportReviewStatus to assign the value, and then use initialChoices[id] =
defaultAction before calling setUserChoices; reference symbols: useEffect,
initialChoices, defaultAction, rvoImportReviewData, RvoImportReviewStatus,
getItemId, setUserChoices.
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar._index.tsx:
- Around line 88-92: The Card currently toggles visibility by adding a "hidden"
class via cn; instead, render it only when needed by wrapping the Card JSX with
a conditional expression (e.g. {isRvoConfigured && ( ... )}) and remove the
isRvoConfigured ? "" : "hidden" branch from the cn call; ensure the wrapper
closes with </Card>)} so the component returns the Card only when
isRvoConfigured.
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx:
- Around line 495-496: The handler currently returns an empty object for unknown
"intent" cases (the line with "return {}"); replace that silent fallback with an
explicit error response: locate the branch handling unrecognized intent values
and either throw a Response or return a JSON error payload with a 4xx status
(e.g., 400) and a clear message like "Unrecognized intent" so form submission
errors are surfaced and debuggable; keep the check that reads the "intent"
hidden field and ensure the error path is hit when no known intent matches.
🪄 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: 17eaed40-0e20-4f06-a14d-92325ca8fb3e
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
fdm-app/app/components/blocks/fertilizer/utils.server.tsfdm-app/app/components/blocks/fertilizer/utils.tsfdm-app/app/integrations/rvo.server.tsfdm-app/app/lib/error.tsfdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsxfdm-app/app/routes/farm.$b_id_farm._index.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.$p_id.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new.$p_id.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new._index.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new.custom.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsxfdm-app/package.jsonfdm-rvo/src/compare.test.tsfdm-rvo/src/process.test.tsfdm-rvo/src/process.ts
💤 Files with no reviewable changes (1)
- fdm-app/app/components/blocks/fertilizer/utils.ts
✅ Files skipped from review due to trivial changes (3)
- fdm-app/package.json
- fdm-rvo/src/process.test.ts
- fdm-rvo/src/compare.test.ts
…ds to be request again
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@fdm-app/.env.example`:
- Around line 73-76: Reorder the RVO environment variable lines so they are
alphabetically ordered to satisfy dotenv-linter's UnorderedKey rule: change the
block with RVO_CLIENT_ID, RVO_CLIENT_NAME, RVO_REDIRECT_URI,
RVO_PKIO_PRIVATE_KEY to the order RVO_CLIENT_ID, RVO_CLIENT_NAME,
RVO_PKIO_PRIVATE_KEY, RVO_REDIRECT_URI so the identifier RVO_PKIO_PRIVATE_KEY no
longer breaks the linter.
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx:
- Around line 430-451: Before initiating the OAuth flow in the start_import
branch, verify the farm's KvK number (farm.b_businessid_farm) and reject the
request if missing; specifically, inside the intent === "start_import" block
(where getRvoCredentials, createConfiguredRvoClient, createRvoState,
generateAuthUrl, b_id_farm and request.url are used) add a guard that reads the
farm object and throws a Response (e.g., 400 or 422) when farm.b_businessid_farm
is falsy so you never call createConfiguredRvoClient / createRvoState / redirect
for farms that cannot complete the import.
In `@fdm-rvo/README.md`:
- Around line 40-76: The examples expose confidential PKIO/private credentials
and perform the token exchange in the browser (see createRvoClient,
generateAuthUrl, exchangeToken, pkioPrivateKey, handleAuthInitiation,
handleRvoCallback, and serverConfig.integrations.rvo); move any use of
pkioPrivateKey and the exchangeToken step to a backend-only handler
(loader/action/server endpoint) so the client only builds the initial redirect
URL (generateAuthUrl) and sends the user to the RVO auth page, then the server
handles the callback (reads code, uses pkioPrivateKey to call exchange token,
validates state) and returns or stores the resulting access token securely
(e.g., HTTP-only cookie or server session); remove pkioPrivateKey from
client-side config and update the README snippets to show client-side only
initiating redirect and backend-only callback/ token exchange flow.
- Around line 14-15: Update the README to match the current API: in the config
block replace the documented RVO_ENVIRONMENT with RVO_CLIENT_NAME; in the
examples remove destructured clientSecret and any environment variable passed to
createRvoClient so the call matches createRvoClient(...) signature; update the
compareFields invocation to pass the calendar argument (i.e., compareFields(...,
calendar, ...)) so the example matches the real call; and add the EXPIRED_LOCAL
member to the documented RvoImportReviewStatus enum to reflect the actual import
flow.
In `@fdm-rvo/src/process.ts`:
- Around line 137-169: The current sync only updates cultivation when
item.localCultivation exists and differs; for matched fields that have no local
cultivation we must also create one from RVO: in the UPDATE_FROM_REMOTE handling
(where item.localCultivation is checked) add an else branch for when
item.localCultivation is falsy that constructs b_lu_catalogue =
`nl_${item.rvoField.properties.CropTypeCode}`, calls
getDefaultDatesOfCultivation(tx, principal_id, b_id_farm, b_lu_catalogue, year)
and then calls addCultivation(tx, principal_id, b_lu_catalogue,
item.localField.b_id, defaultDates.b_lu_start, defaultDates.b_lu_end) so the RVO
cultivation is created for fields without an existing local cultivation (use the
same helper functions
removeCultivation/getDefaultDatesOfCultivation/addCultivation used elsewhere).
🪄 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: a8ad0140-0be2-42f1-b99e-590db6a7bd81
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (21)
fdm-app/.env.examplefdm-app/app/components/blocks/fertilizer/utils.server.tsfdm-app/app/components/blocks/fertilizer/utils.tsfdm-app/app/integrations/rvo.server.tsfdm-app/app/lib/config.server.tsfdm-app/app/lib/error.tsfdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsxfdm-app/app/routes/farm.$b_id_farm._index.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.$p_id.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new.$p_id.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new._index.tsxfdm-app/app/routes/farm.$b_id_farm.fertilizers.new.custom.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar._index.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsxfdm-app/app/types/config.d.tsfdm-app/package.jsonfdm-calculator/package.jsonfdm-rvo/README.mdfdm-rvo/src/compare.test.tsfdm-rvo/src/process.test.tsfdm-rvo/src/process.ts
💤 Files with no reviewable changes (1)
- fdm-app/app/components/blocks/fertilizer/utils.ts
✅ Files skipped from review due to trivial changes (7)
- fdm-app/app/routes/farm.$b_id_farm.fertilizers.new._index.tsx
- fdm-app/app/lib/error.ts
- fdm-app/app/routes/farm.$b_id_farm.fertilizers.new.$p_id.tsx
- fdm-app/package.json
- fdm-calculator/package.json
- fdm-rvo/src/process.test.ts
- fdm-rvo/src/compare.test.ts
🚧 Files skipped from review as they are similar to previous changes (7)
- fdm-app/app/routes/farm.$b_id_farm.fertilizers.$p_id.tsx
- fdm-app/app/routes/farm.$b_id_farm.fertilizers.new.custom.tsx
- fdm-app/app/components/blocks/fertilizer/utils.server.ts
- fdm-app/app/routes/farm.$b_id_farm._index.tsx
- fdm-app/app/routes/farm.create.$b_id_farm.$calendar._index.tsx
- fdm-app/app/lib/config.server.ts
- fdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsx
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsx (1)
85-86: Consider consistent variable naming with the sibling route.This file uses
RvoImportReviewData(PascalCase) whilefarm.$b_id_farm.$calendar.rvo.tsxusesrvoImportReviewData(camelCase). Aligning naming conventions between these similar routes would improve consistency and reduce confusion when maintaining both.Also applies to: 166-166, 180-180, 194-194, 217-217, 385-385, 469-469, 472-472, 484-484, 519-519, 523-523
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx around lines 85 - 86, The variable RvoImportReviewData is using PascalCase while the sibling route uses camelCase; rename all occurrences of RvoImportReviewData to rvoImportReviewData (including declarations and all references) to match the sibling route naming, and ensure any related handlers or setters that reference it are updated accordingly (keep type RvoImportReviewItem as-is). Update every instance in this file where RvoImportReviewData appears so the variable name is consistently camelCase (rvoImportReviewData) throughout.fdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsx (1)
109-185: Consider redirecting away after successful OAuth code exchange.After
exchangeToken()succeeds, thecodeandstatequery params remain in the URL. OAuth authorization codes are single-use per RFC 6749, so a page refresh will fail at token exchange. While the error handler (lines 128-142) catchesinvalid_grant/expirederrors with a user-friendly message, persisting the review data in session/flash storage and redirecting to a clean URL would provide a smoother experience.The current approach works but may confuse users who refresh and see an error despite having successfully loaded data moments before.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx around lines 109 - 185, After a successful exchangeToken() call, persist the minimal post-exchange state (e.g., a flash/session flag or necessary rvoCredentials) and then redirect the user to the same route without the code and state query params so refreshes won't attempt a reused authorization code; implement this by setting a session flash (or session value) immediately after exchangeToken() and issuing a redirect (throw redirect) to the current route with code/state removed, and then in the subsequent loader/run path detect that flash/session flag and continue the work (createConfiguredRvoClient, fetchRvoFields, compareFields to produce rvoImportReviewData) so the token exchange happens only once and the UI is loaded from the clean URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx:
- Around line 483-485: After parsing RvoImportReviewDataJson and
userChoicesJson, validate their shapes before proceeding: ensure
RvoImportReviewData (variable RvoImportReviewData) is an array (Array.isArray)
and that userChoices has the expected type/shape (e.g., object or array as
required by downstream code), and if validation fails throw or return a clear
error message indicating malformed input (include which payload failed). Update
the parse block that currently sets RvoImportReviewData =
JSON.parse(String(RvoImportReviewDataJson)) and userChoices =
JSON.parse(String(userChoicesJson)) to perform these checks and short-circuit
with a descriptive error when the structure is invalid so downstream code does
not assume a correct shape.
In `@fdm-rvo/README.md`:
- Line 5: Update the README package name to match the actual import used in the
codebase: replace the incorrect `@svenvw/rvo-connector` reference with
`@nmi-agro/rvo-connector` (the package imported in fdm-rvo/src/auth.ts). Make
sure the README description and any dependency mentions consistently reference
`@nmi-agro/rvo-connector` to avoid confusion.
- Line 64: Replace the non-standard Crypto.randomUUID() example with the correct
Node.js API by using crypto.randomUUID(); ensure the README example also shows
importing or requiring the crypto module (e.g., referencing the crypto
identifier used) so the call is valid — update the example line where
Crypto.randomUUID() appears and confirm the surrounding text/demo uses the
lowercase crypto symbol consistently.
---
Nitpick comments:
In `@fdm-app/app/routes/farm`.$b_id_farm.$calendar.rvo.tsx:
- Around line 109-185: After a successful exchangeToken() call, persist the
minimal post-exchange state (e.g., a flash/session flag or necessary
rvoCredentials) and then redirect the user to the same route without the code
and state query params so refreshes won't attempt a reused authorization code;
implement this by setting a session flash (or session value) immediately after
exchangeToken() and issuing a redirect (throw redirect) to the current route
with code/state removed, and then in the subsequent loader/run path detect that
flash/session flag and continue the work (createConfiguredRvoClient,
fetchRvoFields, compareFields to produce rvoImportReviewData) so the token
exchange happens only once and the UI is loaded from the clean URL.
In `@fdm-app/app/routes/farm.create`.$b_id_farm.$calendar.rvo.tsx:
- Around line 85-86: The variable RvoImportReviewData is using PascalCase while
the sibling route uses camelCase; rename all occurrences of RvoImportReviewData
to rvoImportReviewData (including declarations and all references) to match the
sibling route naming, and ensure any related handlers or setters that reference
it are updated accordingly (keep type RvoImportReviewItem as-is). Update every
instance in this file where RvoImportReviewData appears so the variable name is
consistently camelCase (rvoImportReviewData) throughout.
🪄 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: 0ec2c76e-3b60-4216-bc65-b6fb19f16c84
📒 Files selected for processing (5)
fdm-app/.env.examplefdm-app/app/routes/farm.$b_id_farm.$calendar.rvo.tsxfdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsxfdm-rvo/README.mdfdm-rvo/src/process.ts
✅ Files skipped from review due to trivial changes (2)
- fdm-app/.env.example
- fdm-rvo/src/process.ts
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@fdm-rvo/README.md`:
- Line 15: The README's conflict diff key list is incomplete; update the
documentation to list the full set of FieldDiff keys by adding
b_acquiring_method, b_lu_catalogue, and b_bufferstrip alongside b_name,
b_geometry, b_start, and b_end so consumers and the UI see the complete expected
diff keys; reference the FieldDiff structure and ensure the README's "diff keys"
or "conflicting properties" section enumerates all seven keys exactly as named.
- Around line 127-129: The README example incorrectly passes accessToken as a
4th argument to fetchRvoFields even though the function signature is
fetchRvoFields(rvoClient, year, kvkNumber); update the example to call
fetchRvoFields(rvoClient, year, kvkNumber) (removing accessToken) OR, if
accessToken must be used, modify the function signature of fetchRvoFields to
accept and handle an accessToken parameter and update its internal usage
accordingly; ensure references to rvoClient, year, kvkNumber, and accessToken
are consistent after the change.
- Around line 63-65: Persist the generated state (the state variable created via
crypto.randomUUID() when calling generateAuthUrl(rvoClient, state)) in a
server-side session or a signed, HttpOnly cookie tied to the user, then verify
the incoming state parameter in your OAuth callback handler by comparing it to
the stored value and rejecting the flow if it differs or is missing; update the
README examples to show storing state before redirect and checking the
callback's state parameter (and clearing it after verification) so
generateAuthUrl, the state variable, and the callback logic are clearly linked
and validated.
🪄 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: ac79ec89-a852-48b6-8ae4-8c762b99394e
📒 Files selected for processing (2)
fdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsxfdm-rvo/README.md
✅ Files skipped from review due to trivial changes (1)
- fdm-app/app/routes/farm.create.$b_id_farm.$calendar.rvo.tsx
Summary by CodeRabbit
Closes #373