Skip to content

Fulcrum Security Architecture Overview

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


Table of Contents

  1. Security Architecture Overview
  2. Defense in Depth Layers
  3. Authentication Mechanisms
  4. Authorization (RBAC)
  5. Data Encryption
  6. Security CI/CD Pipeline
  7. Vulnerability Management
  8. Incident Response
  9. Compliance

Security Architecture Overview

Fulcrum implements a defense-in-depth security architecture designed for enterprise AI governance workloads. The platform protects sensitive data across multiple layers, from network perimeter to database records.

Trust Boundaries

                                  INTERNET
                                     |
                    +----------------+----------------+
                    |         PERIMETER LAYER         |
                    |   - TLS 1.2+ termination        |
                    |   - Rate limiting (per-tenant)  |
                    |   - DDoS protection (infra)     |
                    +----------------+----------------+
                                     |
                    +----------------+----------------+
                    |       AUTHENTICATION LAYER      |
                    |   - API key validation (SHA-256)|
                    |   - Clerk (dashboard SSO)       |
                    |   - Service-to-service mTLS     |
                    +----------------+----------------+
                                     |
                    +----------------+----------------+
                    |       AUTHORIZATION LAYER       |
                    |   - Scope-based RBAC            |
                    |   - Tenant context injection    |
                    |   - Method-level enforcement    |
                    +----------------+----------------+
                                     |
                    +----------------+----------------+
                    |         APPLICATION LAYER       |
                    |   - Input validation            |
                    |   - Parameterized queries       |
                    |   - Context propagation         |
                    +----------------+----------------+
                                     |
                    +----------------+----------------+
                    |           DATA LAYER            |
                    |   - PostgreSQL RLS isolation    |
                    |   - Encrypted at rest           |
                    |   - Audit logging               |
                    +----------------+----------------+

Security Principles

Principle Implementation
Defense in Depth Multiple overlapping security controls at each layer
Least Privilege Scope-based API keys with minimal permissions
Zero Trust All requests authenticated; tenant context validated
Fail Securely Errors return generic messages; no information leakage
Secure by Default TLS required in production; restrictive defaults

Defense in Depth Layers

Layer 1: Network Perimeter

  • TLS 1.2+: All production traffic encrypted in transit
  • gRPC + HTTP/2: Multiplexed connections with built-in security
  • Rate Limiting: Redis-backed token bucket algorithm (10 req/s default, 20 burst)
  • Network Isolation: Internal services on private networks (Docker/Kubernetes)

Layer 2: Authentication Gateway

  • API Key Authentication: SHA-256 hashed keys with expiration support
  • Clerk SSO: OAuth2/OIDC for dashboard users
  • Service Accounts: Dedicated keys for machine-to-machine communication

Layer 3: Authorization Enforcement

  • Scope-based RBAC: Fine-grained permissions per API key
  • Tenant Isolation: Context injection at middleware layer
  • Method Guards: Per-endpoint permission checks

Layer 4: Application Security

  • Input Validation: All request fields validated before processing
  • Parameterized Queries: No SQL string concatenation
  • Output Encoding: XSS prevention on response data

Layer 5: Database Security

  • Row-Level Security (RLS): PostgreSQL policies enforce tenant isolation
  • Encryption at Rest: Database-level encryption (AES-256)
  • Audit Logging: All policy evaluations logged with timestamps

Authentication Mechanisms

API Key Authentication (gRPC/REST)

Fulcrum uses SHA-256 hashed API keys for programmatic access. Keys are stored as hashes; the plaintext is never persisted.

Implementation (/internal/middleware/auth.go):

// API key validation flow
// 1. Extract x-api-key header from gRPC metadata
// 2. Compute SHA-256 hash of provided key
// 3. Lookup hash in fulcrum.api_keys table
// 4. Verify expiration (expires_at IS NULL OR expires_at > NOW())
// 5. Inject tenant_id and scopes into request context

