Docs/Calcifer.Forge
🔥
Architecture Engine

Calcifer.Forge

The .NET 8 microservice foundation with built‑in licensing, feature gating, seat control, and modular architecture. Everything you need to turn an API into a monetisable product.

# Overview

Calcifer.Forge is not just a template — it's the missing layer between your software and your business model. While most .NET templates give you CRUD endpoints and basic auth, Forge ships with the infrastructure that actually makes software sellable.

Built on .NET 8 LTS with Clean Architecture principles and vertical slice organisation, Forge provides a production‑ready foundation that includes:

  • Authentication & authorisation (JWT + Identity)
  • Licensing engine (key generation, validation, expiry, machine binding)
  • Feature gating with declarative attributes
  • Seat control (concurrent usage limits)
  • Modular feature architecture (plug‑and‑play modules)
  • Background jobs (Hangfire) and event bus
  • OpenAPI / Swagger out of the box

💡 Design Philosophy

Every feature in Forge exists because a real developer hit a wall trying to monetise their software. No vanity features. No "nice to have." Every module solves a real business problem.

# Architecture

Forge follows Clean Architecture with a practical twist — vertical slices within each layer. This means features are self‑contained, testable, and deployable independently.

Layer breakdown

Core

Entities, interfaces, domain logic. Zero external dependencies.

Application

Use cases, DTOs, validators. Orchestrates domain operations.

Infrastructure

EF Core, Identity, email, external APIs.

API

Minimal API endpoints, middleware, filters.

Modules

Feature modules with self‑contained routes and logic.

Licensing

License engine, activation, feature resolver, seat manager.

Request flow

Client → API Gateway (Kong/YARP) → Authentication Middleware (JWT) → License Validation Middleware → Feature Gate Filter → Module Handler → Response

Each module can define its own endpoints, validators, and dependencies — but they all share the same licensing and gating pipeline.

# Licensing Engine

The licensing engine is the heart of Forge's monetisation infrastructure. It handles the complete lifecycle — creation, validation, activation, expiration, and revocation — with no third‑party dependencies.

🔑

License Key Generation

Generate cryptographically secure keys bound to tiers and feature sets. Time‑limited or perpetual.

✅

Activation & Validation

Activate against machine IDs. Validates expiry, features, tier, and seats in one call.

💺

Seat Control

Limit concurrent activations per license. Blocks new activations when seats are exhausted.

📊

Usage Tracking

Monitor activation patterns and feature usage across your customer base.

API reference

POST /api/license/activateREQUEST
{
  "licenseKey": "LIC-PRO-XXXX-XXXX",
  "machineId": "DESKTOP-A1B2C3"
}
200 OKRESPONSE
{
  "activated": true,
  "tier": "professional",
  "features": ["analytics", "export", "multi-tenant"],
  "seatsRemaining": 4,
  "expiresAt": "2027-04-01T00:00:00Z",
  "machineIdBound": "DESKTOP-A1B2C3"
}

🔐 Security note

License keys are generated using System.Security.Cryptography with a secret salt. Machine IDs are SHA‑256 hashed before storage – we never store raw machine identifiers.

# Feature Gating

Feature gating in Forge goes beyond simple role checks. It operates at the endpoint level using custom attributes, allowing you to control which license tiers can access which features — declaratively.

AnalyticsEndpoints.cs
[RequireFeature("analytics")]
[RequireFeature("export")]
public async Task<IResult> ExportAnalyticsReport(
    IAnalyticsService analytics,
    ILicenseContext license)
{
    var report = await analytics.GenerateReport(license.TenantId);
    return Results.File(report.ToCsv(), "text/csv");
}

Available attributes

AttributeDescription
[RequireFeature]Requires one or more features (AND logic).
[RequireAnyFeature]Requires at least one of the listed features (OR logic).
[RequireSeat]Consumes a seat – blocks if no seats left.
[RequireLicenseTier]Checks license tier (basic, pro, enterprise).

How it works under the hood

A custom IAuthorizationFilter reads the attributes, resolves the current license from HttpContext.User (via a claim), and checks feature membership using a cached license resolver. If validation fails, a 403 Forbidden is returned immediately — no controller code runs.

# Seat Control

Seat control limits concurrent usage of a license key. Each activation consumes one seat; when the user logs out or the machine is deactivated, the seat is freed.

// Seat management service
public class SeatManager : ISeatManager
{
    public async Task<bool> TryOccupySeatAsync(string licenseKey, string machineId)
    {
        var license = await _licenseRepo.GetByKeyAsync(licenseKey);
        var activeSeats = await _seatRepo.CountActiveSeatsAsync(licenseKey);
        if (activeSeats >= license.SeatLimit) return false;
        await _seatRepo.AddAsync(new Seat(licenseKey, machineId));
        return true;
    }
}

Seat limits are enforced at the API middleware level, so even custom endpoints cannot bypass seat checks.

# Tech Specifications

Framework.NET 8 LTS
ArchitectureClean Architecture + Vertical Slices
AuthJWT Bearer + ASP.NET Identity
DatabaseEF Core (SQL Server / PostgreSQL)
API StyleMinimal APIs + Feature Modules
License ModelKey‑based with machine binding
Feature GatingAttribute‑driven [RequireFeature]
SeedingAuto‑seed roles, admin, reference data
TestingxUnit + Integration Tests
DockerDockerfile + Compose included

# Configuration

All settings are in appsettings.json and can be overridden by environment variables (using the __ delimiter).

{
  "Licensing": {
    "Salt": "your-secret-salt-here",
    "DefaultTier": "basic",
    "AllowOfflineValidation": false,
    "SeatTimeoutMinutes": 720
  },
  "FeatureGating": {
    "CacheDurationSeconds": 300,
    "StrictMode": true
  },
  "Jwt": {
    "Issuer": "calcifer-forge",
    "Audience": "calcifer-api",
    "ExpiryMinutes": 60
  }
}

# Getting Started

1

Clone the repository

Start by cloning the Forge template.

git clone https://github.com/calcifer-shop/forge.git my-project
cd my-project
2

Configure your database

Update appsettings.json with your connection string.

"ConnectionStrings": { "Default": "Server=localhost;Database=MyApp;Trusted_Connection=true;" }
3

Run migrations & seed data

Apply migrations and seed roles, admin user, and reference data.

dotnet ef database update
dotnet run --seed
4

Start building

The API runs at https://localhost:5001. Swagger at /swagger.

dotnet run

# Best Practices

  • Always validate licenses at the middleware level – never trust client‑side checks.
  • Cache feature sets per user to avoid database round trips on every request.
  • Use the module system to isolate business logic – each module can be deployed independently.
  • Run the seed command during development to populate roles and an admin user.
  • Enable Swagger and document all feature‑gated endpoints with OpenAPI extensions.

# FAQ

Can I use Forge without the licensing engine?

Yes – you can disable the license validation middleware in Program.cs. But then it's just a normal .NET template.

How do I create a new feature module?

Run dotnet new calcifer-module -n MyModule (custom template included). It will generate endpoints, validators, and a feature flag placeholder.

Does Forge support multi‑tenancy?

Built‑in multi‑tenancy is on the roadmap. For now, you can implement it via a tenant resolver middleware and inject ITenantContext.

Ready to build?

Forge is designed to get you from zero to a monetisable API in under a day.