Skip to main content

🗺️ Evalium – User Management & Cohorts Roadmap

Owner: Product Engineering Status: Approved Related: assignments-backend-roadmap.md, FOUNDATION.md, roles-and-access-control.md

Evalium’s Users & Cohorts system enables SMB-simple onboarding and Enterprise-scale dynamic grouping, while maintaining strict multi-tenant & org-unit isolation via PostgreSQL RLS.

This roadmap provides the backend-first, schema-first plan for Users, Metadata, Groups, Dynamic Cohorts, CSV Imports, and Assignment integration.

Evalium’s goal is to make user management:

  • Effortless for SMBs
  • Flexible for future Enterprise integrations (SCIM, HRIS, ATS)
  • Immutable, auditable, and high-integrity

This roadmap is designed so our backend remains stable even as UX grows in complexity.


Phase 0 — Data Foundation (Schema + RLS)

Goal: Provide a schema capable of supporting all future UX (dynamic cohorts, HRIS sync, metadata rules) without needing further database redesign.


0.1 Schema: Flexible User Metadata (JSONB)

Evalium does not add rigid fields like department, job_title, etc. Instead, we store all org-specific attributes inside a flexible JSONB object:

ALTER TABLE users
ADD COLUMN metadata JSONB DEFAULT '{}' NOT NULL;

CREATE INDEX idx_users_metadata_gin ON users USING gin (metadata);

Why JSONB?

  • Future-proof for HRIS integrations
  • Enables Dynamic Groups without schema changes
  • Compatible with RLS and query-time performance patterns
  • Avoids schema churn when onboarding new customers

0.2 Schema: Groups (Cohort Container)

Groups act as “soft teams” or “logical cohorts” inside an org unit. Groups can be manual OR dynamic (generated by rules).

CREATE TABLE groups (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
org_unit_id UUID NOT NULL,

name TEXT NOT NULL,
description TEXT,

-- Dynamic rule-based membership
is_dynamic BOOLEAN DEFAULT false,
membership_rule JSONB,

-- Secure user-join path
join_token TEXT UNIQUE,
allowed_domains TEXT[],

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

0.3 Schema: Group Members (Source of Truth)

Even with dynamic rules, we store members explicitly so that:

  • assignment targeting remains fast (no dynamic evaluation at redeem time)
  • changes over time are audited
  • historical reporting remains accurate
CREATE TABLE group_members (
group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
added_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (group_id, user_id)
);

0.4 RLS & Security Invariants

These are non-negotiable architectural constraints:

  • Users only visible within their tenant (RLS)
  • Groups only exist within a single org-unit
  • A user cannot join a group from another org-unit
  • Dynamic rules only evaluate user.metadata, never join other tables
  • Dynamic rule evaluation must run through TxManager — never bypass RLS
  • Code must log/audit all automatic membership additions/removals

Phase 1 — Dynamic Cohorts (“Smart Groups”)

Dynamic groups allow eval admins to manage high volumes of users without manual lists.

1.1 Rule Engine (Evaluator Service)

Runs on:

  • User Creation
  • User Update
  • CSV Import
  • SCIM Sync (future)

Evaluation:

  1. Fetch all is_dynamic = true groups in the tenant+org
  2. Apply JSON rule to user.metadata
  3. If match → insert membership
  4. If no longer match → remove membership

Supported MVP Operators:

OperatorExampleMeaning
equals{"department": "Sales"}exact match
contains{"skills": ["Go"]}metadata array contains any
exists{"employee_id": true}key present

1.2 Auditability

All rule-triggered changes must be recorded:

  • group_id
  • user_id
  • rule version
  • previous → new state

This supports compliance (especially for HR and regulated industries).


Phase 2 — Safe, Conversational CSV Import (“Dry Run”)

Evalium’s import engine must never let bad data enter the system.

2.1 POST /users/import/preview (Dry Run)

  • No writes
  • Fuzzy header detection
  • Normalize all emails
  • Validate metadata structure
  • Return a validation report including enriched metadata and rule-trigger results

Example response:

{
"import_id": "tmp_9273",
"valid_count": 45,
"error_count": 2,
"preview": [
{ "email": "alice@co.uk", "metadata": {"dept": "Sales"}, "status": "valid" },
{ "email": "bob", "status": "error", "msg": "Invalid email" }
]
}

2.2 POST /users/import/commit

  • Uses sanitized payload (or cached preview)
  • Batches inserts in a transaction
  • Triggers Dynamic Rule Evaluator upon commit

This eliminates brittle “import failed → no idea why” flows.


Phase 3 — Zero-Touch Onboarding (Join Links)

For product-led growth and small teams.

3.1 Secure Group Join Flow

POST /groups/join/\{token\}

Flow:

  1. Validate session (magic-link identity)
  2. Resolve group by join_token
  3. Validate allowed_domains
  4. Validate org-unit match
  5. Add to group_members

This creates:

  • easy self-serve enrollment
  • Slack/Teams-friendly flows
  • enterprise-safe guardrails

Phase 4 — Assignment Integration

Assignments become dramatically more powerful once Groups exist.

4.1 Assignments Target Groups

Extend assignment creation with:

target_type = 'group_id'
target_ref = group_id

4.2 Redeem Logic (Assignments Phase 1)

For group assignments:

exists := repo.CheckGroupMembership(...)
if !exists { return 403 }

This ensures:

  • Dynamic groups auto-resolve before redeem
  • No expensive rule evaluation at assignment-delivery time
  • RLS ensures cross-org spoofing is impossible

RBAC: Required Capabilities

Update roles-and-access-control.md to include:

User & Group Management

  • users.manage – CRUD users
  • users.import – CSV import preview + commit
  • groups.manage – Create/manage groups
  • groups.view – Read group lists
  • groups.join – User can join via token (session-required)

Assignment Integration

  • assignments.create
  • assignments.monitor
  • assignments.manage
  • assignments.override

This ensures least-privilege and clean audit trails.


Why This strategy Wins

🎯 1. Maximizes Flexibility

JSONB metadata + rule-based grouping allows Evalium to support:

  • HRIS attributes
  • ATS attributes
  • Custom department structures
  • Job grades, levels, cost-centers
  • Regional and union compliance

No schema changes required.

🔐 2. Strong Security & RLS Alignment

All tables include:

  • tenant_id
  • org_unit_id

All access flows through:

  • TxManager
  • SET LOCAL scopings
  • RLS policies

Impossible to leak data cross-tenant/org.

🪢 3. Perfect Fit with Assignments

Assignments can now target:

  • users
  • emails
  • groups
  • public links

…and everything flows through:

assignment → delivery_session → submission → snapshot → reporting

with assignment_id frozen into sessions + submissions.

🧠 4. Superior UX for SMBs and Enterprise

SMBs get:

  • effortless CSV import
  • auto-grouping
  • join links

Enterprise gets:

  • SCIM-ready metadata
  • rule-based cohorts
  • assignment integration at scale

🧱 5. Fully Backend-First

All functionality is secure, auditable, and production-safe before any UI is built.


Summary

Evalium’s User & Cohorts system is now:

✔ JSONB metadata–driven ✔ Dynamic group–powered ✔ Fully RLS-secured ✔ Assignment-integrated ✔ Import-safe (“Dry Run”) ✔ Scalable to HRIS + SCIM ✔ Friendly for SMBs and Enterprise

This roadmap is fully aligned with the architecture, foundation, and assignments roadmap — you can now safely implement Users/Groups as a permanent system pillar.