hash := sha256.Sum256([]byte(apiKey))
hashStr := hex.EncodeToString(hash[:])
tenant, scopes, err := store.GetTenantByAPIKeyHash(ctx, hashStr)

Security Properties:

Property Implementation
Key Storage SHA-256 hash only; plaintext never stored
Key Rotation Keys can be revoked and re-issued via API
Expiration Optional expires_at timestamp per key
Key Hint Last 4-8 characters stored for identification
Timing Attacks Hash comparison via database lookup (constant-time at DB level)

Best Practice: Generate keys with 32+ bytes of entropy:

export FULCRUM_API_KEY=$(openssl rand -hex 32)

Clerk Integration (Dashboard SSO)

The Next.js dashboard uses Clerk for authentication, providing OAuth2/OIDC-based SSO.

Implementation (/dashboard/src/middleware.ts):

// Protected routes require Clerk authentication
const isProtectedRoute = createRouteMatcher([
  '/app(.*)',
  '/api/approvals(.*)',
  '/api/policies(.*)',
  '/api/traces(.*)',
  '/api/keys(.*)',
]);

// Security: Block production access when Clerk is not configured
if (process.env.NODE_ENV === 'production' && !isClerkEnabled()) {
  return NextResponse.redirect(new URL('/auth-error', request.url));
}

Security Properties:

  • Production mode requires Clerk configuration (fails closed)
  • Development mode allows unauthenticated access for testing only
  • Session management handled by Clerk (not custom implementation)

Service-to-Service Authentication (mTLS)

For internal service communication, Fulcrum supports mutual TLS.

Configuration:

# Enable TLS
export GRPC_TLS_ENABLED=true
export GRPC_TLS_CERT_FILE=/path/to/server.crt
export GRPC_TLS_KEY_FILE=/path/to/server.key
export GRPC_TLS_CA_FILE=/path/to/ca.crt  # For mTLS

TLS Configuration (/cmd/fulcrum-server/main.go):

config := &tls.Config{
    Certificates: []tls.Certificate{serverCert},
    MinVersion:   tls.VersionTLS12,
    CipherSuites: []uint16{
        tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    },
}

Authorization (RBAC)

Role Definitions

Fulcrum implements scope-based RBAC. Each API key is assigned a set of scopes that determine permitted operations.

Scope Description Endpoints
* Full admin access (legacy keys) All endpoints
policy:read Read policy configurations ListPolicies, GetPolicy
policy:write Create/update policies CreatePolicy, DeletePolicy
policy:approve Approve pending policies UpdatePolicy (status=ACTIVE), UpdateApproval
cost:read View cost data GetCostSummary, GetBudgetStatus
cost:write Manage budgets CreateBudget, UpdateBudget
api_key:read List API keys ListApiKeys
api_key:write Manage API keys CreateApiKey, RevokeApiKey
admin Administrative operations Key management, approvals

Permission Enforcement Points

Middleware Layer (/internal/middleware/auth.go):

// HasScope checks if the context has a specific scope (or admin *)
func HasScope(ctx context.Context, scope string) bool {
    scopes, ok := GetScopes(ctx)
    if !ok {
        return false
    }
    for _, s := range scopes {
        if s == "*" || s == scope {
            return true
        }
    }
    return false
}

Service Layer (example from /cmd/fulcrum-server/main.go):

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

Tenant Isolation

All authenticated requests include a tenant_id in the context. This ID is used to:

  1. Filter database queries via RLS
  2. Namespace resources (policies, budgets, envelopes)
  3. Apply per-tenant rate limits

Data Encryption

At Rest: PostgreSQL Encryption

Database-Level: - PostgreSQL Transparent Data Encryption (TDE) available via cloud providers - Column-level encryption for sensitive fields (future) - API key hashes stored as SHA-256 (one-way)

Row-Level Security (/infra/migrations/postgres/000002_enable_rls.up.sql):

