IF1EIGHT0STY
srciam_core.lock

/**
* ING IAM — centralized identity & access console, frontend core
* @author Roshan Aryan Majhi · top contributor by volume
*/

One identity.
Every tenant.

ING IAM is the access plane for ING applications: Keycloak SSO at the gate, then a multi-tenant RBAC console where admins map applications → tenants → roles → permission groups, audit every change, and issue API tokens. I am its top contributor by commit volume on a small team.

// design_system

System first, screens second.

design_system.fig

color/tokens

primary

#EA580C

success

#0C9D61

info

#2F6FED

warning

#F59E0B

error

#DC2626

border

#E4E4E7

type/scale

Aa

Inter Variable / Geist

Heading 20

Body 14 · tracking-tight

mono 11 · tables & tokens

radius/0.625rem

sm
md
lg
4xl

buttons lg · badges full

components/ui

SaveCanceladmin
Search…⌘K
Tokens → components, no hard-coded hex
loc.stat
28,500+
lines shipped
lines of TypeScript
modules.stat
320
source files
source modules
policy.json
{
  "application": "attendease",
  "tenant": "everest-campus",
  "role": "role_student",
  "permissions": ["attendance.read"]
}
Scoped RBAC policy
role_access.demo
attendeaseeverest-campus
Roleusers.writeroles.assigntokens.issue
admin
developer
viewer
5/9 granted
One mapping, two directions
search.cmdk
⌘K
attendeaseapplication
everest-campustenant
role_studentrole
attendance.readpermission
Aarav Sharmauser
CmdK across everything
activity.log
Aarav granted roles.assign → developer2m
superadmin rotated SSO certificates1h
deploy-token-01 revoked3h
Kazi created tenant everest-campus5h

view all →

Every change, audited
auth.gate
Search…⌘K
Keycloak SSOSSO
RoleGuard03
RWelcome, RoshanadminLIVE
active session · refresh 04:59revoke
guard.tsx
// unauthenticated → IdP login
<ProtectedRoute>
  <RoleGuard allowedRoles={["admin"]}>
    <Layout />
  </RoleGuard>
</ProtectedRoute>
Auth at the edge
commits.log
330 commits · top contributor
keys.factory
// key factory per domain
GET_USERS: (params) => ["get", "users", params];
// refetch all list variants
invalidate(GET_USERS_PREFIX);
One invalidate, every variant
package.json
react19.2.5
react-router-dom7.14.2
@tanstack/react-query5.100.9
keycloak-js26.2.4
zustand5.0.12
zod4.4.3

+22 more in package.json

The stack
url.state

toggle to compare

iam/role-access?app=attendease&tenant=3&tab=roles

app=attendeasetenant=3tab=roles✓ shareable, refresh-safe
Filters live in the URL
saved_views.json
Views worth keeping
share.link
iam.app/v/everest-roles

opens the exact filters, for anyone with access

Send the view, not a screenshot

// why_it_exists

Every app needs auth. None should own it.

Without a central IAM, each product re-implements login, roles and permissions — drift, duplicated admin screens, and access reviews done in spreadsheets.

ING IAM centralizes that. Identity in Keycloak, authorization in one console: applications register once, tenants scope them, roles bundle permission groups, and every grant is auditable. Products ask who-can-what — the IAM answers.

// feature_modules

What ships inside.

sso_auth_gate

Keycloak SSO via keycloak-js (check-sso), protected routes that bounce unauthenticated users to the IdP login, and role guards that redirect per role — superadmin, admin, developer.

keycloak-jsprotected routerole guard

role_access_matrix

The heart of the console. Pick an application + tenant, then map roles↔permissions in both directions — roles-to-permissions and permissions-to-roles — with indeterminate states, select-all, and scoped search.

bidirectional mappingindeterminaterbf matrix

tenant_mappings

Tenant-role and tenant-permission mapping screens bind identities to their scope: which tenants an application sees, which roles and permission groups each tenant carries.

multi-tenantscoped rbac

identity_crud

Full lifecycle for applications, tenants (with logo upload + size validation), users, students, admins, roles and permission groups — tables, dialogs, soft delete / restore, status toggles.

tanstack tablerhf + zodsoft delete

global_search

A cmdk command-palette search across the whole IAM graph with per-application indicators, loading and empty states, resetting on navigation and dialog close.

cmdkcross-entity

audit_and_tokens

Activity logs with detail dialogs (actor, subject, diff grid), plus personal access token management — issue, list with creator column, and revoke.

audit trailapi tokens

data_layer

TanStack Query throughout with a central key factory per domain (prefix + params) so list variants invalidate in one call; axios instance with refresh handling; nuqs keeps filters in the URL.

query key factorynuqsaxios

// engineering_decisions

Worth noting.

  • +Identity stays in Keycloak the app never stores passwords — SSO login, refresh and redeem flow through the IdP, the console only models authorization on top.
  • +Mappings are bidirectional role→permissions for least-privilege reviews, permissions→roles for blast-radius checks — same data, two questions answered.
  • +Query keys are a factory GET_*_PREFIX plus params means one invalidate call refetches every filtered, sorted or paginated variant of a list.
  • +Filters live in the URL nuqs serializes table state so a filtered roles view is shareable and refresh-safe, same philosophy as the CRM build.
  • +One table, every entity a shared shadcn data-table (sorting, selection, pagination, column widths) renders applications through tokens — new entities get UI for free.

// my_role

What I built.

Top contributor by commit volume, owning global search, the role-access matrix, mapping guards and the QC polish pass across the console.

330
commits
320
files in app
#1
by volume · small team

$global_search

  • API integration for cross-entity search with per-application indicators
  • Loading, empty-state and scoped search (incl. disabled search on mapping screens)
  • Reset-on-navigate, dialog permission viewer, hover and UX fixes

$role_access_matrix

  • Scoped permission display per tenant in roles→permissions views
  • Permission-group fetch by role id, edit-table fixes, toast migration to custom toasts
  • Tenants column for roles→permissions and permission listings

$mappings_and_guards

  • Disabled-state fixes for roles in tenant-role mapping
  • Unauthorized-path navigation guard (typing a path no longer leaks pages)
  • Table-height, sidebar scroll and collapse-mode fixes across viewports

$qc_and_polish

  • QC pass: nav colors, cancel/create-another buttons, user-create route, activity subject descriptions
  • Tenant column-width and permission-scoping fixes
  • Font, hover and layout polish across topbar, sidebar and dialogs

// in_one_line

A single access plane where SSO is the gate and a bidirectional matrix is the map — every grant scoped, searchable and auditable.
React 19TypeScriptReact RouterTanStack Query/TableKeycloakTailwind v4shadcn/radixRHF + ZodnuqsZustandDocker