Skip to content

Roadmap and known issues

This page is the single list of things that do not (yet) work as the rest of the documentation might lead you to expect. Every entry was re-verified against the current code; items that were fixed have been removed (the August 2026 remediation pass closed the entire High-severity backlog — RBAC-gated Admin tabs, the SNMPv3 secret-reference mismatch, the dead second deploy target, check periods, SLA downtime exclusion, snooze/incident UI, and some forty more). The documentation describes the real current behaviour wherever an item below applies.

Severity: High = blocks a core flow, loses data, or misleads in a security-relevant way · Medium = wrong or missing behaviour with a workaround · Low = cosmetic, inconsistency, or documentation-only. Type: Bug · UX · Enhancement (missing feature) · Doc (behaviour is fine, expectations were wrong). IDs OBJ-1, DENSITY-1, I18N-1, A11Y-1 are the August audit’s; all other IDs are assigned on this page.

No High-severity items remain open. The Medium items:

ID Item Severity Type
ALM-1 Alert groups can be configured and attached to rules but are not evaluated anywhere at runtime Medium Enhancement
ALM-3 Suppression re-arm state and pendingFor drafts are in-memory and lost on restart Medium Bug
NTF-1 Escalation steps select channel types; several channels of one type cannot be addressed Medium Enhancement
NTF-6 Web push is server-ready (VAPID, subscription endpoints) but the UI has no subscription flow Medium Enhancement
NTF-2 IMAP/e-mail inbound: attachments ignored, no STARTTLS Medium Enhancement
API-2 X-Forwarded-For is not honoured — rate limiter, ipBind and audit sourceIp see the proxy Medium Bug
CHK-7 Audit-chain verification is not reliable on PostgreSQL (jsonb normalisation) Medium Bug
CHK-2 A passive host result with state DOWN/1 maps to UP (WARNING→UP host mapping) Medium Bug
CHK-4 RRULE downtimes: active-downtime listing filters on the literal end_at Medium Bug
DEP-3 No periodic backup (backup.interval parsed but unused); no vzdump job on the hypervisor Medium Enhancement
RBAC-3 Role scope.folder/scope.selector/scope.tenantId stored but never enforced Medium Enhancement
OBJ-1 The objects list mixes hosts and services flat; no grouping by host/folder Medium UX
AI-3 northplaned mcp (stdio) runs without scheduler/escalation/planner wiring Medium Doc
AGT-2 The Agents tab says the host “appears automatically under Objects”; the server rejects unknown hosts Medium Doc
AGT-3 An agent batch beyond the server’s 1 MiB JSON cap is not handled (potential stuck buffer) Medium Doc
CHK-3 CheckCommand.timeout is not used by the executor (the object’s timeout is) Medium Doc
ID Severity Description Notes
RBAC-3 Medium · Enhancement Role scope.folder / scope.selector / scope.tenantId are stored and editable but never enforced — the principal’s folder scope is never populated, so np:auth/scope cannot trigger and selector is never evaluated. Treat folder/selector scoping as not implemented; tenant scoping comes from the principal’s tenant.
RBAC-7 Medium · Doc Ingest URLs carry no tenant: /api/v1/ingest/{source} resolves the source by id or name across all tenants (first match in slug order wins), and ack links search all tenants for the alert. Event-source names are effectively global for ingest; prefer ids in URLs.
RBAC-8 Low · Enhancement Tenants can be created but not renamed, disabled or deleted — there is no PUT/DELETE /api/v1/tenants. The Admin tab says so explicitly.
RBAC-9 Low · Doc dashboards:read, dashboards:write, reports:read and config:propose are granted by built-in roles but no route checks them (dashboards/reports use objects:read/config:write; config tools need config:write). Legacy/forward-looking permission names.
RBAC-10 Low · Enhancement No RP-initiated (IdP) logout — LogoutURL exists in the OIDC client but nothing calls it. Local, LDAP and OIDC logins and logouts are audited.
RBAC-11 Low · Doc Routes with an empty permission that still require a logged-in principal (whoami, branding, preferences, push subscriptions, change-password) cannot express that in x-required-permission. The generated API reference shows no permission for them.

See Tenancy and RBAC and Users, roles and permissions.

