Skip to content

Crucial Edge Cases & Anti-Patterns

This document outlines critical edge cases, known architectural limitations, and a consolidated list of anti-patterns. Adhering to these guidelines is crucial for maintaining application stability, security, and code quality.

Backend: Manual and Inconsistent Workspace Scoping

Section titled “Backend: Manual and Inconsistent Workspace Scoping”

A critical aspect of the backend architecture is its multi-tenant data isolation, which is handled by workspace_id scoping. However, this is not a “set-it-and-forget-it” system.

  • Scoping is Manual: GORM does not have a default, automatic scope to enforce workspace isolation. Developers must manually add .Where("workspace_id = ?", ...) to every single database query, for both list and detail/update/delete operations.
  • Inconsistency Risk: Because it’s a manual process, it is easy to forget. Some older modules or less-used repositories may have missing workspace checks.
  • Known Flaw: An audit of internal/repository/outlet_repository.go revealed that the GetByID, Update, and Delete methods are missing workspace scoping. This is a potential security vulnerability, as a user from one workspace could theoretically access or modify data in another if they can guess the record ID.

Mobile: “Offline-First” for Reads Only (No Mutation Queue)

Section titled “Mobile: “Offline-First” for Reads Only (No Mutation Queue)”

The mobile application is described as “offline-first,” but this primarily applies to data reading, not writing.

  • Cached Reads: TanStack Query is configured with networkMode: 'offlineFirst'. This means any data fetched while online is cached via MMKV. If the app goes offline, it will serve this cached data, allowing for read-only access to previously viewed information.
  • No Offline Mutations: The application does not have an offline mutation queue. Any attempt to create, update, or delete data (e.g., submitting a form, updating a profile) will fail if the device is offline.
  • Implication: There is no automatic synchronization or replaying of failed mutations when the network becomes available again. Users must be online to make any changes. This is a significant limitation of the current “offline-first” strategy.

This list combines the “DO NOT” sections from all three repository rulebooks.

  • DO NOT put SQL/GORM calls directly in handlers. Use the repository layer.
  • DO NOT use c.JSON for responses. Always use utils.HandleResponse for standardized API output.
  • DO NOT skip workspace_id scoping on any query. This is a security and data-integrity requirement.
  • DO NOT skip middleware.RequirePermission on any new route. All endpoints must have RBAC enforcement.
  • DO NOT use raw SQL unless it is a pre-existing pattern in the module you are editing.
  • DO NOT create “god handlers” or “god services” with hundreds of lines of mixed concerns. Keep them focused.
  • DO NOT use interface{} in DTOs or models. Use strongly-typed structs.
  • DO NOT use useEffect + useState for fetching server data. Always use TanStack Query hooks.
  • DO NOT load full datasets for tables. All lists with more than a handful of items must use server-side pagination.
  • DO NOT create custom modal or table components if DialogTable or CommonTable can be used.
  • DO NOT hardcode API URLs. Use the shared lib/api.ts Axios instance.
  • DO NOT mix filter state (URL search params) with local component UI state.
  • DO NOT create new UI components if a suitable one exists in shadcn/ui.
  • DO NOT allow filter parameter names (project_id) to mismatch the backend form:"..." tags.
  • DO NOT use AsyncStorage or SQLite. The only permitted storage is MMKV.
  • DO NOT use Redux, MobX, or React Context for global state. Use Jotai.
  • DO NOT introduce new UI libraries (e.g., react-native-elements). The only permitted UI library is React Native Paper MD3.
  • DO NOT use NativeWind or Tailwind. Styling must be done with StyleSheet.create.
  • DO NOT use inline styles (e.g., style={{ flex: 1 }}). This creates new objects on every render and hurts performance.
  • DO NOT use default exports anywhere. All components, hooks, and services must use named exports and be barrel-exported from an index.ts file.
  • DO NOT store server data in local state (useState, Jotai atoms). All server state must be managed by TanStack Query.
  • DO NOT create a new query without setting networkMode: 'offlineFirst'.
  • DO NOT forget to memoize list item components with React.memo.
  • DO NOT pass large, complex objects as navigation parameters. Pass IDs and fetch the data in the target screen.