How we run the service
Security Overview
DKT Digital, St Peter Port, Guernsey GY1 · [email protected]
DRAFT — pending legal review, not binding. This document has not been reviewed by a solicitor. It is published so you can read our terms before you talk to us, and so we can be held to what it says — but it is a working draft, not a vetted contract, and nothing here is legal advice. A binding version will be issued for signature only once it has been through legal review. If you are relying on any part of it, ask us and we will tell you where it stands.
Where your data physically lives, what is encrypted and what is not, every outside company that can process it, and how backups and access control work. Measured against the running system rather than described from intention.
*Last updated: 2026-08-01 (hosting, encryption and backup sections re-measured against the live system after the VPS migration). Owner: Daniel Thomas, DKT Digital (Guernsey).*
1. Where your data is hosted
Measured 2026-08-01, not assumed. The automation engine and the database run on a dedicated virtual server operated by Hetzner Online GmbH in Falkenstein, Saxony, Germany (EU). The public website, client portal, and edge security are served through Cloudflare. Nothing client-facing runs on the owner's own hardware any more; the earlier "Guernsey hardware" statement in this document described the pre-migration setup and was replaced once the move was verified.
So, in one sentence: **your data lives in Germany (EU), reached only through Cloudflare, and DKT Digital — the business you contract with — is established in Guernsey.**
What that means for the law that applies:
- DKT Digital is established in Guernsey, whose data-protection law (the Data Protection (Bailiwick of Guernsey) Law, 2017) is GDPR-aligned, with its own regulator, the ODPA.
- The data is processed in Germany, inside the EU/EEA. Guernsey is the subject of a European Commission adequacy decision, and the EU/EEA is not a "third country" for most purposes here — but the transfer analysis for this routing is a question for the solicitor to confirm, not one this document settles. What this document is responsible for is stating the route accurately.
- Transfers outside the UK/EEA — the model providers and the US-based tools in §3 — are the ones that need an explicit transfer mechanism; see §3 and DPA §7B.
2. Encryption
In transit: all traffic is over TLS/HTTPS. The website, client portal, form submissions, and every API call to a third party use encrypted connections. Public endpoints sit behind Cloudflare with modern TLS.
At rest:
- Verified 2026-08-01 on the live server: the database volume is a plain
ext4filesystem with no block-level encryption (/dev/mapperholds onlycontrol, i.e. no LUKS device). So the operational client database is not encrypted at rest at the disk level — this is a known, stated gap, not a claim we make and then qualify. Access to it is controlled instead (the database is not internet-facing, administrative access is not publicly exposed, and the host is single-tenant). Closing it properly means an encrypted volume on the host; until that exists, this document says so. - Per-client accounting/banking OAuth tokens are additionally encrypted at the row level (
pgp_sym_encrypt) with a key held only in the server environment, never in the database or in version control. Verified 2026-08-01 by reading the stored bytes directly: they begin with the OpenPGP packet header, i.e. they are genuinely ciphertext. So even a database dump does not expose a client's Xero/bank tokens in readable form. - Backups: the off-site copy is encrypted, the on-box copy is not. The nightly bundle written to the server itself is a
tar.gz, root-readable only, not separately encrypted. The copy replicated off-site to Cloudflare R2 every night is encrypted withagebefore it leaves the machine (.tar.gz.age), under a key that is not stored in the bucket. Per-client tokens stay pgp-encrypted inside both. See §5. - Application secrets (API keys, webhook secrets, the portal shared secret) live only in a permissions-restricted secrets file on the server and are injected as environment variables — never committed to the code repository. This is enforced by an automated secret-scan on every structure check and by the 10-minute watchdog.
3. Sub-processors — who else touches client data
We use third-party services to deliver the automations. Below is the **full list of sub-processors that can process client personal data**, enumerated from the live automations (not guessed). The client remains the data controller for their own customers' data; DKT Digital and these providers are processors/sub-processors.
| Sub-processor | What it does with client data | Primary region |
|---|---|---|
| Hetzner Online GmbH | Hosts the server the automation engine and the client database run on — every piece of client data at rest sits on this machine | Germany (Falkenstein) |
| Cloudflare | Website/portal hosting, CDN, tunnel, access control (Zero Trust), bot protection (Turnstile), encrypted off-site backup storage (R2) — all client-facing traffic passes through it | Global edge |
| Resend | Sends transactional client emails (welcome, reminders, reports, invoice chases) | US |
| Brevo | Email delivery/transactional (secondary email path) | EU (France) |
| Google (Workspace / Cloud, via service account) | Calendar events for bookings (client name/email), optional Sheets sync, Search Console | US / EU |
| GoCardless | Direct Debit mandates and recurring retainer collection (client billing details) | UK |
| Stripe | Card payments / one-off charges | US / Ireland (EU) |
| TrueLayer | Open-banking bank-feed verification for accounting audits (client bank data) | UK |
| Xero | The client's own accounting data, accessed under the client's per-client authorisation | NZ / global |
| Twilio | SMS reminders/notifications (client phone numbers). Not live — listed because it is wired and would become a sub-processor the moment SMS is switched on for a client, not because it is processing anything today. | US |
| Calendly | Meeting booking (client/prospect name, email) | US |
| Crisp | Website live-chat (visitor/lead messages, email) | EU (France) |
| Hunter.io | Email-address verification for cold/nurture outreach only (never transactional client sends) | EU / US |
| Apollo | Prospect/lead sourcing for outreach (marketing contacts, not existing-client data) | US |
| Telegram | Operational alerts to the owner — client identifiers (names/emails) can appear inside alert messages | Global (Telegram FZ-LLC) |
| AI inference — Groq, Cerebras, Google Gemini, OpenRouter | LLM processing where a feature needs it (e.g. drafting a reply, summarising). See §4 on what is and isn't sent. | US |
Not sub-processors of client personal data (listed for completeness — these handle market data, the agency's own content/research, or internal ops, and do not receive client customers' personal data): Alpaca, Nasdaq, Yahoo Finance, Finnhub, CNN, SEC/EDGAR, arXiv, Hacker News, Reddit, TechCrunch, VentureBeat, Wikipedia (market/trading & research sources); Beehiiv (the agency's own newsletter, with its own subscribers); Buffer, Dev.to, LinkedIn (the agency's own content publishing); Tavily, Exa, Firecrawl (web research); Dub.co (link shortening); GitHub (private code/workflow backup — secrets are held in the environment, not in the backed-up files); Notion, Slack (internal operations).
The solicitor should decide which of these belong in the contractual sub-processor schedule of the DPA. The table above is the honest engineering enumeration to work from.
4. AI / model use — your data is never used to train models
- Client data is never used to train, fine-tune, or improve any AI model. The AI providers we call (Groq, Cerebras, Google Gemini, OpenRouter) are used through their APIs, where inputs are processed to return a result and are not used for training under their API terms. We rely on that and state it plainly.
- Data minimisation: we send the least data needed for a task. Where a feature can work on non-personal content, we do not send names, emails, phone numbers, or financial detail.
- No Chinese-jurisdiction AI for personal or sensitive data: as a hard internal rule, client names, emails, phone numbers, financial account details, health data, and legal documents are never sent to models subject to China's National Intelligence Law (e.g. Z.ai/GLM, Moonshot/Kimi). Those are used, if at all, only for non-personal code/content tasks. Personal-data AI processing stays on Western (GDPR-aligned) providers.
5. Backups and recovery
*Re-measured 2026-08-01 against the live backup log, because the previous version of this section described the pre-migration Mac setup and reported the off-site leg as broken. It is not broken any more, and saying so is as much a correction as reporting a failure would be.*
- On-box: a nightly bundle at 02:30 containing the database dump, the automation engine's own database and the restore instructions, written to the server (
tar.gz, root-readable only, not separately encrypted). Every step is integrity-checked — an empty dump, an unreadable dump index or a failed SQLite integrity check aborts the run rather than saving a corrupt file, and any non-zero exit sends the owner a Telegram alert. There is no silent backup failure. - Off-site (Cloudflare R2) — working, and encrypted. The same bundle is encrypted with
agebefore it leaves the machine and replicated nightly to Cloudflare R2 (.tar.gz.age, last 14 retained). Verified 2026-08-01:offsite ok: R2:dkt-agency-backups/…tar.gz.ageon every night through to the most recent run. The decryption key is held outside the bucket, so possession of the bucket is not possession of the data. - Off-box (USB): retired. It was a copy to an external drive attached to the owner's Mac, which was only current when the drive happened to be mounted; the encrypted R2 leg replaces it with something that runs whether anyone is present or not.
- Restore is tested — a nightly dump has been restored into a throwaway database and its table and client-record counts verified against the live source (see our internal incident runbook §7). An untested backup is not a backup.
- Recovery objectives (proposal — confirm): recovery point objective (max data loss) ~24 hours (nightly backup) tightening as backup frequency increases; recovery time objective measured in the fire-drill and recorded in our internal incident runbook.
6. Data retention (per table)
Current reality: the operational database keeps client records for the life of the engagement; there is no automatic deletion of client business tables yet. The automation engine's own execution logs are pruned automatically (kept 240 hours / max 5,000 runs).
Tables that hold client personal data today (with the honest current retention):
| Table | Holds | Current retention | Proposed retention (for solicitor) |
|---|---|---|---|
clients, saas_clients | Client profile, onboarding answers, data-source declarations | Life of engagement | Duration + 6 years (financial records) or as agreed |
client_integrations | Encrypted Xero/bank OAuth tokens | Until disconnected | Deleted on offboarding / disconnect |
leads, outbound_queue | Prospect/lead contacts, outreach queue | Indefinite | 24 months from last contact, then purge |
invoices, invoice_chases, payment_events | Billing/payment records | Indefinite | 6 years (tax) |
meetings | Bookings (name/email/time) | Indefinite | 24 months |
client_reports, client_roi, savings_log | Outcome/reporting data | Indefinite | Duration + 12 months |
client_tasks | Setup/data-migration tasks | Indefinite | Duration + 12 months |
feedback | Client feedback | Indefinite | Duration + 12 months |
email_delivery_log | Delivery events (recipient email, status) | Indefinite | 12 months |
sms_log | SMS attempts (phone, status) | Indefinite | 12 months |
Open item: implement automatic retention/purge jobs to match whatever the solicitor sets. Right now retention is "kept unless manually deleted (or exported+deleted at offboarding)" — stated honestly rather than claimed. **The "Proposed retention" column above is a proposal only. Nothing in this table is enforced by a job today**, and no document in this set should be read as promising automatic deletion, because none happens.
[SOLICITOR] — 6 YEARS OR 7? THE DOCUMENTS DISAGREE, AND THIS IS NOT SETTLED HERE. The published Privacy Policy says client data is kept 7 years from the end of the contract, citing Guernsey financial record-keeping. The "Proposed retention" column above says **6 years (tax)** for billing and payment records. Those are two different numbers for substantially the same records, and a client reading both would get two answers. **No figure has been invented or changed here to make them agree** — picking a statutory retention period is a legal judgement, not a consistency edit, and getting it wrong in either direction is a real problem (too short breaches a record-keeping duty; too long breaches storage limitation). The solicitor should settle one figure for a Guernsey sole trader serving UK clients, and then it goes in all three places at once — here, the Privacy Policy, and DPA §7.2. Tracked as
LEGAL-RETENTION-6-VS-7-YEARS.
7. Access control
- Production access is currently the owner only. There is no second account with production access, and no named continuity contact has been appointed yet — so there is also nobody whose access needs revoking. Arranging that contact, and the sealed-access instructions that go with it, is an open item tracked in Service Level Agreement §6; this section will name the arrangement once it exists rather than describe one that does not.
- The client portal is fail-closed: a client can only ever retrieve their own data, keyed on the identity verified by Cloudflare Access (not on any value the user supplies). A request without a verified identity returns nothing.
- Internal proxy endpoints require a shared secret held only in the server environment (moved out of the workflow code 2026-07-20), and reject anything without it.
- Inbound webhooks that carry money/events (payments, email delivery) verify a signature (HMAC / svix) before acting.
8. Deletion / your rights
On request, and always on offboarding, a client's data is exported in standard formats and then deleted from the operational database and from future backups (older encrypted backups age out under the backup retention window). See Offboarding for the process and the rehearsed handover.
*Related: Service Level Agreement · Offboarding · our how-it-works notes · our internal incident runbook. The binding privacy policy and DPA are separate solicitor-drafted documents; this overview must be reconciled with them.*