ID Severity Description Notes
ALM-1 Medium · Enhancement Alert groups (/alert-groups, the Groups tab, groupId on rules) are configuration only — no runtime component evaluates them. Rules behave as if no group were set.
ALM-3 Medium · Bug Suppression re-arm state and pendingFor drafts are in-memory and lost on restart; a pending alert restarts its timer, a suppressed alert will not re-notify after the downtime ends if the server restarted meanwhile. See Reliability.
ALM-7 Low · Doc A step that lists channels overrides the contacts’ notification preferences completely — including their time-period and min-severity filters. Intended; easy to miss.
ALM-8 Low · Doc An acknowledged alert never receives a next step or repeat regardless of unlessAcked; unlessAcked: true only suppresses the send of an already-due step.
ALM-9 Low · Doc The correlator reuses an existing incident of any clustered alert (last seen wins) rather than always opening a new one.
ALM-10 Low · Doc labels.source is stamped only by the email, snmp-trap and ESPA adapters; webhook, Alertmanager, MQTT and SMS events carry the source only as event.source. Put a source label on the source’s labels if rules need it.
ALM-12 Low · Doc GET /incidents/{id} returns {incident, alerts} only — no timeline. GET /alerts documentation mentions a firing status; the real statuses are open, acked, resolved, expired.
ALM-13 Low · Doc EventSource.type values heartbeat and agent appear in a struct comment but have no adapter.
ALM-14 Low · Doc Default severities differ per adapter: imap/email, snmp-trap and sms-inbound warning; mqtt, espa, espa-x info; voice-inbound and asterisk-inbound critical; alertmanager label-driven; webhook body-driven (info if empty).
ID Severity Description Notes
NTF-1 Medium · Enhancement Escalation steps select channel types; the notifier uses only the alphabetically first enabled channel of each type. Several channels of one type (for example two Twilio voice accounts) cannot be addressed from steps.
NTF-2 Medium · Enhancement IMAP/e-mail inbound: attachments are ignored and STARTTLS is not supported (implicit TLS or plaintext only).
NTF-6 Medium · Enhancement Web push: the server stores subscriptions (POST/DELETE /push-subscriptions) and holds VAPID keys, but no endpoint returns the public key and the SPA has no subscription flow. fcm:///apns:// registration for the mobile app works. Mobile push
NTF-9 Low · Doc The Twilio SMS provider has no language; German replies to inbound SMS depend on the source’s language. The voice (Twilio TTS voice) key is read only by the inbound IVR, not by outbound Twilio calls — with a TTS profile voices are chosen per language for both directions.
NTF-10 Low · Doc Ack links are valid until expiry (24 h) rather than one-shot as a comment claims; re-clicking shows the same page, and only open alerts are acknowledged. Acknowledge and snooze
NTF-11 Low · Doc NotifyPending/NotifyDead statuses are declared but unused.
ID Severity Description Notes
AGT-2 Medium · Doc The Agents tab says the host “appears automatically under Objects”; the server rejects results for unknown hosts. Create hosts/services first (UI, API, bundle, discovery).
AGT-3 Medium · Doc An agent batch that grows beyond the server’s 1 MiB JSON cap is not handled in code (potential stuck buffer after a long outage). Inferred from code, not reproduced. Keep interval and collector counts reasonable on flaky links.
AGT-4 Low · Enhancement No mTLS / enrollment (join/CA) flow — explicitly roadmap in the agent’s source. No listener rate limiting or IP allow-listing, no SIGHUP config reload, no Windows service wrapper (sc.exe runs the console binary), and the systemd unit’s DynamicUser=yes versus the readability of /etc/northplane/agent.yaml is not addressed.
AGT-7 Low · Bug np get silences|downtimes, describe, export and doctor ignore --json; np apply --dry-run still needs config:write (it does not use :plan); list commands are not paginated (hosts/services ≤ 500, events 50, audit 30, alerts 100).
AGT-8 Low · Doc np defaults to NP_SERVER=https://localhost:8443, while the dev server listens plaintext on 127.0.0.1:8443. Set NP_SERVER=http://127.0.0.1:8443 for make dev.
ID Severity Description Notes
CHK-2 Medium · Bug A passive host result with state DOWN/1 maps to UP because of the WARNING→UP host mapping; use 2/CRITICAL for a down host. Flagged for verification. Plugins and Nagios
CHK-3 Medium · Doc CheckCommand.timeout is not used by the executor (the object’s timeout is).
CHK-4 Medium · Bug RRULE downtimes: the active-downtime listing filters on end_at > now; a recurring downtime whose literal end lies in the past may be excluded from later occurrences. Unclear whether intended. Keep the literal window open-ended enough.
CHK-7 Medium · Bug Audit-chain verification is not reliable on PostgreSQL (TestAuditChain fails: before_json/after_json are jsonb, which normalises the text the hash was computed over; timestamps round-trip at microsecond precision). The CI postgres job is continue-on-error. SQLite is fully green. Storage
CHK-8 Low · Doc Template.labels is described as merged into objects but no merge path exists; Template.kind (host|service|command) is not enforced by validation; TimePeriod.exclude and Acknowledgement{sticky, expiresAt} have no implementation.
CHK-9 Low · Doc Bundle kind Heartbeat is listed but not applied; Tenant is not a bundle kind; metadata.name (not spec.name) identifies documents. Bundle apply is not transactional — earlier documents stay applied after a failure. Config bundles
CHK-10 Low · Doc SavedFilter exists as a generic resource but has no schema and no UI consumer; event types comment, anomaly, forecast are defined but never emitted; CheckResult.source = satellite:<zone> exists only in a comment.
CHK-11 Low · Doc The staleness escalation (soft→hard timing) for passive checks is not spelled out in code comments.
ID Severity Description Notes
API-2 Medium · Bug X-Forwarded-For is not honoured (despite a comment in config.go): trustProxy only trusts X-Forwarded-Proto; token ipBind, the login rate limiter (burst 8, one attempt per 15 s) and the audit sourceIp all use the TCP peer address. Behind a reverse proxy every client shares one login bucket and the audit shows the proxy’s IP; omit ipBind or bind to the proxy address. TLS and proxy
API-5 Low · Enhancement Dashboard shareToken has no backend route — there is no public, unauthenticated wallboard link.
API-6 Low · Doc /metrics, /api/v1/system/health and /api/v1/system/info are anonymous and expose version, Go version, goroutines and queue depths. Restrict at the proxy if needed. Observability
API-7 Low · Doc np_*_total scrape gauges are typed gauge, not counter; decode() claims a strict content-type check that does not exist; an ingest ?token= query parameter is accepted and will appear in access logs (prefer the header or HMAC).
API-8 Low · Enhancement No audit-log retention or purge exists.
ID Severity Description Notes
AI-3 Medium · Doc northplaned mcp (stdio) runs without scheduler, escalation, planner, reports or resource-admin wiring: config tools and reports answer “not wired”, run_check_now/acknowledge_alert are not safe there. Use the HTTP transport for anything beyond reads. MCP server
AI-4 Low · Doc propose_config_change goes through the approval queue even for a dry-run plan; the built-in ai-agent role carries config:propose, which no tool checks (config tools need config:write).
AI-6 Low · Doc Keys for keyed providers cannot be stored without a secretKeyFile (SecretBox); keyless Ollama/OpenAI-compatible connections work. Incident summaries are generated in German regardless of UI language.
ID Severity Description Notes
OBJ-1 Medium · UX The objects list mixes hosts and services flat; the folder is only a text column; no grouping by host/folder or collapsing. Full tree grouping conflicts with the row virtualiser.
DENSITY-1 Low · UX Object detail: perfdata meters are wide and mostly empty for values like rta 0.2ms; “Last hard change —” stays empty; the Interval & Scheduling card is sparse while Metrics/Services scroll.
I18N-1 Low · UX Mixed German/English in the German UI (“Wallboard”, “Business Services”, “Reports”, “Discovery”, “Alle Severities”, “Start”); there is no language switcher (browser language only) and the server-rendered pages are German only. Navigation
A11Y-1 Low · UX The service donut and row states rely primarily on green/amber/red; text labels are small and grey — hard for colour-blind users.
UX-2 Low · Enhancement Non-default public status pages (/status/<slug>) read a statuspage/<slug> KV document that no UI or API writes; only /status/default is usable.
UX-3 Low · Enhancement The counters (KPI) widget cannot be scoped to a selector — it needs an /overview selector parameter on the backend. Per-field origin in the effective-config table is not exposed by the API.
INC-1 Low · Enhancement Incident merge has no UI — POST /api/v1/incidents/{id}:merge is API-only (creating incidents manually is in the UI).
DIALOG-1 Low · Enhancement Radix modals set pointer-events: none on the body — third-party overlays (product tours) cannot be operated while a dialog is open.
TOURS-1 Low · UX Tour content depends on data: the alert tour anchors Acknowledge/Resolve (only present with open alerts); the objects tour (/objects*) also matches detail pages.
ROLES-1 Low · Check The Roles tab lists only the active tenant’s system roles; the Users tab names tenant-admin, which is missing from the role list of tenant Default — verify whether intended.
ID Severity Description Notes
DEP-2 Low · Doc The default-admin seeding closes /setup on a bare default install (the server seeds admin@localhost with a generated password); the root docker-compose.yml sets NP_DEFAULT_ADMIN_DISABLED so /setup works there. Read the generated password from the logs, set NP_DEFAULT_ADMIN_EMAIL/PASSWORD, or set NP_DEFAULT_ADMIN_DISABLED=1 to use /setup. Authentication
DEP-3 Medium · Enhancement No periodic backup: backup.interval is parsed but no scheduler uses it; only northplaned backup on demand. No vzdump job on the production Proxmox host. Back up secret.key and the data volume yourself. Operations
DEP-5 Low · Doc The TLSConfig comment mentions autocert, but no ACME implementation exists — TLS termination in production is Caddy’s job. TLS and proxy
DEP-7 Low · Doc Cloudflare in front of doktrace.com blocks Python user agents (HTTP 403) — scripts need a curl-like User-Agent.
DEP-8 Low · Doc /register on production follows the repo variable NORTHPLANE_ALLOW_SIGNUP (default off). Set the variable to re-enable the showcase signup; turn off for private instances.
ID Severity Description Notes
DEV-1 Low · Doc internal/web/dist is committed; a local go build without make web embeds whatever is committed, which can lag behind web/src. CI and the Dockerfile always rebuild it. Run make web (or make all) before a local build. Frontend
DEV-2 Low · Doc Code comments reference SPEC/ADR documents (§7.7, §12.4 …) that are not in the repository. Treat them as design notes. Backend
DEV-4 Low · Doc The server-rendered login/register pages allow-list their inline Stept bootstrap script by SHA-256 hash; changing its bytes (new workspace key) requires recomputing the hash. The SPA injects the widget at runtime and needs no hash. Frontend

