From 9d8354e58f51cf82037dcf670a68235f44e8bdbb Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Thu, 2 Apr 2026 20:31:08 +0000 Subject: [PATCH] feat(docs,ops-dashboard): document unified database and reusable security profile and network target management --- changelog.md | 8 ++ package.json | 4 +- pnpm-lock.yaml | 28 +++---- readme.md | 140 +++++++++++++++++-------------- ts/00_commitinfo_data.ts | 2 +- ts_interfaces/readme.md | 27 ++++++ ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/ops-dashboard.ts | 30 ++++++- ts_web/readme.md | 6 ++ 9 files changed, 164 insertions(+), 83 deletions(-) diff --git a/changelog.md b/changelog.md index 6c7372a..3de5c41 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2026-04-02 - 12.3.0 - feat(docs,ops-dashboard) +document unified database and reusable security profile and network target management + +- Update project and interface documentation to replace separate storage/cache configuration with a unified database model +- Document new security profile and network target APIs, data models, and dashboard capabilities +- Add a global dashboard warning when the database is disabled so unavailable management features are clearly indicated +- Bump @design.estate/dees-catalog and @serve.zone/catalog to support the updated dashboard experience + ## 2026-04-02 - 12.2.6 - fix(ops-ui) improve operations table actions and modal form handling for profiles and network targets diff --git a/package.json b/package.json index 8180bac..e57f646 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@api.global/typedserver": "^8.4.6", "@api.global/typedsocket": "^4.1.2", "@apiclient.xyz/cloudflare": "^7.1.0", - "@design.estate/dees-catalog": "^3.49.2", + "@design.estate/dees-catalog": "^3.50.2", "@design.estate/dees-element": "^2.2.4", "@push.rocks/lik": "^6.4.0", "@push.rocks/projectinfo": "^5.1.0", @@ -61,7 +61,7 @@ "@push.rocks/smartunique": "^3.0.9", "@push.rocks/smartvpn": "1.19.1", "@push.rocks/taskbuffer": "^8.0.2", - "@serve.zone/catalog": "^2.9.1", + "@serve.zone/catalog": "^2.10.0", "@serve.zone/interfaces": "^5.3.0", "@serve.zone/remoteingress": "^4.15.3", "@tsclass/tsclass": "^9.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be0b694..b8de1c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: ^7.1.0 version: 7.1.0 '@design.estate/dees-catalog': - specifier: ^3.49.2 - version: 3.49.2(@tiptap/pm@2.27.2) + specifier: ^3.50.2 + version: 3.50.2(@tiptap/pm@2.27.2) '@design.estate/dees-element': specifier: ^2.2.4 version: 2.2.4 @@ -102,8 +102,8 @@ importers: specifier: ^8.0.2 version: 8.0.2 '@serve.zone/catalog': - specifier: ^2.9.1 - version: 2.9.1(@tiptap/pm@2.27.2) + specifier: ^2.10.0 + version: 2.10.0(@tiptap/pm@2.27.2) '@serve.zone/interfaces': specifier: ^5.3.0 version: 5.3.0 @@ -350,8 +350,8 @@ packages: '@configvault.io/interfaces@1.0.17': resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==} - '@design.estate/dees-catalog@3.49.2': - resolution: {integrity: sha512-ChVf5IW/w1WSsfuI3BA1SX2QJFjZljnAvnyPDXnbzTXuOdTgs054p66JwlDca9KM8yBlndwibgAYJfD6/4sONw==} + '@design.estate/dees-catalog@3.50.2': + resolution: {integrity: sha512-oxB1kB3IxEwHgf+DjytTBilkDVVb8hryq465OhhzgBiJiHaNLPyBASAQaNTVp6eaORQGzyCmy/ac/GdQglZiIg==} '@design.estate/dees-comms@1.0.30': resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==} @@ -1583,8 +1583,8 @@ packages: '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} - '@serve.zone/catalog@2.9.1': - resolution: {integrity: sha512-W+4x5O834DiEtcqfVNFrP6qYlj/6c9UTR9oEl2Wthf0R2SN0zC6Hbs16US2kP+mmQBKAIDMQYvTUI9oaXqvcog==} + '@serve.zone/catalog@2.10.0': + resolution: {integrity: sha512-/y3gDrf3UHXaDhLJtqJTeHSXOCKGQ4ou6Dd80tMxQYm8/I/OJmifkgerLKP05WdbMyj0pLp33QhjLElJrpME8Q==} '@serve.zone/interfaces@5.3.0': resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==} @@ -4260,13 +4260,11 @@ packages: xterm-addon-fit@0.8.0: resolution: {integrity: sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==} - deprecated: This package is now deprecated. Move to @xterm/addon-fit instead. peerDependencies: xterm: ^5.0.0 xterm@5.3.0: resolution: {integrity: sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==} - deprecated: This package is now deprecated. Move to @xterm/xterm instead. y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} @@ -4341,7 +4339,7 @@ snapshots: '@api.global/typedrequest-interfaces': 3.0.19 '@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3) '@cloudflare/workers-types': 4.20260317.1 - '@design.estate/dees-catalog': 3.49.2(@tiptap/pm@2.27.2) + '@design.estate/dees-catalog': 3.50.2(@tiptap/pm@2.27.2) '@design.estate/dees-comms': 1.0.30 '@push.rocks/lik': 6.4.0 '@push.rocks/smartdelay': 3.0.5 @@ -4870,7 +4868,7 @@ snapshots: dependencies: '@api.global/typedrequest-interfaces': 3.0.19 - '@design.estate/dees-catalog@3.49.2(@tiptap/pm@2.27.2)': + '@design.estate/dees-catalog@3.50.2(@tiptap/pm@2.27.2)': dependencies: '@design.estate/dees-domtools': 2.5.4 '@design.estate/dees-element': 2.2.4 @@ -4978,7 +4976,7 @@ snapshots: '@design.estate/dees-wcctools@3.8.0': dependencies: - '@design.estate/dees-domtools': 2.5.3 + '@design.estate/dees-domtools': 2.5.4 '@design.estate/dees-element': 2.2.4 '@push.rocks/smartdelay': 3.0.5 lit: 3.3.2 @@ -6906,9 +6904,9 @@ snapshots: domhandler: 5.0.3 selderee: 0.11.0 - '@serve.zone/catalog@2.9.1(@tiptap/pm@2.27.2)': + '@serve.zone/catalog@2.10.0(@tiptap/pm@2.27.2)': dependencies: - '@design.estate/dees-catalog': 3.49.2(@tiptap/pm@2.27.2) + '@design.estate/dees-catalog': 3.50.2(@tiptap/pm@2.27.2) '@design.estate/dees-domtools': 2.5.4 '@design.estate/dees-element': 2.2.4 '@design.estate/dees-wcctools': 3.8.0 diff --git a/readme.md b/readme.md index f6643b2..7110ec5 100644 --- a/readme.md +++ b/readme.md @@ -93,10 +93,11 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community - **Socket-handler mode** — direct socket passing eliminates internal port hops - **Real-time metrics** via SmartMetrics (CPU, memory, connections, throughput) -### 💾 Persistent Storage & Caching -- **Multiple storage backends**: filesystem, custom functions, or in-memory -- **Embedded cache database** via smartdata + smartdb (MongoDB-compatible) +### 💾 Unified Database +- **Two deployment modes**: embedded LocalSmartDb (zero-config) or external MongoDB +- **15 document classes** covering routes, certs, VPN, RADIUS, security profiles, network targets, and caches - **Automatic TTL-based cleanup** for cached emails and IP reputation data +- **Reusable references** — security profiles and network targets that propagate changes to all referencing routes ### 🖥️ OpsServer Dashboard - **Web-based management interface** with real-time monitoring @@ -104,7 +105,9 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community - **Live views** for connections, email queues, DNS queries, RADIUS sessions, certificates, remote ingress edges, VPN clients, and security events - **Domain-centric certificate overview** with backoff status and one-click reprovisioning - **Remote ingress management** with connection token generation and one-click copy -- **Read-only configuration display** — DcRouter is configured through code +- **Security profiles & network targets** — reusable security configurations and host:port targets with propagation to referencing routes +- **Global warning banners** when database is disabled (management features unavailable) +- **Read-only configuration display** for system overview - **Smart tab visibility handling** — auto-pauses all polling, WebSocket connections, and chart updates when the browser tab is hidden, preventing resource waste and tab freezing ### 🔧 Programmatic API Client @@ -269,11 +272,8 @@ const router = new DcRouter({ ], }, - // Persistent storage - storage: { fsPath: '/var/lib/dcrouter/data' }, - - // Cache database - cacheConfig: { enabled: true, storagePath: '~/.serve.zone/dcrouter/tsmdb' }, + // Unified database (embedded LocalSmartDb or external MongoDB) + dbConfig: { enabled: true }, // TLS & ACME tls: { contactEmail: 'admin@example.com' }, @@ -311,8 +311,7 @@ graph TB CM[Certificate Manager
smartacme v9] OS[OpsServer Dashboard] MM[Metrics Manager] - SM[Storage Manager] - CD[Cache Database] + DB2[DcRouterDb
smartdata + smartdb] end subgraph "Backend Services" @@ -339,8 +338,7 @@ graph TB DC --> CM DC --> OS DC --> MM - DC --> SM - DC --> CD + DC --> DB2 SP --> WEB SP --> API @@ -365,8 +363,7 @@ graph TB | **RemoteIngress** | `@serve.zone/remoteingress` | Distributed edge tunneling with Rust data plane and TS management | | **OpsServer** | `@api.global/typedserver` | Web dashboard + TypedRequest API for monitoring and management | | **MetricsManager** | `@push.rocks/smartmetrics` | Real-time metrics collection (CPU, memory, email, DNS, security) | -| **StorageManager** | built-in | Pluggable key-value storage (filesystem, custom, or in-memory) | -| **CacheDb** | `@push.rocks/smartdb` | Embedded MongoDB-compatible database (LocalSmartDb) for persistent caching | +| **DcRouterDb** | `@push.rocks/smartdata` + `@push.rocks/smartdb` | Unified database — embedded LocalSmartDb or external MongoDB for all persistence | ### How It Works @@ -509,24 +506,16 @@ interface IDcRouterOptions { }; dnsChallenge?: { cloudflareApiKey?: string }; - // ── Storage & Caching ───────────────────────────────────────── - storage?: { - fsPath?: string; - readFunction?: (key: string) => Promise; - writeFunction?: (key: string, value: string) => Promise; - }; - cacheConfig?: { + // ── Database ──────────────────────────────────────────────────── + /** Unified database for all persistence (routes, certs, VPN, RADIUS, etc.) */ + dbConfig?: { enabled?: boolean; // default: true + mongoDbUrl?: string; // External MongoDB URL (omit for embedded LocalSmartDb) storagePath?: string; // default: '~/.serve.zone/dcrouter/tsmdb' dbName?: string; // default: 'dcrouter' cleanupIntervalHours?: number; // default: 1 - ttlConfig?: { - emails?: number; // default: 30 days - ipReputation?: number; // default: 1 day - bounces?: number; // default: 30 days - dkimKeys?: number; // default: 90 days - suppression?: number; // default: 30 days - }; + seedOnEmpty?: boolean; // Seed default profiles/targets if DB is empty + seedData?: object; // Custom seed data }; } ``` @@ -1213,49 +1202,55 @@ The OpsServer includes a **Certificates** view showing: - One-click reprovisioning per domain - Certificate import and export -## Storage & Caching +## Storage & Database -### StorageManager +DcRouter uses a **unified database** (`DcRouterDb`) powered by [`@push.rocks/smartdata`](https://code.foss.global/push.rocks/smartdata) + [`@push.rocks/smartdb`](https://code.foss.global/push.rocks/smartdb) for all persistence. It supports two modes: -Provides a unified key-value interface with three backends: +### Embedded LocalSmartDb (Default) + +Zero-config, file-based MongoDB-compatible database — no external services needed: ```typescript -// Filesystem backend -storage: { fsPath: '/var/lib/dcrouter/data' } - -// Custom backend (Redis, S3, etc.) -storage: { - readFunction: async (key) => await redis.get(key), - writeFunction: async (key, value) => await redis.set(key, value) -} - -// In-memory (development only — data lost on restart) -// Simply omit the storage config +dbConfig: { enabled: true } +// Data stored at ~/.serve.zone/dcrouter/tsmdb by default ``` -Used for: TLS certificates, DKIM keys, email routes, bounce/suppression lists, IP reputation data, domain configs, cert backoff state, remote ingress edge registrations. +### External MongoDB -### Cache Database - -An embedded MongoDB-compatible database (via smartdata + smartdb) for persistent caching with automatic TTL cleanup: +Connect to an existing MongoDB instance: ```typescript -cacheConfig: { +dbConfig: { enabled: true, - storagePath: '~/.serve.zone/dcrouter/tsmdb', + mongoDbUrl: 'mongodb://localhost:27017', dbName: 'dcrouter', - cleanupIntervalHours: 1, - ttlConfig: { - emails: 30, // days - ipReputation: 1, // days - bounces: 30, // days - dkimKeys: 90, // days - suppression: 30 // days - } } ``` -Cached document types: `CachedEmail`, `CachedIPReputation`. +### Disabling the Database + +For static, constructor-only deployments where no runtime management is needed: + +```typescript +dbConfig: { enabled: false } +// Routes come exclusively from constructor config — no CRUD, no persistence +// OpsServer still runs but management features are disabled +``` + +### What's Stored + +DcRouterDb persists all runtime state across 15 document classes: + +| Category | Documents | Purpose | +|----------|-----------|---------| +| **Routes** | `StoredRouteDoc`, `RouteOverrideDoc` | Programmatic routes and hardcoded route overrides | +| **Certificates** | `ProxyCertDoc`, `AcmeCertDoc`, `CertBackoffDoc` | TLS certs, ACME state, per-domain backoff | +| **Auth** | `ApiTokenDoc` | API token storage | +| **Remote Ingress** | `RemoteIngressEdgeDoc` | Edge node registrations | +| **VPN** | `VpnServerKeysDoc`, `VpnClientDoc` | Server keys and client registrations | +| **RADIUS** | `VlanMappingsDoc`, `AccountingSessionDoc` | VLAN mappings and accounting sessions | +| **References** | `SecurityProfileDoc`, `NetworkTargetDoc` | Reusable security profiles and network targets | +| **Cache** | `CachedEmailDoc`, `CachedIpReputationDoc` | TTL-based caches with automatic cleanup | ## Security Features @@ -1324,6 +1319,8 @@ The OpsServer provides a web-based management interface served on port 3000 by d | 🔐 **Certificates** | Domain-centric certificate overview, status, backoff info, reprovisioning, import/export | | 🌍 **RemoteIngress** | Edge node management, connection status, token generation, enable/disable | | 🔐 **VPN** | VPN client management, server status, create/toggle/export/rotate/delete clients | +| 🛡️ **Security Profiles** | Reusable security configurations (IP allow/block lists, rate limits) | +| 🎯 **Network Targets** | Reusable host:port destinations for route references | | 📡 **RADIUS** | NAS client management, VLAN mappings, session monitoring, accounting | | 📜 **Logs** | Real-time log viewer with level filtering and search | | ⚙️ **Configuration** | Read-only view of current system configuration | @@ -1410,6 +1407,22 @@ All management is done via TypedRequest over HTTP POST to `/typedrequest`: 'setVlanMapping' // Add/update VLAN mapping 'removeVlanMapping' // Remove VLAN mapping 'testVlanAssignment' // Test what VLAN a MAC gets + +// Security Profiles +'getSecurityProfiles' // List all security profiles +'getSecurityProfile' // Get a single profile by ID +'createSecurityProfile' // Create a reusable security profile +'updateSecurityProfile' // Update a profile (propagates to referencing routes) +'deleteSecurityProfile' // Delete a profile (with optional force) +'getSecurityProfileUsage' // Get routes referencing a profile + +// Network Targets +'getNetworkTargets' // List all network targets +'getNetworkTarget' // Get a single target by ID +'createNetworkTarget' // Create a reusable host:port target +'updateNetworkTarget' // Update a target (propagates to referencing routes) +'deleteNetworkTarget' // Delete a target (with optional force) +'getNetworkTargetUsage' // Get routes referencing a target ``` ## API Client @@ -1518,12 +1531,12 @@ const router = new DcRouter(options: IDcRouterOptions); | `remoteIngressManager` | `RemoteIngressManager` | Edge registration CRUD manager | | `tunnelManager` | `TunnelManager` | Tunnel lifecycle and status manager | | `vpnManager` | `VpnManager` | VPN server lifecycle and client CRUD manager | -| `storageManager` | `StorageManager` | Storage backend | | `opsServer` | `OpsServer` | OpsServer/dashboard instance | | `metricsManager` | `MetricsManager` | Metrics collector | -| `cacheDb` | `CacheDb` | Cache database instance | -| `certProvisionScheduler` | `CertProvisionScheduler` | Per-domain backoff scheduler for cert provisioning | -| `certificateStatusMap` | `Map` | Domain-keyed certificate status from SmartProxy events | +| `dcRouterDb` | `DcRouterDb` | Unified database instance (smartdata + smartdb) | +| `routeConfigManager` | `RouteConfigManager` | Programmatic route CRUD manager | +| `apiTokenManager` | `ApiTokenManager` | API token management | +| `referenceResolver` | `ReferenceResolver` | Security profile and network target resolver | ### Re-exported Types @@ -1589,7 +1602,8 @@ tstest test/test.opsserver-api.ts --verbose --timeout 60 | `test.jwt-auth.ts` | JWT login, verification, logout, invalid credentials | 8 | | `test.opsserver-api.ts` | Health, statistics, configuration, log APIs | 8 | | `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 | -| `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 | +| `test.reference-resolver.ts` | Security profiles, network targets, route resolution | 20 | +| `test.security-profiles-api.ts` | Profile/target API endpoints, auth enforcement | 13 | ## Docker / OCI Container Deployment diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index a135352..671a8fe 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '12.2.6', + version: '12.3.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_interfaces/readme.md b/ts_interfaces/readme.md index bbc2765..22e3e52 100644 --- a/ts_interfaces/readme.md +++ b/ts_interfaces/readme.md @@ -90,6 +90,13 @@ interface IIdentity { | `IApiTokenInfo` | Token info: id, name, scopes, createdAt, expiresAt, enabled | | `TApiTokenScope` | Token scopes: `routes:read`, `routes:write`, `config:read`, `tokens:read`, `tokens:manage` | +#### Security & Reference Interfaces +| Interface | Description | +|-----------|-------------| +| `ISecurityProfile` | Reusable security config: id, name, description, security (ipAllowList, ipBlockList, maxConnections, rateLimit, etc.), extendsProfiles | +| `INetworkTarget` | Reusable host:port destination: id, name, description, host (string or string[]), port | +| `IRouteMetadata` | Route-to-reference links: securityProfileRef, networkTargetRef, snapshot names, lastResolvedAt | + #### Remote Ingress Interfaces | Interface | Description | |-----------|-------------| @@ -241,6 +248,26 @@ interface ICertificateInfo { | `IReq_GetRadiusStatistics` | `getRadiusStatistics` | RADIUS stats | | `IReq_GetRadiusAccountingSummary` | `getRadiusAccountingSummary` | Accounting summary | +#### 🛡️ Security Profiles +| Interface | Method | Description | +|-----------|--------|-------------| +| `IReq_GetSecurityProfiles` | `getSecurityProfiles` | List all security profiles | +| `IReq_GetSecurityProfile` | `getSecurityProfile` | Get a single profile by ID | +| `IReq_CreateSecurityProfile` | `createSecurityProfile` | Create a reusable security profile | +| `IReq_UpdateSecurityProfile` | `updateSecurityProfile` | Update a profile (propagates to routes) | +| `IReq_DeleteSecurityProfile` | `deleteSecurityProfile` | Delete a profile (with optional force) | +| `IReq_GetSecurityProfileUsage` | `getSecurityProfileUsage` | Get routes referencing a profile | + +#### 🎯 Network Targets +| Interface | Method | Description | +|-----------|--------|-------------| +| `IReq_GetNetworkTargets` | `getNetworkTargets` | List all network targets | +| `IReq_GetNetworkTarget` | `getNetworkTarget` | Get a single target by ID | +| `IReq_CreateNetworkTarget` | `createNetworkTarget` | Create a reusable host:port target | +| `IReq_UpdateNetworkTarget` | `updateNetworkTarget` | Update a target (propagates to routes) | +| `IReq_DeleteNetworkTarget` | `deleteNetworkTarget` | Delete a target (with optional force) | +| `IReq_GetNetworkTargetUsage` | `getNetworkTargetUsage` | Get routes referencing a target | + ## Example: Full API Integration > 💡 **Tip:** For a higher-level, object-oriented API, use [`@serve.zone/dcrouter-apiclient`](https://www.npmjs.com/package/@serve.zone/dcrouter-apiclient) which wraps these interfaces with resource classes and builder patterns. diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index a135352..671a8fe 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '12.2.6', + version: '12.3.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/elements/ops-dashboard.ts b/ts_web/elements/ops-dashboard.ts index 1178ec5..79f7347 100644 --- a/ts_web/elements/ops-dashboard.ts +++ b/ts_web/elements/ops-dashboard.ts @@ -2,7 +2,6 @@ import * as plugins from '../plugins.js'; import * as appstate from '../appstate.js'; import * as interfaces from '../../dist_ts_interfaces/index.js'; import { appRouter } from '../router.js'; - import { DeesElement, css, @@ -43,6 +42,12 @@ export class OpsDashboard extends DeesElement { theme: 'light', }; + @state() accessor configState: appstate.IConfigState = { + config: null, + isLoading: false, + error: null, + }; + // Store viewTabs as a property to maintain object references private viewTabs = [ { @@ -112,6 +117,20 @@ export class OpsDashboard extends DeesElement { }, ]; + private get globalMessages() { + const messages: Array<{ id: string; type: string; message: string; dismissible?: boolean }> = []; + const config = this.configState.config; + if (config && !config.cache.enabled) { + messages.push({ + id: 'db-disabled', + type: 'warning', + message: 'Database is disabled. Creating and editing routes, profiles, targets, and API tokens is not available.', + dismissible: false, + }); + } + return messages; + } + /** * Get the current view tab based on the UI state's activeView. * Used to pass the correct selectedView to dees-simple-appdash on initial render. @@ -137,6 +156,14 @@ export class OpsDashboard extends DeesElement { }); this.rxSubscriptions.push(loginSubscription); + // Subscribe to config state (for global warnings) + const configSubscription = appstate.configStatePart + .select((stateArg) => stateArg) + .subscribe((configState) => { + this.configState = configState; + }); + this.rxSubscriptions.push(configSubscription); + // Subscribe to UI state const uiSubscription = appstate.uiStatePart .select((stateArg) => stateArg) @@ -205,6 +232,7 @@ export class OpsDashboard extends DeesElement { name="DCRouter OpsServer" .viewTabs=${this.viewTabs} .selectedView=${this.currentViewTab} + .globalMessages=${this.globalMessages} > diff --git a/ts_web/readme.md b/ts_web/readme.md index 05dc50e..7a24ab1 100644 --- a/ts_web/readme.md +++ b/ts_web/readme.md @@ -68,6 +68,12 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community - API token creation, revocation, and scope management - Routes tab and API Tokens tab in unified view +### 🛡️ Security Profiles & Network Targets +- Create, edit, and delete reusable security profiles (IP allow/block lists, rate limits, max connections) +- Create, edit, and delete reusable network targets (host:port destinations) +- In-row and context menu actions for quick editing +- Changes propagate automatically to all referencing routes + ### ⚙️ Configuration - Read-only display of current system configuration - Status badges for boolean values (enabled/disabled)