mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-18 06:27:20 +00:00
4.8 KiB
4.8 KiB
Organization Scoping Security Implementation - Complete
Overview
All high-risk database queries have been secured with organization-level scoping to prevent cross-org data leakage.
Changes Implemented
1. Helper Layer (server/org-storage.ts)
- getOrgIdOrThrow(req): Extracts and validates org context
- orgEq(req): Returns { organization_id: orgId } filter
- orgScoped(table, req): Returns scoped Supabase query builder
2. Middleware Strengthening (server/org-middleware.ts)
- ✅ Cache
req.orgMemberIdto avoid repeated DB lookups - ✅
requireOrgMemberreturns 400 (not 403) when org context missing - ✅ Clear error message: "Please select an organization (x-org-id header)"
3. Route Protection (server/routes.ts)
Sites (aethex_sites)
GET /api/sites: Scoped byorgScoped('aethex_sites', req)POST /api/sites: Requiresorganization_idin insertPATCH /api/sites/:id: Validates.eq('organization_id', orgId)DELETE /api/sites/:id: Validates.eq('organization_id', orgId)
Opportunities (aethex_opportunities)
GET /api/opportunities: Optional?org_id=query param for filteringPOST /api/opportunities: Requiresorganization_idPATCH /api/opportunities/:id: Validates org ownershipDELETE /api/opportunities/:id: Validates org ownership
Events (aethex_events)
GET /api/events: Optional?org_id=query paramPOST /api/events: Requiresorganization_idPATCH /api/events/:id: Validates org ownershipDELETE /api/events/:id: Validates org ownership
Projects (projects)
- Already protected via multi-tenancy implementation
- Uses
assertProjectAccessfor collaborator/owner checks
Files (files - in-memory)
- Storage keyed by
${userId}:${orgId} - All CRUD operations require org context
- Files can be linked to
project_idfor additional access control
4. Project Access Middleware (requireProjectAccess)
requireProjectAccess(minRole: 'owner' | 'admin' | 'contributor' | 'viewer')
Applied to:
GET /api/projects/:id(viewer)GET /api/projects/:id/collaborators(contributor)- All project mutation routes via
assertProjectAccess
Role hierarchy:
owner>admin>contributor>viewer- Org owners are implicit project owners
- Project collaborators override org role
5. WebSocket Updates (server/websocket.ts)
- ✅ Join
org:<orgId>room on auth - ✅ Join
user:<userId>room - ✅ Alerts emitted to org-specific rooms
- ✅ Socket auth accepts
orgIdparameter
6. Audit Script (script/org-scope-audit.ts)
npm run audit:org-scope
Scans server/routes.ts for:
- Supabase
.from(table)calls - Missing
.eq('organization_id', ...)for org-scoped tables - Exits non-zero if violations found
7. Integration Tests (server/org-scoping.test.ts)
npm run test:org-scope
Test coverage:
- ✅ User B in orgB cannot list orgA sites
- ✅ User B in orgB cannot update orgA opportunities
- ✅ User B in orgB cannot delete orgA events
- ✅ User A in orgA can access all orgA resources
- ✅ Projects are scoped and isolated
Middleware Application Pattern
// Org-scoped routes
app.get("/api/sites", requireAuth, attachOrgContext, requireOrgMember, handler);
app.post("/api/sites", requireAuth, attachOrgContext, requireOrgMember, handler);
// Project-scoped routes
app.get("/api/projects/:id", requireAuth, requireProjectAccess('viewer'), handler);
app.patch("/api/projects/:id", requireAuth, requireProjectAccess('admin'), handler);
// Public routes (no org required)
app.get("/api/opportunities", handler); // Optional ?org_id= filter
app.get("/api/events", handler);
Exception Routes (No Org Scoping)
/api/auth/*- Authentication endpoints/api/metrics- Public metrics/api/directory/*- Public directory/api/me/*- User-specific resources- Admin routes - Cross-org access with audit logging
Verification Checklist
- All 15 high-risk gaps from audit closed
- Sites CRUD protected
- Opportunities CRUD protected
- Events CRUD protected
- Projects protected (via existing multi-tenancy)
- Files protected (org-scoped storage keys)
- WebSocket rooms org-scoped
- Middleware caches membership
- requireOrgMember returns 400 with clear error
- Audit script detects violations
- Integration tests verify isolation
Next Steps (Blocked Until This Is Complete)
- ✅ Security gaps closed - COMPLETE
- 🔜 Project Graph canonicalization (projects vs aethex_projects)
- 🔜 Revenue event primitive
- 🔜 Labs organization type
- 🔜 Cross-project identity primitive
Running Tests
# Run org-scoping audit
npm run audit:org-scope
# Run integration tests
npm run test:org-scope
# Full type check
npm run check
Status: ✅ All 15 high-risk security gaps closed. Production-ready for org-scoped operations.