How mahmudulhasanriaz/keygen-api works
1. What this repo is
- A Ruby on Rails API for software licensing, activation, validation, and package distribution.
- It serves both the public product API and several protocol-specific distribution endpoints for package registries and release downloads.
2. Core request path
- Incoming HTTP requests hit Rails controllers under app/controllers.
- Shared controller concerns handle authentication, authorization, current account/environment resolution, request logging, rate limiting, compression, pagination, and response rendering.
- Most endpoints follow a common flow: controller → policy check → service object / model logic → serializer → JSON or protocol-specific response.
3. Primary domain boundary
- The main business entities are Account, Environment, Product, Policy, License, Machine, User, Token, Release, ReleaseArtifact, WebhookEndpoint, and WebhookEvent.
- These models encode the licensing graph: accounts own products and policies; policies govern licenses and machines; licenses connect users, groups, machines, and entitlements; releases and artifacts distribute software.
4. Authorization and tenancy
- Access control is centralized in app/policies using Action Policy.
- Data is strongly scoped by account and, in newer paths, by environment; many controllers rely on current_account_scope and current_environment_scope.
- The repo has Enterprise Edition-specific boundaries in lib/keygen/ee and matching EE-only controllers/policies for features like permissions, environments, audit logs, request logs, and SSO.
5. Service layer and business workflows
- app/services contains the business operations that controllers delegate to.
- Key workflows include license checkout/validation, machine checkout, token lookup, release upload/download/upgrade/yank, webhook broadcasting/retries, billing customer/subscription management, and alias/account/environment resolution.
- These services are the main boundary between HTTP handling and domain mutations.
6. Release and distribution subsystem
- Releases are modeled as products with engines, packages, platforms, arches, channels, and artifacts.
- Dedicated controllers exist for engine-specific distribution protocols:
- OCI for container manifests/blobs/tags
- PyPI simple index
- RubyGems compact index/gems/specs
- npm package metadata
- Tauri upgrade feeds
- raw artifact delivery
- Background workers process uploaded artifacts and generate or finalize downloadable release assets.
7. License validation and device activation subsystem
- Licensing flows center on licenses/actions/*, machines/actions/*, and machine_processes/actions/*.
- The system supports checkout, permits, uses, validations, heartbeats, proofs, and versioned legacy paths such as v1x0 and v1x5.
- Machines, machine components, and machine processes are tracked separately, with policies controlling matching, uniqueness, leasing, heartbeat, and culling strategies.
8. Billing and external integrations
- Billing is isolated under app/services/billings and app/controllers/api/v1/stripe_controller.rb.
- The app integrates with Stripe for subscriptions, customer lifecycle, and webhook event handling.
- Slack integration exists for notifications/invites, and WorkOS-backed SSO appears in the auth flow and account/user fields.
- Webhooks are first-class: endpoints receive events, events are persisted, retried, and delivered asynchronously.
9. Persistence and data stores
- The main transactional store is the relational database defined in db/schema.rb and migrations under db/migrate.
- Analytics and logs use a separate ClickHouse path under db/clickhouse with ClickhouseRecord and analytics models for gauges, series, leaderboards, heatmaps, request logs, and event logs.
- The architecture is therefore split between OLTP domain data and high-volume analytical/event data.
10. Async processing and background jobs
- Sidekiq is the background job runner; queue config is in config/sidekiq.yml.
- Workers handle heartbeats, culling dead machines/processes, webhook delivery, billing initialization, expiration checks, pruning expired sessions/tokens/download links, and analytics aggregation/spark recording.
- This is the main async boundary: request-time writes enqueue jobs, and jobs later update derived state, logs, notifications, or external services.
11. Observability and audit pipeline
- Request logs and event logs are persisted and also summarized into “spark” and analytics tables.
- There are dedicated workers for recording user/license/machine/request/event sparks and for vacuum/analyze/pruning tasks.
- The repo clearly separates operational request handling from historical analytics and audit reporting.
12. Frontend/API surface and versioning
- The repo is API-first; app/views contains only a few protocol-facing HTML responses such as PyPI simple index pages and mailer templates.
- Versioned API behavior is present throughout, including api/v1, v1x0, and v1x5 compatibility paths.
- There are also binary/short URL endpoints under app/controllers/bin, indicating non-JSON delivery paths for downloads and legacy clients.
13. Infrastructure and deployment
- The app runs on Rails with Puma, fronted by Caddy in containerized/self-hosted deployments.
- Redis is used for background jobs and caching/coordination; there are initializers for rate limiting, request timeouts, CORS, S3/R2 storage, and Stripe/Slack/WorkOS integrations.
- This is designed as a self-hostable service but also backs Keygen Cloud.
14. Testing and quality boundaries
- The repo is heavily tested with RSpec and Cucumber feature specs.
- Feature files mirror the API/resource structure closely, which makes them a good map of the external contract and supported flows.
- The test suite reinforces the architectural split between controllers, policies, services, workers, and persistence models.
Main entry points: base_controller.rb API v1 · policies Policies · workers Workers · stripe_controller.rb Billing/Webhooks
Components 23
HTTP/API
Rails request handling, versioned controllers, protocol endpoints, and shared concerns.
- Application · Top-level controller base for shared request behavior.
app/controllers/application_controller.rb - API v1 · Primary API controller base for versioned JSON and protocol responses.
app/controllers/api/v1/base_controller.rb - Concerns · Authentication, tenancy scoping, logging, rendering, limits, and pagination.
app/controllers/concerns - Licenses · Checkout, validation, permits, uses, and relationship endpoints for licenses.
app/controllers/api/v1/licenses_controller.rb - Machines · Machine activation, heartbeat, proofs, and related resource endpoints.
app/controllers/api/v1/machines_controller.rb - Releases · Release CRUD, publish/yank actions, and legacy upgrade paths.
app/controllers/api/v1/releases_controller.rb - Dist. endpoints · OCI, PyPI, RubyGems, npm, Tauri, and raw artifact delivery controllers.
app/controllers/api/v1/release_engines_controller.rb - Billing/Webhooks · Stripe, Slack, webhook endpoints, and webhook event retry flows.
app/controllers/api/v1/stripe_controller.rb - Analytics · Private analytics and observability endpoints for gauges, sparks, heatmaps, and leaderboards.
app/controllers/priv/analytics/base_controller.rb
Domain
Core licensing, tenancy, release, and authorization model layer.
- Tenant scope · Account and environment resolution services used across request paths.
app/services/resolve_account_service.rb - Licensing · License lookup, checkout, validation, and token resolution workflows.
app/services/license_validation_service.rb - Machines · Machine checkout and lifecycle workflows plus legacy proof handling.
app/services/machine_checkout_service.rb - Releases · Release upload, download, upgrade, and yank workflows.
app/services/v1x0/release_upload_service.rb - Billing · Stripe customer, subscription, and portal lifecycle operations.
app/services/billings/create_subscription_service.rb - Webhooks · Event broadcasting, persistence, retries, and delivery orchestration.
app/services/broadcast_webhook_service.rb - Core models · Accounts, environments, products, policies, licenses, machines, users, tokens, and releases.
app/models - Policies · Authorization rules and tenancy constraints for the public and EE paths.
app/policies
Async
Background jobs and deferred workflows.
- Workers · Heartbeat, culling, artifact processing, pruning, webhook delivery, billing, and analytics jobs.
app/workers
Data
Transactional and analytical persistence layers.
- ClickHouse · Request, event, spark, gauge, heatmap, and leaderboard analytical tables.
db/clickhouse_schema.rb - Postgres · Primary transactional schema, migrations, and seeded domain state.
db/schema.rb
Platform
Runtime, integrations, and internal support code.
- EE ext · Enterprise-only router, SSO, protected methods, and protected model behavior.
lib/keygen/ee.rb - Routing · Exporter/importer, JSON:API rendering, middleware, pagination, and routing helpers.
lib/keygen/routing.rb - Init · Runtime configuration for Redis, Sidekiq, Stripe, Slack, WorkOS, CORS, timeout, and storage.
config/initializers
Connections 31
- Application → Concerns: includes · Shared request behavior is composed from controller concerns.
- API v1 → Concerns: uses · Versioned API controllers rely on the shared concern stack.
- Licenses → API v1: inherits · License routes sit on the API v1 base controller.
- Machines → API v1: inherits · Machine routes sit on the API v1 base controller.
- Releases → API v1: inherits · Release routes sit on the API v1 base controller.
- Dist. endpoints → API v1: inherits · Protocol-specific distribution endpoints share the API v1 base.
- Billing/Webhooks → API v1: inherits · Billing and webhook endpoints are served through API v1.
- Analytics → API v1: inherits · Private analytics endpoints follow the same controller base patterns.
- Licenses → Policies: authorizes · License actions are guarded by policy checks.
- Machines → Policies: authorizes · Machine actions are guarded by policy checks.
- Releases → Policies: authorizes · Release lifecycle is policy-controlled.
- Dist. endpoints → Policies: authorizes · Registry and download paths enforce access policy.
- Billing/Webhooks → Policies: authorizes · Billing, webhook, and integration paths enforce policy.
- API v1 → Tenant scope: resolves · Controllers derive account and environment scope through services.
- Licenses → Licensing: delegates · Checkout, validation, and lookup actions are service-driven.
- Machines → Machines: delegates · Activation and heartbeat actions are service-driven.
- Releases → Releases: delegates · Publish, upgrade, upload, download, and yank actions are service-driven.
- Billing/Webhooks → Billing: delegates · Stripe billing operations are isolated into billing services.
- Billing/Webhooks → Webhooks: delegates · Event persistence and delivery use webhook services.
- Core models → Postgres: persists to · Primary domain state lives in the relational database.
- Analytics → ClickHouse: reads from · Analytics endpoints read analytical and log data from ClickHouse.
- Workers → Postgres: updates · Jobs mutate transactional state and derived records.
- Workers → ClickHouse: aggregates · Jobs record sparks, request logs, and analytics summaries.
- Workers → Webhooks: executes · Background delivery and retries are worker-backed.
- Workers → Releases: processes · Artifact processing and release finalization run asynchronously.
- EE ext → Policies: extends · Enterprise features add protected authorization and routing boundaries.
- EE ext → Core models: extends · EE-specific model behavior augments core entities.
- Routing → API v1: supports · Rendering, routing, and pagination helpers underpin API behavior.
- Init → Workers: configures · Background job runtime and queues are configured at boot.
- Init → Billing: configures · External integrations such as Stripe are initialized at boot.
- Init → Webhooks: configures · Webhook, Redis, timeout, and storage settings are initialized at boot.