Skip to content

Feature status

What works, what is partial, what is not

Edit this page
On this page

Loomscope covers a broad surface. This page states what actually works today, what is partial, and what is not implemented — without rounding anything up.

What these words mean

Nothing on this page means "proven in production". Loomscope has no production deployments yet, so no label here can claim that, and the one this page used to use — Stable — read as though it did. It only ever meant "finished writing it".

Each label below is backed by something you can check out and run:

LabelWhat it means
TestedAutomated tests in CI exercise it. make test runs them.
Partly testedSome of it is covered and some is not. The note says which part.
UntestedImplemented and used in development. Nothing in CI proves it works, so treat it as unproven.
Not implementedAbsent. Not partially present, not planned-and-half-done.

The "What backs it" column names the actual files. If a row claims a test and you cannot find it, that is a defect — please open an issue.

Status

AreaStatusWhat backs it
Host discovery — ICMP, ARP, TCP, UDP, IPv4 + IPv6Partly testedicmp_test.go covers ICMP. ARP is covered on all three platforms and cross-checked against a second source on each — /proc/net/arp on Linux, GetIpNetTable2's own row count on Windows — because counting entries proves nothing when the count is allowed to be zero. TCP, UDP and DNS have no unit tests; scripts/e2e-detection.sh exercises them against the fixture stack.
Service detection — built-in signatures plus custom YAMLTestedpattern_test.go, yaml_test.go, scripts/e2e-detection.sh
MAC vendor identificationTestedoui_test.go. The IEEE assignment table is compiled in (all three registries, longest prefix wins) and one test walks every one of the 13 690 sub-allocations asserting none resolves to the registrar rather than the manufacturer — the failure a /24-only table would have had on a quarter of the registry. Verified against this machine's real neighbours. (ADR-0026)
nmap and NSE, when the daemon's host has onePartly testedparse_test.go runs against testdata/fixtures-scan.xml, a captured nmap 7.99 run against the project's own service fixtures — not a document written to match the parser. run_test.go pins the argv and asserts every script selection excludes nmap's external category. TestScanAgainstARealNmap runs wherever an nmap exists and skips where none does; it has been run against nmap 7.99 in a container. Never run on a real estate. Loomscope ships no nmap. (ADR-0024)
The daemon on Linux, Windows and macOSTestedCI's Go matrix builds and tests the daemon on ubuntu-latest, windows-latest and macos-latest, and each job prints how many neighbours its reader actually saw rather than only ok/FAIL. The macOS reader had never executed anywhere before that matrix existed. No installer or service wrapper is shipped. (ADR-0025)
Topology — L2, L3, workloads and application viewsTestedAll four generators, against a real database: generateL2.test.ts, generateL3.test.ts, generateWorkloads.test.ts, generateApplication.test.ts, plus shares.test.ts for the share links. Writing them found three defects, all of the same shape — a map that renders and is wrong. Route edges and dependency edges were built from queries scoped by row-level security but not by site or deletion, so they pointed at nodes the payload had excluded; a route with no next hop, which is what a traceroute records, drew nothing at all; and "is there flow data" was asked of the whole organisation, so a site with none of its own was denied the co-hosted fallback because another site had records.
Exports — Mermaid, draw.io, shareable read-only linksTestedmermaid.test.ts, drawio.test.ts, shares.test.ts
SNMP v1/v2c/v3, LLDP/CDP, VLANs, routing tablesTestedsnmp_test.go, iftable_test.go, route_test.go, vlan_test.go, scripts/e2e-snmp.sh
Flow collection — NetFlow v5/v9, sFlowPartly testedparse_v5_test.go and aggregator_test.go. v9 and sFlow parse without a test.
Cloud discovery — AWS, KubernetesTestedec2.test.ts, nodes.test.ts, fingerprint.test.ts, two e2e scripts
TLS certificates — inventory, expiry warnings, chain trustTestedtrust_test.go, certificates.test.ts
CVE matching — OSV and NVD, offline mirror supportedTestedmatcher.test.ts, osv_test.go, nvd_test.go
Snapshots and history diffTesteddiff.test.ts, snapshotTick.test.ts, scripts/e2e-snapshot-diff.sh
PDF attestationUntestedserver/snapshot/pdf/ has no test. The claim that it is byte-reproducible is unverified.
Multi-site scoping — one control plane, per-site rolesTestedrls.test.ts, scope.test.ts, scripts/e2e-multisite.sh
Tenant isolation — row-level securityTestedrls.test.ts asserts the boundary against a real database as an unprivileged role.
Scheduled work — scans, sync, matching, snapshotsTestedpool.test.ts, retry.test.ts, snapshotTick.test.ts
People — first-run setup, invitations, roles, removalTestedsetup.test.ts, invitations.test.ts, members.test.ts, permissions.test.ts
SSO — OpenID Connect, JIT provisioning, group-to-roleTestedoidc.test.ts, provision.test.ts, config.live.test.ts, scripts/sso-e2e.sh
SCIM 2.0 — Users, Groups, deprovisioning, group-to-roleTestedgroups.test.ts, protocol.test.ts, scripts/scim-e2e.sh
Public inventory REST API — 8 collections, 4 writes, per-host topology and its SVGTestedcollection.test.ts, writes.test.ts, contract-agreement.test.ts, topology/__tests__/host.test.ts, exports/__tests__/host-svg.test.ts
loomscope command-line clientTestedservices/cli/internal/cli/cli_test.go covers the exit codes, the config cascade, the argument reordering and the problem-details mapping. scripts/cli-exit-codes.sh checks every documented code against a running deployment.
MCP server — read-only, stdio transportTestedservices/cli/internal/mcp/server_test.go covers the framing, the error mapping and the tool arguments; scripts/mcp-smoke.sh speaks a real client's opening exchange against a running deployment. The Streamable HTTP transport ships too, with the specification's DNS-rebinding protection: http_test.go covers the origin check, the bearer refusals, session handling and version negotiation, and scripts/mcp-http-smoke.sh drives a listening socket — which is where a wrong bind address or a swallowed Authorization header would show and a handler test cannot.
Prometheus /metrics, scoped by API keyTestedapp/api/v1/metrics/__tests__/route.test.ts
Alerting — Slack, Teams, PagerDuty, Jira, signed webhooksPartly testedadapters.test.ts, events.test.ts, dryrun.test.ts cover formatting and routing. No test delivers to a real endpoint.
Audit log — every privileged action, with actor and addressPartly testedwrites.test.ts asserts the rows the public API writes. The session-authenticated paths have no test.
AI assistant — local Ollama, or a remote providerPartly testedproviders.test.ts covers provider selection; scripts/e2e-ai-chat.sh needs a live model. Off by default.
Backup and restoreTestedscripts/backup-roundtrip.sh backs up, verifies the archive, restores into a scratch database, compares nine tables row for row, and checks that every stored credential still decrypts under the current key. It never touches the source database, and refuses if the scratch name resolves to it. It runs in CI on every change — which it did not actually do until 2026-08-20: the runner installed PostgreSQL 16's pg_dump against a 17 server, so the step failed on every commit for a day while the row above said Tested. The client is pinned to the server's major version now, and both versions are printed.
Helm chartPartly testedCI lints it, asserts it refuses to render with no secrets configured, renders it and validates the output against the Kubernetes API schema with kubeconform. CI installs it now, into a throwaway kind cluster, from images it builds itself: scripts/check-helm.sh runs on every change and asserts the migration hook left a schema behind, the server answered its own health check, a fresh install lands on the setup form, and the daemon was scheduled with exactly NET_RAW and never privileged. That script is what found every real defect this chart has had — the four checks above passed all of them. It has also been installed into a real k3s cluster with ingress-nginx and cert-manager (scripts/k3s-install.sh), which is what found a helper naming a Secret the chart never creates.
Browser (end-to-end) testsTestedTen Playwright specs run on every change: sign-in through the real form, the host list and its search, a topology regenerated and painted onto a canvas, and the vulnerability filters. They run against a production build served the way the container serves it, seeded with scripts/seed.ts plus scripts/seed-demo.ts. The recorded reason they never ran — "installing Chromium's system libraries needs root" — was a developer's WSL constraint written down as a property of CI; a GitHub runner installs them with --with-deps. A page that throws an uncaught exception or logs a console error fails its test even when the assertions passed, because a component that throws during a transition otherwise fails nothing by itself. Twelve specs, all green.
SAMLNot implemented—
LDAP / Active Directory bindNot implementedOpenID Connect and SCIM cover directories that speak either.

