HASSAR.AI Platform Documentation

Code Structure

Version 1.0
Date July 2026
Audience Developers & Technical Contributors
01

Repository Layout

HassarAI/ ├── frontend/ # Next.js 16 web application │ ├── app/ # App Router pages and layouts │ │ ├── layout.tsx # Root layout (HTML shell, fonts) │ │ ├── page.tsx # Landing page (/) │ │ ├── not-found.tsx # 404 page │ │ ├── login/page.tsx # /login │ │ ├── signup/page.tsx # /signup │ │ ├── profile/page.tsx # /profile (protected) │ │ └── dashboard/ │ │ ├── layout.tsx # Dashboard shell (sidebar + header) │ │ ├── page.tsx # /dashboard │ │ ├── blueprint/ # My IoT Blueprint wizard │ │ ├── chat/ # Jim AI chat with multi-session │ │ ├── decrypt/ # Review Existing Blueprint │ │ └── admin/ # Admin panel (admin role required) │ ├── context/ │ │ └── AuthContext.tsx # Auth state, silentRefresh, idle timeout │ ├── lib/ │ │ └── crypto.ts # Blueprint encrypt/decrypt (Web Crypto API) │ ├── next.config.ts # Next.js configuration │ └── package.json ├── backend/ # FastAPI Python backend │ └── app/ │ ├── main.py # FastAPI app entry point, CORS, startup │ ├── database.py # SQLAlchemy engine and session factory │ ├── models.py # ORM models (User, SystemConfig) │ ├── schemas.py # Pydantic request/response schemas │ ├── limiter.py # Rate limiter (slowapi) config │ ├── auth/ │ │ ├── dependencies.py # get_current_user (JWT + DB check) │ │ ├── hash.py # bcrypt password hashing │ │ └── jwt_handler.py # JWT create/decode (access + refresh) │ └── routes/ │ ├── auth.py # /auth/* endpoints │ ├── features.py # /chat, /blueprint/register, /ai/status │ └── admin.py # /admin/* endpoints ├── docs/ # Project documentation │ ├── USER_GUIDE.md │ ├── SOP.md │ ├── TESTING_AND_IMPLEMENTATION_PLAN.md │ └── CODE_STRUCTURE.md └── README.md # Root repository overview
02

Frontend — Next.js 16 Frontend

The frontend uses Next.js 16 App Router with React 19 and TypeScript. All pages are React Server Components by default; client interactivity uses the "use client" directive.

App Router Routes
FileRoutePurpose
app/page.tsx/Landing / marketing page
app/login/page.tsx/loginLogin form
app/signup/page.tsx/signupRegistration form with password strength meter
app/profile/page.tsx/profileUser profile / change password (protected)
app/dashboard/layout.tsx/dashboard/*Dashboard shell: sidebar navigation + top header
app/dashboard/page.tsx/dashboardDashboard home
app/dashboard/blueprint/page.tsx/dashboard/blueprintMy IoT Blueprint 5-step wizard
app/dashboard/chat/page.tsx/dashboard/chatJim AI chat with multi-session support
app/dashboard/decrypt/page.tsx/dashboard/decryptReview Existing Blueprint (decrypt & inspect)
app/dashboard/admin/page.tsx/dashboard/adminAdmin panel (admin role required)
03

Page Components

My IoT Blueprint — 5-Step Wizard

Client component. Encrypts blueprint data in Step 5 using the Web Crypto API. Key encryption logic:

// 1. Derive key via PBKDF2
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv   = crypto.getRandomValues(new Uint8Array(12));
const keyMaterial = await crypto.subtle.importKey(
  "raw", encode(passphrase), "PBKDF2", false, ["deriveKey"]
);
const key = await crypto.subtle.deriveKey(
  { name: "PBKDF2", salt, iterations: 390000, hash: "SHA-256" },
  keyMaterial,
  { name: "AES-GCM", length: 256 },
  false, ["encrypt"]
);
// 2. Encrypt and bundle
const ciphertext = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv }, key, encode(JSON.stringify(blueprint))
);
download(bundle({ salt, iv, ciphertext }), `${name}.hassar`);

Jim AI Chat (dashboard/chat)

The most complex page. Manages multiple sessions in localStorage, handles blueprint upload and decryption, and forwards messages to the backend with up to 20 messages of history.

localStorage key: hassar_sessions_{email} — stores the full sessions array per user.

ConstantValue
Max sessions per user20
Max messages per session100
History sent to AILast 20 messages

System Admin Panel (dashboard/admin)

Client component. Tabbed interface: Overview · Users · Logs · AI Config. On mount, checks if the user's role is "admin"; redirects non-admins to /dashboard.

Review Existing Blueprint (dashboard/decrypt)

Client component. Accessed from the Blueprint Hub "Review Existing Blueprint" button. User selects a .hassar file, enters passphrase, and the decrypted blueprint is displayed on screen.

04

Utilities

context/AuthContext.tsx

Provides auth state across all client components. Key exports:

ExportPurpose
useAuth()Hook: returns { user, login, logout, loading }
silentRefresh()Calls POST /api/auth/refresh and saves new access token. Called by chat and profile pages on 401.

Token stored in sessionStorage as hassar_token. Idle timeout: 10 min with 1 min warning. Auto-refresh 120 s before token expiry.

lib/crypto.ts

Implements blueprint AES-256-GCM encryption and decryption using the browser's Web Crypto API. Used by both the Blueprint wizard (encrypt) and the decrypt page (decrypt).

Key fixThe toBase64() helper uses an explicit loop (not spread operator) to convert large Uint8Array to base64 — avoiding a stack overflow on large blueprint files.
05

Backend — FastAPI Backend

main.py — Entry Point

Creates the FastAPI app, registers CORS middleware, rate limiter exception handler, and calls run_migrations() at startup. Mounts three routers under /api:

RouterPrefix
auth_router/api/auth
features_router/api
admin_router/api/admin
database.py
def get_db():
    db = SessionLocal()
    try:
        yield db
    except Exception:
        db.rollback()
        raise
    finally:
        db.close()
06

Data Models

User — table: users
ColumnTypeNotes
idInteger PKAuto-increment
emailString UNIQUELogin identifier
password_hashTextbcrypt hash (cost 12)
roleString"user" or "admin"
created_atDateTime TZServer default: NOW()
failed_login_attemptsIntegerAccount lockout counter
locked_untilDateTime TZ nullableLockout expiry (15 min after 5 failures)
SystemConfig — table: system_config
ColumnTypeNotes
keyString PKe.g. "agim_url", "ollama_model"
valueText nullableConfig value
updated_atDateTime TZAuto-updated

Stores AI config (AGIM URL/Key, Ollama URL/Model) and per-user blueprint hashes (blueprint_hash:{email}) as key-value rows.

07

API Routes

Auth Routes — /api/auth/*
MethodPathAuthDescription
POST/auth/registerNoneRegister. Returns 201 regardless (prevents email enumeration).
POST/auth/loginNoneLogin with JSON body. Sets access + refresh cookies.
POST/auth/tokenNoneOAuth2 form login. Returns access_token in body.
POST/auth/refreshRefresh cookieIssue new access token. Checks lockout.
GET/auth/profileBearerGet current user (id, email, role).
POST/auth/change-passwordBearerChange password (verifies current password; 5/min rate limit).
POST/auth/logoutClear auth cookies.
Feature Routes — /api/*
MethodPathAuthDescription
GET/NoneRoot health check
GET/ai/statusBearerReturns active AI mode (agim or ollama). Does not expose AGIM URL.
POST/chatBearerSend message to Jim. Routes to AGIM first, falls back to Ollama.
POST/blueprint/registerBearerStore SHA-256 hash + size of encrypted blueprint for ownership verification.
Admin Routes — /api/admin/* (admin role required)
MethodPathDescription
GET/admin/usersList all users (id, email, role)
PATCH/admin/users/{id}/roleToggle user role (user ↔ admin). Cannot change own role.
DELETE/admin/users/{id}Delete user. Cannot delete own account.
GET/admin/system-logsSystem event logs (no email PII in messages).
GET/admin/ai-configGet AI config. AGIM key is masked (********XXXX).
POST/admin/ai-configSave AI config. Validates both URLs for SSRF. Preserves existing AGIM key if masked placeholder submitted.
08

Data Flow Diagrams

Authentication Flow
Browser                        Backend                      Database
  │                               │                              │
  ├── POST /api/auth/login ───────►                              │
  │   { email, password }         ├── SELECT user WHERE email ──►│
  │                               │◄── User row ─────────────────┤
  │                               ├── verify_password()           │
  │                               ├── create_access_token()       │
  │                               ├── create_refresh_token()      │
  │◄── 200 { access_token } ──────┤                              │
  │    Set-Cookie: refresh_token  │                              │
  │                               │                              │
  │  [30 min later]               │                              │
  ├── POST /api/auth/refresh ─────►                              │
  │   Cookie: refresh_token       ├── decode + verify type       │
  │                               ├── check locked_until ────────►│
  │◄── 200 { access_token } ──────┤                              │
Blueprint Encryption Flow
Browser only — server is never involved

User enters passphrase
        │
        ▼
crypto.subtle.importKey("PBKDF2")
        │
        ▼
crypto.subtle.deriveKey (390,000 iterations, SHA-256, 16-byte salt)
        │
        ▼
AES-256-GCM key (256-bit)
        │
        ▼
crypto.subtle.encrypt(blueprint JSON, key, 12-byte IV)
        │
        ▼
{ version: 1, salt: b64, iv: b64, ciphertext: b64 }
        │
        ▼
Download as <name>.hassar (wrapped in ENC_STREAM header)
AI Chat Flow
Browser                       Backend                     AGIM / Ollama
  │                              │                               │
  ├── POST /api/chat ────────────►                               │
  │   { message, history,        │                               │
  │     blueprint_context }      ├── Build AGIM payload          │
  │                              │   (chat_history, query,       │
  │                              │    user_context)              │
  │                              │                               │
  │                              ├── POST to AGIM ───────────────►
  │                              │                       [AGIM responds]
  │                              │◄── { response: "..." } ───────┤
  │                              │                               │
  │                              │   [if AGIM fails or unconfigured]
  │                              ├── POST to Ollama ─────────────►
  │                              │◄── { message: { content } } ──┤
  │                              │                               │
  │◄── 200 { content } ──────────┤                               │
  │                              │                               │
[Stored in localStorage]
09

Key Design Decisions

DecisionReasonTrade-off
Client-side-only blueprint encryption Core privacy guarantee — even the platform operator cannot access user blueprint data Lost passphrase = unrecoverable data; documented clearly
Chat sessions in localStorage Keeps potentially large blueprint context off-server; aligns with client-side privacy model History not synced across devices or browsers
JWT dual-token pattern sessionStorage prevents access token persisting across tabs; httpOnly cookie prevents XSS stealing refresh token Requires /auth/refresh call on tab reopen
AI two-tier fallback (AGIM → Ollama) AGIM is production-grade but an external dependency; Ollama provides reliability during outages Ollama requires local server setup; quality may differ
SSRF prevention on AI config URLs Admin-supplied URLs are validated against private/loopback IP ranges before use Admins cannot target internal services via AI config
10

Environment & Configuration

Frontend
VariableRequiredDescription
NEXT_PUBLIC_API_URLYesBackend API base URL (e.g. https://api.hassar.ai)
Backend
VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string
JWT_SECRET_KEYYesJWT signing key (min 32 chars)
APP_ENVNo"production" enables prod-specific behaviour (secure cookies, HSTS, CF-Connecting-IP trust)

AGIM and Ollama settings are managed through System Admin → AI Config and stored in the system_config database table.

11

Dependencies

Frontend (key packages)
PackageVersionPurpose
next16.xFramework (App Router)
react19.xUI library
react-dom19.xDOM rendering
tailwindcss4.xCSS framework
typescript5.xType system
Backend (key packages)
PackagePurpose
fastapiREST API framework
uvicornASGI server
sqlalchemyORM
pydanticData validation / schemas
python-jose[cryptography]JWT handling
bcryptPassword hashing
slowapiRate limiting
httpxAsync HTTP client (AGIM/Ollama requests)
psycopg2-binaryPostgreSQL driver