Trust is the product.
diagnosly runs on your machines and reads your telemetry. Here's exactly how we handle it — what stays local, what we encrypt, who can see what, and how to tell us if something looks off.
Data flow
The agent (observer-core, written in Rust) runs as a system
service on each machine you manage. It reads PDH counters, Windows event
logs, and ETW events locally, then sends a sanitised summary up to the
gateway over TLS 1.3.
- Collect — telemetry stays on the machine until the next heartbeat.
- Scrub — a 13-rule PII scrubber removes usernames, hostnames, MACs, IPs, SIDs, emails, secrets, and BitLocker keys before any payload leaves the agent.
- Sign & send — payload is signed with the device token and posted to
https://api.diagnosly.co.uk. Connection is HTTPS-only; certificate is pinned at the agent layer. - Store — telemetry lands in Postgres with row-level isolation by
tenant_id; case memory uses pgvector. - Diagnose — only when an operator initiates a diagnose command does an LLM see the (already-sanitised) data, with a system prompt scoped to that tenant.
Telemetry is never sold, never used to train shared LLMs, and never leaves the gateway except via your own LLM provider (Anthropic, OpenAI, or self-hosted GLM) using your API key.
PII scrubber
Implemented in the Rust agent at the edge — before the network call. 13 regex rules match common PII shapes and replace them with stable placeholders so logs remain useful for debugging without containing identifiable data.
| Pattern | Example match | Replacement |
|---|---|---|
| Email addresses | alex@acme.com | [email] |
| Windows usernames | C:\Users\alex.kim\Documents | C:\Users\[user]\Documents |
| Hostnames | jamie-thinkpad-x1 | [host] |
| MAC addresses | 00:1A:2B:3C:4D:5E | [mac] |
| IPv4 / IPv6 | 192.168.10.42 | [ip] |
| Windows SIDs | S-1-5-21-... | [sid] |
| BitLocker recovery keys | 48-digit blocks | [bitlocker-key] |
| API tokens / bearer headers | Authorization: Bearer ... | Authorization: [redacted] |
Per-rule hit counters surface in the dashboard so you can see what's being stripped. A separate gateway-side passthrough audit detects bypassed agents (any payload arriving with a recognisable PII shape flags the device for inspection).
Encryption
- In transit — TLS 1.3 between agent ↔ gateway, gateway ↔ orchestrator, dashboard ↔ gateway. Cloudflare terminates TLS at the edge with a managed certificate.
- At rest (sensitive fields) — API keys, SAML x509 certs, and other secrets stored in Postgres are encrypted with Fernet (AES-128-CBC + HMAC-SHA256). The Fernet key is derived from the gateway's JWT secret via PBKDF2-HMAC-SHA256, 100,000 iterations.
- At rest (everything else) — Postgres data files use the underlying volume's encryption. Backups are encrypted before leaving the host.
- Session tokens — JWTs are signed (HS256) by the gateway. The session cookie is
HttpOnly,Secure,SameSite=Lax, scoped to.diagnosly.co.uk, with a 7-day max-age. The gateway re-validates the JWT and session record on every authenticated request.
Identity
Identity is pluggable. Each tenant can enable any combination of:
- Local password — bcrypt-hashed, 5-attempt lockout with 5-minute cooldown.
- Multi-factor (TOTP) — per-tenant policy:
disabled,optional,admin_only,required. - OpenID Connect — Google, Azure AD / Entra ID, Okta, Auth0, Keycloak, any standards-compliant OIDC IdP. ID-token validation includes
at_hash, signature, issuer, audience, expiry. - SAML 2.0 — SP-initiated SSO for Okta, Entra, OneLogin. Validates assertion signature,
NotBefore/NotOnOrAfter,InResponseTo,AudienceRestriction, and email-domain allow-lists. - SCIM 2.0 — auto-provision users + groups from your IdP. Bearer-token auth with scope enforcement (
users:read,users:write,groups:read,groups:write).
Access control
Three roles — admin, operator, viewer. Every API endpoint declares its required role. Per-feature plan gates sit on top: paid features (group operations, prompt templates, install bundles, etc.) return HTTP 402 with a structured payload describing the required tier.
Audit
Every command, every diagnose, every script run, every settings change is written to a tenant-scoped audit log with the operator's identity, the action, the target, the result, and the timestamp. Retention is 90 days on Pro and 7 years on Enterprise.
The audit log is exportable as JSON (Pro) or streamed to your SIEM via webhook (Enterprise). Splunk, Datadog, and Elastic ingestion adapters are available on request.
Compliance
- GDPR — diagnosly is built on the principle that customer data is yours. We process telemetry on your behalf as a sub-processor; a DPA is available on request to legal@diagnosly.co.uk.
- SOC 2 Type II — in progress. We expect to complete the observation period in 2026. Status updates land here.
- ISO 27001 — not yet pursued. On the roadmap once SOC 2 is complete.
- Sub-processors — Cloudflare (DNS + TLS), Oracle Cloud (compute + Postgres), Vercel (marketing site), Resend (transactional email), Anthropic / OpenAI (LLM, customer-controlled API key). Full list with contracts on request.
What we don't do
- We don't sell or share telemetry with third parties.
- We don't train shared LLMs on your data. The diagnose loop uses your API key against the LLM provider you choose.
- We don't have a back door for support to access your tenant — operators on our side go through the same auth + RBAC + audit pipeline as you do.
- We don't run a beacon. The agent only talks to the gateway you configured.
Reporting a vulnerability
Email security@diagnosly.co.uk with details and steps to reproduce. We aim to triage within 24 hours, ship a fix or mitigation within 7 days for high-severity issues, and credit the reporter (with permission) in our changelog.
For sensitive disclosures, request our PGP key in your initial email and we'll respond out-of-band.
We don't currently run a paid bug bounty, but we do say thank you properly — recognition + swag for valid reports.