Known gaps worth stating plainly

Each of these is the kind of gap that looks like good news until you go looking.

Scheduled work does not retry across a restart

A failed tick is retried within the same run, with backoff, where the job's interval is long enough for the wait to matter. But a worker that dies mid-retry resumes the normal schedule rather than resuming the attempts.

Closing it properly means a durable queue, which is a dependency decision still open. See Scheduled jobs.

SAML is not implemented

If your identity provider only speaks SAML, Loomscope cannot federate with it. OIDC and SCIM cover the directories that speak either.

No public inventory API yet

/api/v1/ today is the daemon protocol plus a few administrative endpoints. The UI talks to the server over tRPC, which is internal and not a stable interface. See REST API.

No email transport

Magic-link sign-in has no mail transport, so requesting one fails rather than silently succeeding. Notifications go to webhooks, Slack, Teams, PagerDuty and Jira instead.

No automatic retention or pruning

Snapshots and audit entries accumulate indefinitely. For a large estate under change, plan disk for it — see Scaling.

Test coverage, honestly

679 TypeScript tests and the Go suites run on every change. They cover parsing, diffing, CVE matching, tenant isolation against a real database as an unprivileged role, the whole public API surface, the pattern engine against both Go and YAML signatures, and both theme palettes for WCAG 2.1 AA contrast.

The OIDC flow is exercised end to end in CI against a real Keycloak, and the SCIM surface against a running server.

What is not covered, stated plainly because the table above is only useful if this paragraph is honest:

  • Anything a browser does. This is the gap that matters most, and it is not theoretical: deploying behind TLS in August 2026 turned up three defects that made the product unusable at any real hostname — a chart helper naming a Secret nothing creates, an auth client with localhost:3000 compiled into the browser bundle, and a session cookie whose name changes under HTTPS and which the middleware did not recognise. None were visible to the tests, the linted chart or the schema validation, because none of those serve a page over HTTPS and press a button.

  • The four topology generators. The centre of the product, and the one area with no test at all.

  • The UI. No browser tests run — Playwright specs exist, but installing Chromium's system libraries needs root, which CI does not grant.

This list is the roadmap for the next stretch, in roughly that order.