ibexharness
DocsBlogReleasesRoadmap
GitHub
ibexharness

Documentation

OverviewServicesData modelRequest lifecycle
Architecture›Data model
Architecture

Data model

Organizations, agents, tokens, and the multi-tenant Postgres schema behind IBEX Harness.

Every customer-facing entity in IBEX Harness is scoped to an organization. Agents and tokens belong to exactly one org; the proxy enforces that the org in the URL path matches the org embedded in the validated token. Row-Level Security (RLS) on ibex_core tables provides a database-level backstop so application bugs cannot leak cross-tenant rows.

Phase 1 migrated tables

Migrations through milestone 1.1.7 create ibex_core.organizations, ibex_core.users, ibex_core.agents, and ibex_core.tokens with RLS policies. Memory, sessions, directives, and billing tables are specified below but not yet applied — run make db-migrate after compose boot for the current subset.

Entity hierarchy

1

Organization

Root tenant. Owns agents, tokens, rate-limit buckets, and billing boundaries. Identified by UUID; human-readable slug for URLs and dashboards.

2

Project (reserved)

Logical grouping inside an org for teams or environments. The schema reserves project boundaries; Phase 1 proxy paths use org_id only. Project scoping arrives with dashboard and memory features.

3

User

Human operator who issues PATs and manages agents. Role: owner, admin, member, or viewer. SSO and MFA fields exist in the full schema; Phase 1 uses the column subset from migration 000006.

4

Agent

Autonomous actor that calls the proxy. Identified by X-IBEX-Agent-ID on each request. Unique (org_id, slug) constraint; status: active, paused, suspended, or archived.

5

Token

Personal Access Token (PAT) or org-scoped credential. Stored as Argon2id hash — plaintext shown once at creation. Carries a 64-bit permission bitmap; never log the raw secret.

Core ER diagram (Phase 1 + planned)

Mermaid diagram: erDiagram
+----------------+      +----------------+      +----------------+                    
| organizations  |      | users          |      | agents         |                    
+----------------+      +----------------+      +----------------+                    
| PK uuid id     |      | PK uuid id     |      | PK uuid id     |                    
|    text name   ||---------------------------o<| FK uuid org_id |                    
| UK text slug   | has  |    townsemail  |      |    text name   |                    
|    text tier   |      |    text role   |      |    text slug   |                    
|    text status |      +----------------+      |    text status |                    
+----------------+               |              +----------------+                    
         |                       |                      >|                            
         --contains--------------------------------------|-accumulates-               
         |    |                  |          |            |            |               
         |   o<                  |         o|            |           o<               
+---------------------------+      +----------------+    | +---------------------+    
| tokens                    |      | projects       |    | | memories            |    
+---------------------------+      +----------------+    | +---------------------+    
| PK uuid id                |      | PK uuid id     |    | | PK uuid id          |    
| FK uuid org_id            |      | FK uuid org_id |    | | FK uuid org_id      |    
| FK u---------------------------------------------------- runs uuid agent_id    |    
| FK u|id agent_id          |      +----------------+    | |    text content     |    
|    t|xt type              |                            | |    vector embedding |    
| UK t|xt hash              |                            | +---------------------+    
|    b|gint permissions     |                            |                            
|    t|mestamptz expires_at |                            |                            
+-----|---------------------+                            |                            
      |                                                  |                            
      |                                                  |                            
      |                                                  |                            
     o<                                                  |                            
+----------+                                                                          
| sessions |                                                                          
+----------+                                                                          
                                                                                      
                                                                                      

Solid relationships reflect migrated Phase 1 tables. projects, memories, and sessions are planned — shown for integrators designing agent layouts ahead of memory milestones.

Key fields

ParameterTypeDescription
organizations.idRequiredUUID
Tenant root. Propagated from validated token; never accepted from request body on protected routes.
organizations.slugRequiredstring
URL-safe identifier (`^[a-z0-9-]+$`). Unique across active orgs.
agents.org_idRequiredUUID
Must match token org_id. Cross-org agent access returns 403 PERMISSION_DENIED.
tokens.hashRequiredstring
Argon2id hash of PAT wire value (`ibex_pat_...`). Indexed for validation on every request.
tokens.permissionsRequiredint64 (bitmap)
64-bit permission set. Proxy chat routes require ProxyChatCompletion bits per ADR-0009.
tokens.agent_idUUID
Optional scope binding. When set, token is limited to that agent within the org.

Row-Level Security

RLS policies on every ibex_core table with org_id compare against current_setting('app.current_org_id'). The auth service sets this from the validated token before queries execute:

SQL
SET LOCAL app.current_org_id = '{org_id_from_token}';
 
-- Example policy on agents
CREATE POLICY agents_isolation ON ibex_core.agents
    USING (org_id = current_setting('app.current_org_id', true)::UUID);

Even if application code omits an org_id filter, Postgres rejects cross-tenant reads. See Multi-tenant RLS.

Redis key namespacing

Cache and rate-limit keys always include org_id as the second segment:

ratelimit:{org_id}:minute
{org_id}:hot_memories:{agent_id}
auth:token:{sha256_hash}

This mirrors the database isolation contract at the cache layer.

Planned tables (not migrated yet)

TableSchemaPurpose
memoriesibex_coreVector-backed agent memory with dedup and conflict tracking
sessions / checkpointsibex_coreSession lifecycle and crash recovery
directives / directive_versionsibex_coreVersioned agent instructions
audit_logibex_auditAppend-only compliance log
inference_tracesClickHousePer-request analytics (90-day TTL)

Local seed data

bash
make compose-dev-up
make db-migrate
make db-seed

Use the printed org, agent, and PAT values for proxy probes. See Org and project model and Issuing API keys.

Related

  • Auth overview
  • Glossary
  • ADR-0014: Migration sequencing

Was this page helpful?

Edit on GitHub

Last updated on

PreviousServicesNextRequest lifecycle

On this page

  • Entity hierarchy
  • Core ER diagram (Phase 1 + planned)
  • Key fields
  • Row-Level Security
  • Redis key namespacing
  • Planned tables (not migrated yet)
  • Local seed data
  • Related
0%