platformkit

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: Apache-2.0

README

PlatformKit

Reference architecture for composable, multi-tenant SaaS in Go: one binary, explicit wiring, Postgres row-level security, generated admin screens, ten CI gates. Read ARCHITECTURE.md.

Run it

git clone https://github.com/septagon-oss/platformkit && cd platformkit
make up
cp config.example.yaml config.yaml
go run ./apps/platformkit bootstrap --config config.yaml \
    --tenant platformkit --host platformkit.localhost \
    --name PlatformKit --admin-email admin@platformkit.localhost
make run

Or scripts/start.sh, which is those five with the checks a first run would otherwise discover one failure at a time — docker, the Go version go.mod asks for, both published ports, the configuration file, the first tenant — and which is safe to run twice.

Then open http://platformkit.localhost:8080/admin/login and sign in with that address and the password bootstrap printed. Behind it is the whole application: the dashboard, a screen for every entity mounted through rest.Spec, and /admin/_gallery for every component it is drawn with. The screens are generated from each entity's schema, so there is one of them for tasks and users without a line of code for either.

The database starts empty. bootstrap migrates it, creates the first tenant, the two roles a tenant starts with, and the administrator who signs in to it, all in one transaction — and refuses to run again once any tenant exists, which is what makes it safe to leave in the binary. The password is printed once, to stderr, or taken from PLATFORMKIT_BOOTSTRAP_PASSWORD.

The same thing over the API, if a screen is not what you came for:

curl -sc jar -H 'Host: platformkit.localhost' -H 'Content-Type: application/json' \
    -d '{"email":"admin@platformkit.localhost","password":"<the printed password>"}' \
    localhost:8080/api/v1/auth/login
curl -sb jar -H 'Host: platformkit.localhost' -H 'Content-Type: application/json' \
    -d '{"title":"chiller-2 supply temperature"}' \
    localhost:8080/api/v1/task/tasks

Every tenant is reached at its own host, so the Host header is what decides whose data a request sees. Ports can be overridden with PLATFORMKIT_PG_PORT / PLATFORMKIT_NATS_PORT.

Gates

make check runs seven commands: build, vet, fmt-check, test, check-loc, check-packages and check-gucs. make e2e is the tenth gate: it boots the application on a database of its own and drives the admin shell with a browser. Against ARCHITECTURE.md's ten gates, all ten are real today. CI runs both targets.

Contributing, security, releases

CONTRIBUTING.md is the shape of a change and the commit rules. SECURITY.md is where a vulnerability goes — privately, never an issue. RELEASE.md is the tag procedure and what the tag builds.

Status

Extracted from a larger private codebase, and complete: the kernel, the browser half, the reference binary and eleven modules, all running. Not yet tagged — v1.0.0 is the first release, and RELEASE.md is what has to be true before it. ADR 0009 says what this repository holds and what the two private ones do; docs/adr says why the rest of it is the way it is, and loc-budget.json is what it costs.

Directories

