feat: add core entities for raid management#10
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
More reviews will be available in 8 minutes and 3 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR adds soft-archive functionality to the accounting system by introducing ChangesProvider and Raid Entity Management with Soft-Archive Support
Sequence DiagramsequenceDiagram
participant User
participant ProviderPage as Provider Admin Page
participant ProviderForm as ProviderCreateForm
participant Action as createProviderWithState
participant CoreMutation as createEntityForAccess
participant Database as DB
participant Toast as Toast Notifier
User->>ProviderPage: Navigate to /admin/providers
ProviderPage->>ProviderPage: Check canAdmin permission
ProviderPage->>ProviderForm: Render form
User->>ProviderForm: Fill name, website, address
ProviderForm->>Action: Submit FormData
Action->>CoreMutation: Parse & validate
CoreMutation->>Database: Check address uniqueness
Database-->>CoreMutation: Address valid
CoreMutation->>Database: Encrypt & insert entity
CoreMutation->>Database: Write audit event
Database-->>CoreMutation: Success
Action->>ProviderPage: Redirect ?added=provider
ProviderPage->>Toast: Show success notification
Toast->>User: "Provider added successfully"
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a new “core entities” layer (entities + entity addresses + raids) with server-side mutation helpers and new admin/cleric UI screens to create/update/archive/delete providers, clients, subcontractors, and raids, along with navigation tweaks to surface the new sections.
Changes:
- Introduces
core-entitiesread helpers andcore-entity-mutationsserver-only CRUD + auditing + revalidation for entities, addresses, and raids. - Adds new management UIs for Raids and Providers, including toast-based feedback and
useActionStateform error rendering for address validation. - Extends DB schema with
archived_at(entities/raids) and enforces case-insensitive uniqueness for(chain_id,address)onentity_addresses.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/core-entity-mutations.ts | Server-only entity/raid mutation helpers: CRUD, archive/restore, address add/remove, audit events, revalidation. |
| src/lib/core-entities.ts | Server-only read/view helpers for entities, addresses, and raids with decryption + mapping. |
| src/db/schema.ts | Adds archived_at columns + indexes and a case-insensitive unique index for entity addresses. |
| src/components/ui/button.tsx | Adjusts base button styling to include cursor-pointer. |
| src/components/auth/wallet-connect.tsx | Updates wallet display styling/layout in the header. |
| src/app/raids/raid-management-toast.tsx | Client toast component for raid management success/error feedback via query params. |
| src/app/raids/raid-management-forms.tsx | Client forms for creating raid-related entities and adding addresses with inline error state. |
| src/app/raids/page.tsx | New raids management page (clients/subcontractors/raids) with CRUD forms and archive/delete flows. |
| src/app/raids/actions.ts | Server actions wiring raid UI to core-entity-mutations, with address-error parsing + redirects/state. |
| src/app/page.tsx | Refactors member header nav with AppNavLink and permission-based section links. |
| src/app/admin/providers/provider-management-toast.tsx | Client toast component for provider management success/error feedback via query params. |
| src/app/admin/providers/provider-management-forms.tsx | Client forms for creating providers and adding addresses with inline error state. |
| src/app/admin/providers/page.tsx | New providers admin page for provider CRUD, archiving, and address management. |
| src/app/admin/providers/actions.ts | Server actions wiring provider UI to core-entity-mutations, with address-error parsing + redirects/state. |
| drizzle/meta/0004_snapshot.json | Drizzle snapshot capturing schema state including archived columns/indexes. |
| drizzle/meta/0005_snapshot.json | Drizzle snapshot capturing schema state including entity address uniqueness index. |
| drizzle/meta/_journal.json | Migration journal updated to include 0004 and 0005. |
| drizzle/0004_flippant_nightshade.sql | Migration adding archived_at to entities/raids and corresponding indexes. |
| drizzle/0005_public_diamondback.sql | Migration adding unique index on entity_addresses (coalesce(chain_id,-1), lower(address)). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/admin/providers/actions.ts`:
- Around line 15-62: Replace brittle message/constraint-string parsing in
getAddressError and getAddressErrorMessage by switching on a structured error
code emitted from the mutation layer: update the mutation(s) to throw a typed
error (e.g., ValidationError or an Error with a stable `code` property like
"duplicate_address", "invalid_address", "invalid_chain", "missing_address"),
then change getAddressError to inspect error.code (and narrow via `instanceof`
or a type-guard) and map those codes to the same return values
("duplicate-address", "invalid-address", etc.); keep the existing message-based
checks only as a fallback for backward compatibility and update typings for the
new error shape so callers and tests reflect the structured codes.
In `@src/app/admin/providers/provider-management-forms.tsx`:
- Around line 94-99: The form disables browser validation via the noValidate
attribute which prevents the required "name" TextInput from showing a
user-facing error and causes server action errors to be thrown; fix by removing
noValidate from the <form> element so native required validation for the "name"
field is preserved, or alternatively extend ProviderFormState (the server action
state type) to include non-address validation errors (e.g., name) and update the
provider create action handler and the form rendering logic to display those
errors for the TextInput "name" field.
In `@src/app/admin/providers/provider-management-toast.tsx`:
- Around line 44-65: The dedupe ref shownToastKey is never reset so once a toast
for a given toastKey is shown it will never show again; inside the useEffect
that computes toastKey (in provider-management-toast.tsx) update the logic to
reset shownToastKey.current to null when the query params are cleared (i.e.,
toastKey === ":" or when you call router.replace("/admin/providers")), and
ensure you still set shownToastKey.current = toastKey only when actually showing
a toast in the added or error branches so future identical params can trigger
toasts again after they were cleared.
In `@src/app/raids/page.tsx`:
- Around line 497-507: The select for clientEntityId uses only the active
clients list so defaultValue={raid.clientEntityId} can mismatch when the raid
references an archived client; update the rendering in src/app/raids/page.tsx so
the options include the raid's current client even if it's archived: before
mapping, build a list (e.g., allClients) that contains clients plus, if
clients.some(c => c.id === raid.clientEntityId) is false, append the raid's
client (lookup by id from archived list or construct from
raid.clientEntityId/name) so the <select name="clientEntityId"> mapping
(clients.map(...) currently) always includes an <option> with value ===
raid.clientEntityId.
In `@src/app/raids/raid-management-forms.tsx`:
- Around line 102-105: The form currently disables browser validation with
noValidate which causes an empty "name" to bypass the native required check and
surface as an uncaught server-action error because createRaidEntityWithState()
only maps address failures into state.message; remove the noValidate attribute
from the <form> element (or alternatively update createRaidEntityWithState() and
the action handler to return per-field validation errors for the "name" field)
so the TextInput required check runs and users get inline browser feedback
instead of a server error.
In `@src/app/raids/raid-management-toast.tsx`:
- Around line 60-69: The dedupe ref shownToastKey prevents toasts after
router.replace clears query params because when toastKey === ":::” you return
early without clearing the ref; update the useEffect that computes toastKey
(inside raid-management-toast component) to reset shownToastKey.current = null
before returning when toastKey === ":::” so the next non-empty toastKey isn't
treated as a duplicate; keep the existing equality check shownToastKey.current
=== toastKey unchanged.
In `@src/lib/core-entity-mutations.ts`:
- Around line 404-416: When deleting an archived entity in the delete flow
(functions: requireEntityAccess, assertUuid/getString, assertArchivedEntity and
the delete call getDb().delete(entities).where(eq(entities.id, id))), add a
pre-delete check that if entity.type === "client" queries the raids table for
any rows where raids.client_entity_id === id; if any exist, abort and return a
controlled validation error (instead of attempting the delete) so callers
receive a clear message that the client cannot be permanently deleted while
dependent raids exist. Perform this check immediately after assertArchivedEntity
and before the delete and audit write.
- Around line 281-301: The entity creation and address insert must be performed
inside a single DB transaction so the address uniqueness check and the insert
are atomic: wrap the sequence using getDb().transaction (or your DB's
transactional API) and move/perform the uniqueness check and
insertAddressForEntity call within that transaction (i.e., call
assertUniqueAddress or perform a SELECT FOR UPDATE of the address inside the
same transaction before inserting the entity), then insert the entity and
immediately insert the address for that entity in the same transaction; on
unique constraint violation from the address insert, rollback and surface a
proper error instead of leaving a committed entity row (handle the DB-specific
unique constraint error in the transaction's catch to return a friendly conflict
error).
- Around line 103-108: The code currently converts rawChainId to a Number and
only checks integer-ness, which allows non-positive values (e.g., -1 or 0) that
collide with the DB's NULL->-1 normalization; update the validation in the block
using getString and variables rawChainId and chainId so that if chainId is not
null it must be a positive integer (reject <= 0) and throw a clear Error (e.g.,
"Chain ID must be a positive whole number") to prevent submitting non-positive
chain IDs that break entity_addresses_chain_address_unique.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a4c14413-9865-4dc3-b863-ed5ae7271de1
📒 Files selected for processing (19)
drizzle/0004_flippant_nightshade.sqldrizzle/0005_public_diamondback.sqldrizzle/meta/0004_snapshot.jsondrizzle/meta/0005_snapshot.jsondrizzle/meta/_journal.jsonsrc/app/admin/providers/actions.tssrc/app/admin/providers/page.tsxsrc/app/admin/providers/provider-management-forms.tsxsrc/app/admin/providers/provider-management-toast.tsxsrc/app/page.tsxsrc/app/raids/actions.tssrc/app/raids/page.tsxsrc/app/raids/raid-management-forms.tsxsrc/app/raids/raid-management-toast.tsxsrc/components/auth/wallet-connect.tsxsrc/components/ui/button.tsxsrc/db/schema.tssrc/lib/core-entities.tssrc/lib/core-entity-mutations.ts
This pull request introduces significant improvements to both the backend and frontend for managing providers and raid-related entities, focusing on form handling, error feedback, and navigation. It adds robust server actions for CRUD operations, client-side forms with error messaging, and enhances the navigation UI for admin and accounting sections. Additionally, it updates the database schema to support archiving and enforces address uniqueness.
Backend and Database Enhancements
archived_atto theentitiesandraidstables to support archiving, along with corresponding indexes for efficient querying.entity_addressestable for the combination ofchain_idand address (case-insensitive), preventing duplicate addresses.Server Actions and Error Handling
actions.tsfor both providers and raid-related entities, supporting create, update, archive, restore, delete, and address management, with detailed error parsing and redirection logic. [1] [2]Frontend Forms and User Feedback
provider-management-forms.tsx,raid-management-forms.tsx) usinguseActionStatefor optimistic UI and inline error messages, improving the user experience for entity and address creation. [1] [2]Navigation and UI Improvements
AppNavLinkcomponent and improved the layout and visibility of admin/accounting links based on user permissions. [1] [2]Most important changes:
Database and Backend:
archived_atcolumns and indexes toentitiesandraidstables for archiving support.entity_addressesfor(chain_id, address)to prevent duplicates.Server Actions and Error Handling:
Frontend Forms and Feedback:
Navigation/UI:
AppNavLinkcomponent and permission-based visibility. [1] [2]Summary by CodeRabbit
Release Notes