175 lines
4.9 KiB
Markdown
175 lines
4.9 KiB
Markdown
# Mercury
|
|
|
|
A high-performance, monolithic Rust API with a dynamic CRUD engine, query registry cache, JWT bitmask permissions, and a Vue 3 admin frontend.
|
|
|
|

|
|

|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
cp .env.example .env # set JWT_SECRET
|
|
docker compose up --build
|
|
```
|
|
|
|
API: http://localhost:3000/api
|
|
Admin UI: http://localhost:3000
|
|
Default credentials: `admin` / `admin`
|
|
|
|
---
|
|
|
|
## API Contract
|
|
|
|
### Authentication
|
|
|
|
```
|
|
POST /auth/login
|
|
Body: { "username": "...", "password": "..." }
|
|
Returns: { "token": "<JWT>" }
|
|
```
|
|
|
|
All admin routes require `Authorization: Bearer <token>`.
|
|
|
|
---
|
|
|
|
### CRUD — Dynamic Table Access
|
|
|
|
Requests are mapped to the named PostgreSQL table. The SQL is generated, cached, and executed automatically.
|
|
|
|
```
|
|
GET /api/{table} List all rows (supports ?col=val filters)
|
|
GET /api/{table}/{id} Get row by id
|
|
POST /api/{table} Insert row (JSON body)
|
|
PUT /api/{table}/{id} Update row by id (JSON body)
|
|
DELETE /api/{table}/{id} Delete row by id
|
|
```
|
|
|
|
**Notes:**
|
|
- `users` and `permissions` tables are blacklisted from public CRUD — use the admin suite.
|
|
- Filters are ANDed together: `GET /api/orders?status=open&priority=high`
|
|
|
|
---
|
|
|
|
### Admin — Query Registry
|
|
|
|
Requires JWT with `ADMIN_QUERY` permission (bit 8).
|
|
|
|
```
|
|
GET /admin/queries List all registered queries
|
|
POST /admin/queries Register a raw SQL template
|
|
GET /admin/queries/{identifier} Get query by slug
|
|
PUT /admin/queries/{identifier} Update SQL template or description
|
|
DELETE /admin/queries/{identifier} Remove query (evicts from cache)
|
|
GET /admin/queries/{identifier}/execute Execute query with ?param=val bindings
|
|
```
|
|
|
|
SQL templates use `:param_name` placeholders:
|
|
```sql
|
|
SELECT * FROM orders WHERE user_id = :user_id AND status = :status
|
|
```
|
|
|
|
---
|
|
|
|
### Admin — Cache
|
|
|
|
Requires JWT with `ADMIN_CACHE` permission (bit 16).
|
|
|
|
```
|
|
GET /admin/cache/stats Cache size, hit count, miss count
|
|
DELETE /admin/cache Flush entire cache
|
|
```
|
|
|
|
---
|
|
|
|
### Admin — Users
|
|
|
|
Requires JWT with `SUPER_ADMIN` permission (bit 32).
|
|
|
|
```
|
|
GET /admin/users List users
|
|
POST /admin/users Create user
|
|
GET /admin/users/{id} Get user
|
|
PUT /admin/users/{id} Update user
|
|
DELETE /admin/users/{id} Delete user
|
|
POST /admin/users/{id}/permissions/grant/{bit} OR bit into permissions mask
|
|
DELETE /admin/users/{id}/permissions/revoke/{bit} AND NOT bit from permissions mask
|
|
```
|
|
|
|
---
|
|
|
|
### Admin — Permissions
|
|
|
|
Requires JWT with `SUPER_ADMIN` permission (bit 32).
|
|
|
|
```
|
|
GET /admin/permissions List permission definitions
|
|
POST /admin/permissions Create custom permission (auto-assigns next bit)
|
|
PUT /admin/permissions/{id} Update name/description
|
|
DELETE /admin/permissions/{id} Remove permission
|
|
```
|
|
|
|
---
|
|
|
|
### Admin — Route Blacklist
|
|
|
|
Requires JWT with `SUPER_ADMIN` permission (bit 32). Changes take effect immediately in memory.
|
|
|
|
```
|
|
GET /admin/blacklist List all entries
|
|
POST /admin/blacklist Add glob pattern
|
|
PUT /admin/blacklist/{id} Update entry (set active: false to disable)
|
|
DELETE /admin/blacklist/{id} Remove entry
|
|
```
|
|
|
|
Pattern syntax: `*` matches one path segment, `**` matches many.
|
|
Example: `/api/sensitive/**` blocks all methods under that path.
|
|
|
|
---
|
|
|
|
## Permission Bitmask
|
|
|
|
| Name | Bit | Value |
|
|
|-------------|-----|-------|
|
|
| READ | 0 | 1 |
|
|
| WRITE | 1 | 2 |
|
|
| DELETE | 2 | 4 |
|
|
| ADMIN_QUERY | 3 | 8 |
|
|
| ADMIN_CACHE | 4 | 16 |
|
|
| SUPER_ADMIN | 5 | 32 |
|
|
|
|
Custom permissions are added via the admin suite and assigned the next available power-of-2 bit. Masks support up to 128 bits (u128).
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `DATABASE_URL` | required | PostgreSQL connection string |
|
|
| `JWT_SECRET` | required | HMAC-HS256 signing secret |
|
|
| `JWT_EXPIRY_SECS` | 3600 | Token lifetime in seconds |
|
|
| `CACHE_MAX_CAPACITY` | 10000 | Max query templates in memory |
|
|
| `CACHE_IDLE_TIMEOUT_SECS` | 300 | Evict after N seconds idle |
|
|
| `CACHE_SWEEP_INTERVAL_SECS` | 60 | Sweep interval for eviction task |
|
|
| `DISABLE_AUTH` | `false` | **Dev only.** When `true`, bypasses all authentication/permission checks — every request is treated as a super-admin and the admin UI skips login. Never enable in production. |
|
|
|
|
---
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# API only (requires local Postgres)
|
|
cargo run
|
|
|
|
# UI dev server (proxies to local API)
|
|
cd ui && npm install && npm run dev
|
|
|
|
# Full stack
|
|
docker compose up --build
|
|
```
|
|
|
|
## Stack
|
|
|
|
- **API:** Rust, Axum, SQLx, PostgreSQL, DashMap, jsonwebtoken, bcrypt
|
|
- **Frontend:** Vue 3, Vite, @nychthemeron/library (dark mode default)
|
|
- **Infra:** Docker multi-stage build, docker compose
|