Software engineer and security engineer. Eight years building backend systems and SaaS products; five in application security. Based in India, working remotely with clients in Europe. Available for contract work: backend and platform engineering, and application security reviews.
I build the parts of a system that are expensive to get wrong: tenant isolation, authentication, money and time-zone arithmetic, compliance with a published standard, rate limiting under concurrency. Everything below is working software with tests, CI and decision records, and four of the repositories run together as one deployed stack.
Start here: grainops
— the analytics stack as docker compose up or helm install, each
proven end to end in CI.
| grainops | Deployment two ways — Compose for one host, a Helm chart for Kubernetes — from pinned, published images: rootless containers, migrations before readiness, default-deny NetworkPolicy, Prometheus/Grafana, backups, runbook. Both paths proven end to end in CI (the Helm path on kind); CI also gates the chart on kubeshield, which found two real gaps (no CPU limits, a writable Postgres root filesystem) — and a real bug in kubeshield itself — before a user could. |
| eventgrain | Self-hosted product analytics. Month-partitioned events in plain SQL; count, unique, funnel and retention in the project's time zone; rollups used only when provably identical to raw; GDPR erasure; retention by partition drop. TypeScript, BSL 1.1. |
| grainview | Its dashboard. Hand-written SVG charts that screen readers can read: a named image with a generated description, and the numbers in a table. React 19, no chart library, BSL 1.1. |
| gatelimit | Rate-limiting reverse proxy. Token bucket and sliding window, in-process or Redis with Lua scripts; 100 concurrent requests across two instances admit exactly 50, under the race detector. Go, MIT. |
| tablewarden | Data-quality checks as a CI gate: TOML rules compiled to one SQL statement each, over Postgres, SQLite or CSV; JUnit output; exit codes that separate "found problems" from "could not look". Python 3.12, MIT. |
| openslot | Appointment booking for a European practice. DST-correct slot engine pinned by tests on both transitions; WAI-ARIA calendar with a keyboard suite; English, German, French via Intl; double booking prevented by a unique index and proven under concurrent requests. Its accessibility statement lists what was not verified. React 19, Hono, BSL 1.1. |
| bailey | Multi-tenant SaaS for continuous web security monitoring. Postgres row-level security as the isolation backstop, mutation-tested; Argon2id and opaque sessions; RBAC with invariant tests; GDPR export, erasure, retention; every form works without JavaScript. Next.js 15, BSL 1.1. |
| camtmatch | Bank-statement reconciliation for accounts receivable. ISO 20022 camt.053 in (all versions in circulation, DTDs refused); payments matched to open invoices by ISO 11649 reference, invoice numbers in the remittance text, then payer IBAN — and every match explains itself in sentences. Amount alone never matches; a statement that doesn't balance applies nothing. Java 21, Spring Boot 4, Postgres, Testcontainers, BSL 1.1. | | dsarclock | GDPR data subject request register. Deadlines counted the way EU law counts a month (Regulation 1182/71: short months, weekends, the controller's national holidays with Easter computed); Art. 12 rules enforced — an extension must come within the first month, a refusal is late after the original month even when extended; an audit trail the database itself refuses to edit. .NET 10, EF Core, Postgres, BSL 1.1. | | idbroker | A minimal, correct OpenID Connect provider. Authorization Code + mandatory PKCE only — no implicit flow, no "plain" PKCE, nothing weaker exists in the code. Opaque, hashed, revocable tokens; refresh-token rotation whose reuse detection revokes the whole token family, proven end to end against real Postgres, not just asserted. TypeScript, BSL 1.1. |
| ubl-billing | EN 16931 / Peppol BIS Billing 3.0 e-invoicing engine. Exact decimal arithmetic, 162 validation rules cited by their specification identifiers, credit notes, serialise → parse round-trip proven by test. Checked in CI against the standard's own Schematron: all 1,695 valid corpus documents accepted, 94% of 4,177 invalid ones rejected, the rest violating rules it says it doesn't implement. TypeScript, MIT. |
| sepapay | SEPA Credit Transfer files (ISO 20022 pain.001.001.09) from a payment run, validated against the official ISO schema before they're written. Catches mistyped IBANs, ambiguous amounts, characters a bank would mangle and TARGET2 closing days, all rows in one pass. The message ID is derived from content, so an accidental re-upload bounces at the bank instead of paying everyone twice. A separate verify re-reads the finished file for whoever approves it. Pays the invoices ubl-billing issues; camtmatch reconciles them. Python, MIT. |
| hookrelay | Outbound webhook delivery. Standard Webhooks signing tested against the spec's vector, quotable retry schedule, dead-lettering and replay, idempotent publish and delivery, circuit breaker, OpenAPI from the route schemas. CI gates that spec on apilint, which found a real undocumented response before this line existed — fixed — and two heuristic matches confirmed (not assumed) safe and waived by name. A non-root production image whose CI runs migrations, the API and the worker on a read-only filesystem against real Postgres and Redis. Fastify, BullMQ, BSL 1.1. |
| terraform-aws-hookrelay | Terraform module running hookrelay on ECS Fargate with RDS and ElastiCache behind an HTTPS load balancer. No credential ever enters Terraform state (ephemeral values, write-only arguments); Redis set to noeviction because BullMQ loses queued jobs otherwise; default-deny security groups. 12 terraform test runs, each shown to fail on the regression it guards, and a tfwarden gate over a real plan that also proves the scanner can read the module. Stated plainly: never applied to a real account. MIT. |
| parapet-scan | Web security posture audit: nineteen checks over headers, TLS, cookies, CORS and disclosure from ~16 requests per scan; terminal, JSON, SARIF and HTML output; ships a deliberately misconfigured lab so the integration tests hit real HTTP. TypeScript, MIT. |
| tfwarden | Terraform plan scanner: ten AWS checks — public buckets, security groups open to the internet, unencrypted storage, wildcard IAM — read from terraform show -json rather than re-implemented HCL evaluation. An attribute Terraform can't resolve yet is reported indeterminate, never guessed pass or fail. Its first real plan (terraform-aws-hookrelay) exposed three bugs, all fixed in v0.2.0 with fixtures from real terraform show -json output: resources inside modules or with count never matched their configuration (9 of 12 findings false on the fixture), split security-group rules went unread, and ::/0 wasn't treated as the whole internet. Go, MIT. |
| credsweep | Secrets scanner for a git repository's full commit history, not just the working tree: finds a credential committed and later removed, at the exact commit that introduced it. Redacted output and a one-way fingerprint for allowlisting — the raw value never leaves the scan loop as itself. Go, MIT. |
| kubeshield | Kubernetes manifest security scanner: ten checks — privileged containers, host namespace sharing, hostPath volumes, wildcard RBAC, unpinned images, missing resource limits — over plain YAML or helm template output, no live cluster needed. Go, MIT. |
| vulnlock | Known-vulnerability scanner for npm, Go and Python lockfiles, against the real OSV.dev database. Real CVSS v3.1 base-score calculation implemented from the spec, not a dependency; severity prefers a curated rating and never fabricates one. Python, MIT. |
| apilint | Static OpenAPI 3.x security linter: ten OWASP API Security Top 10 checks — missing authorization on a per-resource endpoint (BOLA/IDOR-shaped), mass assignment, sensitive fields in a response, weak auth schemes — with no live server needed. Distinguishes "no security declared" from an endpoint that says so on purpose. Go, MIT. |
| outboxer | Transactional outbox for Postgres. publish() writes to the caller's own transaction, so an event and the business write it describes live or die together by construction; a relay delivers per aggregate in order via a non-blocking advisory lock, proven under two concurrent workers racing the same aggregate. TypeScript, MIT. |
| apkwarden | Android APK manifest scanner: twelve checks (debuggable builds, exported services and receivers with no permission, backups with no rules, cleartext traffic) from a single binary with no Android SDK or Java. It decodes Android's binary XML itself, fuzzed with millions of hostile inputs and checked against what F-Droid's indexer published for three real apps. A value it can't read is reported indeterminate, never guessed; accepted risks are waivers that expire. Go, MIT. |
| bomdelta | Diffs two CycloneDX SBOMs for release review: downgrades, older duplicate copies, licences that became more restrictive. On real npm output it catches an express downgrade that has no advisory of its own but brings back three fixed CVEs in transitive packages, and TinyMCE's MIT to GPL relicensing inside a routine major bump. Its first CI run found a false positive in credsweep, fixed there. Rust, MIT. |
| dmarcwatch | Reads DMARC aggregate reports and says whether a domain can move to p=reject: which sending sources fail, whether they authenticate as someone else or not at all, and which failures are just forwarding. Refuses DOCTYPEs and decompression bombs. Rust, MIT. |
- Decisions that weren't obvious get an ADR recording what was rejected and what the choice costs.
- Tests state their expected values from hand-worked arithmetic, not from the code's output.
- READMEs say what was verified and what was not; a rule that can't fail isn't counted as implemented.
- Commit history is incremental and explains reasoning; there is no "initial commit" containing the whole project.
- Licensing is deliberate per project: tools are MIT, products are source-available.
TypeScript (strict), Node, React, Next.js · Java 21, Spring Boot · C#, .NET 10, EF Core · Go · Rust · Python 3.12 (typed,
ruff/mypy strict) · PostgreSQL (partitioning, window functions, plain SQL
as readily as an ORM), Redis · Docker, Kubernetes/Helm, GitHub Actions,
Prometheus/Grafana
· WCAG 2.2 AA and Intl-based i18n · Linux, TLS, HTTP, the OWASP corpus.