Tenants — the module and its seams

Tenants — the module and its seams An architecture diagram generated by Archify. auth · main's seedRoles · Deps.OnCreate: []contracts.Hook · Deps · hooks main satisfies · Deps auth · main's seedRoles Deps.OnCreate: []contracts.Hook Deps user · main's firstAdmin · Deps.Invite: contracts.Inviter · Deps · hooks main satisfies · Deps user · main's firstAdmin Deps.Invite: contracts.Inviter Deps admin's switcher · Deps.Tenants: Service · List · consumers · consumer admin's switcher Deps.Tenants: Service · List consumer task · billing · audit · jobs.TenantLister ← Active · consumers · consumer task · billing · audit jobs.TenantLister ← Active consumer auth · notification · PublicHost ← Service.Hosts · consumers · consumer auth · notification PublicHost ← Service.Hosts consumer main · kit/httpx · TenantLoader · Bootstrap · consumers · consumer main · kit/httpx TenantLoader · Bootstrap consumer contracts/ · Tenant · 3 events · 1 permission · Service · modules/tenant contracts/ Tenant · 3 events · 1 permission · Service module.go · Module(Deps{OnCreate, Invite}) · Bootstrap · modules/tenant module.go Module(Deps{OnCreate, Invite}) · Bootstrap internal/ · Service: Create · AddHost · Suspend · ByHost · modules/tenant internal/ Service: Create · AddHost · Suspend · ByHost RegisterRoutes · httpx.Register · /api/v1/tenant/tenants · suspend, hosts, invite · kit/ seams RegisterRoutes · httpx.Register /api/v1/tenant/tenants · suspend, hosts, invite admin page · no Spec · /admin/tenant/tenants · kit/ seams admin page · no Spec /admin/tenant/tenants events · tenant.created · suspended · host_added · kit/ seams events tenant.created · suspended · host_added jobs · none · Jobs: nil · kit/ seams jobs none · Jobs: nil migrations/000006 · 000020 · tenants, tenant_hosts · FORCE RLS · kit/ seams migrations/000006 · 000020 tenants, tenant_hosts · FORCE RLS Events · Nav NewService(OnCreate) RegisterRoutes · SystemToken() SQL over Tx[System] events.PublishFor Jobs: nil Nav path Deps Deps Tenants.List modules/tenant kit/ seams Deps · hooks main satisfies consumers Legend Frontend Backend Database Message bus

Promises

  • • tenant:manage is an operator permission: every route and the switcher, refused at any tenant but the operator's
  • • tenant.created after the hooks; tenant.suspended once, a retry says nothing; tenant.host_added for a new host

Needs

  • • OnCreate: []contracts.Hook, main's seedRoles over auth.SeedRoles; Invite: contracts.Inviter, main's firstAdmin
  • • No rest.Spec: a Tenant has no tenant_id, so hand-written handlers open system transactions from api.SystemToken()

Proof

  • • tenanttest: the fake and the real service pass one suite; internal tests: the hook, own row only, Bootstrap once
  • • app_test.go: a second tenant as the operator, 403 at another tenant's host, an administrator invited; no browser journey