# CoreLicense Documentation Software license management platform documentation for developers. Canonical HTML URL: https://corelicense.net/docs Plain-text URL: https://corelicense.net/docs/index.txt ## Pages - Introduction: https://corelicense.net/docs (plain text: https://corelicense.net/docs/index.txt) - Node.js SDK Quick Start: https://corelicense.net/docs/nodejs-sdk/quick-start (plain text: https://corelicense.net/docs/nodejs-sdk/quick-start.txt) - Node.js SDK Integration: https://corelicense.net/docs/nodejs-sdk/integration (plain text: https://corelicense.net/docs/nodejs-sdk/integration.txt) - Deep Integration: https://corelicense.net/docs/nodejs-sdk/deep-integration (plain text: https://corelicense.net/docs/nodejs-sdk/deep-integration.txt) - Node.js SDK API Reference: https://corelicense.net/docs/nodejs-sdk/api-reference (plain text: https://corelicense.net/docs/nodejs-sdk/api-reference.txt) - Client API Reference: https://corelicense.net/docs/client-api (plain text: https://corelicense.net/docs/client-api.txt) - Server Architecture: https://corelicense.net/docs/server-architecture (plain text: https://corelicense.net/docs/server-architecture.txt) --- # Introduction Overview of CoreLicense — software license management platform for SaaS, desktop, and enterprise apps. Canonical HTML URL: https://corelicense.net/docs Plain-text URL: https://corelicense.net/docs/index.txt ---# CoreLicense Documentation > SDK integration and Client API documentation for software license management. This site is **public** — no admin console login required. ## Overview CoreLicense is a software license management platform for SaaS and on-premise applications. It consists of two main components: - **License Server** — Go API backend that manages products, licenses, instances, and policies - **Node.js SDK** (`@corelicense/node v0.0.0`) — runtime layer integrated into client applications ## Basic integration flow ``` Admin creates Product + License ↓ Developer installs SDK in Node.js app ↓ SDK calls POST /v1/client/activate (first run) ↓ SDK calls POST /v1/client/check (periodically) ↓ Server returns signed policy token ↓ SDK verifies token, enforces features & limits ``` ## SDK philosophy > CoreLicense is not just middleware. The SDK is designed as a **Runtime Layer** embedded in bootstrap, runtime config, module registry, service guards, and quota enforcement. ## Documentation index | Page | Description | |------|-------------| | [Quick Start](/docs/nodejs-sdk/quick-start) | Install, configure, and run the SDK with Express | | [Integration](/docs/nodejs-sdk/integration) | Express, Fastify, NestJS, Worker & CLI | | [Deep Integration](/docs/nodejs-sdk/deep-integration) | Module registry & dependency injection | | [API Reference](/docs/nodejs-sdk/api-reference) | CoreLicense class public API | | [Client API](/docs/client-api) | Activate, check, refresh endpoints | | [Server Architecture](/docs/server-architecture) | Go API, Admin Console, data model | | [Policy](/policy) | License terms, acceptable use & enforcement | --- # Node.js SDK Quick Start Install @corelicense/node and integrate license activation, validation, refresh, and policy enforcement into a Node.js application. Canonical HTML URL: https://corelicense.net/docs/nodejs-sdk/quick-start Plain-text URL: https://corelicense.net/docs/nodejs-sdk/quick-start.txt ---# Installation > Install the package, configure environment variables, and run `boot()` for the first time. ## 1. Install package ```bash npm install @corelicense/node ``` ### Peer dependencies (framework-specific) Install only when using the corresponding integration: ```bash npm install express # Express middleware npm install fastify # Fastify plugin npm install @nestjs/common @nestjs/core # NestJS ``` The SDK does not require peer dependencies — tree-shaking is safe if you only use `CoreLicense` directly. --- ## 2. Environment variables ### Required | Variable | Description | |----------|-------------| | `CORELICENSE_KEY` | License key from admin (`CL-...` or `CL1..CL-...`) | | `CORELICENSE_PRODUCT_ID` | Product ID on the License Server | ### Optional (SDK handles automatically if not set) | Variable | Description | Default | |----------|-------------|---------| | `CORELICENSE_API_URL` | Override License API URL | From `CL1.*` key or `api.corelicense.net` | | `CORELICENSE_PUBLIC_KEY` | Pin public key (SPKI PEM) | Auto-fetch from server | | `CORELICENSE_CACHE_PATH` | Cache directory | `~/.cache/corelicense/` (scope = 16-char hash of `productId:licenseKey`) | | `APP_DOMAIN` | Deploy domain (instance ID) | `hostname()` or URL from PaaS env (see below) | **Auto-detected domain variables** (in order): `APP_DOMAIN`, `CORELICENSE_APP_DOMAIN`, `APP_URL`, `PUBLIC_APP_URL`, `VERCEL_URL`, `RAILWAY_PUBLIC_DOMAIN`, `RENDER_EXTERNAL_URL`. **API URL resolution order** (no manual config needed in production): 1. `options.apiUrl` / `CORELICENSE_API_URL` 2. URL embedded in `CL1..CL-...` key 3. Cache `sdk.endpoint.json` 4. `https://api.corelicense.net` ### Local development ```env CORELICENSE_KEY=CL-AAAAA-BBBBB-CCCCC-DDDDD-EEEEE CORELICENSE_PRODUCT_ID=demo CORELICENSE_API_URL=http://localhost:8080 ``` ### Production ```env CORELICENSE_KEY=CL1.xxxxx.CL-AAAAA-BBBBB-... CORELICENSE_PRODUCT_ID=my-product # No CORELICENSE_API_URL needed — SDK uses api.corelicense.net ``` Production Go server needs `SDK_PUBLIC_URL=https://api.corelicense.net` when generating `CL1.*` keys. --- ## 3. Minimal initialization ```ts import { CoreLicense, loadOptionsFromEnv } from '@corelicense/node'; const license = new CoreLicense(loadOptionsFromEnv()); await license.boot(); ``` Only `CORELICENSE_KEY` + `CORELICENSE_PRODUCT_ID` in `.env` are required. The SDK automatically resolves: - API URL (from license key) - Public keys (fetch + cache) - Cache path (`~/.cache/corelicense/...`) - Instance ID (persists `install.id` + `instance.json` after successful boot) - Domain/instance fingerprint (`hostname` or `APP_DOMAIN` if set) `loadOptionsFromEnv()` throws `ConfigError` (`CONFIG_MISSING_ENV`) if required variables are missing. --- ## 4. `CoreLicenseOptions` (constructor) | Field | Type | Default | Description | |-------|------|---------|-------------| | `productId` | `string` | — | **Required** | | `licenseKey` | `string` | — | **Required** | | `apiUrl` | `string` | auto | License Server base URL | | `publicKey` | `string` | — | Pin SPKI PEM | | `cachePath` | `string` | `~/.cache/corelicense/` | Cache directory (override with `CORELICENSE_CACHE_PATH`) | | `checkIntervalMs` | `number` | `21600000` (6h) | Background refresh; `0` = disabled | | `requestTimeoutMs` | `number` | `5000` | HTTP timeout | | `offlineGrace` | `boolean` | `true` | Allow cached policy when server unreachable | | `defaultBlockMode` | `'block' \| 'limited'` | `'limited'` | Default middleware mode | | `instance.strategy` | `'install-id-domain-hash' \| 'custom' \| 'fixed'` | `'install-id-domain-hash'` | Instance ID calculation | | `instance.instanceId` | `string` | — | Required when `strategy: 'fixed'` | | `instance.domain` | `string` | — | App domain (for hash) | | `instance.customId` | `string` | — | When `strategy: 'custom'` | | `audit.enabled` | `boolean` | `true` | Write local audit log | | `audit.path` ...[truncated — see full HTML doc]... --- # Node.js SDK Integration Integrate CoreLicense with Express, Fastify, and NestJS using middleware and plugins. Canonical HTML URL: https://corelicense.net/docs/nodejs-sdk/integration Plain-text URL: https://corelicense.net/docs/nodejs-sdk/integration.txt ---# Integration Detailed guide for integrating `@corelicense/node` into a production system — for developers and AI agents generating code. **Read first:** [Installation](/docs/nodejs-sdk/quick-start) --- ## Table of Contents 1. [Architecture & Principles](#1-architecture--principles) 2. [Runtime Lifecycle](#2-runtime-lifecycle) 3. [Express Integration (Full)](#3-express-integration-full) 4. [Fastify Integration](#4-fastify-integration) 5. [NestJS Integration](#5-nestjs-integration) 6. [Feature Gate, Limit & Quota](#6-feature-gate-limit--quota) 7. [Worker & CLI Guard](#7-worker--cli-guard) 8. [Deep Integration — Module Registry & DI](#8-deep-integration--module-registry--di) 9. [Large Application Patterns](#9-large-application-patterns) 10. [Error Handling](#10-error-handling) 11. [Events & Background Sync](#11-events--background-sync) 12. [Security & Data Sent to Server](#12-security--data-sent-to-server) 13. [Production Checklist](#13-production-checklist) 14. [Troubleshooting](#14-troubleshooting) --- ## 1. Architecture & Principles ### Middleware Is Not Enough HTTP middleware only blocks requests. Attackers or bugs can call services/workers directly. **Deep integration** means: - Modules/services **must not be bound** if the feature is disabled in policy - Every `get()` / `resolve()` **re-checks** the license (revoke blocks immediately) - Workers/CLI have their own guards - Quota/limit enforced at the point of consumption ### Two Layers of Protection | Layer | Mechanism | When | |-------|-----------|------| | **HTTP** | `express()` / `fastifyPlugin()` / Nest guards | Every API request | | **Runtime** | `requireFeature`, registry, DI, worker guard | Service, job, CLI | ### Policy Is the Source of Truth The policy token (JWT, EdDSA) contains: - `status`: `active` | `suspended` | `revoked` | ... - `features`: map of feature → boolean - `limits`: maximum values (users, workers, ...) - `quotas` / local usage: daily consumption Admin changes policy on the server → SDK refreshes → runtime updates. **Binding modules/services** only happens at `bootstrap()` — changing a feature requires an **app restart** to mount/unmount modules; but `get()`/`resolve()` still block immediately on revoke. --- ## 2. Runtime Lifecycle ``` constructor → boot() → [bootstrap()] → app running ↓ background check (6h default) ↓ syncFromServer (mutex — no race) ↓ requireActive() on every critical gate ``` ### `boot()` — Required Before Everything ```ts await license.boot(); ``` - Fail-closed v0.5: if license is revoked/expired and offline grace is exhausted → **throw**, process should exit - Call `boot()` **once** when the process starts (before `listen()`) ### Instance ID ```ts instance: { strategy: 'install-id-domain-hash', // default — recommended for production domain: process.env.APP_DOMAIN, // e.g.: app.customer.com } ``` - `install-id-domain-hash`: `sha256(productId:licenseKey:installId:domain)` — install ID stored in `install.id` file under `cachePath` - `fixed`: use existing `instance.instanceId` (reuse a registered instance) - `custom`: `sha256(customId)` — custom container/K8s pod id The server counts **max instances** per license — each install-id + domain pair is one instance. --- ## 3. Express Integration (Full) ### App Skeleton ```ts import express from 'express'; import { CoreLicense, loadOptionsFromEnv, registerLicensedRoutes } from '@corelicense/node'; const app = express(); app.use(express.json()); const license = new CoreLicense( loadOptionsFromEnv({ cachePath: './storage/corelicense', instance: { strategy: 'install-id-domain-hash', domain: process.env.APP_DOMAIN }, checkIntervalMs: 6 * 60 * 60 * 1000, }), ); async function main() { await license.boot(); // --- Routes that do NOT require license --- app.get('/health', (_req, res) => res.json({ ok: true })); app.get('/license/status', async (_req, res) ...[truncated — see full HTML doc]... --- # Deep Integration Module registry, dependency injection, feature gates, quotas, and advanced policy enforcement patterns. Canonical HTML URL: https://corelicense.net/docs/nodejs-sdk/deep-integration Plain-text URL: https://corelicense.net/docs/nodejs-sdk/deep-integration.txt ---# CoreLicense Node.js SDK — Design & Deep Integration Documentation > Goal: build a license/policy SDK for Node.js that ensures a developer's product only runs with a valid license, can revoke access when usage policies are violated, but **does not send business data / end-user data back to the developer's server**. --- ## 1. Design Philosophy CoreLicense should not be just middleware. If it only sits at the middleware layer, users with source code on their server can remove the middleware and continue running the app. Therefore CoreLicense must be designed as a **Runtime Layer** embedded deep within multiple critical points of the system: - Bootstrap app - Runtime config - Module registry - Service container - Business services - Worker / Queue / Cron - CLI command - Quota / Limit - Local audit - Policy token verification Principle: ```txt Don't guard the door. Build the whole house around CoreLicense. ``` CoreLicense must make removing the license a matter of restructuring the architecture, not simply deleting one line of middleware. --- ## 2. SDK v1 Scope SDK v1 prioritizes the Node.js ecosystem: - Express.js - Fastify - NestJS - Node.js service - PM2 process - Docker deployment - Worker / Queue / Cron - CLI tools - TypeScript project - JavaScript project Official package: ```txt @corelicense/node ``` --- ## 3. Overview Model ```txt ┌────────────────────────────────────────────┐ │ Node.js App │ │ Routes / Controllers / Views / API │ └────────────────────┬───────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Core Runtime Layer │ │ Bootstrap / Config / Registry / Container │ └────────────────────┬───────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ CoreLicense SDK │ │ Verify Token / Feature / Limit / Policy │ └────────────────────┬───────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Business Modules │ │ Worker / Automation / Export / API / Jobs │ └────────────────────┬───────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Database / Queue / Storage │ └────────────────────────────────────────────┘ ``` Standard placement of CoreLicense: ```txt App bootstrap ↓ CoreLicense boot() ↓ Runtime config ↓ Module registry ↓ Service container ↓ Business module ↓ Worker / Queue / Cron / CLI ``` --- ## 4. What CoreLicense Is Allowed to Do CoreLicense is allowed to: - Check whether the license is valid. - Verify signed policy tokens. - Check product ID. - Check instance ID. - Check license status: active, suspended, revoked, expired. - Check feature flags. - Check quota / limits. - Cache tokens locally. - Allow a grace period when the license server is temporarily unreachable. - Write local audit logs about license status. - Return runtime config to the app. - Disable sensitive modules when policy is violated. CoreLicense should not: - Send the customer's database to the developer's server. - Send business logs / private data to the developer's server. - Delete customer files on its own. - Destroy services/servers on its own. - Hide its process. - Self-recover like malware. - Install secret services. - Bypass system administration privileges. --- ## 5. License Status Standard statuses: ```txt active - Normal usage allowed limited - Usage allowed but with feature restrictions suspended - Temporarily suspended due to suspicion/violation/unverified revoked - Permanently or severely revoked expired - License expired offline - Cannot reach license server, using cache grace_expired - Grace period has ended invalid - Token/license incorrect or tampered ``` Behavi ...[truncated — see full HTML doc]... --- # Node.js SDK API Reference Reference for CoreLicense Node.js SDK classes, methods, configuration, and error handling. Canonical HTML URL: https://corelicense.net/docs/nodejs-sdk/api-reference Plain-text URL: https://corelicense.net/docs/nodejs-sdk/api-reference.txt ---# API Reference Public API `@corelicense/node` v0.5.9. --- ## CoreLicense ### Constructor ```ts new CoreLicense(options: CoreLicenseOptions) ``` ### Lifecycle | Method | Returns | Description | |--------|---------|-------------| | `boot()` | `Promise` | Initialize, sync server, fail-closed | | `refresh()` | `Promise` | Force refresh policy | | `startBackgroundCheck()` | `void` | Enable sync interval | | `stopBackgroundCheck()` | `void` | Disable interval | ### License gates | Method | Description | |--------|-------------| | `requireActive()` | Throw if not active | | `requireFeature(feature)` | Throw + audit if feature is off | | `checkLimit(name, current)` | Throw if limit exceeded | | `consumeQuota(name, amount?)` | Consume local quota | | `getStatus()` | Current status | | `getPolicy()` | Verified policy (null if not yet available) | | `getRuntimeConfig()` | Config derived from policy | ### HTTP integrations | Method | Description | |--------|-------------| | `express(options?)` | Express `RequestHandler` | | `fastifyPlugin(options?)` | Fastify plugin | ### Worker / CLI | Method | Description | |--------|-------------| | `guardWorker(name)` | Guard worker process | | `guardCommand(name)` | Guard CLI/cron command | ### Deep integration | Method | Description | |--------|-------------| | `bootstrap(options)` | Register modules + services | | `createLicensedRegistry()` | Dedicated `LicensedModuleRegistry` | | `createLicensedContainer()` | Dedicated `LicensedServiceContainer` | ### Events ```ts license.on(event, handler) ``` Events: `statusChanged` | `policyUpdated` | `licenseRevoked` | `licenseSuspended` | `offlineMode` > `CoreLicense` only exposes `on()`. To unsubscribe, keep a reference to the handler and use the internal `EventBus` if custom wiring is needed. --- ## LicensedModuleRegistry | Method | Description | |--------|-------------| | `bootstrap(definitions, ctx)` | Bulk register | | `registerLicensed(def, ctx)` | Register a single module | | `has(name)` | Is module bound? | | `get(name)` | Get module + re-check license | | `list()` | Names of registered modules | --- ## LicensedServiceContainer | Method | Description | |--------|-------------| | `bootstrap(definitions, ctx)` | Bind services | | `resolve(name)` | Resolve + re-check license | | `has(name)` | Is service bound? | --- ## Helpers ```ts loadOptionsFromEnv(overrides?: Partial): CoreLicenseOptions resolveApiUrl(options, cachedApiUrl?): string parseEmbeddedApiUrl(licenseKey): string | null registerLicensedRoutes(app, registry, routes): string[] isLicenseError(error): boolean formatLicenseError(error): string isFeatureEnabled(policy, feature): boolean ``` --- ## Subpath exports ### `@corelicense/node/express` ```ts createExpressMiddleware(license, options?): RequestHandler ``` ### `@corelicense/node/fastify` ```ts createFastifyPlugin(license, options?): FastifyPluginAsync coreLicenseFastifyPlugin ``` ### `@corelicense/node/nestjs` ```ts CoreLicenseModule.forRoot(options): DynamicModule CoreLicenseGuard CoreLicenseFeatureGuard CoreLicenseExceptionFilter RequireFeature(feature) // decorator REQUIRE_FEATURE_KEY ``` --- ## Types ### `CoreLicenseOptions` See [installation.md](/docs/nodejs-sdk/quick-start#4-corelicenseoptions-constructor). ### `ExpressGuardOptions` / `FastifyGuardOptions` ```ts { allowPaths?: string[]; mode?: 'block' | 'limited'; } ``` ### `BootstrapResult` ```ts { modules: LicensedModuleRegistry; services: LicensedServiceContainer; registeredModules: string[]; registeredServices: string[]; skipped: { name: string; feature: string; reason: 'feature_disabled' }[]; } ``` ### `LicenseStatus` ```ts { status: 'active' | 'suspended' | 'revoked' | 'expired' | 'invalid' | 'blocked' | 'offline' | 'grace_expired' | 'limited'; policyVersion?: string; expiresAt?: number; graceUntil?: number; offline?: boolean; // ... } ``` --- ## Error codes ...[truncated — see full HTML doc]... --- # Client API Reference CoreLicense Client API reference — activate, check, refresh, and status endpoints for license activation and policy token flows. Canonical HTML URL: https://corelicense.net/docs/client-api Plain-text URL: https://corelicense.net/docs/client-api.txt ---# License Server — Client API Reference > Public REST API that client applications and the Node.js SDK call to activate licenses, validate status, and refresh policy tokens. > **Base path:** `/v1/client` — no admin JWT required. Authentication uses license key + product ID (slug or UUID). ## Endpoints | Method | Path | Description | Used by SDK? | |--------|------|-------------|--------------| | POST | `/v1/client/activate` | First-time license activation, create/record instance, return policy token | Yes — first boot | | POST | `/v1/client/check` | Periodic license validation, return new policy token if active | Yes — background sync | | POST | `/v1/client/refresh` | Alias of `check` on the server | Yes — `license.refresh()` | | POST | `/v1/client/status` | Fast status read, **does not** return policy token | No — custom clients | > **Note:** Business errors (revoked, expired, etc.) return HTTP `200` with `ok: false`. Only rate limiting returns HTTP `429`. ## POST /v1/client/activate ### Request ```json { "productId": "mediahub", "licenseKey": "CL1.xxxxx.CL-AAAAA-BBBBB-CCCCC-DDDDD-EEEEE", "instanceId": "sha256_hex...", "application": { "domainHash": "sha256-of-normalized-domain", "environment": "production" }, "sdk": { "name": "@corelicense/node", "version": "0.0.0", "runtime": "node", "runtimeVersion": "v22.0.0", "appVersion": "1.0.0" } } ``` `application` is only sent during activate. The SDK sends `domainHash` (hash of normalized domain) and `environment` from `NODE_ENV` — plain domain is never sent. ### Response (success) ```json { "ok": true, "status": "active", "policyToken": "eyJhbGciOiJFZERTQSJ9...", "policyVersion": "12", "serverTime": "2026-06-07T12:00:00Z", "nextCheckAfter": 21600, "apiUrl": "https://api.corelicense.net" } ``` ### Response (error) ```json { "ok": false, "status": "revoked", "code": "LICENSE_REVOKED", "message": "License has been revoked" } ``` `message` may include an admin-provided reason (suspend/revoke/block). Example for blocked instance: `status: "blocked"`, `code: "INSTANCE_BLOCKED"`. ## POST /v1/client/check ### Request ```json { "productId": "mediahub", "licenseKey": "CL1.xxxxx.CL-AAAAA-BBBBB-CCCCC-DDDDD-EEEEE", "instanceId": "sha256_hex...", "currentPolicyHash": "sha256...", "sdk": { "name": "@corelicense/node", "version": "0.0.0", "runtime": "node", "runtimeVersion": "v22.0.0", "appVersion": "1.0.0" } } ``` ### Response (success) ```json { "ok": true, "status": "active", "policyToken": "eyJhbGciOiJFZERTQSJ9...", "policyVersion": "12", "serverTime": "2026-06-07T12:00:00Z", "nextCheckAfter": 21600, "apiUrl": "https://api.corelicense.net" } ``` ### Response (error) ```json { "ok": false, "status": "revoked", "code": "LICENSE_REVOKED", "message": "License has been revoked" } ``` ## POST /v1/client/status Request body is the same as `check`, but the server **does not** sign a policy token and does not record new instances. A successful response only includes `ok`, `status`, `apiUrl`, `serverTime`, `nextCheckAfter`, and `policyVersion`. ## License status values | Status | Meaning | |--------|---------| | `active` | License is valid with full entitlements | | `suspended` | Temporarily suspended by admin | | `revoked` | Permanently revoked | | `expired` | Past expiration date | | `invalid` | Invalid key, not yet started, or max instances exceeded | | `blocked` | Instance blocked (may include block reason) | ## Error codes | Code (server) | SDK mapping | Description | |---------------|-------------|-------------| | `PRODUCT_NOT_FOUND` | `PRODUCT_NOT_FOUND` | Product ID/slug does not exist | | `INVALID_PRODUCT` | `PRODUCT_NOT_FOUND` | Legacy alias | | `LICENSE_NOT_FOUND` | `LICENSE_NOT_FOUND` | License key does not exist | | `LICENSE_INVALID` / `INVALID_LICENSE` | `LICENSE_INVALID` | License does not belong to specified product | | `LICENSE_REVOKED` | `LIC ...[truncated — see full HTML doc]... --- # Server Architecture CoreLicense License Server architecture — Go API, Admin Console, data model, policy tokens, and operational design. Canonical HTML URL: https://corelicense.net/docs/server-architecture Plain-text URL: https://corelicense.net/docs/server-architecture.txt ---# CoreLicense Server Architecture > Public overview for developers integrating with CoreLicense — system components, technology stack, and domain model. Database DDL, admin-console APIs, deployment configuration, and other operator-only details are **not** published here. ## 1. System Overview CoreLicense Server is the central hub for managing: - Product - Customer / Client - Application - License - Instance - Policy - Feature flags - Limits / Quotas - License checking history - Activation history - Revocation / suspension - Admin users - Audit logs Client applications use the Node.js SDK to call the server in order to: - Register / activate an app instance - Check license status - Refresh the policy token - Obtain a signed token - Report minimum SDK version - Receive a new policy when available The server does not collect business data from client applications. --- ## 2. High-Level Architecture ```txt ┌──────────────────────────────────────┐ │ Client Application │ │ Node.js App + CoreLicense SDK │ └───────────────────┬──────────────────┘ │ │ HTTPS ▼ ┌──────────────────────────────────────┐ │ CoreLicense API │ │ Backend: Go │ │ - Activate │ │ - Check │ │ - Refresh Token │ │ - Policy Signing │ │ - Check History │ └───────────────────┬──────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Database / Cache / Queue │ │ PostgreSQL + Redis │ └───────────────────┬──────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Admin Frontend │ │ Next.js │ │ - Product management │ │ - License management │ │ - Client app management │ │ - Check history │ │ - Policy editor │ │ - Audit log │ └──────────────────────────────────────┘ ``` --- ## 3. Recommended Technology Stack Backend: ```txt Language: Go HTTP framework: Gin / Chi / Fiber Database: PostgreSQL Cache: Redis ORM/Query: sqlc or GORM Migration: Goose / Atlas / golang-migrate Auth: JWT session or secure cookie session Crypto: Ed25519 signing Logging: Zap / Zerolog Config: Viper / envconfig Queue optional: Asynq or NATS ``` Frontend: ```txt Framework: Next.js Language: TypeScript UI: Tailwind CSS + shadcn/ui Data fetching: TanStack Query or Server Actions Auth: NextAuth or custom session Charts: Recharts Forms: React Hook Form + Zod Table: TanStack Table ``` Infra: ```txt Reverse proxy: Nginx / Caddy TLS: Cloudflare / Let's Encrypt Deploy: Docker Compose Monitoring: Prometheus / Grafana optional Logs: Loki optional ``` --- ## 4. Main Components ```txt corelicense-server/ cmd/ api/ main.go internal/ config/ database/ redis/ http/ middleware/ auth/ crypto/ license/ product/ client/ instance/ policy/ checklog/ audit/ admin/ errors/ migrations/ docs/ docker-compose.yml ``` ```txt corelicense-admin/ app/ dashboard/ products/ licenses/ clients/ instances/ checks/ policies/ audit/ settings/ components/ lib/ hooks/ services/ types/ ``` --- ## 5. Domain Model ### 5.1. Product A Product is your software product. Examples: - MediaHub - CorpMaster - VPS Manager - Browser App - Automation Toolkit Fields: ```txt id name slug description public_key_id status created_at updated_at ``` Status: ```txt active deprecated disabled ``` --- ### 5.2. Customer / Client A Customer is the person or organization granted a license. Fields: ```txt id name email company phone telegram note ...[truncated — see full HTML doc]...