Core Docs

Frontend Architecture

Frontend Architecture



Three separate frontend surfaces, all served from core.auth.medkronos.com, all using core.assets stylesheets and core.backend HTML init.

Frontend Surfaces



SurfaceURLPurpose




Registration / Login/register, /loginAccount creation and authentication
Account Management/accountUser settings, security, data management
App Authorization/authorizeConsent screen for app data access

All three share the same visual language (colors, buttons, typography) from core.assets. Registration/login and app authorization use the single-page progressive-reveal pattern. Account management uses a sidebar + main content layout.

Registration / Login Frontend



See Registration & Login for complete flow details.

Key characteristics:
  • Single HTML page, all screens loaded at once

  • Progressive reveal via JS (only current screen visible)

  • AJAX calls to core.auth API

  • connection_ref parameter carries app context

  • Mobile responsive

  • No framework — vanilla JS + DOM manipulation

Account Management Frontend



Served at core.auth.medkronos.com/account. Requires authentication (valid JWT or session_ref cookie). If not authenticated, redirects to login.

Layout



┌──────────────────────────────────────────────────────┐
│ core.auth [Logo] │
├────────────┬─────────────────────────────────────────┤
│ │ │
│ Overview │ [Main Content Area] │
│ │ │
│ Settings │ Content changes based on selected │
│ │ nav item. AJAX-loaded, no page reload. │
│ Personal │ │
│ Data │ │
│ │ │
│ Security │ │
│ │ │
│ App │ │
│ Access │ │
│ │ │
│ Terms & │ │
│ Policies │ │
│ │ │
└────────────┴─────────────────────────────────────────┘


Navigation Sections



#### 1. Overview

┌─────────────────────────────────────────┐
│ │
│ Account Overview │
│ │
│ Account type: Free │
│ Member since: January 2026 │
│ │
│ ┌─ Storage ──────────────────────────┐ │
│ │ ████████░░░░░░░░░░░░ 412 MB / 1 GB│ │
│ └────────────────────────────────────┘ │
│ │
│ ┌─ AI Tokens (Today) ───────────────┐ │
│ │ ██████░░░░░░░░░░░░░░ 423 / 1000 │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌─ AI Tokens (This Month) ──────────┐ │
│ │ ███░░░░░░░░░░░░░░░░░ 3,210 / 15k │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌─ Special Credits ─────────────────┐ │
│ │ ████████████████░░░░ 812 / 1000 │ │
│ └────────────────────────────────────┘ │
│ │
│ Connected apps: 3 │
│ Active sessions: 2 │
│ │
└─────────────────────────────────────────┘


#### 2. Settings

  • Language preference

  • Notification preferences (email notifications for security events)

  • Theme (light/dark)

#### 3. Personal Data

  • Display name (editable)

  • Email (editable, requires verification on change)

  • Phone (editable, requires verification on change)

  • Avatar (upload/change)

  • Third-party accounts:
- List of linked providers (Google, Apple, Facebook)
- "Link another account" button
- Unlink option (if user has password set)

#### 4. Security

  • Change password (requires current password)

  • 2FA management:
- Enable/disable TOTP
- Register/passkey management
- View recovery codes (requires re-authentication)
- Regenerate recovery codes
  • Active sessions:
- List of all active sessions (device, IP, location, last activity)
- "This device" indicator
- Revoke individual sessions
- "Log out everywhere" button
  • Account deletion (requires re-authentication + confirmation)

#### 5. App Access

Lists all apps the user has authorized. For each app:

┌─────────────────────────────────────────┐
│ 📦 Todo App │
│ Authorized: Jan 15, 2026 │
│ Last used: 2 hours ago │
│ Data accessed: Profile, Email │
│ │
│ [Revoke Access] │
└─────────────────────────────────────────┘


  • Revoke Access → calls POST /api/app/revoke → immediately invalidates the app's ability to refresh tokens for this user → next time the app tries to refresh, it gets 401 → app must redirect user back through auth flow

#### 6. Terms & Policies

  • Terms of service

  • Privacy policy

  • Data processing agreement

  • Links to legal documents (served from core.docs or static pages)

Data Export (GDPR)



Under Personal Data or a dedicated "Your Data" section:

  • "Download my data" button → generates a JSON/ZIP export of all user data stored in core.auth

  • Includes: profile, sessions, ident_events, linked apps, third-party auth records

  • Excludes: password hash, 2FA secrets, recovery codes

  • Generated asynchronously, emailed as a download link

Account Deletion



Under Security:

User clicks "Delete Account"


Re-authentication required (password + 2FA if enabled)


