Optare v1.0 is now available. Get started →
Architecture
Data Model

Data Model

This document describes the core entities and their relationships in Optare.

Entity Relationship Diagram

┌────────────────┐       ┌────────────────┐
│     User       │       │  Organization  │
├────────────────┤       ├────────────────┤
│ id             │       │ id             │
│ email          │       │ name           │
│ name           │       │ slug           │
│ avatarUrl      │       │ logoUrl        │
│ emailVerified  │       │ settings       │
└───────┬────────┘       └───────┬────────┘
        │                        │
        │   ┌────────────────┐   │
        └───│   Membership   │───┘
            ├────────────────┤
            │ userId         │
            │ organizationId │
            │ role           │
            │ permissions    │
            └───────┬────────┘

        ┌───────────┴───────────┐
        │                       │
┌───────▼────────┐     ┌───────▼────────┐
│  Subscription  │     │    Product     │
├────────────────┤     ├────────────────┤
│ id             │     │ id             │
│ organizationId │◄────│ name           │
│ productId      │     │ slug           │
│ status         │     │ features       │
│ seats          │     │ description    │
└────────────────┘     └────────────────┘

Core Entities

User

A person who can authenticate.

interface User {
  id: string;           // Unique identifier
  email: string;        // Email address (unique)
  name?: string;        // Display name
  avatarUrl?: string;   // Profile picture
  emailVerified: boolean;
  createdAt: Date;
  updatedAt: Date;
}

Relationships:

  • Has many Memberships (belongs to many Organizations)
  • Has many Sessions

Organization

A tenant/customer account.

interface Organization {
  id: string;
  name: string;         // Display name
  slug: string;         // URL-safe identifier (unique)
  logoUrl?: string;
  settings: OrgSettings;
  createdAt: Date;
}
 
interface OrgSettings {
  allowedDomains?: string[];
  requireMfa?: boolean;
  sessionTimeout?: number;
  samlConfig?: SAMLConfig;
}

Relationships:

  • Has many Members (Users through Memberships)
  • Has many Subscriptions
  • Has many OAuth Clients
  • Has many Invitations

Membership

Links Users to Organizations with a role.

interface Membership {
  id: string;
  userId: string;
  organizationId: string;
  role: 'owner' | 'admin' | 'member' | 'guest';
  customPermissions?: string[];
  createdAt: Date;
}

Roles:

RoleDescriptionPermissions
ownerFull controlAll, including billing and delete
adminManage teamInvite, remove, settings
memberUse productStandard access
guestLimited accessRead-only

Product

A software product or plan.

interface Product {
  id: string;
  name: string;         // "Pro Plan"
  slug: string;         // "pro"
  description?: string;
  features: string[];   // ["sso", "analytics"]
  metadata?: Record<string, any>;
}

Subscription

Links an Organization to a Product.

interface Subscription {
  id: string;
  organizationId: string;
  productId: string;
  status: 'active' | 'trial' | 'cancelled' | 'expired';
  totalSeats: number;
  usedSeats: number;
  pricePerSeat?: number;
  billingCycle?: 'monthly' | 'yearly';
  startDate: Date;
  endDate?: Date;
}

Session

An active user session.

interface Session {
  id: string;
  userId: string;
  token: string;
  expiresAt: Date;
  ipAddress?: string;
  userAgent?: string;
  createdAt: Date;
}

OAuth Client

An application registered for OAuth.

interface OAuthClient {
  id: string;
  organizationId: string;
  name: string;
  clientId: string;     // Public identifier
  clientSecret?: string; // For confidential clients
  redirectUris: string[];
  grantTypes: string[];
  scopes: string[];
  createdAt: Date;
}

Query Patterns

Get User's Organizations

SELECT o.*, m.role
FROM organizations o
JOIN memberships m ON m.organization_id = o.id
WHERE m.user_id = $userId;

Get Organization's Members

SELECT u.*, m.role
FROM users u
JOIN memberships m ON m.user_id = u.id
WHERE m.organization_id = $orgId;

Check Feature Access

SELECT p.features
FROM subscriptions s
JOIN products p ON p.id = s.product_id
WHERE s.organization_id = $orgId
  AND s.status = 'active';

Validate Org Membership

SELECT role FROM memberships
WHERE user_id = $userId
  AND organization_id = $orgId;

Indexes

TableIndexPurpose
usersemailLogin lookup
membershipsuser_idUser's orgs
membershipsorganization_idOrg's members
subscriptionsorganization_idOrg's products
sessionstokenSession validation
sessionsuser_idUser's sessions

Next Steps