OSS-first docs
These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.
Database setup
Set up Drizzle without coupling modules to your database
Use Drizzle as the PostgreSQL migration and query layer while keeping ContractSpec modules portable. Compose schemas from module contributions, apply migrations explicitly, seed deterministic fixtures, and bind AuthOS, BillingOS, and RBAC through host-owned adapters.
Install the database boundary
bun add drizzle-orm drizzle-kit @lssm-tech/lib.schema @lssm-tech/integration.provider-database @lssm-tech/lib.identity-rbacDrizzle owns SQL schema and migrations. ContractSpec owns portable entities, domain contracts, RBAC policy semantics, and governed database operation envelopes.
identity-rbac
Provides User, Session, Organization, Team, Role, Permission, PolicyBinding, API key, and passkey entities through identityRbacSchemaContribution.
packages/libs/identity-rbac/src/entities@lssm-tech/lib.identity-rbac/entities
AuthOS
Treat AuthOS as the UI/runtime adapter layer. Persist identities, sessions, organizations, teams, and RBAC through identity-rbac tables and auth adapters.
packages/modules/auth-os@lssm-tech/module.auth-os
BillingOS
Keep BillingOS country-neutral and provider-free. Implement search, quote, invoice, payment, and tax ports with database-backed adapters in the host app.
packages/modules/billing-os/src/ports@lssm-tech/module.billing-os/ports
Recommended setup flow
- Compose database entities from module schema contributions before writing Drizzle tables by hand.
- Generate or maintain a Drizzle PostgreSQL schema from the composed model, then keep the Drizzle schema as migration input.
- Use drizzle-kit generate for migration files, drizzle-kit migrate for applying them, and custom migrations for RLS, seed prerequisites, or unsupported DDL.
- Bind runtime reads and writes through @lssm-tech/integration.provider-database instead of importing Drizzle into modules such as AuthOS or BillingOS.
- Seed tenants, users, roles, permissions, and minimal domain fixtures in deterministic order after migrations and before UI demos/tests.
- Fail closed on RBAC data access: tenant id, actor id, policy decision, idempotency key, audit refs, and expected write sets must be explicit for governed writes.
Drizzle configuration
Keep drizzle.config.ts, src/db/schema.ts, and the drizzle/ migration folder in the host app or deployment package. Do not place provider credentials or migration side effects inside reusable modules.
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
schema: "./src/db/schema.ts",
out: "./drizzle",
dbCredentials: { url: process.env.DATABASE_URL! },
strict: true,
});Compose module schemas
Start with reusable contributions such as identityRbacSchemaContribution, then add host-owned entities for AuthOS adapters and BillingOS persistence. Generate Drizzle tables from that composed source or keep a reviewed generated schema checked in.
import { composeModuleDatabaseSchemas } from "@lssm-tech/lib.schema";
import { identityRbacSchemaContribution } from "@lssm-tech/lib.identity-rbac/entities";
const schemaSource = composeModuleDatabaseSchemas([
identityRbacSchemaContribution,
authHostSchemaContribution,
billingHostSchemaContribution,
]);
await writeFile("src/db/schema.ts", schemaSource);Bind modules through providers and ports
Use @lssm-tech/integration.provider-database for tenant-scoped providers, governed reads, and governed mutations. AuthOS and BillingOS should receive host adapters, not raw Drizzle clients.
import { createTenantScopedDatabaseProvider } from "@lssm-tech/integration.provider-database/impls";
const tenantDb = createTenantScopedDatabaseProvider({
provider: postgresDatabaseProvider,
tenantId: session.tenantId,
});
export const billingPorts = {
searchCustomers: (query) => customerRepository.search(tenantDb, query),
searchSellableItems: (query) => priceBookRepository.search(tenantDb, query),
};Seed in dependency order
- Tenant/workspace rows and environment metadata.
- Identity rows: users, accounts, sessions, organizations, members, teams.
- RBAC rows: roles, permissions, policy bindings, and deny fixtures.
- Domain fixtures: BillingOS customers, price books, quotes, invoices, and payment evidence.
- Audit and replay rows used by governed mutation tests.
Set up i18n
Use ContractSpec translation specs, the translation runtime, SSR snapshots, mobile locale ownership, and optional i18next projection from one reusable i18n layer.
Flexible import templates
Publish a recommended data-exchange import shape while users import CSV, JSON, or XML files with alternate headers and localized values.
Why ContractSpec
Keep educational and comparison content reachable without letting it define the primary OSS learning path.