Design change: vibe_erp deliberately does NOT support multiple companies in
one process. Each running instance serves exactly one company against an
isolated Postgres database. Hosting many customers means provisioning many
independent instances, not multiplexing them.
Why: most ERP/EBC customers will not accept a SaaS where their data shares
a database with other companies. The single-tenant-per-instance model is
what the user actually wants the product to look like, and it dramatically
simplifies the framework.
What changed:
- CLAUDE.md guardrail #5 rewritten from "multi-tenant from day one" to
"single-tenant per instance, isolated database"
- api.v1: removed TenantId value class entirely; removed tenantId from
Entity, AuditedEntity, Principal, DomainEvent, RequestContext,
TaskContext, IdentityApi.UserRef, Repository
- platform-persistence: deleted TenantContext, HibernateTenantResolver,
TenantAwareJpaTransactionManager, TenancyJpaConfiguration; removed
@TenantId and tenant_id column from AuditedJpaEntity
- platform-bootstrap: deleted TenantResolutionFilter; dropped
vibeerp.instance.mode and default-tenant from properties; added
vibeerp.instance.company-name; added VibeErpApplication @EnableJpaRepositories
and @EntityScan so PBC repositories outside the main package are wired;
added GlobalExceptionHandler that maps IllegalArgumentException → 400
and NoSuchElementException → 404 (RFC 7807 ProblemDetail)
- pbc-identity: removed tenant_id from User, repository, controller, DTOs,
IdentityApiAdapter; updated UserService duplicate-username message and
the matching test
- distribution: dropped multiTenancy=DISCRIMINATOR and
tenant_identifier_resolver from application.yaml; configured Spring Boot
mainClass on the springBoot extension (not just bootJar) so bootRun works
- Liquibase: rewrote platform-init changelog to drop platform__tenant and
the tenant_id columns on every metadata__* table; rewrote
pbc-identity init to drop tenant_id columns, the (tenant_id, *)
composite indexes, and the per-table RLS policies
- IdentifiersTest replaced with Id<T> tests since the TenantId tests
no longer apply
Verified end-to-end against a real Postgres via docker-compose:
POST /api/v1/identity/users → 201 Created
GET /api/v1/identity/users → list works
GET /api/v1/identity/users/X → fetch by id works
POST duplicate username → 400 Bad Request (was 500)
PATCH bogus id → 404 Not Found (was 500)
PATCH alice → 200 OK
DELETE alice → 204, alice now disabled
All 18 unit tests pass.