Is this you? As a journalist, you can create a free Muck Rack account to customize your profile, list your contact preferences, and upload a portfolio of your best work.
Claim your profile
Articles by Vadym Arnaut
My memory auditor said half my agent's facts were dead. Three were.
My coding agent keeps memory in flat markdown files. One fact per file, a frontmatter header, an index that loads at the start of every session. Ninety files, two weeks old, twenty five sessions. Every one of those files makes claims about my machine. This path holds that project. This command exists. This credential lives under that id. Claims decay, and nothing in the format tells you when one goes bad. So I wrote a script to walk the memory and check each claim against the machine as it is right now.
You can't transition a CSS variable. @property says otherwise.
You've probably written something like this: .button { --hue: 220; background: hsl(var(--hue) 70% 50%); transition: --hue 0.3s ease; } .button:hover { --hue: 340; } You expected a smooth color shift. You got a snap cut. That's not a browser bug. It's the result of one architectural decision baked into custom properties from the start: CSS variables are text substitution, and the browser has no idea what type they hold.
I sent HTTP QUERY through the real internet. The smarter the layer, the harder it broke.
TL;DR. HTTP got a new method in June: QUERY (RFC 10008), a GET that carries a body. Everyone wrote explainers and threat models. Nobody actually fired it at real infrastructure. So I did, for a few nights: ten production edges from CloudFront to raw nginx, three browser engines, real client libraries. One law fell out of all of it. The more a layer "understands" HTTP methods, the more likely it is to break the newest one.
HTTP finally shipped QUERY. I fired it at production and the edge called it a bot.
TL;DR. QUERY (RFC 10008) is a real HTTP method now, a GET that carries a body. I deployed echo endpoints on Vercel (Python and Node), Supabase Edge, and local FastAPI, then fired GET, POST and QUERY at each. Every runtime handled QUERY fine. Then Vercel's default bot mitigation started 403-challenging my QUERY traffic specifically. Same client, same body: 20 GETs clean, 20 POSTs clean, QUERY tripped the challenge on request #4. Reproduced from a second client. The functions are ready for QUERY.
Three dumb ways our prod got slow (and not one was a slow algorithm)
TL;DR. Three prod slowdowns in one week. A 30-second timeout that was secretly TWO MINUTES. A math library we shipped twice to students who don't even have math. And a dashboard that built tens of thousands of objects just to draw a few hundred rows. Not one of them was a slow algorithm. The cause was never where I looked first. We run Equip (open-source LMS: FastAPI + React + Supabase Postgres). I spent a week chasing latency, and the slow-query log lied to me every single time.
I had real backend auth. The browser just walked around it.
Here's the thing nobody warns you about when you put Supabase behind a "real" backend. My stack is React + FastAPI + Supabase Postgres. Every write goes through FastAPI. Every endpoint checks the user, the role, the ownership. I audited that backend HARD — rate limits, JWT validation, RLS, the whole thing. I was proud of it. And none of it mattered for the two holes I actually shipped. Because the Supabase anon key lives in the browser. It HAS to — that's how supabase-js talks to your project.
I ran 4 AI agents on yesterday's PRs. Two real security bugs surfaced.
After every coding session I run a 4-agent parallel audit on the diff I just shipped. A recent session of mine was seven PRs landing a new daily-challenge feature on my open-source LMS. Two of the audit findings were real security or integrity bugs that my human review missed. This is the playbook. The four agents I split the audit into four narrow roles. Narrow because a generalist agent tells you everything is fine; a specialist with a clear mandate tells you what is broken. Cleanup agent.
There is no source language: a manifesto for symmetric multilingual content
Three weeks ago I shipped a bilingual LMS. The architecture modeled one language as source and the rest as overlay: a source_locale column on every translatable entity, an MT pipeline reading source rows and writing overlay rows. It worked. Students used it. Certificates issued. Three published courses, fourteen real users, end-to-end. Last week it broke in a way that did not fit a bug fix. A teacher whose interface was set to English wrote a course entirely in Russian.
The auth_rls_initplan linter has a blind spot: SECURITY DEFINER bodies
If you've ever migrated a Supabase project to the wrapped (SELECT auth.uid()) pattern, you know the linter that flags the bare call. auth_rls_initplan reads every RLS policy expression and warns whenever auth.uid() is used directly instead of inside a scalar subselect. The wrap turns the call from a per-row evaluation into a single InitPlan. On a million-row table that is the difference between a 30ms read and a 30-second read. The linter is good. It is also incomplete.
Equip: an open-source LMS for Bible schools — bilingual, scripture-aware, 4 weeks of real users
TL;DR. Equip is a free, open-source LMS built for Bible schools and small ministries. MIT-licensed. Bilingual Russian↔English out of the box — the same course renders in either language depending on who's reading. Self-hostable end-to-end on free tiers. 4 weeks in production: 14 real users, 3 published courses, 3 issued certificates. This post is what's in it, what's wired in, and how it's built.
76 RLS policies rewritten in one migration: the auth.uid() init-plan trap in Supabase
TL;DR. If your Supabase RLS policies call auth.uid() directly inside USING(...) or WITH CHECK(...), Postgres re-evaluates the function once per row. Wrap it as (SELECT auth.uid()) and the planner hoists the call to a single init plan that runs once per query. Same logical query, different plan, different cost at scale. We had 76 policies doing this wrong on Equip. Supabase's own auth_rls_initplan advisor lint found every one of them.
4 footguns integrating YouVersion's new platform API — and a clean Verse of the Day
TL;DR. YouVersion opened its API in April 2026. We wired it into our open-source Bible LMS as a Verse of the Day card on the dashboard. Four small things in their API surface cost us time. Writing them up so you don't repeat them. Equip is an open-source LMS for Bible schools (FastAPI + React + Supabase, MIT).
Two days lost to PGRST116: when Supabase RLS hides a successful write
TL;DR. Our Supabase upsert wrote the row. The chained .select().single() returned PGRST116. The wrapper read that as a failed write. The frontend retried. The retry was wrong. Two days to find why. We've been running an LMS on Supabase for the past several months — auth, RLS on every table, FastAPI talking to Postgres. The bug below cost us two days last quarter, and the fix changed how we read PGRST116 in our wrapper. The setting We have a quiz_attempts table.
The 3 i18n mistakes every open-source LMS makes
TL;DR. Every open-source LMS treats internationalization as one problem. It's three. UI strings, user-generated content, and canonical artifacts each need a different mechanism. Most codebases collapse them into one — that's the bug. We've been building an open-source Bible school LMS for about 5 months. It runs in Russian and English (Ukrainian coming), with auto-translated user content and canonical-text preservation for scripture quotes.
From 0 to 20 Chapters: My Story‑Driven Rust Book for Kids Now Has a Bilingual Interactive Demo
Great question, and thank you for the thoughtful feedback! You’re right – I’m following the classic pattern: write fast in the stronger language (Persian), then translate later. Right now Persian and English are completely separate source files (different Markdown files, different folders). I didn’t implement a locale‑tagged canonical format from day one. That’s partly because the Persian version was written and polished before I started the English translation.
Two weeks of building Bible School LMS in public: first contributor, bilingual content, real production bug
Two weeks ago I posted "Open Source Bible School LMS, we need your help" and asked for contributors. Today the first community PR landed. Plus a stack of changes shipped that I think are worth sharing, both because some of them are genuinely interesting, and because it gives a concrete picture of where help would land.
Show More
loading
Actions
Is this you?
As a journalist, you can create a free Muck Rack account to customize your profile, list your contact preferences, and upload a portfolio of your best work.Get in touch with Vadym
Contact Vadym, search articles and posts on X, monitor coverage, and track replies from one place.
Learn more about Muck Rack