Hackorda Docs

Permissions

Complete reference for who can do what in Hackorda — covering human users, API keys, and AI agents.

See Agent Platform for the agent-native strategy. See Authentication for the Clerk implementation. See system-overview.md §4 for the high-level summary.


1. Actor types

ActorHow they authenticateIdentity source
Human (browser)Clerk session cookieusers.clerk_id
External agentAPI key hk_live_...api_keys table
Internal runnerSystem token (env var)Internal service identity

2. System roles (global, users.role_id)

Applies to humans only. Agents use the scope system (§4) instead.

RoleIDPasses any requireAdmin?Passes requireSuperAdmin?Notes
SUPER_ADMIN5Money + role-change gating
ADMIN1Everything else
QA4"Tester" in UI — not the cycle-access gate
STUDENT2Legacy LMS role
GUEST3Public landing only

Key rule: ROLES.QA does not grant cycle access. Having a testers row for that specific cycle grants access.


3. Per-cycle roles (testers.role)

Scoped to one cycle. Applies to humans; agents use cycleIds restriction on their API key.

RoleFiled issuesView all issuesTriage/approveEdit cycleManage members
lead
testerOwn only
observer✅ (read)

Admin users bypass this table — checkTestCycleAccess() returns isAdmin: true and skips the testers row check.


4. API key scopes (agents + programmatic access)

Scope definitions

ScopeResourceActionHuman equivalent
cycles:readCycles, docs, members, test planGETAny member of the cycle
cycles:writeCreate/update cyclesPOST/PATCHAdmin
issues:readIssues, comments, attachments, AI suggestionsGETTester (own) or admin (all)
issues:writeFile issues, add comments, upload attachmentsPOSTTester
issues:triageApprove/reject/reclassify, change payout amountPOSTAdmin
runs:writeStart + complete test runsPOST/PATCHTester
payouts:readPayout status, balance, batch historyGETAdmin or own-tester
payouts:writeRun batch, mark paid, voidPOSTSuper-admin
analytics:readUsage events, cycle reportsGETAdmin
ai:writeTrigger/re-run AI analysis on issuesPOSTAdmin
admin:readOrgs, products, users (read)GETAdmin

Scope combinations by use case

Use caseMinimum scopes
CI bug filingcycles:read, issues:write, runs:write
Triage automationissues:read, issues:triage, ai:write
Read-only reportingcycles:read, issues:read, payouts:read, analytics:read
Linear sync agentissues:read, issues:write
Full admin automationAll scopes (use sparingly; prefer narrow keys)

Key restrictions

Beyond scopes, a key can be further restricted:

  • cycleIds: limit to specific cycles (empty = all cycles in the org)
  • expiresAt: auto-expire the key on a date
  • rateLimit: calls per minute (default: 60/min)

5. What each actor can do — the full matrix

5.1 Cycles

ActionAdminLeadTesterObserverAgent (cycles:read)Agent (cycles:write)
List cycles✅ (joined)✅ (joined)
Get cycle detail
Create cycle
Update cycle status
Manage members
Read cycle docs
Write cycle docs

5.2 Issues

ActionAdminLeadTesterObserverAgent (issues:read)Agent (issues:write)Agent (issues:triage)
List all issues
List own issues
Get issue detailOwn only
File issue
Edit own issue
Add comment
Triage (approve/reject)
Change severity

5.3 Payouts

ActionSuper-adminAdminLeadTesterAgent (payouts:read)Agent (payouts:write)
View payout statusOwn only
View own balance
Run batch payout
Mark issue paid
Void payment

6. Enforcement points in code

LayerFileWhat it enforces
Clerk middlewaremiddleware.tsProtects all /app/* routes; redirects unauth to sign-in
Global admin gatesrc/lib/auth/roles.tsrequireAdmin()Admin-only API routes
Super-admin gatesrc/lib/auth/roles.tsrequireSuperAdmin()Money + role-change actions
Cycle accesssrc/lib/auth/test-cycle-auth.tscheckTestCycleAccess()Per-cycle data
API middlewaresrc/lib/auth/api-middleware.tsRoute-level wrappers
Issue permissionssrc/lib/issues/permissions.tsIssue-level read/write
(planned) API key middlewaresrc/lib/auth/api-key-auth.tsAgent API key validation + scope check

7. Future: agent-to-agent delegation

When Phase 2 (agent runner) ships, the internal runner needs to file issues on behalf of an org — without a human's credentials. The model:

  • The runner holds an internal system token (env var, rotated periodically).
  • Issues filed by the runner carry reporter_type: 'agent' + runner_run_id for provenance.
  • Attribution is to a synthetic "Agent tester" user per org, created on first run.
  • Payouts don't apply to agent-filed issues (or go to the org, not a tester).

8. Security checklist (before shipping agent auth)

  • API keys stored as SHA-256 hashes — never plaintext
  • Keys shown in full only at creation time (same as GitHub PAT model)
  • Key compromise path: revoke-by-id, immediate effect
  • Rate limiting enforced per key (not per IP)
  • Scope escalation impossible — a cycles:read key cannot reach /api/admin/* endpoints even with direct HTTP calls
  • Cycle restriction enforced server-side — cycleIds checked in checkTestCycleAccess(), not just in the MCP layer
  • Audit log entry on every API key action (creation, revocation, scopes)
  • SUPER_ADMIN-only scope: payouts:write cannot be issued to a key by a non-super-admin user

On this page