ploykit

module
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2026 License: MIT

README

CI React 19


ploykit is a full-stack framework for building multi-tenant SaaS products: eleven production-grade business domains, a cross-cutting authorization layer, a strong-profile authorization engine, 18 platform packages, and a React 19 client/UI layer — wired end-to-end in a runnable example app.

Dependencies are strictly one-way: product → framework. Your repository consumes ploykit; ploykit never knows your product. That rule (and every other boundary) is enforced by architecture tests, not by convention.

Why ploykit

  • Months of table-stakes work, already built. Auth (password + OAuth + federated SSO), workspaces & membership, billing with Stripe and manual channels, quotas with reservations, notifications, audit trail, analytics, webhooks with retry and key rotation, scheduling, site settings — domain code you would otherwise write before writing your product.
  • Security is a gate, not a guideline. Tenant isolation, CSRF, impersonation-safe sessions, egress SSRF protection, secret sealing, CSV-injection-safe exports — invariants pinned by architecture tests that fail the build when a boundary is crossed.
  • Production posture out of the box. Prerendered SSR with versioned caching, River-backed transactional events, partitioned audit and analytics tables with retention workers, health and readiness probes, Prometheus metrics, structured logging with secret redaction.
  • A real app, not a toy. The example/ product exercises every domain — pages, API, migrations, and tests — and is the reference for how a product consumes the framework.

What's inside

Layer What you get
Business domains (11) identity · workspace · billing · quota · admin · notify · audit · analytics · webhooks · schedule · settings
Cross-cutting authz (simple RBAC) · authorization (strong profile: YAML operation catalog, staged evaluator, allow / deny / challenge)
Platform packages (18) renderx (SSR + prerender + QuickJS sandbox) · pg (tenant-scoped pools) · pgmigrate · pgpart · events (River) · webx · wsx (WebSocket rooms) · egressx (SSRF-safe egress) · sealx (secret sealing) · storagex · redactx · logx · metrics · workers · cronx · redisx · relayx · ids
Frontend @ploykit/ui (Base UI component system, 40+ pages) · @ploykit/client (typed API + CSRF + realtime) · @ploykit/runtime (hydration and prerender bridge)

Screenshots

Workspace billing — plans & manual channel
Billing

Extend it in minutes

Every domain exposes hooks. React to anything your product cares about in a few lines — inside your own transaction boundary:

import "github.com/haozing/ploykit/platform/events"

// react to a domain event emitted by the framework
events.Subscribe("task.created", func(ctx context.Context, ev events.Event) error {
    slog.Info("task created", "workspace", ev.WorkspaceID)
    return nil // return an error to fail the emitting transaction
})

That is the whole idea: the framework owns the machinery (tenancy, auth, billing, quotas, events, rendering); your repository owns the product — pages, product migrations (1001+), and the reactions that make it yours. The example/ app is a complete, working demonstration.

Architecture at a glance

graph LR
    subgraph Product["Your product repository"]
        APP["Your application code"]
        WEB["@ploykit/ui · client · runtime"]
    end
    subgraph Framework["ploykit framework"]
        DOMAINS["11 business domains<br/>identity · workspace · billing · quota · …"]
        CORE["authz · authorization"]
        PLATFORM["18 platform packages<br/>renderx · pg · events · webx · sealx · …"]
    end
    DB[("PostgreSQL")]

    APP --> WEB
    APP --> DOMAINS
    WEB --> DOMAINS
    DOMAINS --> CORE
    DOMAINS --> PLATFORM
    PLATFORM --> DB

Every arrow above is one-directional and enforced: the architecture tests fail the build if a domain imports another domain, if platform/* reaches into business code, or if a product page shadows a framework page.

Quickstart

# 1. database (Docker)
make -C example db-up

# 2. backend (:8030, runs migrations, wires every domain)
make -C example backend

# 3. frontend dev server (:5173, proxies to :8030)
make -C example frontend

Open http://localhost:5173, register with the dev verification code 000000, and the whole stack is yours. Prefer a single production-style binary? make -C example build prerenders the frontend and embeds it into one Go executable.

No make on your machine (Windows/Git Bash)? Every target has a native equivalent in docs/dev-environment.md. Building example/web for production requires the root npm run build first (dev mode consumes package sources directly, prod consumes dist/) — details in the same doc.

Integrating against the HTTP API? Read docs/api-conventions.md first — CSRF token rotation on session establishment is the #1 integration pitfall.

Full-stack verification:

go test ./...                             # unit gates (architecture boundaries included)
make -C example db-up && make test-db     # integration tests against PostgreSQL
make verify-ui                            # frontend component tests
python tools/check_api.py                 # OpenAPI ↔ route contract check

Documentation

Doc Contents
docs/architecture.md Layering, domain map, hook model, boundary enforcement
docs/api-index.md Every domain extension point (25 hooks) with semantics
docs/platform-api-index.md The full platform/* API surface
docs/rendering.md SSR, prerender, hydration, caching, sandboxing
docs/pages.md Frontend page inventory and ownership rules
docs/dev-environment.md Toolchain, database, sealing keys, RLS playground
docs/adr/ Architecture decision records
docs/ROADMAP.md Trigger-based roadmap — what lands next and why not yet

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md for the full setup and the architecture contract. The short version: the architecture tests are the contract; if your change crosses a boundary on purpose, update the ADR and the allowlist in the same PR. Security issues go through SECURITY.md, never public issues.

License

MIT — see LICENSE.

Directories

Path Synopsis
app
app
app
app
internal
Package notify is the notification domain: the in-app bell (notification table + preferences) plus the email adapter surface.
Package notify is the notification domain: the in-app bell (notification table + preferences) plus the email adapter surface.
app
platform
ids
logring
Package logring captures slog output into an in-memory ring buffer so a developer agent can fetch the records behind a single failed request by its request id ("one artifact per failure").
Package logring captures slog output into an in-memory ring buffer so a developer agent can fetch the records behind a single failed request by its request id ("one artifact per failure").
mcpx
Package mcpx is the mountable MCP (Model Context Protocol) server kernel: it turns a product's app into an agent-operable control plane by exposing intent-level tools over the streamable-HTTP MCP transport.
Package mcpx is the mountable MCP (Model Context Protocol) server kernel: it turns a product's app into an agent-operable control plane by exposing intent-level tools over the streamable-HTTP MCP transport.
pg
sealx
Package sealx seals tenant credentials at rest with AES-256-GCM (authenticate-then-store; the sealed form carries an authenticated timestamp blob, base64-encoded under the SealedPrefix).
Package sealx seals tenant credentials at rest with AES-256-GCM (authenticate-then-store; the sealed form carries an authenticated timestamp blob, base64-encoded under the SealedPrefix).
storagex
Package storagex HTTP companions (storage-walk #14): the serving handler for the /uploads/ URL convention LocalBackend.URL() produces, and the multipart parsing helper for upload endpoints.
Package storagex HTTP companions (storage-walk #14): the serving handler for the /uploads/ URL convention LocalBackend.URL() produces, and the multipart parsing helper for upload endpoints.
whsign
Package whsign implements the ploykit webhook delivery signature protocol.
Package whsign implements the ploykit webhook delivery signature protocol.
wsx
Package webhooks delivers workspace events to subscriber-controlled HTTP endpoints (the SaaS "outgoing webhook" surface).
Package webhooks delivers workspace events to subscriber-controlled HTTP endpoints (the SaaS "outgoing webhook" surface).
app
app

Jump to

Keyboard shortcuts

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