Skip to content

Move organization management from fdm-core to better-auth#403

Merged
SvenVw merged 19 commits into
developmentfrom
FDM402
Jan 12, 2026
Merged

Move organization management from fdm-core to better-auth#403
SvenVw merged 19 commits into
developmentfrom
FDM402

Conversation

@SvenVw
Copy link
Copy Markdown
Collaborator

@SvenVw SvenVw commented Jan 5, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Authentication type now correctly includes plugins and configuration settings.
  • Refactor

    • Organization and invitation management moved to a centralized auth API; UI updated to display user names, avatars/initials, Dutch role labels, invitation expiries, and improved organization descriptions.
    • Organization creation and slug checks now use the centralized API; session handling simplified.
  • Chores

    • Added changeset entries documenting version bumps and notes.
  • Tests

    • Organization-related tests removed or reworked.

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

Closes #402

@SvenVw SvenVw self-assigned this Jan 5, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jan 5, 2026

🦋 Changeset detected

Latest commit: 41a73fa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@svenvw/fdm-core Minor
@svenvw/fdm-app Patch
@svenvw/fdm-calculator Patch

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 5, 2026

Walkthrough

Migrates organization and invitation logic from fdm-core into the Better‑Auth (auth.api) surface: removes fdm-core organization module and tests, moves FdmAuth export, updates schema relations, and adapts fdm-app routes, loaders, actions, types, and UI to the auth.api shapes.

Changes

Cohort / File(s) Summary
Changesets
\.changeset/curvy-flowers-grin.md, \.changeset/polite-otters-follow.md, \.changeset/twelve-chicken-poke.md
Adds metadata entries: version bumps and notes about migrating org functions to better-auth and a type-fix for FdmAuth.
fdm-core — organization removal
\fdm-core/src/organization.ts`, `fdm-core/src/organization.test.ts`, `fdm-core/src/index.ts``
Deletes the entire custom organization implementation and its tests; removes organization-related exports from the fdm-core public index.
fdm-core — authentication types/export
\fdm-core/src/authentication.ts`, `fdm-core/src/authentication.d.ts`, `fdm-core/src/authentication.test.ts``
Moves FdmAuth export to runtime module (authentication.ts), removes the .d.ts alias, makes createFdmAuth return type inferred, and updates test import paths.
fdm-core — tests updated to direct DB seeding
\fdm-core/src/authorization.test.ts`, `fdm-core/src/principal.test.ts`, `fdm-core/src/farm.test.ts`*`
Tests no longer use organization helpers; they seed organizations/members directly and adjust FdmAuth import locations.
fdm-core — schema/authn changes
\fdm-core/src/db/schema-authn.ts`**`
Adds table-level indices, defaults, unique constraints (e.g., organization.slug), timestamps defaults/onUpdate, and explicit relation exports (user/session/account/organization/member/invitation).
fdm-app — organization routes (loaders/actions)
\fdm-app/app/routes/organization.tsx`, `fdm-app/app/routes/organization._index.tsx`, `fdm-app/app/routes/organization.$slug.tsx`, `fdm-app/app/routes/organization.new.tsx`, `fdm-app/app/routes/organization.invitations._index.tsx`, `fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx``
Replaces fdm-core calls with auth.api endpoints (list/create/update/delete organizations, list/create/cancel/accept/reject invitations, listMembers); adapts loaders/actions/forms and data shapes (id, member.user, invitation.*); some loader/action signatures changed.
fdm-app — types & UI tweaks
\fdm-app/app/types/extended-user.d.ts`, `fdm-app/app/routes/user._index.tsx`, `fdm-app/app/routes/organization._index.tsx`, `fdm-app/app/routes/organization.$slug.tsx``
Redefines ExtendedUser to FdmAuth["$Infer"]["Session"]["user"]; minor null-safety and UI/label/layout adjustments to reflect new member/invitation shapes and Dutch role labels.

* denotes multiple related files under same directory.
** schema-authn contains many relation/table exports and index/default changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Browser
  participant Route as fdm-app Route
  participant AuthAPI as auth.api (better-auth)
  participant DB as Database
  participant Email as EmailService

  Browser->>Route: GET /organization/:slug
  Route->>AuthAPI: listOrganizations / getOrganization ({ headers, slug })
  AuthAPI-->>DB: query organization, members, invitations
  DB-->>AuthAPI: org{ id,name,slug,metadata }, members[], invitations[]
  AuthAPI-->>Route: organization payload (member.user, invitation.*)
  Route-->>Browser: render organization page

  Browser->>Route: POST /organization/:slug/invite (email, role)
  Route->>AuthAPI: createInvitation({ headers, body:{ organizationId, email, role } })
  AuthAPI-->>DB: insert invitation
  DB-->>AuthAPI: invitation { id, expiresAt, inviterId, ... }
  AuthAPI-->>Route: invitation
  Route->>Email: renderInvitationEmail({ invitationId, organizationName })
  Email-->>Route: sent confirmation
  Route-->>Browser: 200 (invitation created)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • BoraIneviNMI
  • gerardhros

Poem

🐰 I hopped from core into auth’s bright glen,

Invitations bundled by a single pen,
Types now tidy, routes point to one API,
Members nested snug — the UI waves “hie!”,
A rabbit nibbles code and hums a happy den.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Move organization management from fdm-core to better-auth' clearly and concisely summarizes the main objective of the pull request.
Linked Issues check ✅ Passed The PR successfully implements all key requirements from issue #402: replaces fdm-core organization functions with auth.api equivalents across routes, removes organization.ts exports, updates type definitions, and adds database indices for better-auth tables.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #402 objectives. Database schema updates enable better-auth organization functionality; type definition changes support the migration; test refactoring addresses removal of fdm-core organization functions.

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

✨ 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 FDM402

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.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 5, 2026

Codecov Report

❌ Patch coverage is 48.38710% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.10%. Comparing base (95388f9) to head (41a73fa).
⚠️ Report is 20 commits behind head on development.

Files with missing lines Patch % Lines
fdm-core/src/db/schema-authn.ts 46.42% 15 Missing ⚠️
fdm-core/src/authentication.ts 66.66% 1 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff               @@
##           development     #403      +/-   ##
===============================================
- Coverage        87.47%   87.10%   -0.38%     
===============================================
  Files               91       90       -1     
  Lines             4559     4380     -179     
  Branches          1391     1347      -44     
===============================================
- Hits              3988     3815     -173     
+ Misses             571      565       -6     
Flag Coverage Δ
fdm-calculator 86.98% <ø> (ø)
fdm-core 86.79% <48.38%> (-0.87%) ⬇️
fdm-data 92.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Move organization management from fdm-core to better-auth Jan 5, 2026
@coderabbitai coderabbitai Bot added branch:development Issue only affecting development, not the main branch (yet) enhancement New feature or request fdm-app fdm-core labels Jan 5, 2026
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

Fix all issues with AI Agents 🤖
In @fdm-app/app/routes/organization._index.tsx:
- Around line 17-27: The OrganizationType currently assumes metadata is always
present, but better-auth may return metadata as null or with missing fields;
update the OrganizationType to make metadata optional or its fields optional
(e.g., metadata?: { isVerified?: boolean; description?: string } | null) and
change direct accesses like org.metadata.description to a safe, defensive access
(e.g., use optional chaining or fallback: org.metadata?.description ?? '' or
similar) wherever org.metadata or its properties are read (notably the usage of
org.metadata.description).

In @fdm-app/app/routes/organization.invitations._index.tsx:
- Around line 31-42: The type InvitationType should allow inviter.name to be
nullable and the render site should defensively handle nulls: change
InvitationType.inviter.name to string | null (or undefined) and update places
that render invitation.inviter.name (eg. the component that displays the
inviter) to use a null-safe expression (optional chaining and a fallback like
"Unknown" or the inviter's email) so null values don't render as "null" or cause
UI issues.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fdm-app/app/routes/organization.$slug.tsx (1)

347-356: Inconsistent role label language between components.

InvitationForm (lines 352-354) uses English labels ("Owner", "Admin", "Member") while MemberAction (lines 254-256) uses Dutch labels ("Eigenaar", "Beheerder", "Lid"). Consider aligning to Dutch for consistency with the rest of the UI.

🔎 Proposed fix for InvitationForm
                 <SelectContent>
-                    <SelectItem value="owner">Owner</SelectItem>
-                    <SelectItem value="admin">Admin</SelectItem>
-                    <SelectItem value="member">Member</SelectItem>
+                    <SelectItem value="owner">Eigenaar</SelectItem>
+                    <SelectItem value="admin">Beheerder</SelectItem>
+                    <SelectItem value="member">Lid</SelectItem>
                 </SelectContent>
🧹 Nitpick comments (4)
fdm-app/app/routes/organization._index.tsx (1)

44-44: Add type parameter to useLoaderData for type safety.

Without a type parameter, organizations is typed as unknown, losing compile-time type checking for the mapped properties.

🔎 Proposed fix
-    const { organizations } = useLoaderData()
+    const { organizations } = useLoaderData<typeof loader>()
fdm-app/app/routes/organization.invitations._index.tsx (1)

59-59: Add type parameter to useLoaderData for type safety.

🔎 Proposed fix
-    const { invitations } = useLoaderData()
+    const { invitations } = useLoaderData<typeof loader>()
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)

56-56: Add type parameter to useLoaderData for type safety.

🔎 Proposed fix
-    const { invitation } = useLoaderData()
+    const { invitation } = useLoaderData<typeof loader>()
fdm-app/app/routes/organization.new.tsx (1)

66-72: Consider adding session validation to the loader.

The loader no longer validates the session, which could allow unauthenticated users to render this page before the action rejects them. Other organization routes call getSession(request) in loaders for consistency.