-- Enable RLS on core tables
ALTER TABLE fulcrum.tenants ENABLE ROW LEVEL SECURITY;
ALTER TABLE fulcrum.budgets ENABLE ROW LEVEL SECURITY;
ALTER TABLE fulcrum.policies ENABLE ROW LEVEL SECURITY;
ALTER TABLE fulcrum.envelopes ENABLE ROW LEVEL SECURITY;

-- Tenant isolation policy
CREATE POLICY tenant_isolation_budgets ON fulcrum.budgets
    FOR ALL
    USING (tenant_id = current_setting('fulcrum.current_tenant')::uuid);

In Transit: TLS 1.2+

gRPC Server Configuration:

Setting Value
Minimum TLS Version TLS 1.2
Preferred Ciphers ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES128-GCM-SHA256
Certificate Type X.509 (RSA or ECDSA)
Key Length RSA 2048+ or ECDSA P-256+

Environment Variables:

GRPC_TLS_ENABLED=true
GRPC_TLS_CERT_FILE=/etc/fulcrum/tls/server.crt
GRPC_TLS_KEY_FILE=/etc/fulcrum/tls/server.key
GRPC_TLS_CA_FILE=/etc/fulcrum/tls/ca.crt  # Optional: for mTLS

API Key Storage

  • Hashing Algorithm: SHA-256
  • Storage Format: Hexadecimal string (64 characters)
  • Plaintext Handling: Returned once at creation; never stored or logged
  • Key Hint: Last 4-8 characters stored for user identification

Security CI/CD Pipeline

Fulcrum runs automated security scans on every push and pull request via GitHub Actions.

Workflow: /.github/workflows/security.yml

Scan Matrix

Scan Tool Schedule Blocking
Dependency Vulnerabilities govulncheck Push, PR, Daily 6AM UTC HIGH/CRITICAL
OSV Database osv-scanner Push, PR, Daily Non-blocking
Static Analysis (SAST) gosec Push, PR Non-blocking
Secret Detection gitleaks Push, PR Non-blocking
Container Scanning trivy Main branch push CRITICAL/HIGH
SBOM Generation syft Main branch push N/A
OWASP ZAP (DAST) zap-baseline Main branch push Non-blocking
API Security Tests Custom Go tests Main branch push Non-blocking

Dependency Scanning (govulncheck)

- name: Run govulncheck
  run: govulncheck -json ./... > vuln-report.json || true

- name: Check for critical vulnerabilities
  run: |
    if grep -q '"severity":"HIGH"\|"severity":"CRITICAL"' vuln-report.json; then
      echo "::error::Critical or High vulnerabilities found"
      exit 1
    fi

Static Analysis (gosec)

- name: Run gosec
  uses: securego/gosec@master
  with:
    args: '-fmt json -out gosec-report.json -stdout -verbose=text ./...'

Detected Issues (OWASP Reference):

Rule Description OWASP
G101 Hardcoded credentials A07:2021
G102 Bind to all interfaces A05:2021
G104 Unhandled errors A09:2021
G201 SQL query construction A03:2021
G401 Weak cryptographic primitives A02:2021
G501 Blacklisted imports A06:2021

Secret Detection (gitleaks)

- name: Run Gitleaks
  run: |
    gitleaks detect --source . --verbose --redact \
      --report-format json --report-path gitleaks-report.json

Container Scanning (Trivy)

- name: Run Trivy
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'fulcrum-server:scan'
    format: 'json'
    output: 'trivy-results.json'
    severity: 'CRITICAL,HIGH'

Vulnerability Management

Dependabot Configuration

File: /.github/dependabot.yml

Ecosystem Directory Schedule PR Limit
Go Modules / Weekly (Monday) 10
GitHub Actions / Weekly (Monday) Auto
npm (Dashboard) /dashboard Weekly (Tuesday) 10
pip (Python SDK) /sdk/python Weekly (Wednesday) Auto
npm (TS SDK) /sdk/typescript Weekly (Wednesday) Auto
Docker / Weekly (Thursday) Auto
Terraform /infra/terraform Monthly Auto