Path Synopsis
apps
platformkit command
Command platformkit is the reference application: one binary, one image, and two subcommands — `run`, which serves, and `bootstrap`, which creates the first tenant of an empty installation.
Command platformkit is the reference application: one binary, one image, and two subcommands — `run`, which serves, and `bootstrap`, which creates the first tenant of an empty installation.
Package design is the application's colours and type, as the two themes it ships and the custom properties they render to.
Package design is the application's colours and type, as the two themes it ships and the custom properties they render to.
kit
app
Package app assembles a running application from a configuration and a list of modules.
Package app assembles a running application from a configuration and a list of modules.
config
Package config is the one configuration surface: a YAML file, the environment overrides, the overrides a composition passes to Load, and a check that nothing needed is missing or malformed.
Package config is the one configuration surface: a YAML file, the environment overrides, the overrides a composition passes to Load, and a check that nothing needed is missing or malformed.
crud
Package crud is the five operations every tenant-owned resource needs, and the schema a generated screen reads.
Package crud is the five operations every tenant-owned resource needs, and the schema a generated screen reads.
db
Package db owns database access.
Package db owns database access.
db/dbtest
Package dbtest gives one test its own Postgres schema.
Package dbtest gives one test its own Postgres schema.
events
Package events is the one door a module's events leave through.
Package events is the one door a module's events leave through.
health
Package health is the two probes an orchestrator calls, and the checks behind the second one.
Package health is the two probes an orchestrator calls, and the checks behind the second one.
httpx
Package httpx builds the single Huma API the application serves, records every operation the adapter mounts, and enforces that each one declares exactly one authorization: a permission, public, or any signed-in user.
Package httpx builds the single Huma API the application serves, records every operation the adapter mounts, and enforces that each one declares exactly one authorization: a permission, public, or any signed-in user.
internal/syscap
Package syscap mints the one capability that opens cross-tenant work.
Package syscap mints the one capability that opens cross-tenant work.
jobs
Package jobs runs the periodic work: the outbox relay, the outbox purge, and whatever a module schedules in its manifest.
Package jobs runs the periodic work: the outbox relay, the outbox purge, and whatever a module schedules in its manifest.
limit
Package limit is one rate limit for every replica.
Package limit is one rate limit for every replica.
module
Package module defines what a module is.
Package module defines what a module is.
problem
Package problem is the one error shape the API returns: RFC 9457 problem details (the revision of RFC 7807), served as application/problem+json.
Package problem is the one error shape the API returns: RFC 9457 problem details (the revision of RFC 7807), served as application/problem+json.
rest
Package rest is an entity's projection onto HTTP: five routes, the commands beside them, and the one mapping from kit/crud's errors to statuses.
Package rest is an entity's projection onto HTTP: five routes, the commands beside them, and the one mapping from kit/crud's errors to statuses.
tenancy
Package tenancy is the one tenant model and how a request carries it.
Package tenancy is the one tenant model and how a request carries it.
Package migrations is the one migration directory.
Package migrations is the one migration directory.
modules
admin
Package admin is the shell: the pages a person sees, as opposed to the routes a program calls.
Package admin is the shell: the pages a person sees, as opposed to the routes a program calls.
admin/internal
Package internal is the shell's implementation: the frame, the pages written by hand, and the screens generated from every resource kit/rest registered.
Package internal is the shell's implementation: the frame, the pages written by hand, and the screens generated from every resource kit/rest registered.
audit
Package audit is the module manifest: what the kernel needs to know about the audit trail that it cannot learn from a function call.
Package audit is the module manifest: what the kernel needs to know about the audit trail that it cannot learn from a function call.
audit/contracts
Package contracts is everything another module, an app or a test may know about the audit trail: the row, the query, the permission and the Service interface.
Package contracts is everything another module, an app or a test may know about the audit trail: the row, the query, the permission and the Service interface.
audit/contracts/audittest
Package audittest is the conformance suite for contracts.Service, and a fake that passes it.
Package audittest is the conformance suite for contracts.Service, and a fake that passes it.
audit/internal
Package internal is every implementation of the audit module.
Package internal is every implementation of the audit module.
auth
Package auth is signing in: sessions, passwords, single sign-on, and the roles that decide what a caller may do.
Package auth is signing in: sessions, passwords, single sign-on, and the roles that decide what a caller may do.
auth/contracts
Package contracts is everything another module, an app or a test may know about signing in: the session, the identity a caller has, the errors a login can fail with, and the Service interface.
Package contracts is everything another module, an app or a test may know about signing in: the session, the identity a caller has, the errors a login can fail with, and the Service interface.
auth/contracts/authtest
Package authtest is the conformance suite for contracts.Service, a fake that passes it, and an OpenID Connect issuer a test can sign in against.
Package authtest is the conformance suite for contracts.Service, a fake that passes it, and an OpenID Connect issuer a test can sign in against.
auth/internal
Package internal is every implementation of the auth module.
Package internal is every implementation of the auth module.
billing
Package billing is the module manifest: what a tenant is paying for.
Package billing is the module manifest: what a tenant is paying for.
billing/contracts
Package contracts is everything another module, an app or a test may know about billing: the two entities, the events, the permissions, the payment provider this module needs somebody else to satisfy, and the Service interface.
Package contracts is everything another module, an app or a test may know about billing: the two entities, the events, the permissions, the payment provider this module needs somebody else to satisfy, and the Service interface.
billing/contracts/billingtest
Package billingtest is the conformance suite for contracts.Service, and a fake that passes it.
Package billingtest is the conformance suite for contracts.Service, and a fake that passes it.
billing/internal
Package internal is every implementation of the billing module.
Package internal is every implementation of the billing module.
content
Package content is the module manifest: the pages and posts a tenant's public site is made of.
Package content is the module manifest: the pages and posts a tenant's public site is made of.
content/contracts
Package contracts is everything another module, an app or a test may know about content: the entity, the events, the permissions and the Service interface.
Package contracts is everything another module, an app or a test may know about content: the entity, the events, the permissions and the Service interface.
content/contracts/contenttest
Package contenttest is the conformance suite for contracts.Service, and a fake that passes it.
Package contenttest is the conformance suite for contracts.Service, and a fake that passes it.
content/internal
Package internal is every implementation of the content module.
Package internal is every implementation of the content module.
file
Package file is the module manifest: uploaded bytes and the rows that name them.
Package file is the module manifest: uploaded bytes and the rows that name them.
file/contracts
Package contracts is everything another module, an app or a test may know about files: the entity, the events, the permissions, the storage this module needs somebody else to satisfy, and the Service interface.
Package contracts is everything another module, an app or a test may know about files: the entity, the events, the permissions, the storage this module needs somebody else to satisfy, and the Service interface.
file/contracts/filetest
Package filetest is the conformance suite for contracts.Service, a Storage in memory that the suite runs against, and a fake Service that passes it.
Package filetest is the conformance suite for contracts.Service, a Storage in memory that the suite runs against, and a fake Service that passes it.
file/internal
Package internal is every implementation of the file module.
Package internal is every implementation of the file module.
notification
Package notification is the module manifest: telling somebody something, in the application and optionally by mail.
Package notification is the module manifest: telling somebody something, in the application and optionally by mail.
notification/contracts
Package contracts is everything another module, an app or a test may know about notifications: the entity, the notice, the events, the two interfaces this module needs somebody else to satisfy, and the Service.
Package contracts is everything another module, an app or a test may know about notifications: the entity, the notice, the events, the two interfaces this module needs somebody else to satisfy, and the Service.
notification/internal
Package internal is every implementation of the notification module.
Package internal is every implementation of the notification module.
site
Package site is the module manifest: the data a tenant's public site is made of, and none of the rendering.
Package site is the module manifest: the data a tenant's public site is made of, and none of the rendering.
site/contracts
Package contracts is everything another module, an app or a test may know about a tenant's public site: the settings, the event, the permission and the Service interface.
Package contracts is everything another module, an app or a test may know about a tenant's public site: the settings, the event, the permission and the Service interface.
site/contracts/sitetest
Package sitetest is the conformance suite for contracts.Service, and a fake that passes it.
Package sitetest is the conformance suite for contracts.Service, and a fake that passes it.
site/internal
Package internal is every implementation of the site module.
Package internal is every implementation of the site module.
task
Package task is the module manifest: what the kernel needs to know about tasks that it cannot learn from a function call.
Package task is the module manifest: what the kernel needs to know about tasks that it cannot learn from a function call.
task/contracts
Package contracts is everything another module, an app or a test may know about tasks: the entity, the events, the permissions and the Service interface.
Package contracts is everything another module, an app or a test may know about tasks: the entity, the events, the permissions and the Service interface.
task/contracts/tasktest
Package tasktest is the conformance suite for contracts.Service, and a fake that passes it.
Package tasktest is the conformance suite for contracts.Service, and a fake that passes it.
task/internal
Package internal is every implementation of the task module.
Package internal is every implementation of the task module.
tenant
Package tenant is the control plane: which customers exist, and which host belongs to which one.
Package tenant is the control plane: which customers exist, and which host belongs to which one.
tenant/contracts
Package contracts is everything another module, an app or a test may know about tenants: the entity, the events, the permission and the Service interface.
Package contracts is everything another module, an app or a test may know about tenants: the entity, the events, the permission and the Service interface.
tenant/contracts/tenanttest
Package tenanttest is the conformance suite for contracts.Service, and a fake that passes it.
Package tenanttest is the conformance suite for contracts.Service, and a fake that passes it.
tenant/internal
Package internal is every implementation of the tenant module.
Package internal is every implementation of the tenant module.
user
Package user is the module manifest: the people in a tenant.
Package user is the module manifest: the people in a tenant.
user/contracts
Package contracts is everything another module, an app or a test may know about users: the entity, the events, the permissions and the Service interface.
Package contracts is everything another module, an app or a test may know about users: the entity, the events, the permissions and the Service interface.
user/contracts/usertest
Package usertest is the conformance suite for contracts.Service, and a fake that passes it.
Package usertest is the conformance suite for contracts.Service, and a fake that passes it.
user/internal
Package internal is every implementation of the user module.
Package internal is every implementation of the user module.
tools
locbudget command
Command locbudget counts tracked source lines per bucket and fails when a bucket exceeds its committed maximum.
Command locbudget counts tracked source lines per bucket and fails when a bucket exceeds its committed maximum.
ui
Package ui is the browser half of the application: one stylesheet and four controllers, served as static files beside the API.
Package ui is the browser half of the application: one stylesheet and four controllers, served as static files beside the API.
components
Package web renders pk-ui component contracts to HTML with gomponents, styled entirely through tw class lists against the PlatformKit design system's role variables.
Package web renders pk-ui component contracts to HTML with gomponents, styled entirely through tw class lists against the PlatformKit design system's role variables.
css
Package css is the CSS intermediate representation the stylesheet is built in: typed values, declarations, rules, custom properties and the two at-rules the design system uses.
Package css is the CSS intermediate representation the stylesheet is built in: typed values, declarations, rules, custom properties and the two at-rules the design system uses.
icon
Package icon is the glyph set the components draw with: the regular-weight Phosphor subset this application uses, vendored as path data.
Package icon is the glyph set the components draw with: the regular-weight Phosphor subset this application uses, vendored as path data.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL