Skip to content

About

SystemForge is a batteries-included Go platform module providing reusable identity, session, authorization, and feature flags for multi-tenant SaaS applications. Think of it as Django/Laravel-style conveniences for Go.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

797 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SystemForge

Go CI Go Lint Go SAST Docs DevGuide Visualization License

SystemForge is a batteries-included Go platform module providing reusable identity, session, authorization, and feature flags for multi-tenant SaaS applications. Think of it as Django/Laravel-style conveniences for Go.

Within the plexusone org, SystemForge is the shared identity/session/authorization foundation the Forge platform family (ActionForge, AgentForge, DashForge) builds on — one contract instead of each app inventing its own. See INIT-SYSTEMFORGE-001 for the unified authorization vocabulary, IAM console, and shell composition work this drives.

Moved from github.com/grokify/systemforge to github.com/plexusone/systemforge in v0.10.0 — the old path still resolves via GitHub's repository-transfer redirect for existing pins, but won't receive new tags. See the v0.10.0 release notes for the full migration.

v0.11.0 renamed coreauth → systemauth, cf_ tables/API-keys → sf_, and unified the principal-link field to sf_principal_id — a hard cutover with no dual-name compatibility. See the v0.11.0 release notes for the full migration.

Features

Identity Module

  • 👤 Principals - One identity root for humans, applications, agents, and services; humans carry email, names, and a platform admin flag
  • 🏢 Organizations - Multi-tenant with name, slug, settings, marketplace-derived entitlements
  • 🔗 Memberships - Principal-organization relationships with flexible roles
  • 👑 Ownership Transfer - Transaction-safe organization ownership transfers
  • 🔐 Credentials - Passwords (Argon2id), API keys, keypairs, and client secrets owned by a principal
  • 🔗 External Identities - Upstream logins (GitHub, Google, federation) linked to a principal by provider and subject
  • 🌐 Social Login - GitHub/Google login served centrally by SystemAuth (__Host-sf_login session, provider-subject account linking, logout, consent)
  • 🤝 Relying Parties - identity/relyingparty: apps federate to SystemAuth via OIDC (ID-token/JWKS verification, sub → sf_principal_id linking), mount the /bff/* cookie-session surface, and accept SystemAuth JWTs or API keys from programmatic clients
  • 🧩 Embeddable SystemAuth - identity/systemauthsvc builds a production-checked SystemAuth http.Handler a host binary can mount next to its own apps, with provider metadata for discovery-free in-process relying parties
  • 🤖 AI Agent Requests - identity/requestprincipal: one protocol-neutral request principal for people and agents; aauthrs verifies AAuth-signed agent requests (HTTP message signatures, person/auth tokens from trusted issuers, resource-token challenges) next to the relying-party human paths
  • 🔑 API Keys - Scoped machine-to-machine credentials on a principal
  • 💌 Invite-Only Sign-Up - A sign-up gate for social login: only verified emails with an invite create accounts, refused people reach a consent-recorded waitlist, and systemauth invite and systemauth waitlist manage both
  • 🧭 App Catalog - Hosts publish the applications they run at /.well-known/sf-apps, and /bff/session lists them so each shell shows the ones a person holds a role in, for a product switcher
  • 🏷️ Per-Application Roles in Tokens - Embedded SystemAuth emits the orgs claim with each organization's application roles, limited to default entitlements

OAuth 2.0 Server (Fosite)

  • 📜 Authorization Code + PKCE - Secure browser-based auth
  • 🤖 Client Credentials - Service-to-service auth
  • 🔄 Refresh Token - Rotation with reuse detection (family revocation) and absolute lifetime
  • 🪪 OpenID Connect - RS256 ID tokens, UserInfo, JWKS with key ID, optional JWT access tokens
  • ⚙️ Service Principals - Non-human identities with scoped credentials and keypairs (the RFC 7523 JWT Bearer grant is not yet implemented)
  • 🔍 Token Introspection & Revocation - RFC 7662/7009

Session Module

  • 🎫 JWT Service - Access/refresh token generation with HS256/RS256/ES256
  • 🔒 DPoP (RFC 9449) - Proof-of-possession token binding
  • 🖥️ BFF Pattern - Backend for Frontend with server-side sessions
  • 💾 OmniStorage Backend - Production session storage with Redis, size limits, and observability
  • 🛡️ Middleware - JWT Bearer and API key authentication

Authorization Module

  • 👥 RBAC/ReBAC - Role and relationship-based access control
  • 🔐 SpiceDB Provider - Zanzibar-style fine-grained authorization
  • ✨ Simple Provider - Lightweight permission checking
  • 🧩 Query Policy Bridge - Use authz.Authorizer to feed safe query languages such as GrokifyQL
  • 🚧 HTTP Middleware - Route protection for Chi and stdlib

Key Management and Connections

  • 🗝️ Key Management - keys wires keyforge as the platform's one key library: envelope encryption, rotation without re-encrypting, the root key read through omnivault, and key events in the audit trail
  • 🔌 Connections - connections composes connectforge so organizations connect accounts at external services; credentials are sealed under managed keys and applications get an authenticated HTTP client, never the secret
  • 🌐 Connections API - /api/v1/organizations/{org}/connections with systemforge:connections:read and :write scopes, served by SystemAuth when connections is configured

Observability

  • 📊 Vendor-Agnostic - Integrates with omniobserve
  • 🔌 Multiple Backends - OTLP, Datadog, New Relic, Dynatrace
  • 📈 Pre-Built Metrics - SystemAuth, rate limiting, JWT/API key validation
  • 🔍 Distributed Tracing - Automatic span creation for OAuth flows
  • 📝 slog Integration - Trace-correlated structured logging

Marketplace

  • 🛒 Listings - Product catalog with tiers and pricing
  • 💳 Stripe Integration - Subscription billing and webhooks
  • 📜 Licensing - Per-seat, unlimited, and time-limited licenses
  • 👥 Seat Management - Assign and revoke user access

Feature Flags

  • 🚩 Flag Engine - Boolean, percentage, and user list flags
  • 🏢 Organization Scoping - Per-org flag evaluation
  • 💾 In-Memory Store - Development and testing

Row-Level Security (RLS)

  • 🗃️ PostgreSQL RLS - Policy generation and session variables
  • 🏠 Tenant Isolation - Multi-tenant data separation
  • 🔗 Ent Integration - Transaction helpers with tenant context

Multi-App Platform

  • 🏗️ Multi-App Server - Run multiple SaaS apps on shared infrastructure
  • 📦 Schema Isolation - Each app gets its own PostgreSQL schema
  • 🔀 X-App-ID Routing - Header-based request routing to app backends
  • 🔌 AppBackend Interface - Composable app registration with lifecycle hooks
  • 💾 Shared Caching - Redis or in-memory with app-scoped prefixes

Installation

go get github.com/plexusone/systemforge

Quick Start

Using Identity Schemas

SystemForge provides Ent schemas with the sf_ table prefix for side-by-side migration.

Direct Schema Usage

package main

import (
    "context"
    "log"

    "github.com/plexusone/systemforge/identity/ent"
    "github.com/plexusone/systemforge/identity/principal"
    _ "github.com/lib/pq"
)

func main() {
    client, err := ent.Open("postgres", "postgres://...")
    if err != nil {
        panic(err)
    }
    defer client.Close()

    // Run migrations
    if err := client.Schema.Create(context.Background()); err != nil {
        panic(err)
    }

    // Create a human principal
    person, err := principal.NewService(client).CreateHuman(context.Background(), principal.CreateHumanInput{
        Email:       "user@example.com",
        DisplayName: "Example User",
    })
    if err != nil {
        panic(err)
    }
    log.Printf("created principal %s", person.ID) // the ID used everywhere else in SystemForge
}

Mixin Composition (Recommended)

Compose SystemForge mixins into your own schemas:

// your-app/ent/schema/user.go
package schema

import (
    "entgo.io/ent"
    "entgo.io/ent/schema/field"
    cfmixin "github.com/plexusone/systemforge/identity/ent/mixin"
)

type User struct {
    ent.Schema
}

func (User) Mixin() []ent.Mixin {
    return []ent.Mixin{
        cfmixin.UUIDMixin{},      // UUID primary key
        cfmixin.TimestampMixin{}, // created_at, updated_at
    }
}

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("username").Unique(),
        // App-specific fields...
    }
}

JWT Authentication

import (
    "github.com/plexusone/systemforge/session/jwt"
    "github.com/plexusone/systemforge/session/middleware"
)

// Create JWT service
svc, err := jwt.NewService(&jwt.Config{
    Secret:             []byte("your-secret-key"),
    AccessTokenExpiry:  15 * time.Minute,
    RefreshTokenExpiry: 7 * 24 * time.Hour,
    Issuer:             "your-app",
})

// Generate tokens
pair, err := svc.GenerateTokenPair(userID, email, name)

// Middleware for protected routes
r.Use(middleware.JWT(svc))

DPoP Token Binding

DPoP (RFC 9449) lives in the standalone github.com/grokify/goauth/dpop package (moved out of SystemForge in v0.9.0). See the goauth DPoP guide.

import "github.com/grokify/goauth/dpop"

// Generate DPoP key pair (BFF side)
keyPair, err := dpop.GenerateKeyPair()

// Create proof for API request
proof, err := dpop.CreateProofWithOptions(keyPair, "POST", "https://api.example.com/data", dpop.ProofOptions{
    AccessToken: accessToken,
})

// Verify proof (API side)
verifier := dpop.NewVerifier(dpop.VerificationConfig{
    MaxAge: 5 * time.Minute,
})
result, err := verifier.Verify(proofJWT, dpop.VerificationRequest{
    Method:      "POST",
    URI:         "https://api.example.com/data",
    AccessToken: accessToken,
})

BFF Pattern

import "github.com/plexusone/systemforge/session/bff"

// Create BFF proxy
proxy := bff.NewProxy(bff.ProxyConfig{
    Backend:        "https://api.internal.example.com",
    AllowedOrigins: []string{"https://app.example.com"},
    SessionStore:   bff.NewMemoryStore(),
})

// Mount proxy handler
r.Handle("/api/*", proxy.Handler())

Authorization

import (
    "github.com/plexusone/systemforge/authz"
    "github.com/plexusone/systemforge/authz/rbac"
)

// Create authorization provider
provider := simple.NewProvider(simple.Config{
    AllowOwnerFullAccess:  true,
    AllowPlatformAdminAll: true,
})

// Add role permissions
provider.AddRolePermissions("admin", []string{
    "users:read", "users:write",
    "settings:read", "settings:write",
})
provider.AddRolePermissions("member", []string{
    "users:read",
})

// Use middleware
mw := authz.NewMiddleware(provider)
r.With(mw.RequireAction(authz.ResourceType("users"), authz.ActionRead)).Get("/users", listUsers)

Module Structure

github.com/plexusone/systemforge/
├── identity/              # User, Organization, Membership, OAuth
│   ├── ent/schema/        # Ent schemas with sf_ prefix
│   ├── apikey/            # API key service
│   ├── oauth/             # OAuth 2.0 server (Fosite)
│   ├── oauthclient/       # GitHub/Google/SystemAuth OAuth client primitives
│   ├── relyingparty/      # OIDC relying party for apps federating to SystemAuth (/bff, bearer)
│   ├── requestprincipal/  # Protocol-neutral request principal and authenticator chain (aauthrs/: AAuth agents)
│   ├── systemauth/        # SystemAuth OAuth 2.0 / OIDC server (social login, userinfo; cmd/systemauth binary)
│   ├── systemauthsvc/     # Embeddable SystemAuth service setup for host binaries (config, production checks, migrations)
│   ├── password.go        # Argon2id hashing
│   └── service.go         # Identity service interfaces
│
├── keys/                  # keyforge wired to the platform (omnivault root key, audit trail)
├── connections/           # connectforge composed with the platform (store, RLS, authz, audit, HTTP API)
│
├── session/               # Session management
│   ├── jwt/               # JWT service with DPoP claims
│   ├── bff/               # Backend for Frontend pattern (DPoP via goauth/dpop)
│   ├── middleware/        # Auth middleware
│   └── ratelimit/         # Rate limiting with observability
│
├── observability/         # Vendor-agnostic observability
│   ├── observability.go   # Core wrapper for omniobserve
│   ├── middleware.go      # HTTP request tracing
│   └── metrics.go         # Pre-defined metric names
│
├── authz/                 # Authorization
│   ├── simple/            # Simple RBAC provider
│   ├── spicedb/           # SpiceDB ReBAC provider
│   ├── noop/              # No-op syncer for testing
│   ├── providertest/      # Provider test suite
│   └── middleware.go      # HTTP middleware
│
├── marketplace/           # SaaS marketplace
│   ├── listing.go         # Product listings and tiers
│   ├── license.go         # License management
│   ├── subscription.go    # Subscription handling
│   └── stripe/            # Stripe billing integration
│
├── featureflags/          # Feature flag engine
│   └── stores/            # Flag stores
│
├── multiapp/              # Multi-app platform
│   ├── server.go          # Multi-app server with routing
│   ├── app.go             # AppBackend interface
│   ├── database.go        # Schema-per-app isolation
│   ├── cache.go           # Redis and memory cache
│   └── context.go         # App context helpers
│
└── rls/                   # PostgreSQL Row-Level Security
    ├── rls.go             # Policy generation
    └── middleware.go      # HTTP middleware

Design Decisions

Decision Choice Rationale
Table prefix sf_ Avoids conflicts, enables side-by-side migration
Role storage String field Apps define own vocabularies (owner/admin/member)
OAuth pattern Fosite library Production-ready, RFC-compliant OAuth 2.0
Refresh tokens Database-backed Enables revocation, theft detection
Primary keys UUID Modern, distributed-friendly
Password hashing Argon2id OWASP recommended, memory-hard

Database Tables

SystemForge creates the following tables (all prefixed with sf_):

Table Description
sf_principals Identity root for humans, applications, agents, and services
sf_humans Human extension: email, names, avatar, verification
sf_applications Application extension for OAuth-client principals
sf_agents Agent extension for AI-agent principals
sf_service_principals Service extension for non-human service identities
sf_credentials Passwords, API keys, keypairs, and secrets owned by principals
sf_principal_tokens Tokens issued to principals
sf_organizations Multi-tenant organizations
sf_principal_memberships Principal-organization relationships
sf_invites Organization invitations
sf_external_identities Upstream login identities (GitHub/Google/federation) linked to principals
sf_oauth_apps OAuth client applications
sf_oauth_app_secrets Client secrets (hashed)
sf_oauth_tokens Issued OAuth tokens
sf_oauth_auth_codes Authorization codes
sf_oauth_consents Principal consent records
sf_login_sessions SystemAuth login sessions (token hashes only)
sf_login_states In-flight upstream social logins (single-use)
sf_consent_grants Consent-page grants per principal, client and scope
sf_listings, sf_licenses, sf_subscriptions, sf_seat_assignments Marketplace catalog, entitlements, billing, and seats

Applications federating to SystemAuth create two more tables in their own database with identity/relyingparty/pgstore.EnsureSchema:

Table Description
sf_rp_sessions Relying-party browser sessions (token hashes; SystemAuth tokens encrypted at rest)
sf_rp_login_states In-flight logins to SystemAuth (single-use; nonce and PKCE verifier encrypted)

Migration Strategy

For existing apps, SystemForge supports side-by-side migration:

  1. Side-by-Side: Create sf_* tables alongside existing tables
  2. Dual-Write: Write to both old and new tables
  3. Cutover: Switch reads to SystemForge tables
  4. Cleanup: Remove old tables

Documentation

Full documentation is available via MkDocs:

# Install MkDocs
pip install mkdocs mkdocs-material

# Serve locally
mkdocs serve

# Build static site
mkdocs build

Relevant authorization guides:

  • docs/authorization/spicedb-setup.md
  • docs/authorization/spicedb-schema.md
  • docs/authorization/integration.md
  • docs/authorization/query-policy-engines.md

Guides for organizations, roles and access invalidation are in docs/guides/:

  • docs/guides/invites.md
  • docs/guides/application-roles.md
  • docs/guides/collaborators.md
  • docs/guides/organization-slugs.md
  • docs/guides/personal-to-team.md
  • docs/guides/access-change-invalidation.md
  • docs/guides/authorization-mode.md
  • docs/guides/connections.md
  • docs/guides/key-management.md

Contributing

Contributions are welcome! Please read the contributing guidelines before submitting PRs.

License

MIT License - see LICENSE file for details.

About

SystemForge is a batteries-included Go platform module providing reusable identity, session, authorization, and feature flags for multi-tenant SaaS applications. Think of it as Django/Laravel-style conveniences for Go.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages