Skip to content

feat: add core entities for raid management#10

Merged
ECWireless merged 3 commits into
mainfrom
codex/core-entity-management
Jun 3, 2026
Merged

feat: add core entities for raid management#10
ECWireless merged 3 commits into
mainfrom
codex/core-entity-management

Conversation

@ECWireless
Copy link
Copy Markdown
Member

@ECWireless ECWireless commented Jun 3, 2026

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

  • Added new columns archived_at to the entities and raids tables to support archiving, along with corresponding indexes for efficient querying.
  • Enforced unique constraints on the entity_addresses table for the combination of chain_id and address (case-insensitive), preventing duplicate addresses.
  • Updated the database migration journal to track these schema changes.

Server Actions and Error Handling

  • Implemented comprehensive server actions in actions.ts for 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

  • Introduced new client-side management forms for providers and raid entities (provider-management-forms.tsx, raid-management-forms.tsx) using useActionState for optimistic UI and inline error messages, improving the user experience for entity and address creation. [1] [2]
  • Added a reusable toast notification component for provider management to display success and error messages based on URL query parameters.

Navigation and UI Improvements

  • Refactored the main navigation in the member home page to use a new AppNavLink component and improved the layout and visibility of admin/accounting links based on user permissions. [1] [2]

Most important changes:

Database and Backend:

  • Added archived_at columns and indexes to entities and raids tables for archiving support.
  • Enforced unique constraint on entity_addresses for (chain_id, address) to prevent duplicates.
  • Updated migration journal with new schema changes.

Server Actions and Error Handling:

  • Implemented robust server actions for providers and raid entities, including detailed error handling for address validation and uniqueness. [1] [2]

Frontend Forms and Feedback:

  • Added new client-side forms for provider and raid entity management, with inline error messaging and optimistic UI. [1] [2]
  • Introduced toast notifications for provider management actions to give immediate user feedback.

Navigation/UI:

  • Improved admin and accounting navigation with a new AppNavLink component and permission-based visibility. [1] [2]

Summary by CodeRabbit

Release Notes

  • New Features
    • Provider Management: New admin interface to create, edit, archive/restore, and delete providers with multiple address support
    • Raid Management: Complete system for managing raids, clients, and subcontractors with address management
    • Soft-archive functionality: Archive and restore providers and raids instead of permanent deletion
    • Improved navigation with quick access to Providers and Accounting sections

Copilot AI review requested due to automatic review settings June 3, 2026 20:54
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
raidguild-accounting Ready Ready Preview, Comment Jun 3, 2026 9:46pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Warning

Review limit reached

@ECWireless, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca64f4bf-cd55-46fb-9ff9-66c3efc3af83

📥 Commits

Reviewing files that changed from the base of the PR and between 5bac22d and 2f36acb.

📒 Files selected for processing (9)
  • src/app/admin/providers/actions.ts
  • src/app/admin/providers/page.tsx
  • src/app/admin/providers/provider-management-forms.tsx
  • src/app/admin/providers/provider-management-toast.tsx
  • src/app/raids/actions.ts
  • src/app/raids/page.tsx
  • src/app/raids/raid-management-forms.tsx
  • src/app/raids/raid-management-toast.tsx
  • src/lib/core-entity-mutations.ts
📝 Walkthrough

Walkthrough

This PR adds soft-archive functionality to the accounting system by introducing archived_at timestamp columns to entities and raids tables, enforcing normalized address uniqueness, and building complete provider and raid management UIs with CRUD operations, permission-gated access, form state handling, and audit logging.

Changes

Provider and Raid Entity Management with Soft-Archive Support

