Ctrl/Cmd + wheel to zoom · drag to pan · double-click to fit · ⛶ opens full-size
oid. schema prefix.
No search_path=oid in the connection string or migration files.
Tables land in the public schema instead of the oid schema.
SET search_path = oid; to each migration, or prefix all tables with
oid.table_name. Add ?options=-csearch_path%3Doid to DATABASE_URL.
rdkafka (events). No reqwest, hyper,
or HTTP client imports found.
tenant_id from JWT claims. RLS on all
business tables. tenant_id column on all business tables. CloudEvents
include tenantid extension.
user_roles uses USING (true)
RLS — no tenant filtering. (b) token.issued event uses
Uuid::nil() for tenant_id.
tenant_id to user_roles with proper RLS policy.
Pass actual tenant to token.issued event factory.
tenants, users, clients, roles
handlers call repositories directly and invoke domain constructors
(Tenant::new, User::new, Client::create)
without a service layer. AuthService only covers OAuth flows.
TenantService, UserService, ClientService.
API handlers: parse input, call service, serialize response. Nothing more.
JWT_ISSUER correctly read from env var. However
src/main.rs:47 provides a hardcoded fallback
"https://oid.agirdigital.com" via unwrap_or_else,
silently misconfiguring production when the env var is missing.
.expect("JWT_ISSUER must be set") to force explicit config.
CloudEvent struct has all required v1.0 fields:
specversion ("1.0"), type, source ("oid"),
id, time, tenantid extension,
datacontenttype, correlationid.
Six event factories: tenant.created, user.created,
client.created, token.issued,
login.succeeded, login.failed.
tenants.rs:94, users.rs:119, clients.rs:140,
auth.rs:48, oauth.rs:168). Architecture requires
correlation_id in every error log.
unwrap() in production — InMemoryProducer
Mutex locks at producer.rs:152,157,172 are reachable at runtime in dev mode.
X-Correlation-Id; add to all tracing::error!.
Replace .unwrap() with .expect("lock poisoned").
| # | Rule | File | Line | Description |
|---|---|---|---|---|
| 1 | Schema Isolation | migrations/001_create_tenants.sql |
5 | Table tenants created without oid. schema prefix |
| 2 | Schema Isolation | migrations/003_create_users.sql |
2 | Table users created without oid. schema prefix |
| 3 | Schema Isolation | .env.example |
7 | DATABASE_URL missing search_path=oid connection parameter |
| 4 | Schema Isolation | migrations/004–011 |
— | All remaining migrations missing schema prefix (roles, clients, auth_codes, refresh_tokens) |
| 5 | Directory Structure | src/api/tenants.rs |
65 | Tenant::new(dto) domain operation called directly in API handler |
| 6 | Directory Structure | src/api/tenants.rs |
75 | repo.create() called directly from handler, bypassing service layer |
| 7 | Directory Structure | src/api/users.rs |
— | User creation, update, and role assignment logic embedded in API handlers |
| 8 | Directory Structure | src/api/clients.rs |
— | Client creation logic (Client::create() + repo) in API handler |
| 9 | Hardcoded URLs | src/main.rs |
47 | Hardcoded fallback "https://oid.agirdigital.com" when JWT_ISSUER unset |
| 10 | Error Handling | src/api/tenants.rs |
94 | Error log missing correlation_id field |
| 11 | Error Handling | src/api/users.rs |
119 | Error log missing correlation_id field |
| 12 | Error Handling | src/api/auth.rs |
48 | Error log missing correlation_id field |
| 13 | Error Handling | src/events/producer.rs |
152, 157, 172 | .unwrap() on Mutex lock in production InMemoryProducer |
| 14 | Multi-Tenancy | migrations/005_enable_rls_users_roles.sql |
37 | user_roles RLS uses USING (true) — no tenant isolation enforced |
SET search_path = oid; to all 11 migration files
or use explicit oid.table_name everywhere. Add ?options=-csearch_path%3Doid
to DATABASE_URL in .env.example and deployment config.
src/api/tenants.rs, users.rs, clients.rs,
roles.rs into TenantService, UserService,
ClientService. API handlers should only parse and serialize.
actix_web middleware
to extract X-Correlation-Id request header. Include
correlation_id = %id in all tracing::error! calls across all API handlers.
tenant_id column to
user_roles and update RLS to
USING (tenant_id = current_setting('app.tenant_id', true)::UUID).
Also fix token.issued to pass actual tenant_id.
unwrap_or_else
in src/main.rs:47 with .expect("JWT_ISSUER env var must be set").