1. Core Concept: The "Building" Metaphor
We are transitioning from a model where a "Person" is physically glued to a single "Floor" (Tenant), to a model where a Person (User) exists independently in the lobby and holds Keys (Memberships) to access specific Floors.
- Building: LogicSpike Platform
- Lobby: Global User Table (Identity)
- Floors: Tenants (Workspaces)
- Apartments: Services (Apps like Blog, Store)
- Keys: Memberships & Permissions
2. Multi-Tenancy Architecture (Decoupling Identity)
Current State
users table contains tenant_id.
- Limitation: A user cannot be a member of multiple workspaces.
- Limitation: "Login" creates a tenant.
Proposed Schema
We will split users into users (Identity) and memberships (Access).
Addressing Your Questions
"If staff of some floor also want to own new floor for there new busineess, how we will handle it?"
With this new schema:
- User A exists once in the
userstable. - User A is a "Staff" in Floor 1 (Membership record:
user_id=A, tenant_id=1, role=staff). - User A decides to start a business. They trigger "Create Tenant".
- Floor 2 is created.
- User A becomes "Owner" of Floor 2 (New Membership record:
user_id=A, tenant_id=2, role=owner). - When User A logs in, they choose which "Floor" to visit. The JWT issued is scoped to that specific floor.
Alternative Consideration: "Instagram Style" (Multiple Accounts, Same Email)
You mentioned an "Instagram-like" model where one email can have multiple accounts.
- Instagram Model: Distinct separate accounts (User A, User B) that just happen to be logged in on the same device. Often have different passwords/credentials.
- Proposed LogicSpike Model: Unified Identity (User A) with multiple Personas (Memberships).
Why we recommend the Unified Identity (Membership) model:
- Single Sign-On: You don't want to remember 5 different passwords for your 5 businesses.
- Centralised Security: If you change your password or enable 2FA, it protects all your businesses.
- "Persona" Support: We can add a
display_nameorusernameto the Membership table.- In
Tenant A, I am "BossMan". - In
Tenant B, I am "SupportAgent01". - But underneath, I am still the same authenticated Human (
user_id).
- In
This achieves the "Multiple Accounts" feel without the headache of managing duplicate user records.
3. Authorization & RBAC
Current State
Hardcoded strings in code: if (user.role === 'owner').
Proposed Schema
We introduce a roles table to define permissions dynamically.
// Table: roles
{
id: "role_123",
tenantId: "tenant_abc", // or NULL for system default roles
name: "Editor",
permissions: ["blog.read", "blog.write", "comments.moderate"] // JSONB
}Policy Enforcement: Middleware will verify permissions, not roles.
// OLD
if (req.user.role === 'admin') deletePost();
// NEW
if (req.user.hasPermission('blog.delete')) deletePost();4. Service-Level Authentication ("Apartments")
User-to-Service (Human entering an Apartment)
When a user on Floor 1 wants to enter the "Blog Apartment":
- Login: User logs into Floor 1.
- Token Issue: Manager issues JWT.
sub:user_123tid:tenant_456permissions:["blog:posts.update", "media:files.read"](Computed from Membership -> Role)
- Access: User requests
POST /blog/posts. - Verification: Blog Service verifies JWT signature and checks for
blog:posts.updatepermission.
Service-to-Service (M2M)
"If apartments also need to authentication how we will handle it?"
Services ("Apartments") are treated as special restricted users. They have their own identity (Service Accounts).
Scenario: Billing Service needs to count posts in Blog Service.
- Identity: Billing Service has a
client_idandclient_secret. - Auth: Billing Service calls Manager: "I am Billing, give me a token for Blog".
- Token: Manager issues a short-lived "Service Token".
sub:service_billingaud:service_blogscopes:["system:metrics.read"]
- Request: Billing Service calls
GET blog-service/internal/metricswith the token. - Verification: Blog Service checks
audandscopes.
5. Security & Token Infrastructure
- Asymmetric Keys (RS256):
- Manager (IdP): Holds Private Key (Signer).
- Services (Gateway, Blog, Store): Hold Public Key (Verifier).
- Benefit: We don't share secrets. If Blog Service is hacked, they can't forge tokens for Store Service.
- Revocation:
- We will implement a
jti(JWT ID) blacklist in Redis or DB for immediate revocation of compromised tokens.
- We will implement a
6. Authentication Methods (New)
Email & Password Login
Currently, the system is OAuth-only. We will introduce credential-based login.
Database Schema
We will use the user_auth_providers table (already exists in schema) but ensure it supports secure password storage.
provider: "email"password_hash: Argon2 or Bcrypt hash of the password.
Registration Flow
- Sign Up: User provides Email + Password.
- Verification: System sends a "Verify Email" link (to prevent fake accounts).
- Creation:
- Create
usersrecord. - Create
user_auth_providersrecord with hashed password. - Create
membershipsrecord (if they are creating a new tenant).
- Create
Login Flow
- Request:
POST /auth/loginwith{ email, password }. - Lookup: Find user by email.
- Verify: Compare hash.
- Tenant Selection:
- If user has 1 membership -> Auto-login to that tenant.
- If user has multiple -> Return list of tenants (Intermediate State).
- Token Issue: Issue JWT for the selected tenant.
7. Audit Logging
We will create a log-db service (or a simple table initially) to track entry and exit.
(timestamp, actor_id, action, resource, tenant_id, metadata)- Example:
(10:00, UserA, "login", "web-portal", Tenant1, {ip: 1.2.3.4})
Implementation Phases
- Phase 1: DB Refactor: Split
users->users+memberships. Migration script. - Phase 2: Role Engine: Create
rolestable and seed default roles (Owner, Member). - Phase 3: Crypto Upgrade: Switch JWT to RS256.
- Phase 4: Service Auth: Implement M2M token flow.