🔎 Proposed fix
-export async function loader() {
+export async function loader({ request }: LoaderFunctionArgs) {
     try {
+        await getSession(request)
         return {}
     } catch (error) {
         throw handleLoaderError(error)
     }
 }

Note: You'll need to add LoaderFunctionArgs to the imports from react-router.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8659259 and 400da07.

⛔ Files ignored due to path filters (1)
  • fdm-app/app/lib/auth.server.ts is excluded by !fdm-app/app/lib/**
📒 Files selected for processing (16)
  • .changeset/curvy-flowers-grin.md
  • .changeset/polite-otters-follow.md
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-app/app/routes/organization.tsx
  • fdm-app/app/routes/user._index.tsx
  • fdm-app/app/types/extended-user.d.ts
  • fdm-core/src/authentication.d.ts
  • fdm-core/src/authentication.ts
  • fdm-core/src/index.ts
  • fdm-core/src/organization.test.ts
  • fdm-core/src/organization.ts
💤 Files with no reviewable changes (3)
  • fdm-core/src/authentication.d.ts
  • fdm-core/src/organization.test.ts
  • fdm-core/src/organization.ts
🧰 Additional context used
🧠 Learnings (29)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • .changeset/polite-otters-follow.md
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.

Applied to files:

  • .changeset/polite-otters-follow.md
  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • .changeset/polite-otters-follow.md
  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • .changeset/polite-otters-follow.md
  • fdm-core/src/index.ts
  • fdm-core/src/authentication.ts
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.

Applied to files:

  • .changeset/polite-otters-follow.md
  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-core/src/authentication.ts
📚 Learning: 2025-08-13T11:05:40.105Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 237
File: fdm-data/src/cultivations/catalogues/brp.ts:65-68
Timestamp: 2025-08-13T11:05:40.105Z
Learning: In fdm-app Select components, using `undefined` instead of empty string (`""`) as fallback value prevents empty strings from being submitted as form values. This approach fixes the issue at the UI source rather than requiring backend validation.

Applied to files:

  • fdm-app/app/routes/user._index.tsx
  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/user._index.tsx
  • fdm-app/app/routes/organization.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-core/src/authentication.ts
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-core/src/index.ts
  • fdm-app/app/routes/organization.invitations._index.tsx
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-09-25T15:10:59.708Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 272
File: fdm-app/app/store/field-fertilizer-form.tsx:45-47
Timestamp: 2025-09-25T15:10:59.708Z
Learning: In the FDM application, Zustand stores with persist middleware using sessionStorage/localStorage don't require SSR hardening guards. The existing store patterns in fdm-app work without typeof window checks or memory storage fallbacks.

Applied to files:

  • fdm-app/app/routes/organization.tsx
📚 Learning: 2025-08-11T11:57:42.225Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields.$centroid.tsx:0-0
Timestamp: 2025-08-11T11:57:42.225Z
Learning: In Remix loaders, the `getSession(request)` call should be retained even when the returned session value isn't used elsewhere in the function, as it serves as an authentication guard that validates the user has a valid session and likely throws an error or redirects if the session is invalid. This is a common security pattern to protect routes.

Applied to files:

  • fdm-app/app/routes/organization.tsx
  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2024-11-27T09:58:24.047Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 9
File: fdm-core/src/cultivation.d.ts:3-13
Timestamp: 2024-11-27T09:58:24.047Z
Learning: In the `fdm-core` TypeScript codebase, interface names should not be prefixed with 'I'; interface names should be meaningful without the 'I' prefix.

Applied to files:

  • fdm-core/src/index.ts
  • fdm-app/app/types/extended-user.d.ts
  • fdm-core/src/authentication.ts
📚 Learning: 2025-04-18T14:18:44.350Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.

Applied to files:

  • fdm-core/src/index.ts
  • .changeset/curvy-flowers-grin.md
  • .changeset/twelve-chicken-poke.md
  • fdm-app/app/types/extended-user.d.ts
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-core/src/authentication.ts
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-core/src/index.ts
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-02-24T10:49:54.523Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 84
File: fdm-app/app/root.tsx:89-145
Timestamp: 2025-02-24T10:49:54.523Z
Learning: In the ErrorBoundary component of fdm-app/app/root.tsx, all client errors (400, 401, 403, 404) are intentionally displayed with a 404 status code for security purposes.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-03-04T11:09:08.169Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 88
File: fdm-core/src/cultivation.ts:246-246
Timestamp: 2025-03-04T11:09:08.169Z
Learning: In the FDM codebase, the `fdm` parameter should be documented as "The FDM instance providing the connection to the database. The instance can be created with {link createFdmServer}." in JSDoc comments.

Applied to files:

  • fdm-core/src/authentication.ts
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-core/src/authentication.ts
🧬 Code graph analysis (5)
fdm-app/app/routes/organization.tsx (1)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization.invitations._index.tsx (5)
fdm-app/app/routes/organization.$slug.tsx (1)
  • loader (32-93)
fdm-app/app/routes/organization._index.tsx (2)
  • loader (29-41)
  • OrganizationsIndex (43-119)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)
  • loader (27-53)
fdm-app/app/routes/organization.tsx (1)
  • loader (33-67)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization.$slug.tsx (3)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-core/src/authorization.ts (1)
  • permissions (32-138)
fdm-app/app/components/blocks/access/invitation-form.tsx (1)
  • InvitationForm (33-114)
fdm-app/app/routes/organization.new.tsx (4)
fdm-app/app/routes/organization.$slug.tsx (1)
  • loader (32-93)
fdm-app/app/routes/organization._index.tsx (1)
  • loader (29-41)
fdm-app/app/routes/organization.tsx (1)
  • loader (33-67)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
🔇 Additional comments (14)
fdm-app/app/routes/user._index.tsx (1)

90-93: LGTM! Type-safe avatar image handling.

The nullish coalescing to undefined ensures type compatibility with the AvatarImage component and aligns with better-auth's user data model. The fallback behavior remains intact.

.changeset/curvy-flowers-grin.md (1)

1-5: Clarify the changeset description—no organization functions exist in fdm-core's public API.

The changelog states "Remove organization functions as better-auth can handle them now server-side," but there is no organization.ts file in fdm-core/src and no organization-related functions are exported from the public API. The organization tables (organization and member) exist only in the database schema, not as exportable library functions. Either this changeset is documenting work from a different commit or the description is inaccurate.

.changeset/polite-otters-follow.md (1)

1-5: LGTM!

The changeset correctly documents the FdmAuth type fix as a patch release, which is appropriate for this type correction.

fdm-core/src/authentication.ts (3)

40-40: LGTM! Return type now inferred via exported type alias.

The explicit return type annotation has been removed in favor of type inference with the new FdmAuth type alias (line 236). This is a cleaner pattern that ensures the exported type always matches the actual return type.


159-159: LGTM! Improved metadata merge logic.

The spread syntax properly merges any existing organization.metadata properties into the default metadata object, ensuring custom metadata fields are preserved during organization creation.


236-237: LGTM! Clean type export pattern.

Exporting FdmAuth as ReturnType<typeof createFdmAuth> ensures the type always stays synchronized with the actual function return type, eliminating potential drift between type definitions and implementation.

fdm-core/src/index.ts (1)

24-24: LGTM! Export path updated correctly.

The FdmAuth type is now exported from ./authentication instead of ./authentication.d, aligning with the new type definition location in fdm-core/src/authentication.ts (line 236).

.changeset/twelve-chicken-poke.md (1)

1-5: LGTM!

The changeset appropriately documents the migration from fdm-core organization functions to Better-Auth functions as a patch release for fdm-app.

fdm-app/app/routes/organization.tsx (1)

44-46: API contract and data structure are compatible with the HeaderOrganization component.

The auth.api.listOrganizations() method from better-auth's organization plugin returns organization objects with the required properties (slug, name, id). These are directly compatible with the HeaderOrganizationOption interface expected by the HeaderOrganization component. The existing error handling patterns (try-catch blocks with 401 redirects) are maintained, and the implementation is consistent across all organization-related routes.

fdm-app/app/types/extended-user.d.ts (1)

1-3: LGTM! Type derivation aligns with better-auth patterns.

The FdmAuth["$Infer"]["Session"]["user"] pattern correctly derives the user type from the auth configuration, ensuring type consistency across the application.

fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)

98-99: Good defensive coding with optional chaining.

The fallback invitation.inviter?.name || "Iemand" properly handles cases where the inviter name may be null or undefined.

fdm-app/app/routes/organization.new.tsx (1)

238-250: LGTM! Proper slug availability check before creation.

The pattern of checking slug availability via auth.api.checkOrganizationSlug before creating the organization prevents conflicts and provides clear user feedback.

fdm-app/app/routes/organization.$slug.tsx (2)

77-82: Good defensive handling for invitations response.

The array check Array.isArray(invitationsListResponse) ? invitationsListResponse : [] properly handles potential API response variations.


182-189: Well-structured type extension for member with user data.

The MemberWithUser type correctly extends Member with the nested user object shape, providing proper type safety for the member rows.

Comment thread fdm-app/app/routes/organization._index.tsx Outdated
Comment thread fdm-app/app/routes/organization.$slug.tsx Outdated
Comment thread fdm-app/app/routes/organization.invitations._index.tsx 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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
fdm-app/app/routes/organization.$slug.tsx (2)

393-443: organizationName may be empty when organization_id is provided in form.

While the condition was fixed from the past review (now just !organizationId), there's still an issue: when organization_id is provided via the form, organizationName remains empty (""), but it's used on line 439 in renderInvitationEmail. This could result in invitation emails missing the organization name.

🔎 Suggested fix - always fetch organization name
     let organizationId = formValues.organization_id
     let organizationName = ""

-    if (!organizationId) {
+    // Always fetch to ensure we have organizationName for emails and to verify access
+    {
         const organizations = await auth.api.listOrganizations({
             headers: request.headers,
         })
         const organization = organizations.find(
             (org) => org.slug === params.slug,
         )
         if (!organization) {
             throw handleActionError("not found: organization")
         }
-        organizationId = organization.id
+        organizationId = organizationId || organization.id
         organizationName = organization.name
     }

Alternatively, only fetch when needed for invite_user intent, or pass organizationName from the form as well.


484-496: Cancel invite message references formValues.email which is not provided.

The cancel_invite form (InvitationRow, lines 311-325) only submits invitation_id and intent, but the success message on line 494 uses formValues.email. This will result in a message like "Uitnodiging voor undefined is ingetrokken".

🔎 Suggested fix

Either add the email as a hidden field in the form:

 <form method="post">
     <input
         type="hidden"
         name="invitation_id"
         value={invitation.id}
     />
+    <input
+        type="hidden"
+        name="email"
+        value={invitation.email}
+    />
     <Button

Or remove the email from the message:

             return dataWithSuccess(null, {
-                message: `Uitnodiging voor ${formValues.email} is ingetrokken`,
+                message: "Uitnodiging is ingetrokken",
             })
♻️ Duplicate comments (2)
fdm-app/app/routes/organization._index.tsx (1)

17-27: Defensive metadata access correctly implemented.

The OrganizationType now properly marks metadata as optional with optional nested fields, and the UI uses org.metadata?.description ?? "Geen beschrijving" for safe access. This addresses the previous review feedback.

Also applies to: 100-101

fdm-app/app/routes/organization.invitations._index.tsx (1)

81-97: Defensive access for inviter.name correctly implemented.

The code properly handles potentially null inviter name with invitation.inviter?.name || "Onbekend", addressing the previous review feedback about nullable inviter.name.

🧹 Nitpick comments (4)
fdm-app/app/routes/organization._index.tsx (1)

43-44: Consider adding type safety to useLoaderData.

The useLoaderData() call lacks type annotation, which reduces type safety. While other routes in this PR use useLoaderData<typeof loader>(), this file defines a local OrganizationType that could be leveraged.

🔎 Suggested fix
-    const { organizations } = useLoaderData()
+    const { organizations } = useLoaderData<typeof loader>()

This ensures type inference from the loader return type.

fdm-app/app/routes/organization.invitations._index.tsx (1)

46-47: Consider adding type safety to useLoaderData.

Similar to the other organization routes, using useLoaderData<typeof loader>() would provide better type inference.

🔎 Suggested fix
-    const { invitations } = useLoaderData()
+    const { invitations } = useLoaderData<typeof loader>()
fdm-app/app/routes/organization.$slug.tsx (2)

204-217: Minor: Redundant key prop and inconsistent optional chaining.

Two small issues:

  1. Line 207: The key={member.id} is redundant since the key is already set on the parent element in the .map() call (line 128).
  2. Line 217: member.user?.name uses optional chaining, but MemberWithUser defines user as required. Either the type should allow user to be nullable, or the optional chaining is unnecessary.
🔎 Suggested cleanup
     return (
         <div
-            key={member.id}
             className="flex items-center justify-between space-x-4"
         >
             <div className="flex items-center space-x-4">
                 <Avatar>
                     <AvatarImage src={member.user.image ?? undefined} />
                     <AvatarFallback>{initials}</AvatarFallback>
                 </Avatar>
                 <div>
                     <p className="text-sm font-medium leading-none">
-                        {member.user?.name}
+                        {member.user.name}
                     </p>

281-284: Minor: Redundant key prop on InvitationRow.

Similar to MemberRow, the key={invitation.id} on line 284 is redundant since it's already set on the component in the parent's .map() call (line 166).

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a67673 and 16e2559.

📒 Files selected for processing (3)
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
🧬 Code graph analysis (2)
fdm-app/app/routes/organization.invitations._index.tsx (3)
fdm-app/app/routes/organization.$slug.tsx (1)
  • loader (32-93)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)
  • loader (27-53)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization._index.tsx (3)
fdm-app/app/routes/organization.$slug.tsx (1)
  • loader (32-93)
fdm-app/app/routes/organization.tsx (1)
  • loader (33-67)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: core (24)
🔇 Additional comments (5)
fdm-app/app/routes/organization._index.tsx (1)

29-41: Loader migration looks correct.

The migration to auth.api.listOrganizations follows the same pattern as other organization routes, with proper session validation and error handling.

fdm-app/app/routes/organization.invitations._index.tsx (2)

32-44: Loader migration is consistent with other routes.

The migration to auth.api.listUserInvitations follows the established pattern with proper session validation and error handling.


208-240: Action handlers correctly migrated to better-auth API.

The accept/reject flows properly use auth.api.acceptInvitation and auth.api.rejectInvitation with the correct payload structure ({ invitationId }), consistent with the organization invitations respond route pattern.

fdm-app/app/routes/organization.$slug.tsx (2)

32-93: Loader properly migrated with permission computation.

The loader correctly:

  • Resolves organization by slug from the user's accessible organizations
  • Fetches members and computes permissions based on the current user's role
  • Conditionally fetches pending invitations only when the user has invite permissions
  • Uses defensive array handling for the invitations response

330-381: Form schema and components properly aligned with new API.

The FormSchema correctly includes memberId and invitation_id fields matching the better-auth API expectations, and InvitationForm properly accepts organizationId as a prop.

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

🤖 Fix all issues with AI Agents
In @fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx:
- Around line 74-76: The component currently throws dataWithError when intent is
invalid (the intent check using the intent variable and dataWithError), which
causes a runtime error because dataWithError returns a Response meant for
loaders/actions; instead handle this case in render by returning a safe UI or
performing a redirect: replace the throw with a call to Remix's redirect to the
invitations list (or return a React error message/state) so the app does not
throw a Response during render; ensure any user-facing toast/error is triggered
from an action/loader or use client-side state to show the error rather than
throwing dataWithError in the component.
🧹 Nitpick comments (5)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (2)

163-187: Error handling in accept flow swallows error details.

The catch block at line 169 discards the error (_) and throws a generic 404. This loses valuable debugging information. If the invitation acceptance fails for reasons other than "not found" (e.g., already accepted, expired, permission denied), users will see a misleading "not found" message.

🔎 Proposed improvement
         try {
             await auth.api.acceptInvitation({
                 headers: request.headers,
                 body: { invitationId: invitationId },
             })
-        } catch (_) {
-            throw data("Invitation not found", 404)
+        } catch (error) {
+            // Log error for debugging, then provide user-friendly message
+            console.error("Failed to accept invitation:", error)
+            throw data("Failed to accept invitation", { status: 400 })
         }

45-49: Inconsistent error handling: mixing data() and dataWithError.

Lines 33-36 use data() for 404 errors while lines 46-48 use dataWithError. The dataWithError function from remix-toast is designed for toast notifications, not HTTP error responses. This inconsistency may cause different error experiences for similar failure scenarios.

Consider using data() consistently for HTTP errors:

🔎 Proposed fix
     if (!invitation) {
-        throw dataWithError("Invitation not found", {
-            message: "Uitnodiging niet gevonden",
-        })
+        throw data("Uitnodiging niet gevonden", {
+            status: 404,
+            statusText: "Invitation not found",
+        })
     }
fdm-app/app/routes/organization.$slug.tsx (3)

182-189: Consider making user.name nullable in MemberWithUser type.

The user.name field is typed as string, but better-auth users may have nullable names. Line 204 already handles this with (member.user.name || "?"), but the type definition should reflect this possibility for type safety.

🔎 Suggested type adjustment
 type MemberWithUser = Member & {
     user: {
         id: string
-        name: string
+        name: string | null
         email: string
         image?: string | null
     }
 }

278-326: Redundant key prop in InvitationRow component.

The key attribute at line 281 is redundant since the parent already sets key={invitation.id} at line 166. This doesn't cause issues but adds unnecessary code.

🔎 Remove redundant key
     return (
         <div
-            key={invitation.id}
             className="flex items-center justify-between space-x-4"
         >

416-435: Email sending should verify invitation creation was successful.

The code checks if (invitation) before sending email, but if auth.api.createInvitation throws on failure, this check won't be reached. However, if the API returns a partial/invalid response, an email might be sent for a failed invitation.

Consider adding explicit success validation or wrapping in try-catch with appropriate error handling.

🔎 More robust check
             const invitation = await auth.api.createInvitation({
                 headers: request.headers,
                 body: {
                     email: formValues.email,
                     role: formValues.role,
                     organizationId: organizationId,
                 },
             })

             // better-auth might not send email by default depending on config.
             // We'll send it manually using our template.
-            if (invitation) {
+            if (invitation?.id) {
                 const invitationEmail = await renderInvitationEmail(
                     formValues.email,
                     session.user,
                     organizationName,
                     invitation.id,
                 )
                 await sendEmail(invitationEmail)
             }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16e2559 and 52925df.

📒 Files selected for processing (4)
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
🧰 Additional context used
🧠 Learnings (20)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-02-24T10:49:54.523Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 84
File: fdm-app/app/root.tsx:89-145
Timestamp: 2025-02-24T10:49:54.523Z
Learning: In the ErrorBoundary component of fdm-app/app/root.tsx, all client errors (400, 401, 403, 404) are intentionally displayed with a 404 status code for security purposes.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.

Applied to files:

  • fdm-app/app/routes/organization.invitations._index.tsx
  • fdm-app/app/routes/organization._index.tsx
  • fdm-app/app/routes/organization.$slug.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/organization._index.tsx
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • fdm-app/app/routes/organization.$slug.tsx
🧬 Code graph analysis (4)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (2)
fdm-app/app/routes/organization.$slug.tsx (2)
  • loader (32-93)
  • action (381-493)
fdm-app/app/routes/organization.invitations._index.tsx (2)
  • loader (30-53)
  • action (203-235)
fdm-app/app/routes/organization.invitations._index.tsx (2)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)
  • loader (27-52)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization._index.tsx (2)
fdm-app/app/routes/organization.tsx (1)
  • loader (33-67)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-app/app/routes/organization.$slug.tsx (3)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
fdm-core/src/authorization.ts (1)
  • permissions (32-138)
fdm-app/app/components/blocks/access/invitation-form.tsx (1)
  • InvitationForm (33-114)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: core (24)
🔇 Additional comments (7)
fdm-app/app/routes/organization._index.tsx (2)

16-28: LGTM! Loader migration to better-auth API looks correct.

The loader correctly validates the session and fetches organizations via auth.api.listOrganizations. The pattern aligns with other organization routes in this PR (e.g., organization.tsx loader at lines 32-66 in relevant snippets).


69-95: Organization card rendering handles the new data shape well.

The defensive access org.metadata?.description with fallback "Geen beschrijving" correctly handles potentially nullable metadata. The navigation using org.slug aligns with the routing pattern.

fdm-app/app/routes/organization.invitations._index.tsx (3)

203-234: Action implementation looks correct.

The action properly validates the session, handles accept/reject intents with the new auth.api methods, and redirects appropriately. Error handling is consistent.


122-126: or after


38-47: N+1 API calls pattern identified.

The loader fetches listUserInvitations then calls getInvitation for each invitation (lines 38-47). For users with many pending invitations, this creates N+1 API requests which could impact page load performance.

Verify whether listUserInvitations already returns all required fields (organizationName, inviterEmail, role, expiresAt, organizationId), or if a batched API endpoint is available. If so, the extra getInvitation calls are redundant.

fdm-app/app/routes/organization.$slug.tsx (2)

32-93: Loader migration looks solid with proper permission handling.

The loader correctly:

  • Resolves organization by slug from the user's accessible organizations
  • Fetches members and derives permissions from the current user's role
  • Conditionally fetches invitations only when the user has invite permission

The permission mapping (owner/admin → canEdit, canInvite, etc.) is clear and appropriate.


251-253: No action required—role values are correct.

The role values owner, admin, member match better-auth's default organization plugin roles. No changes needed.

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

🤖 Fix all issues with AI Agents
In @fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx:
- Around line 158-162: The action handler currently throws a 404 using
dataWithError("Invitation not found", {...}) when invitation is missing; change
this to return data({ message: "Uitnodiging niet gevonden" }, { status: 404 })
(i.e., use the same data() pattern as the loader) so the ErrorBoundary handles
it consistently—locate the missing-invitation branch in the respond action (the
block that checks invitation) and replace the dataWithError call with a
data(...) return including status: 404.
- Around line 164-189: The code assumes organization.slug is always present
after calling auth.api.getFullOrganization and uses it in redirectWithSuccess,
which can produce '/organization/undefined'; modify the accept-invitation branch
to check organization.slug (the value assigned to organizationSlug) for
null/undefined and handle it: either throw a user-facing error, use a sensible
fallback (e.g., organization.id or a default path), or ensure slug is generated
before redirect; update the block around auth.api.getFullOrganization,
organizationSlug, and redirectWithSuccess to perform this null check and handle
the missing slug case accordingly.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52925df and 98aa171.

📒 Files selected for processing (2)
  • fdm-app/app/routes/organization.$slug.tsx
  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • fdm-app/app/routes/organization.$slug.tsx
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-02-24T10:49:54.523Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 84
File: fdm-app/app/root.tsx:89-145
Timestamp: 2025-02-24T10:49:54.523Z
Learning: In the ErrorBoundary component of fdm-app/app/root.tsx, all client errors (400, 401, 403, 404) are intentionally displayed with a 404 status code for security purposes.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-30T08:51:44.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 64
File: fdm-core/src/farm.ts:25-48
Timestamp: 2025-01-30T08:51:44.741Z
Learning: The `handleError` function always throws an error, but for better code clarity and to satisfy TypeScript's control flow analysis, it's recommended to add a return statement after it, even though it will never be reached.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-14T16:06:24.294Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-01-14T16:06:21.832Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-04-18T13:49:17.029Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-app/app/components/custom/farm/farm-title.tsx:3-3
Timestamp: 2025-04-18T13:49:17.029Z
Learning: In the fdm project, NavLink and other routing components can be imported from either "react-router" or "react-router-dom" as react-router-dom is included in react-router.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx
🧬 Code graph analysis (1)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (1)
fdm-app/app/routes/organization.invitations._index.tsx (2)
  • loader (30-53)
  • action (203-235)
🔇 Additional comments (2)
fdm-app/app/routes/organization.invitations.$invitation_id.respond.tsx (2)

27-53: LGTM! Clean loader implementation.

The loader correctly validates the invitation ID, fetches the invitation via auth.api, and handles the not-found case appropriately with a 404 response.


191-207: LGTM! Reject and do_nothing flows are well-implemented.

The rejection flow appropriately handles errors and provides user feedback. The do_nothing intent offers a good escape hatch for users who navigate away.

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: 2

🤖 Fix all issues with AI Agents
In @fdm-core/src/db/schema-authn.ts:
- Around line 72-74: The account table's updatedAt column
(timestamp("updated_at").$onUpdate(...)) is missing .defaultNow(), causing
inserts to fail; update the column definition for updatedAt in the account
schema to include .defaultNow() before calling .$onUpdate(() => new Date()) so
it has a default timestamp on insert and still updates on modify.
- Around line 42-44: The updatedAt column definitions in the session and account
table schemas (the updatedAt fields) lack a default value causing inserts to
fail; update both definitions to include .defaultNow() (e.g., call .defaultNow()
on the updatedAt column before the .$onUpdate(...) and .notNull()) so they
mirror the user and verification tables and provide a default timestamp for
inserts.
🧹 Nitpick comments (1)
fdm-core/src/db/schema-authn.ts (1)

100-105: Redundant unique constraint on slug.

Line 100 uses .unique() which already creates a unique constraint (and implicitly a unique index in PostgreSQL). The explicit uniqueIndex on line 105 is redundant.

🔎 Proposed fix - remove redundant index
     (table) => [uniqueIndex("organization_slug_uidx").on(table.slug)],
+    // Remove the uniqueIndex callback entirely, or use regular index if needed:
+    // (table) => [],

Or remove .unique() from line 100 and keep only the named uniqueIndex if you prefer explicit index naming.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 98aa171 and ee7fb35.

⛔ Files ignored due to path filters (3)
  • fdm-core/src/db/migrations/0020_thick_zodiak.sql is excluded by !fdm-core/src/db/migrations/**
  • fdm-core/src/db/migrations/meta/0020_snapshot.json is excluded by !fdm-core/src/db/migrations/**
  • fdm-core/src/db/migrations/meta/_journal.json is excluded by !fdm-core/src/db/migrations/**
📒 Files selected for processing (1)
  • fdm-core/src/db/schema-authn.ts
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:18:44.350Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • fdm-core/src/db/schema-authn.ts
🔇 Additional comments (7)
fdm-core/src/db/schema-authn.ts (7)

1-11: LGTM!

The new imports for relations, index, and uniqueIndex are appropriate for the added relation mappings and table indices.


16-33: LGTM!

The user table has appropriate defaults for emailVerified, createdAt, updatedAt with the correct $onUpdate pattern, and lang. The timestamp handling is consistent and complete.


79-93: LGTM!

The verification table correctly implements the timestamp pattern with both .defaultNow() and .$onUpdate() on updatedAt. The index on identifier improves lookup performance.


108-125: LGTM!

The member table is well-structured with:

  • Appropriate default role of "member" for RBAC
  • Cascade delete on foreign keys
  • Indices on organizationId and userId for join performance

127-147: LGTM!

The invitation table is well-designed with:

  • Sensible defaults for status ("pending") and createdAt
  • Indices on organizationId and email for efficient lookups
  • Appropriate cascade delete on foreign keys

149-155: No concerns.

Rate limit table unchanged.


156-202: LGTM!

The relation mappings are correctly defined:

  • userRelations: Properly wires one-to-many relationships to sessions, accounts, members, and invitations
  • sessionRelations, accountRelations: Correctly reference back to user
  • organizationRelations: Properly links to members and invitations
  • memberRelations: Correctly joins organization and user
  • invitationRelations: Appropriately uses inviterId for the user relation

Comment thread fdm-core/src/db/schema-authn.ts
Comment thread fdm-core/src/db/schema-authn.ts
@SvenVw SvenVw requested a review from BoraIneviNMI January 6, 2026 12:21
@SvenVw SvenVw merged commit 0911b4d into development Jan 12, 2026
8 of 11 checks passed
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fdm-app/app/routes/organization.new.tsx (1)

66-72: Add session check to maintain consistency with sibling routes.

The parent organization.tsx loader protects this route with a session check, so the omission of getSession() from this loader is not a security issue. However, organization._index.tsx and other sibling routes retain the session check, and established patterns in this codebase (consistent with how other routes handle authentication guards) suggest keeping getSession(request) in the loader, even when the value isn't directly used. The action already calls getSession() for form submission validation, so adding it to the loader would simply align with the pattern used elsewhere.

🤖 Fix all issues with AI agents
In @fdm-app/app/routes/organization.new.tsx:
- Around line 238-262: There is a TOCTOU between auth.api.checkOrganizationSlug
and auth.api.createOrganization: remove the unreliable pre-check or handle
createOrganization duplicate-slug errors so users see the same friendly message;
specifically either delete the call to checkOrganizationSlug and rely on
createOrganization's error handling to map duplicate-slug errors into
dataWithError("Naam voor organisatie is niet meer beschikbaar..."), or wrap the
auth.api.createOrganization call in a try/catch that inspects the thrown error
for a duplicate-slug/conflict code and returns the same dataWithError response;
also confirm the pre-check's returned property name (do not assume it is status)
when you keep the check to avoid using a non-existent field.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee7fb35 and 41a73fa.

📒 Files selected for processing (1)
  • fdm-app/app/routes/organization.new.tsx
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The schema defined in fdm-core/src/db/schema-authn.ts follows better-auth's structure and requirements. While the schema is defined in the application code, modifications to it should maintain compatibility with better-auth's expectations.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:69-76
Timestamp: 2025-04-18T14:18:44.350Z
Learning: The authentication schema (fdm-authn) is based on better-auth's schema structure, which does not include `updatedAt` fields for tables like `organization`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm.settings._index.tsx:1-1
Timestamp: 2025-01-14T16:06:21.832Z
Learning: In the fdm project, `redirect` and other routing utilities should be imported from `react-router` instead of `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 45
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:1-1
Timestamp: 2025-01-14T16:06:24.294Z
Learning: In the fdm-app codebase, the `redirect` function should be imported from `react-router`, not `react-router-dom`.
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts will be updated in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5 to include id and email fields, which are necessary for subsequent role updates and user removal operations.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needs to include user ID and email fields to support role updates and user removal operations, which will be fixed in a future commit (b17fac16c9e5a0de56d0346e712b2ce966d305d5).

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts needed to include id and email fields for users, which was fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-04-18T14:51:48.033Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 124
File: fdm-core/src/organization.ts:300-339
Timestamp: 2025-04-18T14:51:48.033Z
Learning: The `getUsersInOrganization` function in fdm-core/src/organization.ts currently returns only firstname, surname, image, and role, but needs to include id and email fields to support downstream operations like role updates and user removal. This will be fixed in commit b17fac16c9e5a0de56d0346e712b2ce966d305d5.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-06-02T10:31:27.097Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 151
File: fdm-app/app/routes/signin._index.tsx:101-101
Timestamp: 2025-06-02T10:31:27.097Z
Learning: In fdm-app/app/routes/signin._index.tsx, the redirect destinations are intentionally inconsistent by design: the component defaults new sign-ins to "/welcome" (line 101) while the loader redirects authenticated users to "/farm" (line 80) and the action uses "/farm" as fallback (line 434). This creates appropriate user flows where new users complete their profile via the welcome page, while existing authenticated users bypass it and go directly to the main application.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:53:44.578Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:53:44.578Z
Learning: In the context of this React Router v7 project, it's important to follow the pattern of importing only the types (like UseFormReturn) from "react-hook-form" while importing the Form component from "react-router" to avoid naming conflicts.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, not from "remix-run/react".

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:41:43.484Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/fertilizer-applications/form.tsx:6-6
Timestamp: 2025-05-09T14:41:43.484Z
Learning: The project uses React Router v7 which exports a Form component directly from the "react-router" package, making importing from "remix-run/react" unnecessary.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-05-09T14:58:10.465Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 138
File: fdm-app/app/components/custom/combobox.tsx:34-37
Timestamp: 2025-05-09T14:58:10.465Z
Learning: When updating React components that use both react-hook-form and React Router v7, it's important to only import types (like UseFormReturn, FieldValues) from react-hook-form to avoid naming conflicts with React Router's Form component. Use `import type { ... } from 'react-hook-form'` syntax to ensure only types are imported.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-08-13T11:05:40.105Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 237
File: fdm-data/src/cultivations/catalogues/brp.ts:65-68
Timestamp: 2025-08-13T11:05:40.105Z
Learning: In fdm-app Select components, using `undefined` instead of empty string (`""`) as fallback value prevents empty strings from being submitted as form values. This approach fixes the issue at the UI source rather than requiring backend validation.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-02-24T10:49:54.523Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 84
File: fdm-app/app/root.tsx:89-145
Timestamp: 2025-02-24T10:49:54.523Z
Learning: In the ErrorBoundary component of fdm-app/app/root.tsx, all client errors (400, 401, 403, 404) are intentionally displayed with a 404 status code for security purposes.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-08-11T11:57:42.225Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields.$centroid.tsx:0-0
Timestamp: 2025-08-11T11:57:42.225Z
Learning: In Remix loaders, the `getSession(request)` call should be retained even when the returned session value isn't used elsewhere in the function, as it serves as an authentication guard that validates the user has a valid session and likely throws an error or redirects if the session is invalid. This is a common security pattern to protect routes.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/organization.new.tsx
🧬 Code graph analysis (1)
fdm-app/app/routes/organization.new.tsx (3)
fdm-app/app/routes/organization._index.tsx (1)
  • loader (16-28)
fdm-app/app/routes/organization.tsx (1)
  • loader (33-67)
fdm-core/src/db/generator/authn.ts (1)
  • auth (41-41)
🔇 Additional comments (3)
fdm-app/app/routes/organization.new.tsx (3)

31-31: LGTM!

Import correctly updated to use the centralized auth.server module, aligning with the migration to better-auth.


99-99: LGTM!

Good defensive coding with null coalescing to ensure convertToSlug always receives a string.


253-262: The code correctly uses metadata.description. Better-auth's createOrganization API does not include a dedicated top-level description field—metadata is the designed mechanism for storing custom organization data. This pattern is confirmed in the codebase's own test setup at ./fdm-core/src/principal.test.ts, which uses the same metadata: { description } structure.

Comment on lines +238 to +262
const { status } = await auth.api.checkOrganizationSlug({
headers: request.headers,
body: {
slug: slug,
},
})

if (!status) {
return dataWithError(
null,
"Naam voor organisatie is niet meer beschikbaar. Kies een andere naam",
)
}

// Create the organization
await createOrganization(fdm, user_id, name, slug, description)
await auth.api.createOrganization({
headers: request.headers,
body: {
name,
slug,
metadata: {
description,
},
},
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the full context of the function containing these lines
fd -e tsx organization.new.tsx | head -5

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Get file size and read the relevant section with more context
wc -l fdm-app/app/routes/organization.new.tsx && sed -n '200,280p' fdm-app/app/routes/organization.new.tsx

Repository: SvenVw/fdm

Length of output: 2623


🏁 Script executed:

# Search for better-auth imports and API usage patterns
rg "auth\.api\." fdm-app/app/routes/organization.new.tsx -B 2 -A 5

Repository: SvenVw/fdm

Length of output: 483


🏁 Script executed:

# Look for type definitions or interfaces for these API calls
fd -e ts -e tsx | xargs rg "checkOrganizationSlug|createOrganization" -l

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Search for handleActionError implementation
rg "handleActionError" -A 10 fdm-app/app/routes/organization.new.tsx

Repository: SvenVw/fdm

Length of output: 658


🏁 Script executed:

# Look for where handleActionError is imported from
rg "import.*handleActionError" fdm-app/app/routes/organization.new.tsx

Repository: SvenVw/fdm

Length of output: 120


🏁 Script executed:

# Find the handleActionError function definition
rg "export.*function handleActionError|export const handleActionError" -A 15

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Search for better-auth API type definitions or usage
fd -e ts -e tsx | xargs rg "auth\.api\." -l | head -10

Repository: SvenVw/fdm

Length of output: 492


🏁 Script executed:

# Look for better-auth package or similar in package files
fd -e json package.json -o -e lock | head -5

Repository: SvenVw/fdm

Length of output: 170


🏁 Script executed:

# Find the error handling library
fd lib/error.ts -o -e lib/error.tsx | xargs cat

Repository: SvenVw/fdm

Length of output: 170


🏁 Script executed:

# Find package.json
fd package.json | head -5

Repository: SvenVw/fdm

Length of output: 168


🏁 Script executed:

# Read package.json to see better-auth version
cat fdm-app/package.json | grep -A 5 -B 5 "better-auth" 2>/dev/null || cat package.json | grep -A 5 -B 5 "better-auth" 2>/dev/null || find . -name package.json -type f | xargs grep -l "better-auth" | head -3

Repository: SvenVw/fdm

Length of output: 446


🏁 Script executed:

# Search for auth setup/initialization
rg "auth\.api\s*=" -A 5 | head -30

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Look for type definitions or interfaces for auth API
fd -e ts -e tsx | xargs rg "interface.*Organization|type.*Organization" | grep -i "slug\|status\|create" | head -10

Repository: SvenVw/fdm

Length of output: 171


🏁 Script executed:

# Let's find the error handling implementation
find . -path ./node_modules -prune -o -name error.ts -o -name error.tsx | grep -v node_modules | xargs cat 2>/dev/null | head -100

Repository: SvenVw/fdm

Length of output: 4074


🏁 Script executed:

# Look for the auth initialization to understand the API structure
rg "auth\s*=" fdm-app/app -A 10 | head -50

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Search for better-auth plugin or organization plugin usage
rg "organizationPlugin\|organization" fdm-app -A 5 -B 5 | head -80

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Check if there are any better-auth type definitions in the project
fd -e ts -e tsx | xargs rg "createOrganization|checkOrganizationSlug" -B 5 -A 10

Repository: SvenVw/fdm

Length of output: 2122


🏁 Script executed:

# Look at how other routes handle similar API calls
rg "auth\.api\." fdm-app/app/routes -l | xargs grep -l "createOrganization\|checkOrganizationSlug"

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Search for handleActionError implementation more broadly
rg "function handleActionError|export.*handleActionError" -A 20

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Check the auth initialization and type definitions
rg "import.*auth|from.*auth" fdm-app/app -B 2 | head -50

Repository: SvenVw/fdm

Length of output: 4186


🏁 Script executed:

# Look for better-auth server setup or plugin configuration
fd -e ts -e tsx | xargs rg "initAuthConfig\|betterAuth\|better-auth" -B 5 -A 10 | head -80

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Check if there are any tests or documentation about these API calls
fd -e test.ts -e test.tsx -e spec.ts | xargs grep -l "checkOrganizationSlug\|createOrganization" 2>/dev/null

Repository: SvenVw/fdm

Length of output: 38


🏁 Script executed:

# Search for any comments or documentation about the organization API
rg "organization" fdm-app/app -B 2 -A 2 | grep -i "slug\|race\|check\|create" | head -30

Repository: SvenVw/fdm

Length of output: 2340


🏁 Script executed:

# Find and read auth.server.ts to understand the auth API setup
fd auth.server.ts -o auth.server.tsx | head -1 | xargs cat | head -200

Repository: SvenVw/fdm

Length of output: 203


🏁 Script executed:

# Look for better-auth version in monorepo root or lockfile
find . -maxdepth 2 -name "package.json" -o -name "pnpm-lock.yaml" -o -name "package-lock.json" -o -name "yarn.lock" | head -5

Repository: SvenVw/fdm

Length of output: 178


🏁 Script executed:

# Check the root package.json or package-lock for better-auth
cat package.json 2>/dev/null | grep -A 5 -B 5 "better-auth" || ls -la | grep -E "lock|pnpm"

Repository: SvenVw/fdm

Length of output: 192


🏁 Script executed:

# Search for any organization plugin or custom organization API implementation
rg "organizationPlugin\|Organization.*Plugin" -A 10 -B 5

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Look at how auth is instantiated or configured
rg "auth\s*=\s*new|auth\s*=\s*{" -A 15

Repository: SvenVw/fdm

Length of output: 171


🏁 Script executed:

# Find auth.server file
find . -path ./node_modules -prune -o -name "*auth.server*" -type f -print

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Look at the auth setup more carefully
rg "auth\s*=" fdm-app/app/lib -A 10

Repository: SvenVw/fdm

Length of output: 109


🏁 Script executed:

# Check if better-auth is used in pnpm-lock
grep -A 5 "better-auth" pnpm-lock.yaml | head -20

Repository: SvenVw/fdm

Length of output: 1092


🏁 Script executed:

# Search for error handling to understand how it works
rg "handleActionError" -A 15 fdm-app/app/lib

Repository: SvenVw/fdm

Length of output: 109


🏁 Script executed:

# Check organization plugin usage more carefully
rg "organizations\|Organization" fdm-app/app/lib -B 3 -A 10 | head -60

Repository: SvenVw/fdm

Length of output: 109


🏁 Script executed:

# Find the actual lib directory structure
find fdm-app/app -type d | grep -E "lib|util" | head -10

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# List the structure of fdm-app/app
ls -la fdm-app/app/

Repository: SvenVw/fdm

Length of output: 844


🏁 Script executed:

# Search for error handling in the entire fdm-app
rg "handleActionError" fdm-app -A 15 | head -80

Repository: SvenVw/fdm

Length of output: 5287


🏁 Script executed:

# Look for auth server configuration
find fdm-app -name "*auth*" -type f | grep -v node_modules

Repository: SvenVw/fdm

Length of output: 352


🏁 Script executed:

# Find where lib is defined
find fdm-app -type d -name lib

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Look at the api.auth route to understand auth setup
cat fdm-app/app/routes/api.auth.$.tsx | head -100

Repository: SvenVw/fdm

Length of output: 1822


🏁 Script executed:

# Search more broadly for error handling
find fdm-app -name "error*" -type f

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Look for all imports from ~/lib
rg "from.*~/lib" fdm-app/app/routes/organization.new.tsx

Repository: SvenVw/fdm

Length of output: 275


🏁 Script executed:

# Find where ~ is aliased to - check vite config or tsconfig
find fdm-app -maxdepth 2 -name "vite.config.*" -o -name "tsconfig.json" | xargs cat | grep -A 10 "alias\|~"

Repository: SvenVw/fdm

Length of output: 430


🏁 Script executed:

# Look for the lib directory relative to the routes
ls -la fdm-app/

Repository: SvenVw/fdm

Length of output: 1138


🏁 Script executed:

# Check if lib is at a different level
find . -type d -name lib | grep -v node_modules

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Read the error handling module
find . -path ./node_modules -prune -o -name "error.tsx" -o -name "error.ts" -print | xargs cat 2>/dev/null | head -100

Repository: SvenVw/fdm

Length of output: 2105


🏁 Script executed:

# Find handleActionError and handleLoaderError specifically
rg "export.*function handleActionError|export.*function handleLoaderError|handleActionError\s*=" fdm-app -A 20

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Search in the entire error module
find . -path ./node_modules -prune -o -name "error.ts" -o -name "error.tsx" -print | xargs rg "handleActionError|handleLoaderError" -A 15

Repository: SvenVw/fdm

Length of output: 38


🏁 Script executed:

# Search more broadly for handleActionError definition
rg "handleActionError" --type ts --type tsx -A 10

Repository: SvenVw/fdm

Length of output: 81


🏁 Script executed:

# Look at all files in the error path
find fdm-app -name "*error*" -type f

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Try searching the entire codebase
rg "function handleActionError" -A 15

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Check if it's exported from a different file
rg "export.*handleActionError" -A 5

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Read the error files directly
cat fdm-app/app/components/custom/error.tsx

Repository: SvenVw/fdm

Length of output: 5386


🏁 Script executed:

# Check if there's an error module at the root app level
ls -la fdm-app/app/*.ts fdm-app/app/*.tsx 2>/dev/null | grep error

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Try finding all files importing from ~/lib/error
rg "from.*error" fdm-app/app/routes -A 1 | head -20

Repository: SvenVw/fdm

Length of output: 1249


🏁 Script executed:

# Search for handleActionError without the export keyword
rg "handleActionError" | head -20

Repository: SvenVw/fdm

Length of output: 2430


🏁 Script executed:

# Find where lib is actually located
find . -path ./node_modules -prune -o -type d -name lib -print | head -10

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Check if lib is at the root level
ls -la lib/ 2>/dev/null || echo "lib not found at root"

Repository: SvenVw/fdm

Length of output: 75


🏁 Script executed:

# List all directories in the monorepo
ls -la

Repository: SvenVw/fdm

Length of output: 1507


🏁 Script executed:

# Search for handleActionError definition across entire monorepo
rg "function handleActionError|const handleActionError" -A 10

Repository: SvenVw/fdm

Length of output: 36


🏁 Script executed:

# Search in fdm-app for where lib is
find fdm-app -type f -name "*.ts" -o -name "*.tsx" | xargs grep -l "handleActionError" | head -3

Repository: SvenVw/fdm

Length of output: 258


🏁 Script executed:

# Let's check if lib is defined inside fdm-app
ls -la fdm-app/

Repository: SvenVw/fdm

Length of output: 1138


🏁 Script executed:

# Look in all subdirectories of fdm-app
find fdm-app -type f \( -name "*error*" -o -name "*lib*" \) | head -20

Repository: SvenVw/fdm

Length of output: 93


🏁 Script executed:

# Try web search for better-auth API documentation
web_search
better-auth checkOrganizationSlug API response format

Repository: SvenVw/fdm

Length of output: 154


🌐 Web query:

better-auth checkOrganizationSlug API response format

💡 Result:

Endpoint: POST /organization/check-slug

Client usage: authClient.organization.checkSlug({ slug: "my-org" }) — response returned as the client wrapper { data, error }. [1]

Server usage: auth.api.checkOrganizationSlug({ body: { slug: "my-org" } }) — server-side endpoint exposed as auth.api.checkOrganizationSlug. Server endpoints return a plain JS object (or throw APIError). [1][2]

Docs: Organization plugin — "Check if organization slug is taken" (shows the endpoint, client call, and server api call). [1][2]

If you want an exact example JSON response (e.g., { available: true } vs { exists: false }), tell me and I will fetch/inspect the implementation or run a sample call. [1]

Sources:
[1] Better Auth — Organization plugin docs (check-slug examples).
[2] Better Auth — API concepts (server endpoints return JS objects / error handling).


🏁 Script executed:

# Let's search for where lib is defined - maybe it's generated
find fdm-app -name "*.ts" -o -name "*.tsx" | head -20 | xargs ls -la

Repository: SvenVw/fdm

Length of output: 2183


🏁 Script executed:

# Look for any imports that create the lib alias
grep -r "handleActionError\|handleLoaderError" fdm-app/app --include="*.ts" --include="*.tsx" -l | head -5 | xargs cat | grep -A 50 "handleActionError\|handleLoaderError"

Repository: SvenVw/fdm

Length of output: 18827


Potential race condition between slug check and organization creation.

There's a TOCTOU (time-of-check to time-of-use) window where another user could claim the slug between lines 238-243 (check) and lines 253-262 (create). If createOrganization throws on duplicate slugs, the error will be caught and handled, but the user would receive a generic error response instead of the friendly "slug not available" message from the pre-check.

Consider one of these approaches:

  1. Remove the pre-check and rely on catching and translating duplicate slug errors from createOrganization
  2. Wrap createOrganization in error handling to catch slug conflicts specifically and return the same user-friendly message

Also verify that the checkOrganizationSlug response actually returns a status field, as the better-auth API documentation suggests it may use a different field name.

🤖 Prompt for AI Agents
In @fdm-app/app/routes/organization.new.tsx around lines 238 - 262, There is a
TOCTOU between auth.api.checkOrganizationSlug and auth.api.createOrganization:
remove the unreliable pre-check or handle createOrganization duplicate-slug
errors so users see the same friendly message; specifically either delete the
call to checkOrganizationSlug and rely on createOrganization's error handling to
map duplicate-slug errors into dataWithError("Naam voor organisatie is niet meer
beschikbaar..."), or wrap the auth.api.createOrganization call in a try/catch
that inspects the thrown error for a duplicate-slug/conflict code and returns
the same dataWithError response; also confirm the pre-check's returned property
name (do not assume it is status) when you keep the check to avoid using a
non-existent field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch:development Issue only affecting development, not the main branch (yet) enhancement New feature or request fdm-app fdm-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate Organization Management to Better-Auth Plugin

1 participant