rest-api
Technical notes on web development, DevOps, and AI integration.
8 articles
- 16:24backend
When a Feature Is Turned Off, Answer 404 Not 403
A disabled reviews feature answered 404 instead of 403. The HTTP spec actually backs that choice, and one cheap gate makes it practical.
TL;DR: Returning 403 for a disabled feature confirms the resource exists, inviting attackers to keep probing. Using 404 instead hides it completely, and a single service-layer flag can protect all related endpoints while the frontend hides UI via feature flags. For admin APIs though, 403 or 410 makes more sense since admins need to know the feature is just disabled.
#http#api#error-handling - 16:24database
Soft Delete Done Right: Predicates, RowsAffected, and Restore
Soft delete is not just DELETE swapped for UPDATE. Predicates on every query, a RowsAffected alarm, and a mirrored restore guard keep it honest.
TL;DR: Switching DELETE to soft delete with an UPDATE on deleted_at left deleted rows visible because SELECTs weren't filtered. Fixing it means adding deleted_at IS NULL to queries, checking RowsAffected to return 404, and mirroring logic for restores. You also need to invalidate cache on every state change, otherwise complexity and leaks quickly outweigh benefits.
#go#mysql#sql - 15:07backend
The Category Trash Can: One Endpoint and POST Restore
A soft delete API contract: the trashed query flag, POST restore, and a 404 that deliberately merges two conditions.
TL;DR: The categories list supports a trashed query param defaulting to false so existing clients keep seeing active items while new UIs can fetch soft-deleted ones. Restore is a POST endpoint returning 200 on success, 403 when out of scope, or a shared 404 for missing or not-trashed cases. It's a clean additive contract-first change that keeps compatibility without new endpoints.
#api#openapi#rest-api - 14:17devops
The document mirror moved offices: work items to Plane Pages
The document mirror moved off the kanban board and into Plane Pages, and the storage contract forced a full identity redesign.
TL;DR: The mirror moved from Work Items to Pages, which preserves HTML comments instead of sanitizing them, forcing a new identity design. Pages are flat with no folders, need full replacement on update, and require archiving before delete with verify-after-write. Sync now trusts content hashes, allows two-way edits only for meeting notes, and keeps library docs one-way with divergence alerts.
#plane#self-hosting#git - 23:25devops
Done on the tracker is a claim; the proof lives in Git
A card flipped to Done with nothing behind it. Now a work item only counts as done when its evidence hashes actually resolve in the repository.
TL;DR: A Done label means nothing without Git proof, so I stopped trusting tracker status alone. I built a gate that only allows Done when visible evidence lines with commit hashes and tags actually resolve in the repo. Strict rules like WIP limits, date handling, and separating docs keep the board honest and verifiable.
#plane#self-hosting#git - 23:25backend
Two-way document sync: the trustworthy tool refuses precisely
A pull returned different content than my push, with no error. The fix was not a smarter parser but a precise map of what the sync refuses to do.
TL;DR: My Markdown quietly broke after a pull because Plane sanitizes HTML and drops unsupported formatting without warning. Instead of forcing acceptance, I built a sync engine that refuses risky work, storing Markdown safely and using stripped text as the stable identity. It classifies every outcome into six explicit statuses and fails loudly rather than guessing, prioritizing data integrity over convenience.
#plane#self-hosting#sync - 22:30devops
Live probe vs my Plane spec: two assumptions died in 27 minutes
My 905-line Plane sync spec lost two assumptions to a live probe: HTML markers stripped by server-side sanitization, archive endpoint 404.
TL;DR: A live probe against Plane Community Edition broke two assumptions in a 905-line sync spec before any code was written. Hidden HTML comments for identity were stripped by server sanitization, and the archive endpoint returned 404 because CE trails cloud. Fix stores metadata in visible text and a config file, uses Done instead of archive, and hashes normalized text.
#plane#self-hosting#rest-api - 00:45tooling
A Failure-Proof Research Script: Two-Provider API Key Rotation
Two-layer API key rotation, provider fallback, and DoH for lying ISP DNS: lessons from building a research script that refuses to die quietly.
TL;DR: Firecrawl's keyless search endpoint died with permanent 403s mid-research, so the author pivoted to keyed APIs. The result is web-direct.py, 125 lines doing search, scrape, and extract with two-layer rotation: next key first, then next provider. A DoH health check catches lying ISP DNS, falling back to curl --resolve.
#automation#tooling#rest-api