Confirmation screen:
"Are you sure? This will:
- Delete your account and all associated data
- Revoke access to all connected apps
- This action cannot be undone

Type DELETE to confirm: [ ]"


User types "DELETE" and confirms


core.auth:
1. Soft-delete user (set deleted_at, set status = 'deleted')
2. Revoke all sessions
3. Revoke all app authorizations
4. Schedule hard deletion after 30-day grace period
5. Send confirmation email


App Authorization Frontend



Served at core.auth.medkronos.com/authorize. Uses the same progressive-reveal pattern as registration/login. Typically shown immediately after login or registration when the user is coming from an app.

When It's Shown



User completes login/registration (has connection_ref)


core.auth checks: has user already authorized this app?

├── Yes → skip, issue auth code, redirect to app
└── No → show authorization screen


Authorization Screen



┌─────────────────────────────────────────┐
│ │
│ [App Logo] │
│ │
│ Todo App wants to │
│ access your account │
│ │
│ This app may request your personal │
│ info, like name, email, etc. for │
│ the login process. │
│ │
│ Storage and AI usage in this app │
│ count towards your global account │
│ usage. │
│ │
│ [ Authorize ] │
│ [ Deny ] │
│ │
└─────────────────────────────────────────┘


Phase 1 (current): No granular permissions. The screen is informational — the user authorizes or denies. If authorized, the app gets access to the user's basic profile (name, email, avatar).

Phase 2+: The screen will list specific permissions the app is requesting (scopes), and the user can modify which ones to grant.

Post-Authorization



User clicks "Authorize"


core.auth:
1. Creates user_app_access record
2. Issues authorization code
3. Redirects to app's callback URL with code + state


App exchanges code for JWT via core.console → user is logged in

User clicks "Deny"


core.auth:
1. Does NOT create user_app_access record
2. Redirects to app's callback URL with error: access_denied


App shows: "Access denied. You need to authorize to use this app."


User Circle



A persistent UI element present on every UNVRSL app page, inspired by Google's profile circle. It serves as the always-visible account indicator and quick-access menu.

Purpose



  • At-a-glance identity — the user always knows which account they're logged into, just by looking at the circle in the corner

  • Quick settings — no need to navigate to the full account dashboard for common actions

  • Account switching — seamless switching between multiple logged-in accounts (e.g. personal vs. work)

  • Quota awareness — live usage indicators so the user never hits a quota wall unexpectedly

Appearance



┌──────────────────────────────────────────────────┐
│ ┌─────┐│
│ [App Content] │ 👤 ││
│ └─────┘│
│ User │
│ Circle │
└──────────────────────────────────────────────────┘


  • Fixed position: top-right corner of every page

  • Size: 36–40px diameter circle

  • Content: user's avatar (photo or initials fallback)

  • Subtle ring color can indicate account type (e.g. free vs. premium) — optional, Phase 2

  • On hover: slight scale-up + shadow

  • Mobile: same position, slightly smaller (32px)

Click → Popover



Clicking the circle opens a popover dropdown anchored to the circle:

┌───────────────────────────────────────────┐
│ ┌───┐ │
│ │ 👤 │ Olivier Mironescu │
│ └───┘ olivier@example.com │
│ Free account │
│───────────────────────────────────────────│
│ │
│ 📦 Storage │
│ ████████░░░░░░░░░░░░ 412 MB / 1 GB │
│ │
│ 🤖 AI Credits (July) │
│ ██████░░░░░░░░░░░░░░ 1.2M / 4M credits │
│ (≈ 8,400 input + 2,100 output tokens) │
│ │
│ 🎨 Hypermedia Credits (July) │
│ ████████████░░░░░░░░ 38K / 100K credits │
│ │
│ ⚡ Special Credits (July) │
│ ████████████████░░░░ 412K / 500K credits │
│ (overflow: 18 MB storage + 12K AI) │
│───────────────────────────────────────────│
│ │
│ 🔄 Switch Account │
│ ├── olivier@example.com ✓ │
│ └── work@company.com │
│ │
│ ⚙️ Account Settings │
│ 🚪 Log Out │
│ │
└───────────────────────────────────────────┘


Popover Sections



#### 1. Account Header
  • Avatar (larger, 48px)

  • Display name

  • Email

  • Account type badge (Free / Standard / Premium)