CVE Response Process

Severity Response SLA Actions
Critical 24 hours Immediate patch, notify affected customers
High 72 hours Patch in next release, security advisory
Medium 14 days Include in scheduled release
Low 30 days Include in scheduled release

Known Vulnerabilities

Current tracked issues (from KNOWN_VULNERABILITIES.md):

CVE Package Severity Status Mitigation
GO-2025-3824 ollama/ollama Medium Accepted Network isolation, rate limiting
GO-2025-3695 ollama/ollama Medium Accepted Resource limits configured
GO-2025-3689 ollama/ollama Medium Accepted Planned replacement Q1 2026

Incident Response

Security Contacts

Contact Email Response Time
Security Team security@fulcrum.dev 24 hours
Urgent Issues security@fulcrum.dev (subject: URGENT) 4 hours
Product Owner td@fulcrum.dev 24 hours

Response Timeline

Phase Timeframe Activities
Acknowledgment 24 hours Confirm receipt, assign responder
Assessment 72 hours Severity classification, scope determination
Containment 24-72 hours Isolate affected systems, revoke credentials
Remediation 7-14 days Develop and test patch
Disclosure 14-28 days Coordinated public disclosure

Disclosure Policy

  1. Day 0: Vulnerability reported via security@fulcrum.dev or GitHub Security Advisory
  2. Day 1: Acknowledgment sent to reporter
  3. Day 3: Initial assessment complete
  4. Day 7-14: Patch developed and tested
  5. Day 14-21: Patch released
  6. Day 21-28: Public disclosure (coordinated with reporter)

Incident Response Checklist

  1. Isolate: Revoke compromised credentials immediately
  2. Investigate: Review audit logs for unauthorized access
  3. Contain: Disable affected components/endpoints
  4. Notify: Contact security@fulcrum.dev
  5. Remediate: Apply patches, rotate secrets
  6. Review: Post-incident analysis and documentation

Compliance

Framework Alignment

Framework Status Notes
SOC 2 Type II Planned Q2 2026 Audit controls in place
GDPR Design compliant Privacy-by-design, tenant isolation
HIPAA Configurable Encryption at rest/transit available
ISO 27001 Roadmap Security controls mapped

Security Controls Summary

Control Category Implementation
Access Control Scope-based RBAC, API key authentication
Audit Logging All policy evaluations logged
Encryption TLS 1.2+ in transit, AES-256 at rest
Incident Response Documented process, 24h acknowledgment SLA
Vulnerability Management Daily scans, Dependabot, govulncheck
Network Security Internal service isolation, rate limiting
Data Protection RLS tenant isolation, no secret logging

Prometheus Security Metrics

# Security event metrics
- fulcrum_auth_failures_total        # Failed authentication attempts
- fulcrum_rate_limit_exceeded_total  # Rate limit violations
- fulcrum_invalid_requests_total     # Malformed requests
- fulcrum_policy_violations_total    # Policy enforcement blocks

Security Testing

Automated Security Tests

Location: /tests/security/api_security_test.go

Test Category Description OWASP Reference
Authentication Bypass Attempts access without valid credentials A07:2021
Authorization Escalation Cross-tenant access attempts A01:2021
SQL Injection Malicious query payloads A03:2021
XSS Prevention Script injection in metadata A03:2021
Rate Limiting Burst request handling A04:2021
Error Leakage Sensitive info in error messages A04:2021
Timing Attacks Constant-time auth comparison A02:2021

Running Security Tests

# Run all security tests (requires running server)
go test -v -timeout 5m ./tests/security/...

# Run in CI (uses docker-compose)
docker compose -f docker-compose.unified.yml up -d
go test -v -timeout 5m ./tests/security/...
docker compose -f docker-compose.unified.yml down -v

References


Document History

Version Date Author Changes
1.0 2026-01-06 Security Team Initial release

Next Review: February 6, 2026 Owner: Security Team (security@fulcrum.dev)