Challenge
Serve eight very different user roles across isolated organizations on one platform — without data leaking between tenants and without polling for updates.
Full Stack · SaaS
Organization-wide bug tracking with eight role-specific portals and real-time updates

Overview1 / 9
Serve eight very different user roles across isolated organizations on one platform — without data leaking between tenants and without polling for updates.
Designed a shared-database, tenant-isolated data model with layered route, controller, and service guards; in-memory access tokens with rotating HttpOnly refresh cookies and CSRF protection; and a WebSocket layer that selectively dispatches events only to the relevant actors.
A production-grade issue platform covering the complete lifecycle — guest and partner intake, QA review, dev assignment, verification, and audit history — with instant cross-portal updates and one-command Docker deployment.
Hover or tap a component to see what it does.
Simpler to run and migrate than a database per tenant. Every query is scoped by tenant ID, and suspended tenants are blocked at auth.
Nothing for an XSS attack to steal. A rotating HttpOnly refresh cookie restores the session on reload.
Comments and status changes should appear instantly. Events go only to the people on that issue, not everyone.
Summaries auto-load for every stakeholder, so calls are cached, de-duplicated, quota-limited per user and tenant, and concurrency-capped.
Tracky is a full-stack, multi-tenant issue and bug management platform. The Next.js frontend serves a tailored dashboard to each of eight roles — super admin, tenant admin, QA admin and member, dev admin and member, stakeholder, and point-of-contact employee — with issue lists, Kanban boards, rich issue detail pages, analytics with Excel export, and a public guest report form protected by email OTP verification.
The Express + Prisma + PostgreSQL backend enforces tenant isolation and role-based access on every route, runs the complete issue lifecycle from intake report to QA-verified closure with an event timeline, and pushes live notifications, comments and typing indicators over WebSockets. External systems submit reports through project-scoped API keys, and the whole stack runs with one docker compose command.
Eight very different user roles, across many isolated organizations, on one platform. A QA member, a developer and an outside stakeholder all need to see the same issue — but with different permissions, actions and views. Data from one organization must never appear in another.
Updates also had to feel instant. Polling eight kinds of dashboards for changes is wasteful and still feels slow.
Issues don't go straight onto the board. Everything — from a portal user, a guest, or a partner system — first lands as a pending report in the project's QA queue. A QA reviewer accepts or rejects it; accepted reports become issues. Devs move them through assigned → in progress → fixed, and QA verifies the fix before the issue is resolved and closed. Issues can also be closed as 'not an issue'. Every change is written to an event timeline with its actor.
Tracky uses a shared-database model: tenant-owned tables (projects, issues, comments, events, notifications, API keys) carry a tenant ID and are indexed on it. Project codes are unique per tenant, not globally, so two organizations can both have a 'BUG' project.
Isolation is enforced in more than one place: role guards on routes, an auth middleware that rejects users of suspended tenants on every request, and services that scope every query by the tenant ID from the verified token — never from the request body.
Every request passes Helmet security headers, CORS origin checks, a per-request ID for traceable logs, rate limiting (200 requests per 15 minutes in production), a 1MB body limit, recursive input sanitization, HTTPS enforcement in production, and CSRF validation on state-changing requests.
Login returns a short-lived access token that the frontend keeps only in memory (a Zustand store, not localStorage), plus two cookies: an HttpOnly refresh token and a readable CSRF token. Refresh tokens are stored hashed, rotated on every refresh, and revoked on logout. On page reload the app silently exchanges the cookie for a new access token.
Clients connect to the WebSocket server with their access token, which is verified on the handshake. The server maps each user to a set of open sockets, so one person with several tabs gets every update in each. Instead of broadcasting, events are dispatched only to the actors on an issue — the creator, assigned devs, and that tenant's admins.
Stakeholders get an AI executive summary on their landing page and can ask questions about their issue data, powered by DeepSeek. The model never sees raw issues: the backend aggregates up to 5,000 issues and 2,000 reports into a compact digest (capped at 14,000 characters), which also keeps prompts small and predictable.
Because the summary loads automatically, 30 stakeholders refreshing would mean 30 paid calls a minute. Four guards prevent that: a TTL cache so identical questions are free, single-flight so concurrent identical requests share one upstream call, per-user and per-tenant daily quotas, and a process-wide concurrency cap. Quota is only charged on a genuine cache miss.
Reports enter from three places: signed-in users inside a portal, guests through a public form verified by email OTP, and partner systems through the Partner API. Partner API keys are issued by a tenant admin, shown only once, stored as a hash, tied to a single tenant and project (so partners never send IDs), and can be revoked at any time.
01 / AI Security
Architected a local-first security firewall and real-time activity monitor for autonomous AI agents and MCP tools, enforcing deterministic policy gating, capability sandboxing, and real-time execution telemetry.
02 / AI
Built an integrated AI marketing platform combining a dynamic context chat agent (`aiagent`) with a full-featured Marketing Operating System SaaS (`marketingtool`) featuring multi-LLM routing, generative UI, Cloudinary asset pipelines, landing page builders, and automated lead capture.
03 / Full Stack
Architected and developed a full-stack e-commerce system from scratch for a Swedish client, featuring a Next.js storefront backed by a custom Java Spring Boot REST API & MySQL CMS, cutting content management overhead by 40%.