Platform Architecture
Internal code structure — the execution proxy, credential vault, OAuth engine, API key auth, and Firebase auth.
System Overview
NIN Connect is a Next.js 15 monorepo with three layers:
- Dashboard — admin and developer UI for managing plugins, tools, auth methods, categories, submissions, reviews, API keys, connections, and logs
- Runtime API — SDK-facing REST endpoints that list plugins/tools, manage user connections, and execute tools with auth injection (only serves approved plugins)
- SDK — TypeScript client (
@nin.in/core) that wraps the runtime API
Internal Architecture
┌─────────────────────────────────────────────────┐
│ Dashboard │
│ (Admin: plugins, review queue, categories) │
│ (Developer: submissions, my plugins, API keys) │
│ (Shared: connections, logs) │
└──────────────────────┬──────────────────────────┘
│ CRUD via /api/dashboard/*
▼
┌─────────────────────────────────────────────────┐
│ PostgreSQL (Drizzle ORM) │
│ plugins │ tools │ auth_methods │ categories │
│ connected_accounts │ api_keys │ execution_logs │
└──────────────────────┬──────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
/api/v1/plugins /api/v1/tools /api/v1/connections
│ │
│ /api/v1/tools/execute
│ │
│ ▼
│ ┌──────────────────┐
│ │ Execution Proxy │
│ │ ─ resolve tool │
│ │ ─ decrypt creds │
│ │ ─ inject auth │
│ │ ─ call ext. API │
│ │ ─ log result │
│ └──────────────────┘
│
▼
┌──────────────┐ ┌───────────────────┐
│ @nin.in/core │────▶│ Developer's App │
│ (SDK) │ │ / AI Agent │
└──────────────┘ └───────────────────┘Key Components
Execution Proxy (lib/proxy/executor.ts)
The core of the runtime. When a tool is executed:
- Resolves the tool by slug from the database
- Looks up the plugin's base URL
- Finds the end-user's connected account and auth method
- Decrypts stored credentials (AES-256-GCM)
- Injects auth into request headers based on auth method type (OAuth2 bearer, API key header, custom injection rules, etc.)
- Interpolates path parameters and builds the request body
- Calls the external API
- Logs the execution result (success/error, latency)
If an OAuth2 token is expired, the proxy auto-refreshes it before making the call.
Credential Vault (lib/encryption/)
All user credentials are encrypted at rest using AES-256-GCM with a 32-byte key from the ENCRYPTION_KEY environment variable. Credentials are only decrypted at the moment of tool execution — never exposed to the dashboard, SDK, or logs.
OAuth Engine (lib/oauth/)
Handles the full OAuth 2.0 Authorization Code flow:
initiateOAuth2— builds the authorization URL with signed state tokenexchangeCode— exchanges authorization code for tokens at the token endpointrefreshAccessToken— refreshes expired access tokens using the refresh token- State tokens — HMAC-signed, base64url-encoded payloads that carry
developerId,userId,pluginId,authMethodId, andredirectUrl
API Key Auth (lib/api-key/)
Developer API keys follow a secure pattern:
- Keys are prefixed
nk_live_followed by 24 random bytes (base64url) - Only the SHA-256 hash is stored in the database
- The raw key is shown once at creation time
- The
withApiKeymiddleware validates keys on all/api/v1/*routes
Firebase Auth
Dashboard users authenticate via Firebase (Google sign-in). The POST /api/auth/sync endpoint verifies Firebase tokens and upserts developer records. Admin routes use requireAdmin(), developer routes use authenticateDeveloper(), and plugin-scoped routes use requirePluginAccess() for creator-or-admin authorization.
Submission & Approval Flow
All new plugins — whether created by a developer or an admin — follow a unified lifecycle:
Draft → Pending Review → Approved (Live)
→ Declined / Revision Requested → Edit → ResubmitOnly approved plugins are exposed through the public Runtime API (/api/v1/*). The execution proxy also enforces the reviewStatus = "approved" check, preventing tool execution against unapproved plugins.
Project Structure
apps/web/src/
├── app/
│ ├── (auth)/login/ # Google sign-in page
│ ├── (dashboard)/ # Admin + developer dashboard pages (plugins, submissions, reviews)
│ ├── connect/ # Hosted connect pages for end-users
│ └── api/
│ ├── auth/ # Firebase token sync
│ ├── dashboard/ # Admin/developer CRUD endpoints
│ ├── connect/ # Public connect page APIs
│ └── v1/ # SDK-facing runtime API
├── components/
│ ├── plugin-builder/ # Plugin/tool form components
│ └── ui/ # Shadcn UI components
└── lib/
├── api-key/ # Key generation, validation, withApiKey middleware
├── auth/ # Firebase auth context + requireAdmin + requirePluginAccess
├── db/ # Drizzle client, schema, migrations, seed
├── encryption/ # AES-256-GCM encrypt/decrypt
├── oauth/ # OAuth2 engine + state tokens
├── proxy/ # Tool execution proxy
└── utils.ts # Tailwind cn() helperTech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 15 (App Router, Turbopack) |
| UI | Tailwind CSS v3, Shadcn/Radix UI |
| Database | PostgreSQL (Neon) via Drizzle ORM |
| Auth | Firebase Auth (Google sign-in) |
| Encryption | AES-256-GCM (Node.js crypto) |
| Validation | Zod |
| SDK | TypeScript (@nin.in/core) |
| Monorepo | pnpm workspaces + Turborepo |