Access Module
Location: apps/api/src/shared/access/
The Access module provides a centralised capability matrix. It answers "what can this user do?" without importing other module services — it reads directly from reputation_snapshots and users tables.
Capabilities
| Capability | Threshold | Logic |
|---|---|---|
canVoteWiki | Total rep ≥ 5 | Sum across all interests |
canMentor | Interest rep ≥ 30 (or total ≥ 50) | Per-interest check; total fallback |
canModerate | role = 'moderator' or role = 'admin' | Role-based only |
canProposeGuild | Always false | Wave 2 stub |
canPostJournalism | Any single interest rep ≥ 20 | findFirst with value >= 20 |
Thresholds
typescript
const MENTOR_INTEREST_THRESHOLD = 30;
const MENTOR_TOTAL_FALLBACK = 50;
const WIKI_VOTE_REP_THRESHOLD = 5;
const JOURNALISM_REP_THRESHOLD = 20;AccessMatrixService
| Method | Description |
|---|---|
canVoteWiki(userId) | Total rep ≥ 5 |
canMentor(userId, interestId?) | Interest ≥ 30 or total ≥ 50 |
canModerate(userId) | Role check |
canProposeGuild(userId) | Stub → false |
canPostJournalism(userId) | Any interest ≥ 20 |
getMatrix(userId) | Returns all capabilities as Capabilities object |
Capabilities Type
typescript
type Capabilities = {
canVoteWiki: boolean;
canMentor: boolean;
canModerate: boolean;
canProposeGuild: boolean;
canPostJournalism: boolean;
};HTTP Endpoint
GET /api/v1/access/me
Authorization: Bearer <token>Returns the caller's capability matrix:
json
{
"canVoteWiki": true,
"canMentor": false,
"canModerate": false,
"canProposeGuild": false,
"canPostJournalism": true
}@RequiresRep Decorator
typescript
@RequiresRep({ min: 20, interestField: 'interestId' })
async createPost(...)Applied to a controller handler to enforce a reputation threshold before the handler runs. Works in tandem with ReputationGuard.
ReputationGuard
ReputationGuard reads @RequiresRep() metadata and checks:
- Extracts
interestIdfrom the request body or params (usinginterestField). - Looks up
ReputationSnapshotfor(userId, interestId). - Throws
ForbiddenExceptionifvalue < min.
Usage Example
typescript
// In posts.controller.ts
@Post()
@UseGuards(JwtAuthGuard, ReputationGuard)
@RequiresRep({ min: 20, interestField: 'interestId' })
async createJournalismPost(...) {}AccessController
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /access/me | JwtAuthGuard | Return Capabilities for current user |