<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Self-Hosted on onelegdave.dev</title><link>https://www.onelegdave.dev/tags/self-hosted/</link><description>Recent posts in Self-Hosted on onelegdave.dev</description><language>en-us</language><generator>Hugo</generator><ttl>60</ttl><image><url>https://www.onelegdave.dev/images/avatar.jpg</url><title>Self-Hosted on onelegdave.dev</title><link>https://www.onelegdave.dev/</link></image><lastBuildDate>Sat, 05 Sep 2026 09:00:00 -0700</lastBuildDate><atom:link href="https://www.onelegdave.dev/tags/self-hosted/index.xml" rel="self" type="application/rss+xml"/><item><title>Tested. Deployed. Wrong Anyway.</title><link>https://www.onelegdave.dev/posts/tested-deployed-wrong/</link><guid isPermaLink="true">https://www.onelegdave.dev/posts/tested-deployed-wrong/</guid><pubDate>Sat, 05 Sep 2026 09:00:00 -0700</pubDate><dc:creator>OneLegDave</dc:creator><category>Self-hosted</category><description>147 tests, a proven arithmetic fix, a clean deployment. Then I actually used the thing for ten minutes and found four bugs the tests were structurally incapable of seeing.</description><media:content url="https://www.onelegdave.dev/images/posts/tested-deployed-wrong.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><media:thumbnail url="https://www.onelegdave.dev/images/posts/tested-deployed-wrong.jpg" width="1200" height="630"/><content:encoded>&lt;p&gt;&lt;img src="https://www.onelegdave.dev/images/posts/tested-deployed-wrong.jpg" alt="Tested. Deployed. Wrong Anyway." width="1200" height="630"&gt;&lt;/p&gt;&lt;p&gt;Same medication tracker as last time, different day, different problem. This one isn&amp;rsquo;t about the app going dark. It&amp;rsquo;s about everything technically working and still being wrong.&lt;/p&gt;&#10;&lt;p&gt;147 tests. Nearly 2,000 lines of Kotlin. Everything green. I deployed it, used it for real for about ten minutes, and found four separate ways it was lying to me, none of which a single one of those 147 tests could ever have caught, because they weren&amp;rsquo;t bugs in what the code did. They were bugs in what the running app was telling a human standing in front of it.&lt;/p&gt;&#10;&lt;h2 id="arithmetic-first-because-the-rest-doesnt-matter-if-this-is-wrong"&gt;Arithmetic first, because the rest doesn&amp;rsquo;t matter if this is wrong&lt;/h2&gt;&#10;&lt;p&gt;Before any database, any HTTP, anything, I wrote the days-remaining math as plain Kotlin with zero dependencies, because if this number&amp;rsquo;s wrong, the app isn&amp;rsquo;t useless, it&amp;rsquo;s actively dangerous. Confidently wrong about whether you&amp;rsquo;re about to run out of insulin is worse than not having an app at all.&lt;/p&gt;&#10;&lt;p&gt;The spec had it as two separate divisions to average weekly and as-needed doses onto one timeline. I collapsed both into one exact fraction, floored once, instead of doing the math in floating point:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;days_remaining = floor( units * 210 / (weekly * 30 + prn_total * 7) )&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Not being clever for the sake of it. Binary floating point flat-out gets this wrong on exact boundaries: 4.5 units on hand, 4.5 used weekly, the honest answer is 7 days, and a &lt;code&gt;Double&lt;/code&gt; hands you 6. I swept roughly 56,000 schedule combinations against exact rational math to check. About 0.2% disagreed, always off by exactly one, always sitting right on a boundary. Rare enough to sail through code review unnoticed. Common enough to flip a real alert on a real person.&lt;/p&gt;&#10;&lt;p&gt;There&amp;rsquo;s now a test that asserts the naive floating-point version returns the wrong number on purpose, so future-me, or anyone else who thinks they&amp;rsquo;re &amp;ldquo;simplifying&amp;rdquo; this, finds out immediately why it&amp;rsquo;s written the ugly way.&lt;/p&gt;&#10;&lt;h2 id="breaking-my-own-tests-on-purpose"&gt;Breaking my own tests on purpose&lt;/h2&gt;&#10;&lt;p&gt;Here&amp;rsquo;s the practice that earned its keep hardest, and it&amp;rsquo;s embarrassingly simple: for anything a test claims to guard, break the actual mechanism on purpose and confirm the test goes red. Then put it back.&lt;/p&gt;&#10;&lt;p&gt;Sounds like paranoid busywork. It caught four tests that were passing for entirely the wrong reason, quietly guarding nothing, forever, until I forced the question.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Moved the error-catch inside the transaction.&lt;/strong&gt; Ten repeat taps took stock down to 50 instead of 59. SQLite aborts the one bad statement, not the whole transaction, so a failed deduction silently committed without its matching dose row. Three tests caught it, that&amp;rsquo;s a test doing its job.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Deleted the HTTP method guard in the service worker.&lt;/strong&gt; Every test still passed. Turns out every write case in the test suite happened to route through &lt;code&gt;/api&lt;/code&gt; and got caught by a completely different check, so that guard was dead weight nobody would&amp;rsquo;ve noticed missing until it mattered.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Deleted the offline navigation fallback.&lt;/strong&gt; Still green. The tests requested &lt;code&gt;/&lt;/code&gt;, which is precached and always resolves fine, but Android tacks a query string onto &lt;code&gt;start_url&lt;/code&gt; on a real home-screen launch, and cache matching compares the full URL including that string. A real phone launch would&amp;rsquo;ve missed the cache entirely and gotten nothing, while every single test sailed past it.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Disabled the SQLite foreign-key pragma.&lt;/strong&gt; Exactly one test failed, which is the correct outcome, and the one I actually wanted to see. Foreign keys are off by default in SQLite, enabled per-connection, and any connection that forgets the pragma just quietly accepts orphaned rows forever.&lt;/p&gt;&#10;&lt;p&gt;Two of those four had the actual mechanism removed and the suite stayed green. A green test suite proves the tests ran. It proves nothing about the code until you&amp;rsquo;ve personally watched each one fail for the reason it claims to exist.&lt;/p&gt;&#10;&lt;h2 id="things-only-the-real-server-was-rude-enough-to-tell-me"&gt;Things only the real server was rude enough to tell me&lt;/h2&gt;&#10;&lt;p&gt;Ran clean locally. Deployed to the actual box and immediately hit three problems no amount of local testing was ever going to surface.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;A tmpfs mounted &lt;code&gt;noexec&lt;/code&gt;.&lt;/strong&gt; First run died instantly: &lt;code&gt;UnsatisfiedLinkError: failed to map segment from shared object&lt;/code&gt;. The SQLite driver extracts its native library to the JVM temp directory and loads it from there. Docker mounts &lt;code&gt;--tmpfs noexec&lt;/code&gt; by default, so the load just failed on the very first database open. The error message says nothing whatsoever about mount flags. &lt;code&gt;/tmp&lt;/code&gt; is now mounted exec, with a comment explaining exactly why, because the &amp;ldquo;obvious&amp;rdquo; future hardening move is a crash loop.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;A port that was already spoken for.&lt;/strong&gt; Installing to a phone needs a service worker, which needs a secure context: HTTPS or bust. Plain HTTP over the tailnet serves the app fine and just silently never offers to install, no warning. So: real cert via Tailscale Serve, which defaults to 443, except 443 on that box was already doing something completely unrelated. Publishing there would&amp;rsquo;ve shadowed an existing service&amp;rsquo;s cert and taken it down as a side effect of deploying a medication app, which is the kind of blast radius nobody signs up for on purpose. Moved to a different port. Costs nothing, a secure context cares about scheme, not port number.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Compose stacks that fail without telling anyone.&lt;/strong&gt; On that server, containers aren&amp;rsquo;t wrapped in systemd units, they lean entirely on Docker&amp;rsquo;s own restart policy. Which means a crash-looping container restarts forever, silently, and nothing ever reports it. I&amp;rsquo;d written that exact fact down months earlier and completely forgotten I had. A dead media server is obvious the second you try to watch something. A dead medication tracker is invisible until the specific morning you go to check it and it isn&amp;rsquo;t there.&lt;/p&gt;&#10;&lt;p&gt;Fix ended up being the nightly low-stock alert script, since that one &lt;em&gt;does&lt;/em&gt; run as a proper systemd timer with real failure notification wired up, but only if it&amp;rsquo;s built to actually notice a dead server instead of politely assuming an empty response means everything&amp;rsquo;s fine:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ALERTS=&amp;#34;$(curl -fsS --max-time 20 &amp;#34;$API/api/alerts&amp;#34;)&amp;#34;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That &lt;code&gt;-f&lt;/code&gt; flag is doing the entire job. Without it, a dead container hands back an error page, the script parses zero alerts out of it, and reports &amp;ldquo;all clear&amp;rdquo; every single night the app is down. Silence dressed up as reassurance. The gap between a real alerting system and one that just resembles one was a single missing character in a shell script.&lt;/p&gt;&#10;&lt;p&gt;I didn&amp;rsquo;t just trust that. Stopped the container, ran the check by hand, watched it die with exit 7, watched systemd catch the failure, watched the notification land on my phone. Good time to prove that chain: database was still empty.&lt;/p&gt;&#10;&lt;h2 id="what-ten-minutes-of-actually-using-it-found"&gt;What ten minutes of actually using it found&lt;/h2&gt;&#10;&lt;p&gt;Everything above, tested and proven. Then I installed it for real, put in my actual medications, and tapped &amp;ldquo;take all&amp;rdquo; for the morning. Four bugs inside ten minutes, and not one of them was about what the code computed. Every single one was about what the app told a person looking at the screen.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Offline hung instead of failing.&lt;/strong&gt; Airplane mode, app opens to its splash screen, and just&amp;hellip; stays there. Forever. No app, no error, nothing. An unreachable server on a tailnet doesn&amp;rsquo;t always politely refuse the connection. The name still resolves, nothing rejects the socket, the fetch just never resolves either way. My service worker was awaiting it with zero timeout, so the whole page had nothing to render and nothing to say. Every network call now has an actual number on it. Reads give up after 4 seconds since someone&amp;rsquo;s standing there waiting and a read is cheap to retry, writes get 8 because a timed-out write might have landed and the only honest move is to make you go check.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;A blank screen making a claim it hadn&amp;rsquo;t earned.&lt;/strong&gt; With the hang fixed, it correctly showed a red &amp;ldquo;can&amp;rsquo;t reach server&amp;rdquo; banner, sitting directly above a completely empty medication list. Which is the single worst thing this specific app is allowed to display, because an empty list and &amp;ldquo;nothing due today&amp;rdquo; are visually identical, and one of those two things at six in the morning is dangerous to get wrong. Fixed: no list is ever blank by default now. Loading says loading. Failure says failure, explicitly, as &amp;ldquo;can&amp;rsquo;t reach the server,&amp;rdquo; never silently rendered as an empty day.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Doses landing on the wrong calendar day.&lt;/strong&gt; Tapped &amp;ldquo;take all,&amp;rdquo; and it logged against yesterday. Today then cheerfully offered to let me take everything again, since as far as it could tell, nothing had happened yet. The write itself was fine, stock even decremented correctly, the client had simply sent the wrong date. I never fully pinned down how it drifted onto the wrong day, so the fix targets the whole category rather than one cause: a loud banner when you&amp;rsquo;re not viewing today, a confirmation before bulk-logging against a past date, and the fix that&amp;rsquo;ll actually matter, following the real date across a midnight rollover on resume, since this is an app that gets opened right before bed and first thing in the morning.&lt;/p&gt;&#10;&lt;p&gt;The fourth bug that day was the app going completely dark on every device while the server was perfectly healthy. That one got its own post, &lt;a href="https://www.onelegdave.dev/posts/server-never-down/"&gt;The Server Was Never Down&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="the-default-i-refused-to-ship"&gt;The default I refused to ship&lt;/h2&gt;&#10;&lt;p&gt;Last thing that came out of actually using it: an as-needed medication was projecting &lt;strong&gt;690 days remaining&lt;/strong&gt; on a bottle of ibuprofen. Technically derived correctly from the math. Read as complete nonsense the second a human looked at it, because a rate based on whatever happened to occur in the last thirty days swings wildly on a single dose and dresses that swing up as precision it doesn&amp;rsquo;t have.&lt;/p&gt;&#10;&lt;p&gt;Fix: as-needed medications alert on raw units left instead of a days projection. That also patched a hole nobody had noticed. Under the days-based rule, an as-needed medication with nothing logged in the past month has no projection &lt;em&gt;at all&lt;/em&gt;, and a null projection never alerts, so it could sit at two tablets left and say absolutely nothing about it.&lt;/p&gt;&#10;&lt;p&gt;The migration wanted a sensible default threshold backfilled onto every existing as-needed medication, ten units seemed reasonable. Checked it against the real data before shipping it, because &amp;ldquo;seemed reasonable&amp;rdquo; is not a threshold, it&amp;rsquo;s a guess wearing a lab coat:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Gabapentin 64 units&#10;Lispro (Insulin) 1385 units &amp;lt;- 10-unit threshold&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A ten-unit warning on 1385 units of insulin would functionally never fire, on the exact medication my own original spec singled out by name as the one where running short is not a minor inconvenience. Ten&amp;rsquo;s fine for a bottle of tablets and dangerously wrong for that. There is no single default that&amp;rsquo;s safe across both, so the migration adds the column and backfills nothing. Existing meds keep their days-based threshold until a real number gets chosen for each one, and the reasoning&amp;rsquo;s written directly into the migration file so nobody &amp;ldquo;helpfully&amp;rdquo; finishes the job for me later without reading why it was left undone.&lt;/p&gt;&#10;&lt;p&gt;Worth naming the general shape of that mistake: a default is a decision made on someone else&amp;rsquo;s behalf without knowing their actual situation. Usually that&amp;rsquo;s a harmless convenience. The moment that number is the thing deciding whether a warning fires at all, it stops being convenient and starts being a bet you didn&amp;rsquo;t ask permission to make.&lt;/p&gt;&#10;&lt;h2 id="breaking-my-own-rule-on-purpose-in-writing"&gt;Breaking my own rule, on purpose, in writing&lt;/h2&gt;&#10;&lt;p&gt;That change directly contradicted a line in my own spec, filed under a heading that literally said &lt;em&gt;settled, do not reopen during implementation&lt;/em&gt;. That rule exists for a good reason: it&amp;rsquo;s there to stop you relitigating design decisions mid-build out of boredom or anxiety.&lt;/p&gt;&#10;&lt;p&gt;But that rule was written before the thing existed, and actually running it produced evidence that plain didn&amp;rsquo;t exist at the time I wrote the rule down. So I reopened it anyway, and documented in the spec itself that it was reopened, when, and specifically why, instead of just quietly contradicting a document I&amp;rsquo;d told myself not to touch. The original math was never wrong. It was unhelpful in a way you can only discover from the far side of a system that actually runs.&lt;/p&gt;&#10;&lt;p&gt;147 tests, all green, the whole time. None of them were ever going to catch a number that was correct and useless, a screen that was blank and honest at the same time, or a default that was reasonable for one drug and reckless for another. That&amp;rsquo;s not a gap in the test suite. It&amp;rsquo;s the actual, permanent boundary of what a test suite can tell you: it verifies what code does. Only running the thing in front of an actual person tells you what it means to them.&lt;/p&gt;&#10;</content:encoded></item><item><title>The Server Was Never Down</title><link>https://www.onelegdave.dev/posts/server-never-down/</link><guid isPermaLink="true">https://www.onelegdave.dev/posts/server-never-down/</guid><pubDate>Fri, 04 Sep 2026 10:00:00 -0700</pubDate><dc:creator>OneLegDave</dc:creator><category>Self-hosted</category><description>A medication tracker I built for myself started refusing to connect, from every device, while the server sat there perfectly healthy the entire time. The bug was a ghost, and I built it myself months earlier without noticing.</description><media:content url="https://www.onelegdave.dev/images/posts/server-never-down.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><media:thumbnail url="https://www.onelegdave.dev/images/posts/server-never-down.jpg" width="1200" height="630"/><content:encoded>&lt;p&gt;&lt;img src="https://www.onelegdave.dev/images/posts/server-never-down.jpg" alt="The Server Was Never Down" width="1200" height="630"&gt;&lt;/p&gt;&lt;p&gt;I built myself a medication tracker. Single user, me, running on my own server, reachable only over my own private network. Not a health app in the App Store sense — no dose advice, no interactions, no clinical logic anywhere in it. It counts what I have, tells me what&amp;rsquo;s due, and yells at me before I run out. That&amp;rsquo;s the entire scope, on purpose, because the second a personal project starts pretending to be a doctor is the second it becomes a fucking liability instead of a tool.&lt;/p&gt;&#10;&lt;p&gt;I finished it. Deployed it. Started actually using it for real medications, which is the part that matters — a supply tracker that only ever gets tested with fake data hasn&amp;rsquo;t actually been tested for shit. And within days it started telling me it couldn&amp;rsquo;t reach the server. From my phone. From my desktop. Every device, same error, connection refused, like the whole thing had just died in the night.&lt;/p&gt;&#10;&lt;p&gt;The server had not died in the night. The server had never been healthier. I was staring at a goddamn ghost.&lt;/p&gt;&#10;&lt;h2 id="guilty-until-proven-guilty"&gt;Guilty until proven guilty&lt;/h2&gt;&#10;&lt;p&gt;First instinct, obviously: check the server. It was fine. Container healthy, every endpoint answering, curl from a completely different device on the network getting clean 200s back like nothing was wrong, because nothing fucking was.&lt;/p&gt;&#10;&lt;p&gt;Second instinct: check the network. Also fine. Nothing had changed there in weeks.&lt;/p&gt;&#10;&lt;p&gt;Third instinct, the one that should embarrass me a little: assume the phone was lying, restart it, uninstall the app, reinstall it from the home screen, watch it fail exactly the same way, immediately, with total confidence, like it had done this before.&lt;/p&gt;&#10;&lt;p&gt;It had done this before. It had done this every single time, because the thing I was reinstalling wasn&amp;rsquo;t actually broken — it was faithfully, perfectly doing exactly what a Progressive Web App is designed to do, and the design was the fucking problem.&lt;/p&gt;&#10;&lt;h2 id="the-ghost-was-mine"&gt;The ghost was mine&lt;/h2&gt;&#10;&lt;p&gt;Here&amp;rsquo;s the part that stung once I found it: a PWA doesn&amp;rsquo;t get installed from an app store with a name and a version number. It gets installed from a URL, and it stays bound to that exact origin forever. Not the app. The address. Reinstalling doesn&amp;rsquo;t fix a stale origin, it just re-commits to the same dead one, because as far as the phone&amp;rsquo;s concerned that origin &lt;em&gt;is&lt;/em&gt; the app&amp;rsquo;s whole identity.&lt;/p&gt;&#10;&lt;p&gt;Months earlier, before there was anywhere real to deploy this thing, I&amp;rsquo;d stood up a quick throwaway address on my laptop just to test how the layout looked on an actual phone screen instead of squinting at a browser window pretending to be one. Totally reasonable thing to do. Tore it down the moment real deployment happened, also totally reasonable. Except at some point during that testing, I&amp;rsquo;d installed the damn thing to my home screen from that scratch address, and never thought about it again, like a dumbass.&lt;/p&gt;&#10;&lt;p&gt;So the icon on my phone was never talking to the server. It had never once talked to the server. It had been faithfully, patiently trying to reach a machine that stopped listening for that address weeks ago, and every single time it failed, it failed with an error that is byte-for-byte identical to &amp;ldquo;the server is down.&amp;rdquo; &lt;code&gt;ERR_CONNECTION_REFUSED&lt;/code&gt; doesn&amp;rsquo;t editorialize. It doesn&amp;rsquo;t say &amp;ldquo;hey, this domain doesn&amp;rsquo;t exist anymore, you absolute muppet, might want to check that.&amp;rdquo; It just refuses, flatly, and leaves you to guess why.&lt;/p&gt;&#10;&lt;p&gt;Fixed by pointing the install at the actual live address and pinning that URL somewhere obnoxiously obvious so future-me doesn&amp;rsquo;t get to relive this shit.&lt;/p&gt;&#10;&lt;h2 id="what-the-silence-was-hiding"&gt;What the silence was hiding&lt;/h2&gt;&#10;&lt;p&gt;Here&amp;rsquo;s where it stopped being embarrassing and started being useful. The server had no access log. None. Which meant when this started, I had zero way to tell the difference between &amp;ldquo;the phone tried to connect and got rejected&amp;rdquo; and &amp;ldquo;the phone never tried at all.&amp;rdquo; Those are completely different failures with completely different fixes, and I couldn&amp;rsquo;t tell them apart because I&amp;rsquo;d never built the thing that would let me.&lt;/p&gt;&#10;&lt;p&gt;So I added one. And the very first thing it proved was that every single entry in it, for the entire time this had supposedly been &amp;ldquo;down,&amp;rdquo; was the container&amp;rsquo;s own healthcheck pinging itself every thirty seconds like clockwork. Nothing else. No failed request. No rejected connection. Not one single byte from my phone had ever arrived, because it was never being sent anywhere near this fucking machine in the first place.&lt;/p&gt;&#10;&lt;p&gt;That log — something I only built because I got burned — is also what turned up two real bugs hiding underneath the fake one, which is exactly what happens when you finally go looking properly instead of vibing it. The app&amp;rsquo;s reconnection logic was trusting the browser&amp;rsquo;s &lt;code&gt;online&lt;/code&gt; event to know when the network came back, and that event is basically decorative on a phone — so a genuinely brief network drop could get treated as permanent, forever, until you manually intervened like an idiot. And separately, when the app &lt;em&gt;did&lt;/em&gt; recover, it only bothered refreshing two of its three screens and left a stale &amp;ldquo;can&amp;rsquo;t reach server&amp;rdquo; panel sitting on the third, so even a fully working reconnect still looked broken if you happened to glance at the wrong tab.&lt;/p&gt;&#10;&lt;p&gt;Neither of those caused the outage. Both would have made a &lt;em&gt;real&lt;/em&gt; outage worse, invisibly, and I only found them because a fake one forced me to build the tooling to actually see what was happening instead of guessing at it.&lt;/p&gt;&#10;&lt;h2 id="the-pattern-underneath-all-of-it"&gt;The pattern underneath all of it&lt;/h2&gt;&#10;&lt;p&gt;I&amp;rsquo;d already built this thing around one rule, from the start, mostly out of paranoia: nothing in this app is allowed to be blank or silent by accident, because for a medication tracker, blank and silent both read as &amp;ldquo;nothing to worry about,&amp;rdquo; and that&amp;rsquo;s exactly the one lie this app is not allowed to tell, ever. An empty list has to mean the server confirmed there&amp;rsquo;s nothing due — never &amp;ldquo;the request hasn&amp;rsquo;t come back yet&amp;rdquo; wearing an empty list&amp;rsquo;s clothes like a coward.&lt;/p&gt;&#10;&lt;p&gt;This whole outage was that exact philosophy failing at a layer I hadn&amp;rsquo;t built it into yet. The client had no way to say &amp;ldquo;I am not even reaching the network you think I am,&amp;rdquo; so it said nothing, and nothing looks exactly like everything being fine, which looks exactly like everything being fucked, depending on which side of the silence you&amp;rsquo;re standing on. A dead request and a healthy one that just hasn&amp;rsquo;t finished look identical if you never bother asking which one you&amp;rsquo;re actually looking at.&lt;/p&gt;&#10;&lt;p&gt;Turns out the same rule that governs whether an empty dose list can be trusted also governs whether &amp;ldquo;can&amp;rsquo;t connect&amp;rdquo; means what you think it means. Silence is never neutral. It&amp;rsquo;s just a claim wearing a disguise, and the whole job is making sure the disguise never fucking fits.&lt;/p&gt;&#10;</content:encoded></item></channel></rss>