Skip to content

Access Control

Document Version: 1.0 Last Updated: January 6, 2026 Classification: Internal / Partner


Table of Contents

  1. Overview
  2. Authentication Mechanisms
  3. Scope‑Based RBAC Model
  4. Tenant Isolation
  5. Permission Matrix
  6. API Key Management
  7. Session Management (Clerk)
  8. Service‑to‑Service Authorization (mTLS)
  9. Auditing & Logging
  10. Best Practices & Recommendations
  11. References

Overview

Fulcrum enforces defense‑in‑depth access control across all entry points. The model combines authentication (who you are) with authorization (what you can do) using scope‑based RBAC and tenant isolation. All enforcement points are implemented in the shared middleware (/internal/middleware/auth.go) and are verified by unit tests and integration tests.


Authentication Mechanisms

Mechanism Use‑case Implementation
API Key Programmatic access (SDKs, services) SHA‑256 hashed keys stored in fulcrum.api_keys table. Validation performed in auth.go.
Clerk SSO Human users accessing the dashboard OAuth2/OIDC flow handled by Clerk SDK. Session cookies managed by Clerk.
mTLS Service‑to‑service calls within the cluster Mutual TLS certificates verified by gRPC server (GRPC_TLS_ENABLED).

All mechanisms require TLS 1.2+ for transport security.


Scope‑Based RBAC Model

Each API key (or Clerk session) is assigned a set of scopes that map to fine‑grained permissions. Scopes are strings like policy:read, cost:write, admin. The special scope * grants full admin rights (legacy keys only).

Scope Definitions

Scope Description Endpoints
policy:read Read policy configurations ListPolicies, GetPolicy
policy:write Create, update, delete policies CreatePolicy, UpdatePolicy, DeletePolicy
policy:approve Approve pending policies UpdatePolicy (status=ACTIVE), UpdateApproval
cost:read View cost and budget data GetCostSummary, GetBudgetStatus
cost:write Manage budgets CreateBudget, UpdateBudget
api_key:read List API keys ListApiKeys
api_key:write Create/revoke API keys CreateApiKey, RevokeApiKey
admin Administrative operations (key rotation, system settings) All admin endpoints

Enforcement

The middleware provides HasScope(ctx, scope string) bool. Example:

func (s *policyService) CreatePolicy(ctx context.Context, req *pb.CreatePolicyRequest) (*pb.CreatePolicyResponse, error) {
    if !middleware.HasScope(ctx, "policy:write") {
        return nil, status.Error(codes.PermissionDenied, "missing policy:write scope")
    }
    // proceed with creation
}


Tenant Isolation

Every authenticated request carries a tenant_id injected by the authentication middleware. This ID is stored in the request context and used by: - PostgreSQL Row‑Level Security policies to filter data. - Rate‑limit buckets (Redis) scoped per tenant. - Resource naming (e.g., S3 buckets, NATS subjects) prefixed with the tenant ID.


Permission Matrix

Resource Required Scope(s)
Policy CRUD policy:read / policy:write
Policy Approval policy:approve
Budget View cost:read
Budget Edit cost:write
API Key Management api_key:read / api_key:write
Admin Dashboard admin

API Key Management

  1. CreationCreateApiKey generates a 32‑byte random secret, stores only the SHA‑256 hash.
  2. Rotation – New keys can be issued; old keys can be revoked via RevokeApiKey.
  3. Expiration – Optional expires_at timestamp; expired keys are rejected.
  4. Hints – Last 4‑8 characters of the key are stored for UI identification.

All operations are audited (see Auditing section).


Session Management (Clerk)

  • Clerk handles OAuth2 token validation, session refresh, and logout.
  • In production, the middleware blocks unauthenticated access and redirects to /auth-error (see dashboard/src/middleware.ts).
  • Session IDs are logged with trace IDs for correlation.

Service‑to‑Service Authorization (mTLS)

  • Internal services authenticate each other using mutual TLS certificates.
  • The client presents a certificate; the server validates it against a trusted CA.
  • Service identities are mapped to scopes via a configuration file (internal/mtls/scopes.yaml).

Auditing & Logging

All access control decisions are logged with the following fields: - tenant_id - principal (API key ID or Clerk user ID) - scopes - resource and action - decision (allow / deny) - trace_id for end‑to‑end correlation

Log format is JSON (see Structured Logging in SECURITY_OVERVIEW.md).


Best Practices & Recommendations

  • Least Privilege: Issue API keys with the minimal set of scopes required.
  • Rotate Secrets: Rotate API keys and TLS certificates every 90 days.
  • Monitor: Alert on fulcrum_auth_failures_total and fulcrum_rate_limit_exceeded_total (see Monitoring guide).
  • Review Scopes: Periodically audit scope assignments for inactive tenants.
  • Use Vault: Store private keys and certificates in a secret manager (e.g., HashiCorp Vault, AWS Secrets Manager).

References

  • Fulcrum SECURITY_OVERVIEW.md
  • Fulcrum ACCESS_CONTROL.md (this document)
  • OWASP Access Control Cheat Sheet
  • NIST SP 800‑53 AC‑* controls
  • PostgreSQL Row‑Level Security documentation

Document version: 1.0 (January 6 2026)