Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AI_CONTRIBUTING_RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Global AI Agent Instructions (Jules)

**1. The "Living Wiki" Mandate:**
This repository maintains its documentation as a living wiki. The primary sources of truth are the `SYSTEM_ARCHITECTURE.md` and `SECURITY_ARCHITECTURE.md` files.

**2. Mandatory PR Checklist:**
For *every single Pull Request* you generate, regardless of the specific issue assigned to you, you MUST perform the following checks before committing:
* **Diff Review:** Analyze your proposed code changes.
* **Wiki Sync:** If your code alters the network flow, port configurations, authentication methods, database schemas, or deployment commands, you MUST open `SYSTEM_ARCHITECTURE.md` (and create it if it doesn't exist) to update the relevant sections to reflect your exact code changes.
* **Commit Inclusion:** The documentation updates must be included in the same commit/PR as the code changes. Do not submit a PR where the code and the architecture wiki are out of sync.

**3. Global Build Constraint:**
Whenever generating or modifying Dockerfiles for this project, you MUST ensure the font package is explicitly set to `fonts-freefont-ttf` to prevent downstream rendering failures.
36 changes: 29 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This repository combines all the OSH modules and dependencies to deploy the OSH
- [Java 21](https://www.oracle.com/java/technologies/downloads/#java21)
- [Oakridge Build Node Repository](https://github.com/Botts-Innovative-Research/osh-oakridge-buildnode)
- Node v22
- [Docker](https://docs.docker.com/get-docker/) (Required to run the PostGIS database system)

## Installation
Clone the repository and update all submodules recursively
Expand Down Expand Up @@ -44,26 +45,47 @@ After the build completes, it can be located in `build/distributions/`

Option 1: Command Line
```bash
unzip build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
unzip build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
```bash
tar -xf build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
tar -xf build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
Option 2: Use File Explorer
1. Navigate to `path/to/osh-oakridge-buildnode/build/distributions/`
2. Right-click `osh-node-oscar-1.0.zip`.
2. Right-click `osh-node-oscar-<version>.zip` (where `<version>` is the current release version, e.g. `3.0.0`).
3. Select **Extract All..**
4. Choose your destination, (or leave the default) and extract.
1. Launch the OSH node:
Run the launch script, "launch.sh" for linux/mac and "launch.bat" for windows.
1. Launch the OSH node and PostGIS Database:
The database management system is handled through Docker. The default launch scripts automatically build and run a PostGIS container using the `Dockerfile` located in `dist/release/postgis`, and then start the OSH node.
Run the launch script, `launch-all.sh` (or `launch.sh` within the `osh-node-oscar` folder directly if the database is already running) for linux, `launch-all-arm.sh` (or `launch-arm.sh` if it exists) for mac, and `launch-all.bat` (or `launch.bat`) for windows.
2. Access the OSH Node
- Remote: **[ip-address]:8282/sensorhub/admin**
- Locally: **http://localhost:8282/sensorhub/admin**

The default credentials to access the OSH Node are admin:admin. This can be changed in the Security section of the admin page.

**Language Selection**
The user can select different languages for the Admin UI by using the language drop-down menu located in the top right corner of the Admin UI toolbar. Selecting a new language will instantly switch the UI localization.

**Two-Factor Authentication (2FA)**
2FA can be configured for users to add an extra layer of security. To set this up:
1. Log in to the Admin UI.
2. Navigate to the **Security** section.
3. Edit the user profile and set up Two-Factor Authentication. A popup window will appear with a QR code.
4. Scan the QR code with an authenticator app (like Google Authenticator or Authy) to complete the setup.

**Importing/Exporting Lane Configurations via CSV**
Configurations for Lane Systems can be bulk managed via spreadsheet (CSV).
1. Log in to the Admin UI.
2. Navigate to **Services -> OSCAR Service**.
3. Within the configuration form for the OSCAR service, locate the property for spreadsheet configuration (`spreadsheetConfigPath`).
4. To export, click the download button to retrieve the current configurations as a CSV file.
5. To import, upload your modified CSV file through the provided upload mechanism in the service configuration to apply new or updated lane setups.

For documentation on configuring a Lane System on the OSH Admin panel, please refer to the OSCAR Documentation provided in the Google Drive documentation folder.

## Deploy the Client
Expand Down
30 changes: 30 additions & 0 deletions SECURITY_ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# OSCAR Security Hardening Architecture

**Critical Domain Context:**
This project is an Open Source Central Alarm Station (OSCAR) monitoring radiation portal monitors. The application runs cross-platform on Windows, macOS, and Linux. The primary critical threat is the unauthorized suppression, modification, or spoofing of alarms. Note this specific nomenclature:
* **G Alarm:** Gamma Alarm.
* **N Alarm:** Neutron Alarm.
* **G-N:** Gamma Neutron Alarm.

**OpenSensorHub (OSH) Ecosystem Constraint:**
OSCAR is built on the OpenSensorHub framework. **Under no circumstances may any code modifications break compatibility with the larger OSH ecosystem.** * Standard OGC SWE, SOS, and SPS API endpoints must remain fully compliant.
* Sensor drivers (e.g., video processing, hardware interfaces mapped in `config.csv`) must not be prevented from initializing or communicating.
* Machine-to-machine API routes cannot rely on human-interactive authentication (like 302 redirects to a TOTP login).

**Global Build Constraint:**
Whenever generating or modifying Dockerfiles for this project, you MUST ensure the font package is explicitly set to `fonts-freefont-ttf`. This is strictly required to prevent downstream rendering failures in the application's graphical reporting components.

## Database Security Implementation

### SCRAM-SHA-256 Authentication
PostgreSQL is configured to enforce `scram-sha-256` authentication for all database users. This is initialized during the PostGIS container setup via `POSTGRES_INITDB_ARGS`.

### Docker Secrets for Database Credentials
The system uses Docker Secrets (via bind mounts) to manage database passwords.
- **Injected Secret Path**: `/run/secrets/db_password` within the container.
- **Environment Variable**: `POSTGRES_PASSWORD_FILE` points to this secret path.
- **Backend Priority**: The OSH Java backend is architected to prioritize the `POSTGRES_PASSWORD_FILE` environment variable during initialization, overriding any plaintext credentials in `config.json`.

### Configurable Networking and TLS
- **DB Host**: The database host is configurable via the `DB_HOST` environment variable (default: `localhost`), enabling secure deployment on separate LAN machines.
- **TLS Enforcement**: All connections from the OSH backend to PostGIS are secured over TLS. This is enforced by using `sslmode=require` in the JDBC connection string in the `ConnectionManager`.
42 changes: 42 additions & 0 deletions SYSTEM_ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# OSCAR System Architecture

## Overview
OSCAR (Open Source Central Alarm Station) is a monitoring system for radiation portal monitors based on the OpenSensorHub (OSH) framework.

## Component Network Flow and Ports

### Components:
- **OSH Backend**: Java-based core application.
- **PostGIS Database**: PostgreSQL with PostGIS extensions for persistent storage.
- **Client Web UI**: React/Frontend viewer.

### Default Port Configuration:
- **OSH Backend API (HTTP)**: `8282`
- **OSH Backend Admin UI**: `8282`
- **PostGIS Database**: `5432`
- **MQTT Server (HiveMQ)**: WebSockets on `/mqtt` (via proxy on port `8282`)

### Network Flows:
- **Client to OSH**: Clients interact with OSH through its REST API and Web UI on port `8282`.
- **OSH to PostGIS**: The OSH backend connects to the PostGIS database over the network (local or LAN) on port `5432`. This connection is secured via TLS and authenticated with SCRAM-SHA-256.

## Deployment and Lifecycle Commands

### Main Launch Scripts:
Located in `dist/release/`:
- `launch-all.sh`: Starts the PostGIS container and the OSH backend (Linux/macOS).
- `launch-all-arm.sh`: Starts the PostGIS container and the OSH backend (ARM64, e.g., Mac M1/M2/M3).
- `launch-all.bat`: Starts the PostGIS container and the OSH backend (Windows).

### Standalone Database Scripts:
Located in `dist/release/postgis/`:
- `run-postgis.sh`: Starts the PostGIS container independently (Linux/macOS).
- `run-postgis-arm.sh`: Starts the PostGIS container independently (ARM64).
- `run-postgis.bat`: Starts the PostGIS container independently (Windows).

## Database Utilities
Cross-platform scripts are provided in the repository root for maintenance:
- `backup.sh/bat`: Safely creates a database dump.
- `restore.sh/bat`: Restores the database from a dump.

These utilities respect the `DB_HOST` and `POSTGRES_PASSWORD_FILE` environment variables.
32 changes: 32 additions & 0 deletions backup.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal enabledelayedexpansion

if "%DB_HOST%"=="" (set DB_HOST=localhost)
set DB_NAME=gis
set DB_USER=postgres

if "%POSTGRES_PASSWORD_FILE%"=="" (
echo Error: POSTGRES_PASSWORD_FILE environment variable is not set.
exit /b 1
)

if not exist "%POSTGRES_PASSWORD_FILE%" (
echo Error: Password file %POSTGRES_PASSWORD_FILE% does not exist.
exit /b 1
)

set /p PGPASSWORD=<"%POSTGRES_PASSWORD_FILE%"

set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set TIMESTAMP=%TIMESTAMP: =0%
set BACKUP_FILE=backup_%TIMESTAMP%.dump

echo Backing up database %DB_NAME% from %DB_HOST%...
pg_dump -h %DB_HOST% -U %DB_USER% -d %DB_NAME% -F c -f "%BACKUP_FILE%"

if %errorlevel% equ 0 (
echo Backup completed successfully: %BACKUP_FILE%
) else (
echo Backup failed.
exit /b 1
)
27 changes: 27 additions & 0 deletions backup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

DB_HOST="${DB_HOST:-localhost}"
DB_NAME="gis"
DB_USER="postgres"

if [ -z "$POSTGRES_PASSWORD_FILE" ]; then
echo "Error: POSTGRES_PASSWORD_FILE environment variable is not set."
exit 1
fi

if [ ! -f "$POSTGRES_PASSWORD_FILE" ]; then
echo "Error: Password file $POSTGRES_PASSWORD_FILE does not exist."
exit 1
fi

export PGPASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")

echo "Backing up database $DB_NAME from $DB_HOST..."
pg_dump -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -F c -f "backup_$(date +%Y%m%d_%H%M%S).dump"

if [ $? -eq 0 ]; then
echo "Backup completed successfully."
else
echo "Backup failed."
exit 1
fi
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply from: gradle.oshCoreDir + '/common.gradle'
description = ''

allprojects {
version = "3.0.0-rc.5"
version = "3.0.0"
}

subprojects {
Expand Down
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# OSCAR Build Node Change Log
All notable changes to this project will be documented in this file.
## 3.0.0 2026-02-04
This is the official first release of 3.0.0
### Changes
- Data from database is purged regularly with "daily files" exported at midnight
- Added internationalization (i18n) to the frontend
- Sorted lanes by alphanumeric order in the frontend dashboard
- Use server-side filters in frontend tables
### Fixed
- Fixed issue where database is queried everytime Admin UI is loaded

## 3.0.0-rc.5 2025-12-11
### Changes
Expand Down
7 changes: 4 additions & 3 deletions dist/config/standard/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"uiClass": "com.botts.ui.oscar.forms.OSCARServiceForm"
}
],
"deploymentName": "OSCAR 3.0.0-rc.5",
"deploymentName": "OSCAR 3.0.0",
"enableLandingPage": false,
"id": "5cb05c9c-9123-4fa1-8731-ffaa51489678",
"autoStart": true,
Expand Down Expand Up @@ -158,7 +158,8 @@
"initialBuckets": [
"sitemap",
"reports",
"videos"
"videos",
"adjudication"
],
"fileStoreRootDir": "files",
"endPoint": "/buckets",
Expand All @@ -174,7 +175,7 @@
"url": "localhost:5432",
"dbName": "gis",
"login": "postgres",
"password": "postgres",
"password": "",
"idProviderType": "SEQUENTIAL",
"autoCommitPeriod": 10,
"useBatch": false,
Expand Down
31 changes: 25 additions & 6 deletions dist/release/launch-all-arm.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
#!/bin/bash

HOST=localhost
HOST="${DB_HOST:-localhost}"
DB_NAME=gis
DB_USER=postgres
RETRY_MAX=20
RETRY_INTERVAL=5
PROJECT_DIR="$(pwd)" # Store the original directory
CONTAINER_NAME=oscar-postgis-container

# Set up DB password secret
if [ -z "$POSTGRES_PASSWORD_FILE" ]; then
export POSTGRES_PASSWORD_FILE="${PROJECT_DIR}/.db_password"
fi

if [ ! -f "$POSTGRES_PASSWORD_FILE" ]; then
echo "Generating new database password..."
openssl rand -base64 32 > "$POSTGRES_PASSWORD_FILE"
fi

#sudo docker rm -f "$CONTAINER_NAME" 2>/dev/null || true

# Create pgdata directory if needed
Expand Down Expand Up @@ -48,10 +58,11 @@ else
--name $CONTAINER_NAME \
-e POSTGRES_DB=$DB_NAME \
-e POSTGRES_USER=$DB_USER \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_PASS=$(cat "$POSTGRES_PASSWORD_FILE") \
-e DATADIR=/var/lib/postgresql/data \
-p 5432:5432 \
-v "$(pwd)/pgdata:/var/lib/postgresql/data" \
-v "$POSTGRES_PASSWORD_FILE:/run/secrets/db_password" \
-d \
oscar-postgis-arm || { echo "Failed to start PostGIS container"; exit 1; }
fi
Expand All @@ -60,16 +71,24 @@ fi
echo "Waiting for PostGIS ARM64 (PostgreSQL) to be ready..."

RETRY_COUNT=0
export PGPASSWORD=postgres # Needed for pg_isready with password

until docker exec "$CONTAINER_NAME" pg_isready -U "$DB_USER" -d "$DB_NAME" > /dev/null 2>&1; do
until docker exec -u "$DB_USER" "$CONTAINER_NAME" pg_isready -d "$DB_NAME" > /dev/null 2>&1; do
echo "PostGIS not ready yet, retrying..."
sleep "${RETRY_INTERVAL}"
done

echo "PostGIS (PostgreSQL) is ready! Please wait for OpenSensorHub to start..."

sleep 10
sleep 30

# Final check
until docker exec -u "$DB_USER" "$CONTAINER_NAME" pg_isready -d "$DB_NAME" > /dev/null 2>&1; do
echo "PostGIS still restarting, waiting..."
sleep 5
done

# Export for OSH backend
export DB_HOST="$HOST"
export POSTGRES_PASSWORD_FILE="$POSTGRES_PASSWORD_FILE"

# Launch osh-node-oscar
cd "$PROJECT_DIR/osh-node-oscar" || { echo "Error: osh-node-oscar not found"; exit 1; }
Expand Down
Loading
Loading