Dmytro Galko

Business automation — Python, Rust, TypeScript. Bulgaria, working with clients across the EU, UK and US.

I build the unglamorous tools businesses run every day: data reconciliation, catalogue and deliverability audits, webhook-to-CRM integrations, and the monitoring that tells you an automation stopped working before a customer does.

Everything below is open source and runs on a clean machine with one command. Each repository has its own tests in CI, documents what it deliberately does not do, and where a README claims a number, the script that produced it is in the repository.

Open data — what AI shopping agents actually see

One in ten sites that publish a guide for AI also ban the readers

How many sites publish an llms.txt has been counted several times this year. This is the next question: of the 123 files found among the 1,500 most visited sites, 13 belong to sites whose robots.txt bans, by name, a crawler that would read them — and 13.5% of the files point at least one link at a page that is gone. A map with dead streets is worse than no map.

1,500 sites2026-09-19raw results publishedrepeatable in one command

Half the security.txt files at the top of the web are invalid

A security.txt tells a researcher where to report a hole in your site, and RFC 9116 makes its Expires field mandatory — an expired file is, in the words of the specification, as good as no file. Of the 158 such files among the 500 most visited sites, 92 carry no Expires at all and 6 have expired: 62% are not valid. Nothing warns when that happens.

500 sites2026-09-18raw results publishedrepeatable in one command

A census of 5,356 live Shopify storefronts

Google and Shopify published the Universal Commerce Protocol so an agent can read a shop and buy from it. Nobody had published a count of how many shops actually speak it, so I measured it: 98.9% publish a valid profile, every one of them on the current release, none with a blocker. The only thing they differ on is whether an agent may sign the shopper into their own account — and 47.5% do not allow it, which turns a returning customer into an anonymous visitor.

5,356 shops2026-09-18domain list and raw results publishedrepeatable in one command

Command-line tools — Rust

csvdiff

Diffs two CSV exports by key and reports what actually changed. Two million rows in 2.8 seconds, a per-column breakdown with counted transitions, and number/null normalisation — so a migration report reads as 9 809 real changes instead of 995 000 rows of timestamp noise.

Rust16 testsbenchmark in repoprebuilt binaries

leakscan

Offline check of what leaves with a file before you send it: tracked changes with the deleted text still readable, review comments, hidden worksheets, PDF attachments, GPS coordinates in photos, validated card and IBAN numbers.

Rust41 testsno network at any point

imgdupe

Perceptual-hash duplicate finder. Complete-linkage grouping, so unrelated pictures never chain together through a path of small steps — and it writes a delete script for you to read instead of deleting anything itself.

Rust23 testsbenchmark in repo

linkscan

Crawls a site and reports the links that are genuinely broken, keeping bot protection and slow third parties out of the "broken" column — which is why the report still gets read after the second run.

Rust28 testsexit code for CI

Integration tooling — TypeScript

webhook-rewind

Record the webhooks a provider sends you once, then replay them at your own code as often as you need — re-signed for Meta, GitHub, Shopify or Stripe, so the receiver runs its real verification instead of having it switched off for the debugging session.

TypeScript35 testsno runtime dependencies

well-known-audit

A site publishes a dozen small files at its root — security.txt, robots.txt, llms.txt, assetlinks.json, mta-sts.txt — each checked by a different tool or by nobody. This reads all of them in one run and says which are missing, malformed, or quietly expired. RFC 9116 gives security.txt an Expires date; past it, the file is no longer valid, and almost nobody notices.

TypeScript106 testsno runtime dependenciesrefuses private addresses

ucp-audit

Google and Shopify's Universal Commerce Protocol lets AI agents shop: every business publishes a profile at /.well-known/ucp and agents read it to decide what they can do. The failure mode is silence — offer checkout without declaring a searchable catalogue and no agent ever surfaces your products. This reads the profile the way an agent does.

TypeScript59 testsno runtime dependenciesrefuses private addresses

cra-report

Since 11 September 2026 a manufacturer placing a product on the EU market has 24 hours to notify ENISA of an actively exploited vulnerability in it. Finding vulnerabilities is not the hard part — any scanner hands you a hundred. This says which of them starts the statutory clock, and drafts the Article 14 notification for the ones that do.

TypeScript31 testsOSV + CISA KEVno API key

api-drift

Records the shape of a JSON API and reports when it changes: removed fields, changed types, values that can now be null. Exits non-zero in CI, so a partner's silent rename stops being something you find out about two weeks later.

TypeScript31 testsruns in cron or CI

Business automation — Python

invoice-reconciler

Matches a bank statement against open invoices in five passes — references, part payments, batch transfers, instalments — and reports only what does not add up. Standard library only.

Python24 checksno dependencies

whatsapp-crm-connector

WhatsApp Business Cloud webhooks into a CRM: signature verification, instant acknowledgement plus queue, de-duplication, conversations logged against both the contact and the company, the 24-hour window, token refresh.

PythonFastAPI42 tests

email-deliverability-check

Finds why a domain's mail lands in spam: SPF lookup limit, duplicated records, revoked DKIM keys, DMARC stuck at p=none, missing MTA-STS. DNS only — no access to the mailbox needed, batch mode for client lists.

Python17 checksbatch mode

lead-responder

Answers a web enquiry in under a second: scores it, writes a personal reply, offers real call slots, escalates the hot ones and files the spam. Rules live in YAML, no API keys.

Python19 checksrules in YAML

Try one in thirty seconds

curl -sSL https://github.com/dkautomation23/csvdiff/releases/latest/download/csvdiff-v1.0.0-x86_64-unknown-linux-gnu.tar.gz | tar xz
./csvdiff-v1.0.0-x86_64-unknown-linux-gnu/csvdiff before.csv after.csv --key customer_id --ignore updated_at

Every release carries a binary for Linux, macOS (Apple silicon) and Windows, each built and tested on the platform it targets rather than cross-compiled.

How I work

Work with me

Something breaks and nobody notices

A workflow that stopped running, an API that changed shape, a feed half-empty for a fortnight. Monitoring that names the failure, not a dashboard nobody opens.

Two systems that will not agree

Webhooks into a CRM, a bank statement against invoices, a catalogue against a supplier feed. Signature verification, de-duplication, retries and the 3am cases.

Data that has to be right

Migration checks, reconciliation, audits of a catalogue, a domain's mail or a site's crawlability — with the numbers reproducible rather than asserted.

Rescue work

An automation someone else built and left. I will read it and tell you honestly whether it is worth repairing or worth replacing.

Tell me what breaks today and what it costs you: [email protected]. You get back an approach and a number, or an honest “this is not my job” and who to ask instead.