Developer guide for working with this repository.
VAL (Vault Asset Log) is a secure asset register application built with React, React-Admin, and TypeScript. It manages items (media assets), batches, projects, dispatch, destruction, and vault locations with role-based access control and comprehensive audit logging.
yarn dev- Start development server with Vite (opens at http://localhost:5173)yarn dev:mock- Start with mock data (uses LocalForage instead of backend)yarn serve:dev- Run soul-cli backend for development (requiresdistfolder to exist first)
yarn build- Build production application (runs TypeScript compiler + Vite build)yarn build:prod- Same asyarn buildyarn build:test- Build test instance with cosmetic changes (different color scheme/title)
yarn serve- Serve production build via soul-cli (requires building first)- Uses SQLite database at
./db/RCO2.sqlite - Requires
.envfile withTOKEN_SECRET - Default port: 8000 (configurable via
PORTenv var)
- Uses SQLite database at
yarn serve:large- Serve with large test database
yarn test- Run Jest unit testsyarn e2e- Run Playwright e2e testsyarn e2e-ui- Run Playwright tests in UI mode
yarn lint- Run ESLint with auto-fix (max warnings: 0)yarn format- Format code with Prettier
yarn- Install dependenciesyarn prepare- Install Husky git hooks (runs lint-staged on commit)
To create a new release for clients:
# Create and push a version tag - that's all you need to do
git tag v1.0.2
git push origin v1.0.2The GitHub Actions release workflow (.github/workflows/release.yml) automatically:
- Updates
package.jsonversion from the tag - Runs tests (must pass)
- Creates GitHub Release with source code
- Auto-generates release notes from commits
Note: The version field in package.json is a placeholder - git tags are the source of truth for version numbers.
For deploying to secure/air-gapped client environments:
On Build Machine (must match target OS):
- Download release source code from GitHub
- Install dependencies:
yarn install --frozen-lockfile - Build production frontend:
yarn build - Create deployment package containing:
dist/- Built React frontend_extensions/- Production soul-cli extensions_devExtensions/- Authentication implementation (required by_extensions/)node_modules/- All dependencies (includes platform-specific native modules)package.json- Package metadata
- Zip the package for transfer
On Target Server:
- Extract deployment package
- Ensure
.envfile exists with required variables (TOKEN_SECRET, etc.) - Ensure
db/folder exists withRCO2.sqliteandSecurity.sqlitedatabases - Start server:
yarn serve
Important Notes:
- DO NOT copy
db/folder or.envfrom build machine - these contain target-specific data - Build machine OS must match target OS (native modules like
better-sqlite3are platform-specific) - For database schema changes, manually apply SQL migrations to target database
- For
.envchanges, manually update target.envfile
- React 18 + TypeScript with strict mode enabled
- React-Admin 4.13.1 - Admin framework providing CRUD interfaces, routing, auth
- Material-UI v5 - UI components and theming
- Vite - Build tool and dev server
- React Hook Form + Yup - Form validation
- soul-cli (v0.7.8) - Node.js backend serving SQLite database via REST API
- Custom API extensions in
_extensions/and_devExtensions/ - SQLite database at
db/RCO2.sqlite
The data provider (src/providers/dataProvider/index.ts) sits
between React-Admin and the backend:
- In production: REST API via soul-cli (
/api/tables) - In mock mode: LocalForage (IndexedDB) for offline development
- Wraps base provider with lifecycle callbacks for audit logging
- Custom methods for loan operations (
loanItems,returnItems) - Configuration data fetched from
_configtable
Located in src/providers/authProvider/:
- Token-based auth stored encrypted in localStorage
- User roles:
rco-user,rco-power-user, superuser - Permission system controls read/write/delete per resource
- Session timeout: 1 hour (idle timer in App.tsx)
- Password expiration: 120 days with validation schema
- Audit trail for all login/logout events
Each resource has lifecycle hooks in src/providers/dataProvider/resource-callbacks/:
UserLifeCycle.ts- Password hashing, role managementItemLifeCycle.ts- Item creation/update audit, vault location trackingBatchLifeCycle.ts- Batch number generation, child item updatesProjectLifeCycle.ts- Project audit trackingDispatchLifeCycle.ts- Dispatch state managementDestructionLifeCycle.ts- Destruction workflowReferenceItemLifeCycle.ts- Generic reference data lifecycle
All callbacks use the trackEvent audit function to log changes.
Defined in src/App.tsx and src/constants.ts:
- Items (
R_RICH_ITEMS,R_ALL_ITEMS) - Media assets with complex relationships - Batches (
R_BATCHES) - Collections of items - Projects (
R_PROJECTS) - Configurable project/programme entities - Dispatch (
R_DISPATCH) - Item dispatch workflows with hastener tracking - Destruction (
R_DESTRUCTION) - Item destruction workflows - Vault Locations (
R_VAULT_LOCATION) - Storage locations - Users (
R_USERS) - User management - Audit (
R_AUDIT) - Comprehensive audit log - Reference Data - Multiple lookup tables (protective marking, cat codes, departments, etc.)
- React-Admin built-in state (no Redux)
- LocalForage for mock data persistence
NotificationContext(src/context/) for app-wide notifications- Custom hooks in
src/hooks/:useAudit- Audit logging helperuseCanAccess- Permission checkinguseLocalStore- LocalForage wrapperuseRefTable- Reference data fetching
All in src/types.d.ts:
- Database entities extend
RCOResource(hasid) orResourceWithCreation(addscreatedAt,createdBy) CustomDataProvider- Extended data provider interfacePermission,ResourcePermissions- Access control types- All SQL table types:
Item,Batch,Project,Dispatch,Destruction, etc.
_extensions/api.js- Production wrapper that serves client and imports auth endpoints_devExtensions/- Soul authentication implementation (login, password management, lockout)- Required by
_extensions/api.jsin production - Used directly by
yarn serve:devduring development
- Required by
- Extensions integrate with soul-cli to add custom Express routes
.env- Environment variables (TOKEN_SECRET,VITE_DATA_VERSION,VITE_APP_VERSION)_configtable in database - Runtime config (project names, labels, report settings)src/constants.ts- Resource names, icons, validation criteria
- Jest tests in
src/providers/dataProvider/tests/ - Playwright e2e tests in
e2e/tests/ - Test environment: jsdom
- Mock data generators in
src/utils/generateData.ts
src/utils/encryption.ts- crypto-js for client-side token encryption- Password hashing with bcryptjs (server-side in extensions)
- Audit logging for security-related events
- Password validation schema enforces complexity requirements
- TypeScript strict rules with
@typescript-eslint - Single quotes, no semicolons
- Explicit function return types required
- React 18 JSX transform (no need for React import)
Husky pre-commit hook runs:
- ESLint on
.ts,.tsx,.js,.jsxfiles - Prettier on all source files
- Define types in
src/types.d.ts - Add resource name constant to
src/constants.ts - Create resource folder in
src/resources/[name]/with Form, List, Show components - Export resource config from
src/resources/[name]/index.tsx - Add lifecycle callbacks in
src/providers/dataProvider/resource-callbacks/ - Register in
lifecycleCallbacksarray insrc/providers/dataProvider/index.ts - Add route and permissions in
src/App.tsx
yarn test path/to/test-file.test.ts- Database schema is managed in SQLite files in
db/directory - Increment
VITE_DATA_VERSIONin.envto trigger data reload - Use
loadDefaultData()insrc/utils/init-data.tsfor seed data
- Backend API:
http://localhost:8000/api/tables - soul-cli serves SQLite via REST with query parameters:
_page,_limit- Pagination_ordering- Sort (prefix-for DESC)_filters- Key:value pairs with operators (__eq,__neq,__null, etc.)_search- Full-text search