Layer / File(s) Summary
Database schema with soft-archive support
drizzle/0004_flippant_nightshade.sql, drizzle/0005_public_diamondback.sql, src/db/schema.ts, drizzle/meta/*
Adds archived_at timestamp columns and indexes to entities and raids tables; adds a unique index on entity_addresses enforcing case-insensitive address uniqueness per chain with NULL-safe chainId normalization. Drizzle snapshots and journal updated.
Core entity and raid data layer
src/lib/core-entities.ts
Exports query functions listEntitiesByTypes() and listRaids() that load entities and raids by type, decrypt encrypted fields, and map database rows into CoreEntityView and RaidView objects with associated addresses.
Core mutations for entities, addresses, and raids
src/lib/core-entity-mutations.ts
Server-only CRUD and lifecycle mutations (create/update/archive/restore/delete) for entities and raids with permission-gated authorization (canAdmin for providers, canWriteRaidAccounting for raids). Enforces address uniqueness, encrypts sensitive fields, logs audit events, and revalidates cache on mutations.
Provider management feature
src/app/admin/providers/actions.ts, src/app/admin/providers/page.tsx, src/app/admin/providers/provider-management-forms.tsx, src/app/admin/providers/provider-management-toast.tsx
Admin page and server actions for provider CRUD with address management. Form components use useActionState to handle validation errors; toast notifications provide user feedback on success/failure. Page enforces canAdmin permission gating.
Raid management feature
src/app/raids/actions.ts, src/app/raids/page.tsx, src/app/raids/raid-management-forms.tsx, src/app/raids/raid-management-toast.tsx
Raid management page and server actions for raid and raid-related entity (client/subcontractor) CRUD. Flow-based UI allows users to select creation type; forms handle address validation errors with state-based feedback. Page enforces canWriteRaidAccounting permission gating.
Application navigation update
src/app/page.tsx
Refactors header navigation to use permission-gated AppNavLink components for accounting sections (Raids, Providers, Quarters, Accounts), replacing hardcoded admin buttons with conditional rendering.
Component styling updates
src/components/auth/wallet-connect.tsx, src/components/ui/button.tsx
Minor CSS adjustments: adds cursor-pointer to buttons; updates wallet-connect container and logout button styling.

Sequence Diagram

sequenceDiagram
  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"
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • raid-guild/accounting#2: Establishes the initial Drizzle ORM schema that this PR extends with archived_at columns and corresponding management UI.

Poem

🐰 Archive Quest Complete!

Soft-delete hops into the schema today,
With timestamps to mark the archived way,
Providers and raids now craft and restore,
Forms dance with validation galore! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the PR, which is adding core entities for raid management including database schema, backend mutations, and frontend UI.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/core-entity-management

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.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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-entities read helpers and core-entity-mutations server-only CRUD + auditing + revalidation for entities, addresses, and raids.
  • Adds new management UIs for Raids and Providers, including toast-based feedback and useActionState form error rendering for address validation.
  • Extends DB schema with archived_at (entities/raids) and enforces case-insensitive uniqueness for (chain_id,address) on entity_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.

Comment thread src/lib/core-entity-mutations.ts
Comment thread src/lib/core-entity-mutations.ts
Comment thread src/app/raids/page.tsx Outdated
Comment thread src/app/admin/providers/page.tsx Outdated
Comment thread src/app/raids/page.tsx Outdated
Copy link
Copy Markdown

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad2c54 and 5bac22d.

📒 Files selected for processing (19)
  • drizzle/0004_flippant_nightshade.sql
  • drizzle/0005_public_diamondback.sql
  • drizzle/meta/0004_snapshot.json
  • drizzle/meta/0005_snapshot.json
  • drizzle/meta/_journal.json
  • src/app/admin/providers/actions.ts
  • src/app/admin/providers/page.tsx
  • src/app/admin/providers/provider-management-forms.tsx
  • src/app/admin/providers/provider-management-toast.tsx
  • src/app/page.tsx
  • src/app/raids/actions.ts
  • src/app/raids/page.tsx
  • src/app/raids/raid-management-forms.tsx
  • src/app/raids/raid-management-toast.tsx
  • src/components/auth/wallet-connect.tsx
  • src/components/ui/button.tsx
  • src/db/schema.ts
  • src/lib/core-entities.ts
  • src/lib/core-entity-mutations.ts

Comment thread src/app/admin/providers/actions.ts
Comment thread src/app/admin/providers/provider-management-forms.tsx Outdated
Comment thread src/app/admin/providers/provider-management-toast.tsx
Comment thread src/app/raids/page.tsx
Comment thread src/app/raids/raid-management-forms.tsx Outdated
Comment thread src/app/raids/raid-management-toast.tsx
Comment thread src/lib/core-entity-mutations.ts
Comment thread src/lib/core-entity-mutations.ts
Comment thread src/lib/core-entity-mutations.ts
@ECWireless ECWireless merged commit aadff02 into main Jun 3, 2026
5 checks passed
@ECWireless ECWireless deleted the codex/core-entity-management branch June 3, 2026 21:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants