devops f30cce4fb3
CI - Build & Test / Backend (.NET) (push) Successful in 35s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 18s
CI - Build & Test / Security Check (push) Successful in 3s
CI - Build & Test / Deploy Nexus (push) Successful in 4s
fix: harden nexus deploy sync
2026-06-24 07:43:02 +02:00
2026-06-24 07:43:02 +02:00
2026-06-24 07:33:10 +02:00
2026-06-24 01:22:55 +02:00
2026-06-24 07:33:10 +02:00

Nexus

Nexus is the operations platform for the Noveria ecosystem. OpenClaw is an adapter-backed agent runtime, not a dependency of the frontend or domain model.

📋 Architektur-Review (2026-06-22): Board-first Orchestrierung, sichere Backend-Brücke und Gateway-Integration geprüft. Siehe docs/architecture-board-first-orchestration.md

CI runs automatically on every push. CD runs inside the green CI run on main or can be triggered manually (workflow_dispatch). Deploy reads VERSION but does not mutate Git or create tags. Rollback and database backup are separate manual workflows. See phases/deployment.md for full CD documentation.

Current foundation

  • Vue 3, TypeScript, Pinia, Vue Router and Tailwind CSS
  • ASP.NET Core 10 REST API (Minimal API pattern)
  • Entity Framework Core and PostgreSQL
  • JWT owner authentication with rotating refresh sessions
  • IAgentRuntime abstraction with an OpenClaw adapter (Ollama and NVIDIA removed — OpenClaw-only)
  • Responsive dark-mode operations dashboard
  • Traefik reverse-proxy with Let's Encrypt TLS on nexus.noveria.net

Local/container start

cp .env.template .env
# Replace every placeholder, especially POSTGRES_PASSWORD, JWT_KEY and BOOTSTRAP_OWNER_EMAIL.
docker compose up --build -d
curl http://127.0.0.1:18880/health

On an empty database the API creates exactly one owner from BOOTSTRAP_OWNER_EMAIL, derives the initial display name from that email, and logs a generated temporary password once. After first seed the password lives only in PostgreSQL. Existing databases are never overwritten by the bootstrap process.

The API is exposed via Traefik reverse-proxy with automatic Let's Encrypt TLS. Health checks, rate limiting, and security headers are active.

Workspace mounts

The API container mounts agent workspaces from the host for file browsing and the config editor. These are mounted under /mnt/workspace-{agentId}:

Host path Container mount
/home/projekte_bao/openclaw/data/openclaw/workspace-iris /mnt/workspace-iris
/home/projekte_bao/openclaw/data/openclaw/workspace-programmer /mnt/workspace-programmer
/home/projekte_bao/openclaw/data/openclaw/workspace-reviewer /mnt/workspace-reviewer
/home/projekte_bao/openclaw/data/openclaw/workspace-architekt /mnt/workspace-architekt
/home/projekte_bao/openclaw/data/openclaw/workspace-researcher /mnt/workspace-researcher
/home/projekte_bao/openclaw/data/openclaw/workspace-executor /mnt/workspace-executor

Frontend architecture

Source layout

frontend/src/
├── App.vue                # Root shell with sidebar + standalone views
├── main.ts                # App bootstrap
├── router.ts              # Vue Router config
├── types/
│   ├── index.ts           # Re-exports
│   ├── agent.ts           # AgentInfo, AgentDetail, TeamMember
│   ├── config.ts          # ConfigFileInfo, SecurityStatus
│   ├── dashboard.ts       # OperationsSnapshot, RuntimeStatus, etc.
│   └── project.ts         # MemoryFile, DocFile types
├── stores/
│   ├── auth.ts            # Auth store (JWT, login/refresh/logout)
│   └── operations.ts      # Operations store (snapshot, CRUD, approve/reject)
├── services/
│   └── api.ts             # Authenticated fetch wrapper (auto-refresh)
├── composables/
│   └── useTime.ts         # Greeting composable (Morgen/Tag/Abend)
├── views/
│   ├── LoginView.vue
│   ├── DashboardView.vue      # New dashboard (Phase 2)
│   ├── ProjectDetailView.vue
│   ├── SettingsView.vue
│   ├── MemoryView.vue
│   ├── DocsView.vue
│   ├── TeamView.vue
│   ├── SecurityView.vue
│   ├── IncidentsView.vue
│   ├── CalendarView.vue
│   ├── AgentDetailView.vue
│   └── AgentsIndexView.vue
├── components/
│   ├── layout/
│   │   ├── AppSidebar.vue
│   │   └── AppHeader.vue
│   └── dashboard/              # New dashboard components (Phase 2)
│       ├── IrisPanel.vue       # Agent overview + metrics + chat
│       ├── OperationsFeed.vue  # Live activity feed with filters
│       ├── AgendaPanel.vue     # Daily agenda with checkboxes + localStorage
│       ├── ActiveInitiatives.vue  # Project cards with progress
│       └── RecentlyFinished.vue   # Quick status chips
└── ModuleView.vue

App.vue standaloneViews whitelist

New views must be registered in the standaloneViews computed property in App.vue (line ~34). Without this entry, RouterView will not render the component — the route is valid but the template stays empty.

New dashboard (Phase 2)

The dashboard was redesigned with a three-column layout:

  • IrisPanel — Agent avatar/greeting, metrics counters (open tasks, blocked, overdue, today), AI suggestions, quick action buttons, and an inline chat box.
  • OperationsFeed — Searchable/filterable activity feed with colour-coded status dots and yesterday/today/week grouping.
  • AgendaPanel — Daily agenda with checkable items persisted in localStorage under key nexus-agenda-done. Items are sectioned into "Heute", "Morgen", and "Überfällig".
  • ActiveInitiatives — Project initiative cards with progress bars, status badges (healthy/attention/blocked/paused/completed), and last activity timestamps.
  • RecentlyFinished — Horizontally scrollable chip list of recently completed items.

Authentication

  • Passwords use versioned PBKDF2-SHA256 hashes with random salts and 210,000 iterations.
  • Access tokens expire after 15 minutes and are held only in browser memory.
  • Refresh tokens are random, stored only as SHA-256 hashes in PostgreSQL, rotated on use and checked for reuse.
  • The browser receives the refresh token only as a HttpOnly, Secure, SameSite=Strict cookie.
  • Login and refresh endpoints are rate-limited per forwarded client IP (5 attempts/minute).
  • All /api/v1 operations routes require a valid access token; /health remains public.
  • Swagger is enabled only in the Development environment.
  • CSRF protection via X-CSRF-TOKEN header and nexus-csrf cookie (not HttpOnly).

Security

  • Never commit .env.
  • Generate JWT_KEY from at least 32 random bytes.
  • Rotate any credential that has appeared in chat before using it.
  • Do not expose PostgreSQL or the API container directly.
  • Keep OpenClaw behind the IAgentRuntime contract.
  • Keep the API reachable only through the bundled web proxy or another trusted reverse proxy.

Frontend routes (SPA)

The SPA uses history-mode routes. Standalone views (whitelisted in App.vue):

Route View Description
/login LoginView Owner login
/dashboard DashboardView Operations snapshot with IrisPanel, Feed, Agenda
/memory MemoryView Memory file browser with search
/docs DocsView Documentation file browser
/team TeamView Agent team org map
/security SecurityView Security status center
/projects/:id ProjectDetailView Project detail
/incidents IncidentsView Incident diary
/calendar CalendarView Cron/scheduler overview
/agents AgentsIndexView Agent inventory
/agents/:id AgentDetailView Agent detail + config editor
/settings SettingsView Profile + password management

Legacy ModuleView routes (not standalone, rendered through ModuleView.vue):

Route Name Description
/projects Projects Project portfolio
/tasks Task Board Task board with visible parent/child agent flow
/models Models Provider routing status
/activity Activity Audit timeline
/chat Mobile Chat Owner-chat preview

API endpoints

Backend Bridge (Agent-zu-Backend, NICHT Frontend)

Der /api/bridge/ Pfad ist ein strukturierter MCP-artiger Kommando-Adapter für die Agent-zu-Backend-Kommunikation. Kein Frontend-Code ruft diese Endpunkte auf.

Auth: X-Agent-Id Header, X-Nexus-Api-Key, oder JWT. Rate-Limited (30/min).

Methode Pfad Kommando Beschreibung
GET /api/bridge/health Bridge-Health-Check
POST /api/bridge/tasks create_task Neue Top-Level-Task erstellen
POST /api/bridge/tasks/{id}/children create_child_task Child-Task unter Parent erstellen
PATCH /api/bridge/tasks/{id}/status update_status Task-Status ändern
POST /api/bridge/tasks/{id}/activity append_activity Aktivitätseintrag anhängen
POST /api/bridge/tasks/{id}/handoff handoff Task an anderen Agent übergeben
GET /api/bridge/board get_board Vollständiges Task-Board
GET /api/bridge/tasks/{id} get_task Einzelne Task abrufen
GET /api/bridge/tasks/{id}/children get_children Child-Tasks abrufen
GET /api/bridge/tasks/{id}/activity get_activity Task-Aktivität abrufen
GET /api/bridge/agent-overview get_agent_overview Agent-Workflow-Übersicht

Response-Format (TaskBridgeCommandResponse):

{
  "ok": true,
  "command": "create_task",
  "data": { ... },
  "error": null,
  "timestamp": "2026-06-22T15:30:00.000Z"
}

Health & Auth (public or rate-limited)

Method Path Auth Description
GET /health No Health check with runtime + PostgreSQL
GET /api/v1/auth/csrf No Get CSRF token
POST /api/v1/auth/login No (rate-limited) Login with email/password
POST /api/v1/auth/refresh No (rate-limited) Refresh access token
POST /api/v1/auth/logout No Clear refresh token
GET /api/v1/auth/me Yes Current user info
PATCH /api/v1/auth/profile Yes Update display name
POST /api/v1/auth/change-password Yes Change password (min 10 chars)

Operations

Method Path Description
GET /api/v1/operations/snapshot Full operations snapshot (runtime, agents, projects, tasks, activity, metrics)

Parent/Child task flow

The Task Board now models OpenClaw delegation as a visible parent/child flow:

  • Iris keeps the parent task In progress while delegated work is running.
  • Delegated agent work is represented as visible child tasks linked via parentTaskId.
  • Child tasks use the normal visible states (Backlog, In progress, Review, Blocked, Done) instead of a separate hidden delegation lane.
  • Agent progress hints on parent tasks derive from recent activity and child-task status summaries.
  • Full workflow documentation: docs/openclaw-task-board-flow.md

Projects

Method Path Description
GET /api/v1/projects List all projects
POST /api/v1/projects Create project
GET /api/v1/projects/{id} Get project detail
PATCH /api/v1/projects/{id} Update project (name, description, status)
DELETE /api/v1/projects/{id} Delete or archive project (archives if has tasks)

Tasks

Method Path Description
GET /api/v1/tasks List all tasks
POST /api/v1/tasks Create task
GET /api/v1/tasks/pending-approval Tasks in progress older than 1 hour
PATCH /api/v1/tasks/{id} Update task (title, priority, projectId)
PATCH /api/v1/tasks/{id}/state Update task state
POST /api/v1/tasks/{id}/approve Approve task (in-progress → done)
POST /api/v1/tasks/{id}/reject Reject task (in-progress → backlog)
DELETE /api/v1/tasks/{id} Delete task (only done/backlog states)

Agents

Method Path Description
GET /api/v1/agents List all agents
GET /api/v1/agents/{id} Agent detail (with sub-agents, identity)
GET /api/v1/agents/{id}/activity Agent-specific activity (last 50)
POST /api/v1/agents/{id}/command Send command to agent
GET /api/v1/agents/{id}/config List agent config files (IDENTITY.md, SOUL.md, etc.)
GET /api/v1/agents/{id}/config/{fileName} Read config file content
PUT /api/v1/agents/{id}/config/{fileName} Save config file (atomic write)

Memory & Docs

Method Path Description
GET /api/v1/memory List memory files (daily + MEMORY.md)
GET /api/v1/memory/search?q= Full-text search in memory files
GET /api/v1/memory/{name} Get memory file content
GET /api/v1/docs List documentation files by category
GET /api/v1/docs/{**path} Get doc file content (catch-all)

Activity & Team

Method Path Description
GET /api/v1/activity Paginated activity feed (supports type, sort, page, pageSize)
GET /api/v1/routing Model routing status
GET /api/v1/team Team org map with identity excerpts
GET /api/v1/incidents List incident diary entries
GET /api/v1/incidents/{name} Get incident detail
GET /api/v1/security/status Security configuration status

Calendar (Scheduler)

Method Path Description
GET /api/v1/calendar Cron job overview (gateway or fallback)
GET /api/v1/calendar/upcoming Upcoming cron jobs

Chat

Method Path Auth Description
POST /api/v1/chat Yes (rate-limited) Route message through IAgentRuntime

Project and task mutations create activity records. The API applies committed EF Core migrations after PostgreSQL becomes healthy. No destructive endpoints are implemented on the data layer.

State machine (tasks)

Tasks follow a simple state machine:

Backlog → In progress → Done
Backlog → Blocked → In progress / Done
  • Only In progress or Blocked tasks can be approved (→ Done) or rejected (→ Backlog).
  • Only Done or Backlog tasks can be deleted.

Runtime chat and model routing

POST /api/v1/chat routes authenticated owner messages through the IAgentRuntime contract. The browser never receives a Gateway password or model provider key. Conversation IDs are stable per browser and Iris is the default agent target.

The configured model-routing policy routes through the OpenClaw Gateway only. Ollama and NVIDIA providers have been removed. Currently active models:

Agent Model
Iris openai/gpt-5.4
Programmer, Executor deepseek/deepseek-v4-flash
Reviewer, Architekt, Researcher deepseek/deepseek-v4-pro

Claude models (Sonnet 4.6, Opus 4.6/4.7/4.8) are available via claude-cli backend.

The Settings module reports runtime and provider state without exposing credentials.

CI/CD

CI — Automatic

Every push to main triggers .gitea/workflows/ci.yaml:

  • Backend: .NET restore → build → test
  • Frontend: pnpm install → type-check → test → build
  • Security: Scan for hardcoded secrets in source code

CI must never break. If it does, Reviewer fixes.

CD — Auto + Manual (CD v4)

Deployment can happen automatically or manually:

Auto-Deploy (after successful CI jobs on main)

  • Runs as the final Deploy Nexus job in .gitea/workflows/ci.yaml
  • Starts only after backend, frontend, and security jobs succeed on main
  • Deploys the current main version after CI succeeds.
  • This replaces workflow_run, which did not create deploy runs in this Gitea 1.26.3 installation.
  • The deploy script reads VERSION; it does not mutate Git, bump versions, or create tags

Manual Deploy (workflow_dispatch)

  1. DevOps triggers Deploy Nexus Manual in Gitea Actions
  2. Workflow validates VERSION, builds and deploys main
  3. Health check + smoke test verify the deployment

Rollback (workflow_dispatch)

  1. DevOps triggers Rollback to Previous Version in Gitea Actions
  2. Enters target git tag (e.g. v0.2.49) + confirmation ROLLBACK
  3. Workflow checks out the tag, rebuilds with --no-cache, redeploys
  4. Health check + smoke test verify the rollback

Database Backup (workflow_dispatch)

  1. DevOps triggers Database Backup in Gitea Actions
  2. Optionally also copies backup to a host path (/home/projekte_bao/backups)
  3. Workflow dumps PostgreSQL via pg_dumpall, gzips, and uploads as a Gitea artifact
  4. Artifacts are retained for 90 days (configurable)
  5. Optional nightly schedule (uncomment the cron trigger in backup.yaml)

Failure Handling

When deploy or rollback fails:

  • DevOps (Architekt) analyses the error
  • Reviewer (Code-Fixer) fixes the problem
  • DevOps re-deploys to verify the fix

The workflow outputs a formatted handoff message with the job URL.

Full CD documentation: phases/deployment.md

S
Description
Nexus Mission Control Platform
Readme 33 MiB
Languages
C# 51.6%
Vue 28.3%
TypeScript 10.4%
JavaScript 5.2%
CSS 3.6%
Other 0.8%