apps/utopia-oe/backend
This page documents the OE Backend service in UtopiaSystem.
OE Backend is the server-side API used by Operation Efficiency Space. It acts as a central facade between the OE dashboard and Business Unit systems such as Encik Beku.
OE Backend is a Spring Boot REST service for the OE dashboard and Business Unit proxy flows.
apps/utopia-oe/backend
http://localhost:8081
OE dashboard facade and Business Unit API proxy.
Backend Services > OE Backend
Finance Backend uses port 8080, so OE Backend uses 8081.
OE Backend coordinates OE dashboard requests, Business Unit access, proxying, notifications, and health checks.
/oe/** routes.X-OE-BU header to select the target BU; falls back to oe.default-bu when absent.OE Backend uses a Java REST stack and integrates with Business Unit APIs instead of owning its own database.
| Area | Technology |
|---|---|
| Backend framework | Spring Boot |
| Language | Java |
| Java version | Java 17 |
| API style | REST API |
| Database | No own database |
| Auth validation | Supabase HS256 JWT |
| API documentation | OpenAPI / Swagger |
| External integration | Business Unit APIs |
| Notification push | OneSignal |
| Deployment package | Docker |
| Deployment platform | DigitalOcean App Platform / Docker hosting |
OE Backend mainly proxies and coordinates requests instead of owning its own business database schema.
| Area | Finance Backend | OE Backend |
|---|---|---|
| Main role | Finance REST API | OE dashboard facade / proxy |
| Local port | 8080 | 8081 |
| Own database connection | Yes | No |
| JPA/Flyway | Used for finance database access | Intentionally absent |
| Main data source | Supabase Postgres | Business Unit API + Hub Supabase lookups |
| Frontend | Finance Frontend | OE Frontend |
OE Backend reads and writes through the configured BU API instead of owning its own OE database schema.
OE Frontend calls OE Backend when the dashboard needs server-side proxying or access resolution.
In local development, the frontend may proxy /api/* requests to the backend on 8081.
OE Backend is designed as a central proxy to Business Unit systems.
encik-beku
oe.default-bu
BU_<CODE>_BASE_URL, BU_<CODE>_TOKEN, OE_BU_<KEY>_UNIT_ID (e.g., EB/ENCIK_BEKU; IS/IBNU_SINA)
Operational data remains inside the BU system.
Per-request BU selection uses the X-OE-BU header. When omitted, OE Backend routes to the BU set in oe.default-bu. If a BU's base-url or token are blank, that BU remains inert and is not routable.
<h3>Add a Business Unit (BU)</h3>
<ol>
<li>
Choose identifiers for the BU:
<ul>
<li>Config key (kebab-case) used in <code>application.yaml</code>, e.g., <code>ibnu-sina</code>.</li>
<li>Short code for env vars, e.g., <code>IS</code> for <code>BU_IS_*</code>.</li>
<li>Uppercase unit key for env vars, e.g., <code>IBNU_SINA</code> for <code>OE_BU_IBNU_SINA_UNIT_ID</code>.</li>
</ul>
</li>
<li>
Add the BU block to <code>apps/utopia-oe/backend/src/main/resources/application.yaml</code>:
<pre><code>oe:
default-bu: encik-beku
business-units:
encik-beku:
name: Encik Beku
base-url: ${BU_EB_BASE_URL:}
token: ${BU_EB_TOKEN:}
unit-id: ${OE_BU_ENCIK_BEKU_UNIT_ID:}
ibnu-sina:
name: Ibnu Sina
base-url: ${BU_IS_BASE_URL:}
token: ${BU_IS_TOKEN:}
unit-id: ${OE_BU_IBNU_SINA_UNIT_ID:}
Leaving base-url or token blank keeps the BU inert (disabled) until credentials are provided.
# API base URL and machine token for the BU
BU_IS_BASE_URL=https://api.ibnusina.example.com
BU_IS_TOKEN=prod-or-dev-bu-machine-token¶ Hub business unit ID used for access resolution
OE_BU_IBNU_SINA_UNIT_ID=00000000-0000-0000-0000-000000000000
X-OE-BU:curl -sS
-H "Authorization: Bearer <Supabase JWT>"
-H "X-OE-BU: ibnu-sina"
http://localhost:8081/oe/dispatch/boardA successful response indicates the request was proxied to the selected BU. If the BU is inert (blank base-url/token) the request will not be routed.
OE Backend route groups separate dashboard proxy traffic, access resolution, passthrough routes, and partner notifications.
| Route Group | Examples | Behavior |
|---|---|---|
| OE dashboard routes | /oe/**GET /oe/dispatch/board | Gated by Supabase JWT validation. OE Backend forwards to the selected BU API based on X-OE-BU (or oe.default-bu when absent) with the configured BU machine token. |
| Auth resolve route | GET /oe/auth/resolve | Verifies the logged-in hub user and determines which BU access the user has. |
| Mobile passthrough routes | /api/v1/oe/**/api/v1/ops/**/api/v1/auth/** | Forwarded verbatim to the BU API. This is how the Ops app reaches every business unit. |
| Partner notification route | POST /partner/notifications | Protected with X-OE-Partner instead of the normal Supabase JWT filter. |
For documentation purposes, OE Backend mainly serves the OE dashboard.
The partner notification endpoint is used when a BU wants to notify a technician or user. Push notifications can now include deep links so tapping a notification opens the related OE job screen.
The X-OE-Partner value must match the configured partner secret. The push payload should include web_url when the notification should open a specific job screen, including cold-start app launches.
Operation Efficiency PWA push notifications can route users directly to the associated job screen.
web_url points to the page that should open when the user taps the notification.
oe.notifications.ops-app-url configures the OE app URL used to build deep links.
The link should still open the target job screen when the PWA was not already running.
OE Backend validates Supabase JWT for /oe/** endpoints.
The frontend sends Authorization: Bearer <Supabase JWT>.
The backend verifies the token using SUPABASE_JWT_SECRET.
/health remains open./oe/** auth gate.Partner notification endpoint uses a shared secret instead of user JWT.
OE access is based on hub user data scopes and configured Business Unit IDs.
unit_idsExample: if a user has the Encik Beku unit ID in data scope, OE Backend allows access to Encik Beku OE data. The per-BU unit-id comes from the BU's config block in application.yaml (e.g., OE_BU_ENCIK_BEKU_UNIT_ID, OE_BU_IBNU_SINA_UNIT_ID).
OE_DEV_ALLOW_ALL_UNITS is a development-only setting for treating a signed-in hub user as scoped to every configured BU.
This shortcut is intended only for development or staging. It must stay disabled in production, where access should rely on real user_data_scopes.unit_ids.
OE Backend provides a health endpoint used by deployment checks.
OE Backend provides Swagger / OpenAPI docs when enabled.
| Local URL | Purpose |
|---|---|
http://localhost:8081/swagger-ui.html | Swagger UI |
http://localhost:8081/v3/api-docs/web | Web API docs |
http://localhost:8081/v3/api-docs/bu-proxy | BU proxy API docs |
Swagger can be disabled with OE_API_DOCS_ENABLED=false. In production, disabling API docs may be preferred.
OE Backend supports multipart upload forwarding for flows such as technician photo or delivery order proof uploads.
max-file-size: 100MB
max-request-size: 105MB
Spring's default upload limit may reject normal phone photos before they reach the BU API.
OE Backend uses server-side variables for BU APIs, hub Supabase access, partner notifications, CORS, and API docs.
| Variable | Purpose |
|---|---|
PORT | Runtime port injected by hosting platform |
BU_EB_BASE_URL | Encik Beku BU API base URL |
BU_EB_TOKEN | Encik Beku BU machine token |
OE_BU_ENCIK_BEKU_UNIT_ID | Hub business unit ID for Encik Beku |
BU_IS_BASE_URL | Ibnu Sina BU API base URL |
BU_IS_TOKEN | Ibnu Sina BU machine token |
OE_BU_IBNU_SINA_UNIT_ID | Hub business unit ID for Ibnu Sina |
HUB_REST_URL | Hub Supabase PostgREST URL |
HUB_ANON_KEY | Hub Supabase anon key |
HUB_SERVICE_ROLE_KEY | Server-side key for notification inbox writes |
OE_PARTNER_SECRET | Shared secret for partner notification endpoint |
OE_NOTIFICATIONS_OPS_APP_URL | OE app base URL used for notification deep links |
ONESIGNAL_APP_ID | OneSignal app ID |
ONESIGNAL_REST_API_KEY | OneSignal REST API key |
SERVER_MAX_HTTP_HEADER_SIZE | Request header limit override for large shared-login sessions |
OE_DEV_ALLOW_ALL_UNITS | Dev-only BU access bypass |
SUPABASE_JWT_SECRET | Supabase JWT secret for /oe/** auth |
OE_CORS_ALLOWED_ORIGINS | Allowed frontend origins |
OE_API_DOCS_ENABLED | Enables or disables Swagger/OpenAPI |
Keep BU_EB_TOKEN, HUB_SERVICE_ROLE_KEY, OE_PARTNER_SECRET, and ONESIGNAL_REST_API_KEY server-side only. Keep OE_DEV_ALLOW_ALL_UNITS=false in production.
Per-BU variables follow a pattern: BU_<CODE>_BASE_URL, BU_<CODE>_TOKEN, and OE_BU_<KEY>_UNIT_ID. Use a short code like EB, IS, etc., and an uppercase key with underscores (e.g., ENCIK_BEKU, IBNU_SINA). Leaving BU_<CODE>_BASE_URL or BU_<CODE>_TOKEN blank keeps that BU inert.
Run OE Backend from the repository root. The backend requires Java 17.
npm exec nx serve utopia-oe-backendnpm exec nx build utopia-oe-backendnpm exec nx test utopia-oe-backendThe backend runs on http://localhost:8081.
OE Backend loads the root .env file as a .properties file.
SUPABASE_JWT_SECRET=abc123 # production secret# production secret
SUPABASE_JWT_SECRET=abc123Inline # may become part of the value and cause JWT validation failures.
OE Backend is deployed as a Docker-based backend service, such as on DigitalOcean App Platform.
| Deployment Detail | Value |
|---|---|
| Dockerfile | apps/utopia-oe/backend/Dockerfile |
| Docker build style | Multi-stage build with JDK build stage and JRE runtime stage |
| Source directory | apps/utopia-oe/backend |
| Runtime port | Hosting platform injects PORT |
| Server port config | server.port=${PORT:8081} |
| Health check path | /health |
OE Backend uses CORS configuration from OE_CORS_ALLOWED_ORIGINS.
https://oe.utopiagroup.com.myIf CORS is not configured correctly, browser requests from OE Frontend may fail even when the backend is running. In local development, requests may be same-origin through the frontend rewrite.
Use these checks when startup, authentication, proxying, notifications, or browser requests fail.
SUPABASE_JWT_SECRET has inline comment text.8081 is already in use./oe/** Returns 401Authorization header.Bearer format.SERVER_MAX_HTTP_HEADER_SIZE is missing or too low.user_data_scopes.unit_ids does not include the configured BU unit ID.OE_BU_ENCIK_BEKU_UNIT_ID is missing or wrong.BU_EB_BASE_URL is wrong.BU_EB_TOKEN is missing or invalid.base-url or token is blank in config/env.X-OE-BU header points to an unknown BU key.OE_PARTNER_SECRET is missing.X-OE-Partner header is missing or wrong.HUB_SERVICE_ROLE_KEY is missing.OE_CORS_ALLOWED_ORIGINS does not include frontend URL.Before changing OE Backend, confirm the affected route, access rules, proxy behavior, and deployment configuration.
/oe/**?X-OE-BU when targeting a non-default BU?OE_DEV_ALLOW_ALL_UNITS still false?Related documentation for backend services, OE frontend behavior, access, and deployment.
Overview of backend services used by UtopiaSystem.
Finance backend service documentation.
Frontend OE Space documentation.
Auth and shared platform behavior.
Feature access and Business Unit scope behavior.
Docker backend deployment notes.
OE Backend is the Spring Boot backend for Operation Efficiency Space. It runs on port 8081, validates Supabase JWTs for OE dashboard routes, resolves Business Unit access using hub data scopes, proxies OE requests to the configured BU API, supports partner notifications, and is deployed as a Docker-based backend service.