The August audit recorded these deliberately, and the production checks behind Environments confirm the platform side:

  • Overview is dense and useful: KPI tiles, problem list, service donut and “On call now” with name and number live from the schedule.
  • On-Call: rotation timeline, hours per person and overrides behaved correctly in a live test — an override visibly rerouted the alarm (and since the remediation pass, escalateTo: backup honours overrides too).
  • IVR menus, channels and escalations are clear tables with Send test/Edit; the configuration verified in the alarm test is findable one-to-one in the UI.
  • Object detail: Overview/History/Configuration tabs, real metric charts with warn/crit bands, linked child services.
  • Server-side tenant isolation holds (a write attempt against another tenant returns 403), and the Admin surface now only offers what the operator’s permissions can actually use.
  • Production (np-01, doktrace.com): healthz/readyz green, the current main image deployed by CI, an agent fleet reporting, real Twilio SMS, ntfy and e-mail channels exercised end-to-end.
  1. Reliability first: ALM-3 (persist re-arm/pending timers), CHK-7 (PostgreSQL audit chain), API-2 (honour X-Forwarded-For behind trustProxy).
  2. Alarming reach: NTF-6 (web push subscription flow), NTF-1 (address channel instances, not types), ALM-1 (evaluate alert groups or remove the surface).
  3. Operations: DEP-3 (periodic backup driven by backup.interval + a vzdump job).
  4. Decide RBAC-3 (implement folder/selector scoping or drop the fields from the role dialog).
  5. Polish: OBJ-1, DENSITY-1, I18N-1, A11Y-1 and the Low items above.