feat: Phase 1 foundation - schema, auth, realtime, shell
- Rewrote Drizzle schema: 20 tables with enums, relations, indexes - Generated migration with DROP TABLE records (v1 EAV removal) - Added passkey auth routes (register/login) - Added requireWorkspaceAccess helper - Added seedDefaultData for Personal workspace + welcome note - Updated SSE endpoint for v2 entities + workspace_id filtering - Created recordActivity helper (insert + pg_notify) - Updated sidebar: Graph replaces Reports, removed Analytics - Updated command palette for v2 entities - Created AGENTS.md with locked contract - Created llm-wiki scaffold (5 stubs) - Added inline AGENT INSTRUCTION comments to all 50 API route files - Fixed globals.css border-border class conflict - Updated database.ts stub for v1 compatibility
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# AGENTS.md — Project E v2 Agent Contract
|
||||
|
||||
## Core Rules
|
||||
|
||||
Every API route that writes data (INSERT/UPDATE/DELETE) MUST follow this pattern:
|
||||
|
||||
1. **Drizzle write** — Perform the database operation
|
||||
2. **Activity feed insert** — Call `recordActivity()` with actor, action, entity_type, entity_id, changes, workspace_id
|
||||
3. **pg_notify** — `recordActivity()` handles this automatically via `pg.notify('project_e_events', payload)`
|
||||
|
||||
## Soft-Delete Only
|
||||
|
||||
- Never use SQL `DELETE` on user data tables
|
||||
- Set `deleted_at = now()` for soft-delete
|
||||
- Default queries MUST filter `deleted_at IS NULL`
|
||||
- Junction tables (task_tags, habit_tags, etc.) use hard DELETE since they have no `deleted_at` column
|
||||
|
||||
## Error Format
|
||||
|
||||
All errors return:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Human-readable message",
|
||||
"details": { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Standard codes: `VALIDATION_ERROR`, `NOT_FOUND`, `UNAUTHORIZED`, `FORBIDDEN`, `CONFLICT`, `INTERNAL_ERROR`
|
||||
|
||||
## Workspace-Scoped Routes
|
||||
|
||||
- All entities are scoped to a workspace (domain)
|
||||
- Route pattern: `/api/domains/[domainId]/[entity]/...`
|
||||
- Every entity table has a `domain_id` FK (or `workspace_id` for activity_feed/webhooks)
|
||||
- Use `requireWorkspaceAccess(workspaceId)` to verify the workspace exists
|
||||
|
||||
## Build Before Commit
|
||||
|
||||
- Run `npm run build --workspace=apps/web` before committing
|
||||
- Do NOT commit build artifacts (`.next/`, `dist/`, `.turbo/`)
|
||||
|
||||
## Schema
|
||||
|
||||
- All Drizzle schema lives in `packages/db/src/schema.ts`
|
||||
- Import via `@project-e/db` or `@project-e/db/schema`
|
||||
- Use Drizzle ORM for all database operations
|
||||
- Never write raw SQL except for `pg_notify` calls
|
||||
|
||||
## Realtime
|
||||
|
||||
- SSE endpoint at `/api/realtime` uses PostgreSQL LISTEN/NOTIFY
|
||||
- Event format: `{ type, action, id, workspace_id }`
|
||||
- Heartbeat every 30 seconds
|
||||
- Filter by `?workspace_id=` query param
|
||||
Reference in New Issue
Block a user