#### 2. Quota Meters
  • Storage — used / total (e.g. "412 MB / 1 GB")

  • AI Credits — credits consumed this month / monthly allowance. Sub-label shows approximate token equivalent for context (e.g. "≈ 8,400 input + 2,100 output tokens")

  • Hypermedia Credits — credits consumed this month / monthly allowance

  • Special Credits — credits consumed this month / monthly allowance. Sub-label shows what overflow was used (e.g. "overflow: 18 MB storage + 12K AI")

  • Each meter is a thin progress bar with label

  • Clicking a meter → navigates to full account dashboard

  • Phase 2: color shifts from green → yellow → red as usage approaches limit

  • All credit meters reset monthly on the same billing cycle

#### 3. Account Switcher
  • Lists all accounts the user has authenticated with on this device

  • Current account has a checkmark (✓)

  • Clicking another account → switches without re-entering password (if session is still valid)

  • "Add account" option → opens core.auth login in a new context (like Google's "Add account")

  • Session cookies are scoped per account; switching is instant

#### 4. Quick Actions
  • Account Settings → navigates to /account dashboard

  • Log Out → logs out of current app (revokes local session, keeps core.auth session alive)

  • Phase 2: "Log out of all apps" option

Technical Implementation



  • Owned by core.auth, delivered through core.console — the User Circle JS (user-circle.js) is built and owned by core.auth, where the session context lives. But apps never call microservices directly: it is served to apps through core.console (the single entry point for all service traffic), embedded via a single <script> tag or PHP helper from core.backend. It is NOT served by core.assets (public static CDN; no user context).

  • Avatar images — user content, stored in S3 via core.storage; the circle renders them by URL (initials fallback).

  • Core.auth session cookie — the popover reads the core.auth session cookie (.medkronos.com domain) to identify the current user. No extra API call needed for basic identity.

  • Quota data — fetched via a lightweight GET /api/user/quota call to core.console when the popover opens. Cached for 60 seconds to avoid hammering the API.

  • Account list — stored in localStorage per device (list of user IDs + emails). Actual switching triggers a redirect to core.auth which checks for existing sessions.

  • Styling — the popover uses the shared design tokens/components from the core.assets design stylesheets that every app already loads via core.backend (DocumentShell); it matches the app's theme (light/dark). No per-component CSS is shipped.

  • No framework — vanilla JS, same as all other auth frontends.

Multi-Account Session Model



Device localStorage:
{
"unvrsl_accounts": [
{ "user_id": "uuid-1", "email": "olivier@example.com", "last_active": 1719840000 },
{ "user_id": "uuid-2", "email": "work@company.com", "last_active": 1719753600 }
],
"unvrsl_active": "uuid-1"
}

core.auth cookies (scoped by user_id):
- session_ref_uuid-1 = "abc123..."
- session_ref_uuid-2 = "def456..."


When the user switches accounts, the User Circle:
  1. Updates unvrsl_active in localStorage

  2. Redirects to core.auth with ?switch_to=uuid-2

  3. core.auth activates that session and redirects back to the app

  4. App receives a fresh JWT for the new account

Mobile Behavior



  • Same top-right position

  • Tap → full-screen bottom sheet instead of popover (better for thumbs)

  • Quota meters and account switcher stacked vertically

  • Swipe down to dismiss

Console Relay



All app-backend → core.auth service calls are routed through core.console with the project API key (https://core.console.medkronos.com/v1/auth/*). Browser-facing UI pages (login, registration, authorize consent, account dashboard) remain on core.auth.medkronos.com — users' browsers interact with core.auth directly for these federated UI flows. Apps never call core.auth.medkronos.com from backend code.




Shared Design System



All three frontends use core.assets for visual consistency:

  • Colors, typography, spacing — from core.assets design tokens

  • Buttons — primary (filled), secondary (outline), danger (red)

  • Form inputs — consistent styling across all screens

  • HTML init — core.backend provides the base HTML structure

  • Responsive breakpoints — mobile-first, responsive layout

Theming



  • Light mode (default)

  • Dark mode (system preference detection + manual toggle)

  • Brand customization per app (logo, accent color) — for the authorization screen

Cross-Origin & Cookie Policies




PolicyValue






SameSiteLax (session_ref cookie sent on top-level navigations)
Securetrue (HTTPS only)
HttpOnlytrue (not accessible to JavaScript)
Domain.medkronos.com (shared across all subdomains)
Path/session/refresh (only sent to refresh endpoint)

CORS for browser-consumable endpoints (e.g. silent refresh, if routed through core.console to the browser) is handled by core.console per project's registered domains. Server-to-server calls (app backend → console) don't require CORS.

CSP Headers



Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'nonce-{random}';
img-src 'self' data: https://*.medkronos.com;
connect-src 'self' https://core.auth.medkronos.com;
frame-ancestors 'none';
form-action 'self';





See also: Registration &amp; Login for auth flow details, App Integration for how apps connect.