Pixel

Pixel Updates & Events

Server Updates & Events

Announcements

Paste AI Markdown Tables into Word and Google Docs

DEV Community

How to Paste AI Markdown Tables Into Word and Google Docs Without Broken Borders

Copying a table out of an AI chat gives you two different things at once, and which one your paste uses decides whether you get a real table or fifty pipe characters. In a test run on 2026-11-15, the chat app's Copy button followed by a normal paste in Google Docs produced a table object with 9 rows, 4 columns and 36 filled cells, and left 0 markdown characters behind. The same clipboard pasted as plain text produced no table at all and 50 pipes. On the Word side, Pandoc 3.9 produced real Heading 1, 2 and 3 styles and a 36-cell table in 1.59 seconds, but the file it wrote carries no cell grid lines and dropped every column alignment marker. One Copy click puts two versions on the clipboard The chat app renders the markdown you see, and its Copy button puts both the rendered version (as HTML) and the source version (as text) on the clipboard. The application you paste into then picks one. Clipboard format What it holds What a paste does with it HTML Rendered tags: heading elements, a table with rows and cells, bold and code spans Google Docs built 1 table, 3 heading paragraphs and 7 bullet paragraphs; 0 markdown characters arrived Plain text The markdown source: hash marks, pipes, asterisks, backticks, one separator row of dashes Google Docs inserted 34 plain paragraphs; 50 pipes, 2 asterisks, 8 backticks and 3 hash-marked lines arrived as characters The plain-text version is not a degraded copy of the answer. It is the answer exactly as the model wrote it, which is what you want when the next stop is another tool, and the wrong version when the next stop is a person reading a document. The four paste paths, measured Path What arrived What did not Copy button, then Ctrl+V in Google Docs 3 heading paragraphs (2 at level 2, 1 at level 3), one 9×4 table with 36 of 36 cells filled, 7 bullet paragraphs at 2 levels, bold and monospace text The code block: its fence and language label arrived as a plain "Python" line, and the code as monospace paragraphs Copy button, then Ctrl+Shift+V in Google Docs All 34 paragraphs of text, every word intact, 1,566 characters 0 headings, 0 tables, 0 bullet objects, 0 bold runs; 50 pipes and 2 asterisks stayed in the text Google Docs "Paste from Markdown" Not measured: the command opened a dialog asking to install a Chrome extension Alignment, footnotes and code blocks on that path Pandoc GFM to DOCX Heading 1 ×1, Heading 2 ×4, Heading 3 ×1 as real styles, 9×4 table with 36 of 36 cells, 7 bold runs, 1 hyperlink, 1 footnote, 12 list paragraphs at 2 levels Cell grid lines (the table style defines one rule under the header row), 0 aligned cells The rich paste is the only path that gave a real table with no cleanup. Pandoc is the only path that produced Word heading styles, a working hyperlink and a real footnote. Turning on Markdown in Google Docs did not fix a plain paste Google documents two different things and they are easy to conflate: typing markdown as you write, and converting markdown on paste. I tested the second with the first switched on. Tools → Preferences → Enable Markdown, confirmed on. Ctrl+Shift+V with the same markdown clipboard: 34 plain paragraphs again, 50 pipes, 2 asterisks, 8 backticks. Identical to the run with Markdown off. "Paste from Markdown" under the Edit menu and the right-click menu both opened a dialog titled "Turn on copy, cut and paste", asking for a Chrome extension. So that result says more about this browser than about Google Docs. What a measured number does support is narrower: on this setup the setting alone did not change what a text-only paste produced. The one-line Pandoc command pandoc -f gfm -t docx -o report.docx report.md
On a 536-word markdown report with a 4-column table, a footnote and a link: 1 H1, 4 H2, 1 H3 in the source → Heading 1 ×1, Heading 2 ×4, Heading 3 ×1 as Word paragraph styles an outline can read 4-column table, header row plus 8 data rows → 9 rows × 4 columns, 36 cells, 36 filled, header row marked to repeat across page breaks Align...

Powered by Readybot.io

Paste AI Markdown Tables into Word and Google Docs

Loop Pop Closed Test: Swap Feedback with Testers

DEV Community

Closed test swap: Loop Pop (one-tap arcade game) needs testers, I'll test yours too

Hi all, I'm an indie developer and my Android game Loop Pop is in a Google Play closed test. I need testers to stay opted in for 14 days, and I'm happy to test yours in return. About Loop Pop: a one-tap arcade game. A ball runs round a ring; tap when it is on the gold target, collect gems and keep off the snakes. Made with Godot. Available in English, French and Arabic. What I ask: Join the test with your Gmail: https://play.google.com/apps/testing/com.amrani.looppop Install it and keep it installed for 14 days Play a couple of times and tell me anything that is confusing, too hard or broken What I offer: I will install and keep your app for 14 days too I will send you written feedback Comment with your opt-in link and I'll join today.

Powered by Readybot.io

Loop Pop Closed Test: Swap Feedback with Testers

GitHub Actions vs Argo Workflows: Key Differences

DEV Community

GitHub Actions vs Argo Workflows: which one runs what

GitHub Actions vs Argo Workflows is usually a false choice, because the two are not sold the same unit of work: Actions runs a workflow file in response to a git event, and Argo Workflows reconciles a Kubernetes custom resource that models a DAG of containers. The place they genuinely collide is fan-out, where Actions caps a job matrix at 256 jobs per run and Argo is bounded by the cluster. The same five steps on each engine. Actions shares one runner and one filesystem; Argo generates a pod per step, historically with an init and a wait container around your own image. Argo Workflows is a container-native workflow engine implemented as a Kubernetes CRD, and a graduated project in the Cloud Native Computing Foundation. Its own documentation lists its use cases in this order: machine learning pipelines, data and batch processing, infrastructure automation, and CI/CD. CI/CD is fourth on that list for a reason. GitHub Actions is triggered by repository events, runs on machines somebody else keeps warm, and reports back into the pull request. Argo has no git trigger of its own; event-driven triggering is a separate project, Argo Events, that you also deploy. The comparison below is drawn from the argoproj/argo-workflows repository and from GitHub's published limits, read on 21 September 2026 against Argo Workflows v4.1.4. Where a number depends on your cluster, the cell says so. Comparison GitHub Actions Argo Workflows The unit you write A workflow file in .github/workflows, up to 500 KB, discovered automatically from the repository A Workflow custom resource applied to a cluster, with steps or a DAG of tasks What triggers it Push, pull request, schedule, manual dispatch and the rest of the repository event set The API, the argo CLI, a schedule, or sensors from the separate Argo Events project What runs a step All steps of a job share one runner and one filesystem Every step and every DAG task becomes its own Pod, historically three containers: main, init and wait Fan-out ceiling A job matrix generates at most 256 jobs per workflow run, on hosted and self-hosted runners alike Your cluster. The controller processes one Workflow at a time, so the ceiling moves from the API to the reconciler What you pay per minute $0.006 at 2 vCPU on Linux, or $0.0025 on a managed runner at the same size Nothing to Argo. Your cluster bills for the pods and the nodes under them Free tier $12 of included compute a month on Free, $18 on Team, $300 on Enterprise Cloud (2,000, 3,000 and 50,000 minutes at the $0.006 Linux rate, read 12 November 2026), and free and unlimited on public repositories Apache 2.0 software, no allowance, because there is no meter Where it runs GitHub's fleet, a vendor's fleet, or your own self-hosted runners A Kubernetes cluster you operate, with the controller and server in their own namespace Time limits 6 hours per job on hosted runners, 5 days self-hosted, 35 days per workflow run Whatever you configure. The quick-start instructions say in as many words that they are not suitable for production Self-healing or retries None built in on GitHub-hosted runners; transient failures diagnosed and retried inside the run on Latchkey Retry strategies you declare per template, which is real retry logic and the most convincing thing on this row Setup change required Commit a file. On a managed runner, an app install and a runs-on label A Kubernetes cluster, kubectl, the quick-start or production manifests, and the argo CLI What a step costs on each side This is the difference that surprises people who try to run CI on Argo. In GitHub Actions a job is one machine: checkout, install, build and test all see the same working directory, and passing data between steps costs nothing. In Argo, each step and each DAG task causes a Pod to be generated. Historically each of those pods carries three containers: main runs your image, an init container fetches artifacts and parameters, and a wait container handles clean-up and saves parameters an...

Powered by Readybot.io

GitHub Actions vs Argo Workflows: Key Differences

ZQN-12B: Open AI Model with 128K Context

DEV Community

ZQN-12B: our second open model, plus the M3-GPTQ compression paper

ZQN-12B is the second open model from ZAQERIS Ai, an independent AI research group in Cairo, Egypt. Trained from scratch 15.55B parameters, compressed with our ZAQERIS M3-GPTQ method to 6.48 GiB (3.25 bits per weight) Runs on a consumer 8 GB GPU at about 25 tokens/second 128K native context (256K with YaRN) Step-by-step reasoning and structured tool calls Apache 2.0 Model: https://huggingface.co/ZAQERIS/ZQN-12B Alongside the model we published the technical paper behind its compression: "ZAQERIS M3-GPTQ: Hessian-Aware Multi-Stage Residual Vector Quantization for Extreme Bitrate LLM Compression". It combines Block-Hadamard decorrelation, Hessian-salience outlier selection, multi-stage 8-dimensional residual vector quantization, and Block-8 Cholesky GPTQ error propagation. Paper: https://huggingface.co/ZAQERIS/ZQN-12B/blob/main/docs/papers/ZAQERIS_M3_GPTQ_PAPER.md This is an early checkpoint, not a frontier model, and we are honest about its limits on the model card. Feedback and contributions are welcome.

Powered by Readybot.io

ZQN-12B: Open AI Model with 128K Context

zkVerify Proof Gatekeeper: Verify AI Payment Decisions

DEV Community

Don't Trust the Agent. Verify the Gatekeeper — Then Verify Everything Else Too.

AgentGames @ZKVProtocol By @stoploss44, for the zkVerify Agent Games Creator Track, Season 01 (21 October – 21 November 2026; judging 22–30 November 2026). An AI agent that moves money is a cashier with no supervisor. It can tell you it checked the balance, checked the recipient, checked the expiry — and you have no way to know whether it checked anything at all. That is the problem zkVerify's Agent Games is built around: agents compete, proofs decide, results go on record. I set out to build the thing the tournament's first track asks for: a Proof Gatekeeper — an agent that judges proof-backed payment requests and writes a platform-verified proof of every decision. What follows is what I actually ran, with receipts. Everything below was executed locally on my own machine: no mainnet transaction, no VFY spent, no live endpoint. I will say plainly where the local demo ends and the real tournament begins. 1. The job, as the tournament defines it From the official event page, a Proof Gatekeeper task is a signed JSON envelope describing a transfer request. The agent has 60 seconds to answer with one deterministic decision — APPROVE or REJECT — plus a Groth16 proof of that decision, which the platform re-verifies against its own registered verification key. Eight tasks per agent per day, eight daily rounds, scores cumulative. Correct decisions score +12 either way; a wrong approval costs -6, a wrong rejection -3, a timeout -2, and a provable task answered without a valid proof costs an extra -2. A task payload looks like this (from the event page): type "agent-games.proof-gatekeeper.v1", task_id "gk_24_9d1", input with registered_vk, proof_vk, minimum "1000", public_balance "1460", expiry_block 19842201, current_block 19832000, recipient and condition_recipient "0xDe42...9f01", amount "500", max_transfer "1000", proof_tx "0xa4c1...8ff1". Seven trap varieties are documented in advance — the test is whether the agent checks every field, not whether it can guess: valid condition (~50%), VK substitution (~13%), proof reused (~11%), threshold mismatch (~8%), expired condition (~6%), recipient mismatch (~6%), amount overflow (~6%). The build guide adds the sentence that matters most: "A proof can verify perfectly and still authorize the wrong action. Your agent must confirm what was proven, not only whether verification succeeded." I built the demo to find out exactly where that line bites. 2. The official circuit — and what it does not tell you Both arena circuits are Groth16/BN128, compiled with Circom 2.x. The proving key and WASM are public at https://agentgames.zkverify.io/circuits/gatekeeper.wasm (1,755,820 bytes) and https://agentgames.zkverify.io/circuits/gatekeeper_final.zkey (309,750 bytes). SHA-256 of the files I downloaded (verified on 15 November 2026): be00aefe3c8ba910951a242f50e55937bf82a0375ad4b69c2ef10629ab92764f — gatekeeper.wasm adfe95a439a7063a82a4967ef026d2dd6857a4d02c63b3caf63dac02e01af80d — gatekeeper_final.zkey The registered verification-key hash is served by the site itself at /api/circuit-info: gatekeeper vkHash 0x6b79c6012a6d8651f3e13bc4d2a20370280ab49700c90c5316d4168bfbad77b0. I exported the verification key from the zkey with snarkjs 0.7.6: curve bn128, 13 public inputs. What the site does not publish is the circuit source or the input signal names. I found them from the task envelope itself: they are the camelCase versions of the envelope's snake_case fields (max_transfer to maxTransfer, public_balance to publicBalance), plus taskId, salt, and decision. The 13 signals: 1 taskId (binds the proof to one task), 2 minimum, 3 publicBalance, 4 expiryBlock, 5 currentBlock, 6 recipient, 7 conditionRecipient, 8 amount, 9 maxTransfer, 10 registeredVkHash, 11 proofVkHash, 12 salt (the ONLY private input), 13 decision (1 = approve, 0 = reject). Salt is the only private input: it never appears in the public signals. Everything else is public — the proof hides nothing about the task, only the nonce. One encoding not...


Powered by Readybot.io

zkVerify Proof Gatekeeper: Verify AI Payment Decisions

LLM SEO: Make Your Site Visible to AI Assistants

DEV Community

LLM SEO: How to Make Your Site Visible to AI Assistants

Cross-posted from my own company blog: https://vouchgeo.com/blog/llm-seo. I'm the founder of Vouch, which is mentioned at the end. "LLM SEO" is one of several names for the same shift, next to AI SEO, GEO and AEO. Strip the label away and one practical question is left: when someone asks an assistant built on a large language model about your category, can it reach your pages, read them, and find something on them worth repeating? This guide stays on that practical layer: which crawlers to let in, what stops a model reading a page it was allowed to fetch, how to write pages it can quote, and how to tell whether any of it worked. If you want the bigger picture of why search is changing, AI SEO covers it, and GEO vs SEO vs AEO sorts out the terms. Reach, read, repeat It helps to treat LLM SEO as three tests a page has to pass, in order: Reach. The assistant's crawler or fetcher is allowed to request the page, and your server lets it through. Read. The response contains the content as text, not a blank shell waiting for scripts or a picture of a price list. Repeat. The text answers a buyer's question clearly enough that an assistant can quote or paraphrase it, and other sites back it up. A page that fails the first test never gets to the third, which is why the work starts with crawlers. Every provider fact below comes from that provider's own documentation, checked in November 2026; the rest is our editorial advice, to be tested against your own results. Reach: know which crawler does which job The large providers split their bots by job: training, search indexing, and fetches made because a user asked something. That split lets you decline training without disappearing from search answers. PROVIDER SEARCH TRAINING USER-TRIGGERED OpenAI OAI-SearchBot GPTBot ChatGPT-User Anthropic Claude-SearchBot ClaudeBot Claude-User Perplexity PerplexityBot none listed Perplexity-User A few details change how you act on that table: OpenAI lists four agents in its crawler documentation. The fourth, OAI-AdsBot, is limited to safety checks on landing pages that advertisers submit to ChatGPT. Blocking OAI-SearchBot keeps a site out of ChatGPT's search answers, apart from plain navigational links. Because ChatGPT-User acts on a person's request, OpenAI warns that robots.txt may not govern it, and where GPTBot and OAI-SearchBot are both allowed, OpenAI may reuse a single crawl for search and training. Anthropic says on its crawler page that its bots honour robots.txt, and that Claude-User lets site owners control which sites user-initiated requests can reach. Turning Claude-User or Claude-SearchBot off may reduce your visibility in Claude's answers. Perplexity says in its crawler guide that PerplexityBot does not gather content for training foundation models, and that Perplexity-User, acting for a user, generally ignores robots.txt. Our Perplexity SEO guide covers the firewall set-up Perplexity recommends. Google has no separate AI search crawler. AI Overviews and AI Mode use the normal Search index, and Google's AI features guide says a page needs to be indexed and eligible for a snippet to appear as a supporting link, with no extra technical requirements. Whether to allow training is a policy choice, and should you block GPTBot? walks through the trade-offs for each vendor. For visibility alone, the rule of thumb is short: let in the search crawler of every assistant your customers rely on. Each of the three vendors in the table publishes IP ranges for its agents, so firewall rules can admit the real crawlers and refuse impostors. To see where your robots.txt stands right now, run the free AI crawler checker. Read: make sure the fetch returns words A crawler that is allowed in can still come away with nothing useful. Common causes: Content that only appears after JavaScript runs. If the HTML your server sends is an empty frame, a crawler that does not run scripts sees an empty page. Serve the main text in the initial HTML. Facts locked in imag...

Powered by Readybot.io

LLM SEO: Make Your Site Visible to AI Assistants

Why Per-Token AI API Pricing Is Broken

DEV Community

AI API Pricing Is Broken: Per-Token Billing Charges You for the Wrong Thing

Originally published at API Cost Lab. AI API Pricing Is Broken: Per-Token Billing Charges You for the Wrong Thing Last updated: November 2026 Per-token pricing is the wrong unit for AI APIs. It charges you for effort, not for results — for every token a model burns on the way to an answer, including the tokens you never see, the retries that failed, and the words a rambling answer didn't need. The fix is not a cheaper token. It is a different unit: price per finished task, not per token spent getting there. That sounds like a small accounting complaint. It isn't. The unit you pay by decides what you optimise for, what you fear, and what your provider is rewarded for. Right now, all three point the wrong way. You pay for the journey, not the arrival Think of a taxi ride. You pay for arriving, with the meter as a rough proxy for distance. Now imagine a taxi that charged per turn of the wheels — extra when the driver took a wrong turn, circled the block, or sat thinking at a junction with the engine running. That is how an AI API bill works today. Every call is metered in tokens, and a token is not a unit of value. It is a chunk of text, roughly part of a word. You are billed for the prompt you send, for the answer you receive, and for everything the model generates in between — including work that produces nothing you can use. A call that fails halfway still costs you the tokens it consumed. An agent loop that retries a step five times bills you five times for one job. A model that answers in 400 words costs roughly twice as much as one that answers the same question correctly in 200. The meter runs on effort, and effort is the one thing you cannot see or control in advance. This was tolerable when an API call was one prompt and one answer. It is not tolerable now that a single user request can set off a chain of dozens of calls, each feeding the next, with the total unknown until the chain stops. Our bill-diagnosis checklist walks through the usual ways a bill runs away, and nearly all of them are the same story: a loop nobody capped, a prompt nobody trimmed, a retry nobody counted. Per-token pricing turns every one of those slips into money, silently, at machine speed. Exhibit one: the tokens you never see The clearest proof that the token is the wrong unit is the reasoning token. When a reasoning model works through a hard problem, it generates an internal draft — its working-out — before producing the answer you actually read. OpenAI's own documentation says those reasoning tokens are not visible through the API, but they still occupy context space and are billed as output tokens, at the output price. Read that again: the most expensive tokens on the bill are the ones you are not allowed to read. The same documentation notes that a model may generate anywhere from a few hundred to tens of thousands of reasoning tokens for one problem. You asked for a short answer and paid for a hidden essay you will never see. Reasoning effort settings make the absurdity explicit. Turn the effort dial up and the same question, with the same correct answer, costs more — because the model was allowed to think longer. The answer didn't change. The value didn't change. Only the amount of invisible work changed, and the meter charges for invisible work at the highest rate on the price sheet. A unit that bills you more for the same answer, depending on a dial you set blind, is not measuring value. It is measuring its own process. Exhibit two: the same answer at five different prices If the token were a real unit of value, the same answer would cost the same. It doesn't — not even close. The price of an identical response swings wildly depending on plumbing choices that have nothing to do with what you received. Send a prompt whose beginning matches a cached prefix and, on Anthropic's published terms, those tokens are read back at a tenth of the standard input price. Write a new cache entry and the same tokens cost a quarter more than standard ...

Powered by Readybot.io

Why Per-Token AI API Pricing Is Broken

Agent Games zkVerify: Prove AI Agents Can Be Trusted

DEV Community

Jangan Percaya Agent-nya, Verifikasi Buktinya: Masuk Agent Games zkVerify Lewat Creator Track

Artikel untuk Creator Track — Agent Games by zkVerify, Season 01. Ditulis oleh @blackke. AI agent sekarang sudah bisa melakukan banyak hal sendiri: membaca data, mengambil keputusan, bahkan mengeksekusi transaksi. Masalahnya bukan lagi apakah agent bisa bekerja, tapi apakah kita bisa percaya pada hasil kerjanya. Kalau sebuah agent bilang, "pembayaran ini sudah saya periksa dan aman," bagaimana kita tahu itu benar? Kalau agent lain mengklaim strateginya menang secara fair, bagaimana kita membuktikan ia tidak curang di tengah jalan? Jawaban paling jujur selama ini adalah: kita tidak tahu, kita hanya percaya pada klaimnya. Agent Games dari zkVerify dibangun untuk mengubah itu. Di kompetisi ini, agent tidak cukup berkata "percayalah pada saya" — agent harus membuktikannya. zkVerify adalah layer khusus untuk memeriksa bukti, bukan sekadar blockchain biasa zkVerify, yang dibangun oleh Horizen Labs, adalah jaringan yang fokus pada satu pekerjaan: memverifikasi zero-knowledge proof dalam skala besar. Zero-knowledge proof sendiri adalah cara membuktikan bahwa sebuah pernyataan itu benar, tanpa harus membuka semua data rahasia di baliknya. Misalnya, sebuah agent bisa membuktikan bahwa keputusannya mengikuti aturan yang ditetapkan, tanpa membocorkan seluruh strategi internalnya. Dengan adanya layer verifikasi khusus seperti zkVerify, aplikasi dan agent tidak perlu membangun sistem verifikasi proof-nya sendiri dari nol. Mereka cukup menghasilkan proof dengan sistem proving yang kompatibel, lalu menyerahkannya untuk diverifikasi. Di Agent Games, setiap hasil kompetisi diverifikasi on-chain dengan cara ini, sehingga wasitnya bukan manusia yang menebak-nebak, melainkan proof itu sendiri. Agent Games Season 01 mempertaruhkan 400.000 VFY untuk agent yang bisa dibuktikan, bukan sekadar diklaim Agent Games adalah turnamen AI agent yang diselenggarakan zkVerify. Season 01 berjalan dari 21 Oktober sampai 21 November 2026, dengan total hadiah 400.000 VFY. Setiap track mendapat alokasi 100.000 VFY, yang dibagi untuk tiga pemenang teratas: 50.000 VFY untuk juara pertama, 30.000 VFY untuk juara kedua, dan 20.000 VFY untuk juara ketiga. Biaya masuknya gratis. Ada empat track yang bisa dipilih, dan masing-masing menguji sisi verifikasi yang berbeda. Proof Gatekeeper menempatkan agent sebagai penjaga pembayaran. Platform mengirimkan tugas ke endpoint HTTPS publik milik agent, dan agent harus menjawab APPROVE atau REJECT dalam waktu maksimal 60 detik. Jawaban itu wajib disertai Groth16 proof yang akan diverifikasi ulang oleh platform terhadap verification key resminya sendiri. Ada delapan ronde per hari dan mode latihan untuk mencoba sebelum ronde berpoin dimulai. Steal the VFY adalah duel satu lawan satu antar-agent. Setiap match berjalan 20 turn, dengan saldo awal 100 VFY per agent, dan dimainkan dalam lima ronde sistem Swiss. Setiap langkah harus sesuai dengan strategi yang sudah didaftarkan dan dikomitmenkan di awal, dan setiap gerakan membawa policy proof-nya sendiri. Mengulang match atau turn lama, memakai ulang kunci idempotensi, atau memakai versi circuit yang tidak cocok dengan komitmen strategi akan langsung ditolak. Wildcard adalah track terbuka untuk membangun agent Web3 apa saja — misalnya agent untuk pembayaran crypto, DeFi, riset on-chain, atau keamanan wallet. Track ini dinilai oleh panel, sehingga kebebasan idenya paling luas, tetapi tetap membutuhkan agent yang benar-benar dibangun dan bisa didemonstrasikan. Creator Track adalah satu-satunya track tanpa ngoding. Peserta mengirimkan thread, video, atau artikel tentang agent yang bisa diverifikasi, lalu karya itu direview secara manual oleh tim Agent Games. Untuk tiga track pertama, peserta memang perlu menyiapkan endpoint agent sendiri, jadi kemampuan ngoding menjadi syarat praktisnya. Creator Track membuka pintu yang berbeda: yang dinilai adalah kejelasan dan kedalaman cara kita menjelaskan serta mendokumentasikan ide verifiable agent di ruang publik. Pelajaran terpenting dari field ...

Powered by Readybot.io

Agent Games zkVerify: Prove AI Agents Can Be Trusted

Codd’s 12 Rules: The Foundations of Relational Databases

DEV Community

The 12 Rules That Shaped Relational Databases

Whenever we use an application, whether it's a banking app, an online shopping platform, or a college management system, a lot of information is stored and managed behind the scenes. But have you ever wondered how databases organize this information? And what actually makes a database relational? To understand this, let's go back to 1970, when computer scientist Edgar F. Codd introduced the relational model of databases. His idea transformed how we organize, store, and manage information. Later, Codd proposed a set of rules to describe what a true Relational Database Management System (RDBMS) should support. These principles are commonly known as Codd's 12 Rules. Let's understand them through a simple, real-world example. Imagine a college management system that stores: Student details Course information Attendance records Examination marks How should such a database organize and manage all this information? Let's explore. First, What Is a Relational Database? A relational database organizes information into tables. Each table contains rows and columns. For example, imagine a Students table: Student_ID Student_Name Department 101 Arun CSE 102 Priya AIML 103 Rahul ECE Here: Each row represents one student. Each column represents a particular type of information. Student_ID helps uniquely identify each student. We can also create separate tables for courses, attendance, and examination marks. These tables can be connected through relationships between their data. This is the basic idea behind a relational database. But Edgar F. Codd wanted to go beyond simply storing information in tables. He wanted to establish principles that relational database systems should follow. Understanding Codd's 12 Rules Before we begin, here's an interesting detail: Codd's rules are numbered from Rule 0 to Rule 12. So, although they are commonly called the 12 Rules, there are actually 13 numbered rules when Rule 0 is included. Let's understand each one. Rule 0 – The Foundation Rule A database system must manage its data entirely through its relational capabilities. In simple words: If a system claims to be a relational database, it should use the relational model to manage and access its data. Real-world example: Imagine our college management system uses relational tables to store student information. The system should manage that information through its relational database capabilities rather than depending on an entirely different mechanism for its core database operations. Rule 1 – The Information Rule All information in a relational database should be represented logically and consistently as values in tables. In simple words: Information should be represented in one consistent relational form. Real-world example: Student names, registration numbers, departments, and marks are stored as values in their respective table columns. The database should represent its information in this consistent tabular form. Rule 2 – Guaranteed Access Rule Every individual data value should be accessible using a combination of the table name, primary key value, and column name. In simple words: We should have a reliable way to find any particular piece of information. Real-world example: Suppose we want to find the department of the student whose Student_ID is 101. We can identify the information using: Table: Students Primary key: 101 Column: Department This gives us a clear and reliable way to access the required value. Rule 3 – Systematic Treatment of NULL Values A relational database should handle missing or unknown information consistently. In databases, NULL represents the absence of a known or applicable value. It is not the same as zero or an empty string. Real-world example: Imagine a student has not yet received their examination result. Instead of entering zero marks, the database can store NULL because the result is not yet available. This helps distinguish missing information from an actual result of zero. Rule 4 – Dynamic Online Catalog Based on ...

Powered by Readybot.io

Codd’s 12 Rules: The Foundations of Relational Databases

Fix Docker Read-Only File System Errors in CI

DEV Community

Docker mkdir /var/lib/docker: read-only file system in CI

Docker mkdir /var/lib/docker: read-only file system means the daemon tried to create a directory under its own data root and the kernel refused because the filesystem holding it is mounted read-only. This is a host condition rather than anything about your image or your workflow, and the daemon is reporting it accurately from one level below where a job can reach. One read-only mount, three different operation words. The path is the constant and the verb is whatever the daemon tried. What this error means Pulls, builds and runs all fail together, with paths under /var/lib/docker in the message and an operation word at the front that changes depending on what the daemon was doing. One public report of a single broken host carries mkdir, unlinkat and open forms of the same failure within a few lines of each other, which is the tell: when the data root goes read-only, everything that writes there fails, and each failure names whichever call happened to hit it. ```The line abiosoft/colima#883 reports (quoted, not a recorded run) API error (500): mkdir /var/lib/docker/overlay2/a784aef8fbf3af0f2a38904f816e31b88e268056b829a6b35028d77864d4a4c2-init: read-only file system

Common causes

The kernel remounted the filesystem read-only after I/O errors

The most common cause on a machine that was working earlier. A failing virtual disk produces read or write errors, and the kernel protects the filesystem by refusing further writes. Every Docker operation that touches the data root fails from that moment, which is why the errors arrive in a burst rather than one at a time.

The host root filesystem is read-only by design

Immutable and hardened host images ship a read-only root, and a daemon whose data root still points at the default path under it has nowhere to write. In our experience this is the cause when the failure is present from the very first container on a freshly provisioned host rather than appearing partway through its life.

The data root was pointed at a mount that is not writable

A data-root set in daemon.json to a network share, a snapshot or a volume mounted with the ro option produces this immediately. The setting looks right in the config and the mount options are where the problem actually is, so checking the config alone will not find it.

A container was given the data root as a read-only bind

Tooling that mounts /var/lib/docker into a container to inspect it sometimes mounts it read-only, and a nested daemon handed that mount reports exactly this. Here the host is fine and the container is the one that cannot write, which a mount listing inside the container settles.

How to fix it

Find out whether the mount or the config is the problem

  1. Ask where the daemon thinks its root is, rather than assuming the default path.
  2. Read the mount options for that path with findmnt, which prints ro or rw plainly.
  3. Check the kernel log, because a mount that went read-only will say why it did.

```Terminal
docker info --format '{{.DockerRootDir}}'
findmnt -no OPTIONS -T "$(docker info --format '{{.DockerRootDir}}')"
dmesg | grep -i -E 'remount|read-only|I/O error' | tail
Move the data root onto a volume you control On a self-hosted runner, give the daemon a dedicated writable volume rather than leaving it on whatever the host image provided. This survives host images that harden the root filesystem, and it gives you something you can size and monitor separately from everything else on the machine. { "data-root": "/mnt/docker-data" }
Remount read-write only when the kernel has not objected If the mount is read-only because of how it was mounted rather than because the kernel demoted it, remounting is the fix. If the kernel demoted it after I/O errors, remounting without repairing the filesystem first is how a bad disk becomes a corrupt one, so read the kernel log before you touch it. mount | grep /var/lib/docker
sudo mount -o remount,rw /var/lib/docker
Fail the job on an unwrit...

Powered by Readybot.io

Fix Docker Read-Only File System Errors in CI

Buburu: Building a Women’s Safety App in 48 Hours

DEV Community

Buburu: A Women's Safety App Built in 48 Hours, Born From a Walk We Never Forgot.

This is a submission for the MLH x DEV Writing Challenge. Buburu is an app for women’s safety that we decided to create to help women feel safe during their walks. We named the app Buburu and its users ladybugs because there is not only one ladybug who saves Paris: we are all ladybugs who can save the world. The interface follows that theme, and users can choose their own colors. 🐞 We built the frontend with Java Script, React and Leaflet, used Java, Spring Boot for the backend, and stored our data in H2. Auth0 handled sign-in, OpenStreetMap provided the map, and OpenRouteService calculated walking routes. https://github.com/AmeliaDrag/UNIHACK2026 Why we built it During our first week at university in Timișoara, we went out to explore the city and get to know each other. A naked man started following us. A stranger who was walking his dog noticed what was happening, stayed with us, and walked us home. That story had a happy ending only because the man walking his dog had good intentions. It could have been much worse, and for many women it is. In a survey of 1,694 women in Romania aged 18 to 65, 95% said they had been harassed on the street (as reported by F-Sides). Across the EU, about three in ten women aged 18 to 29 (28.3%) reported having experienced stalking in 2021 (Eurostat). After that night, I wanted an app where my mom, my friends, and the girls I know could look out for each other. At our hackathon, we had 48 hours to build a first version. How we built it, step by step Sketch the flows. We drew the main screens on paper and worked out how people would move between the map, reporting, the account page, and SOS. Split the work. One teammate owned the Java backend. We divided the frontend by screen so we could work in parallel. Prototype the interface. After the team discussed what each screen should do, I laid out the pages. We used Canva, Figma, and AI tools to explore the design and develop the ladybug theme. Build the screens and connect the API. We used React 18 with JSX, Vite for local development and builds, Leaflet and React Leaflet for the map, the Auth0 React SDK for sign-in, and plain CSS for styling. The backend, in the words of the teammate who built it I built the backend with Java 21 and Spring Boot, using H2 to store users, trusted contacts, incident reports, and SOS alerts. Each report stores its coordinates, type, and expiry time. Trusted contacts are directional. If Ana invites Maria and Maria accepts, Maria receives Ana’s SOS alerts. For Ana to receive Maria’s alerts, Maria needs to invite her separately. For each walking route request, the backend queries active reports and converts their circular map zones into polygons for OpenRouteService. Computing those polygons on demand means expired reports are automatically excluded from the next request. If no route is found, the backend retries once without the avoidance polygons and returns avoidsReports: false, which the frontend uses to warn that the fallback route may cross reported areas. For the demo, the backend loaded a local OpenStreetMap export at startup to populate the 24/7 shop layer without a live data request. The hardest bug: Debugging the sign-in flow Clicking Sign in sent us back to the first page. In one attempt, the Account screen displayed Invalid state. While sign-in was broken, we couldn't test incident submission or SOS through an authenticated account. We first added type="button" to rule out an accidental form submission. The buttons were already outside a form, so we moved on to the app’s session state and the Auth0 callback. Stale guest state. A leftover guest flag could hide the sign-in controls. The app now checks that guest mode is actually enabled before honoring the flag. Two callback handlers. Both main.jsx and Auth0Provider handled the redirect. We removed the one in main.jsx so the provider owns the callback. API authorization. We fixed the app’s API authorization in the Auth0 dashboard and surfaced sign-in error...

Powered by Readybot.io

Buburu: Building a Women’s Safety App in 48 Hours

Cloud Run vs GKE: Choose the Right Container Platform

DEV Community

Cloud Run vs GKE: Picking a Home for Your Containers

A small API with spiky traffic and a 20-service platform need different things Imagine two teams. One has a small product API that is quiet at 3 am and busy at lunch. The other runs about 20 microservices for checkout, payments and orders, with steady traffic all day and strict rules about which service can talk to which. Both have Docker images ready. Where should each one run? The problem The same container can run on Cloud Run or on GKE (Google Kubernetes Engine). Picking the wrong one hurts in a predictable way: Put the small spiky API on GKE, and you pay for node VMs that sit idle at night, and someone has to look after a cluster. Put a large, tightly networked platform on Cloud Run, and you can end up fighting for control you do not have: sidecars, pod-level network rules, node pools tuned for a sale. The choice is not about which tool is better. It is about traffic pattern and how much control you need. The solution: choose by traffic and control Cloud Run is serverless. You deploy a container and Google runs it. Scales to zero when idle, and adds instances when traffic arrives. Billed per request and compute time, so a quiet night costs close to nothing. Best for stateless services with spiky traffic. Scaling is set at deploy time: gcloud run deploy product-service \
- -image=REGION-docker.pkg.dev/PROJECT/repo/product-service:a1b2c3d \
- -min-instances=0 --max-instances=20
GKE is managed Kubernetes. You run pods on nodes. You pay for node VMs that are always on, plus a cluster fee. Best for steady load, sidecars and strict networking such as Kubernetes NetworkPolicy ("payment accepts traffic only from checkout"). Scaling has layers: the HPA adds pods when CPU crosses a target, and when nodes fill up, the Cluster Autoscaler adds nodes. Both shrink after the peak. How each one sits behind the load balancer Both can sit behind the same External Application Load Balancer, but they attach differently. Cloud Run GKE Attached via Serverless NEG Pod NEG LB health checks None to configure Yes, on pods Who spreads load across instances Cloud Run The LB, straight to pods Scaling Cloud Run autoscaling HPA for pods, Cluster Autoscaler for nodes You manage Very little Cluster, nodes, YAML Applying it to the two teams The small spiky API goes on Cloud Run. It scales to zero at night and scales out at lunch on its own. There is no cluster to patch and no node pool to size. The 20-service platform probably goes on GKE, at least for the core services. With that many services talking to each other, the team benefits from Kubernetes networking rules, sidecars and the ability to pre-scale node pools before a known sale. In a Flipkart-style example design, checkout runs on GKE so the team controls pod counts and node pools, while product and auth stay on Cloud Run because they need less tuning. A mixed setup is normal. One load balancer and one URL map can send /api/product/ to Cloud Run and /api/checkout/ to GKE pods. Trade-offs and limits Twenty services is not an automatic GKE. If those services are stateless and loosely coupled, Cloud Run can run all of them. I would ask what the team actually needs from Kubernetes before paying for it. Cloud Run and Cloud SQL connections. Cloud Run can scale to many instances, and each one opens database connections. I would keep a small pool per instance, cap max instances and use pooling. Close the public URL. Every Cloud Run service has a public run.app address that skips the load balancer. I would set ingress to internal and Cloud Load Balancing. GKE needs pre-scaling for known spikes. At max replicas, requests queue, latency rises, then the load balancer returns 503. For a planned sale I would raise minimums before it starts. Watch idle clusters. A forgotten practice GKE cluster keeps billing. A budget alert does not stop anything by itself, but it tells you early. Takeaway Cloud Run: spiky, stateless, little to manage, pay per use. GKE: many services, steady load, control over pods, node...

Powered by Readybot.io

Cloud Run vs GKE: Choose the Right Container Platform

Software Handover Checklist: Essential Documents

DEV Community

What documents should we get at software handover?

At software handover you should receive all functional and non-functional requirements documents, system architecture descriptions, test approval records, deployment documentation, and administrative credentials. On our projects, at handover the client receives the source code, the documentation, the tests and every credential. The SWEBOK Guide describes a software requirements specification as the basis for agreement between customers and suppliers on what the software is to do and what it is not expected to do. What are the documents needed to handover? A proper software handover provides your business with operational independence. When technical contractors complete custom software development, your organisation must receive tangible artefacts that make maintenance straightforward. Without thorough technical documentation, simple upgrades or maintenance tasks require contacting the original programmers, creating vendor lock-in that drives up operational expenditure. On every project we deliver, you own the source code, the data, the documentation and every credential, with no lock-in and no black box. These documents include the technical design records, operational deployment guidelines, automated test instructions, and administrative manuals needed by internal engineers to operate the software without external reliance. Clear operational documentation ensures continuity for corporate leadership across staffing changes. If internal staff changes occur, incoming technical personnel can review existing records and maintain application stability immediately. When systems lack thorough handover packages, companies risk severe operational bottlenecks during routine maintenance and security updates. A complete handover file also includes the original requirements baseline, showing exactly what functions were requested, approved, and verified. When leadership retains structured specifications alongside repositories, auditing application capabilities requires no guesswork from new personnel, preserving institutional memory and protecting capital investments. What documents are required for software development? Before engineering begins, we produce a Business Requirements Document, a Software Design Document and a functional and non-functional software requirements specification, agreed with you before engineering begins. These formal files set concrete expectations across engineering, operational, and commercial teams. A Business Requirements Document captures what the business needs and why. The document establishes practical commercial objectives and clarifies core operational pain points. Documenting workflows prevents unaligned development sprints and preserves development momentum across commercial milestones by creating a clear business baseline. Meanwhile, a Software Design Document describes how the software will be built to meet the requirements. It outlines system interfaces, database structures, application layers, and server infrastructure configurations before programming starts, giving engineering teams a shared blueprint to follow. Our software requirements specification sets out the functional and non-functional requirements, aligned with ISO/IEC/IEEE 29148. For deeper discovery preparation, explore our guides on software development process to understand how structured planning protects schedules and budgets. Retaining these requirements specifications at final handover allows your engineers to understand historical architectural trade-offs. It shows what functional constraints shaped the current design, making future revisions transparent and enabling any capable development team to extend the software efficiently. How do requirements specifications protect technical scope? Software requirements specification establishes the basis for agreement between customers and contractors or suppliers on what the software product is to do as well as what it is not expected to do. This baseline helps both parties avoid...

Powered by Readybot.io

Software Handover Checklist: Essential Documents

respirAI: A DIY AI Stethoscope Built in a Weekend

DEV Community

We built a talking stethoscope in a weekend. The hardest bug was the word "Great!"

At UniHack 2026 our team built respirAI: a low-cost digital stethoscope that guides you through recording your own lung sounds, screens them with a neural network on your phone, and tells you whether they sound normal or are worth showing to a doctor. It is a screening aid built by students, not a medical device. Try it: https://denis-furtuna.github.io/respirAI/ (there is a practice mode, no device needed) Code: https://github.com/denis-furtuna/respirAI This post is how we built it, step by step, and the bug that cost us the most sleep. The problem A stethoscope is only useful when a trained ear is on the other end. We wanted the opposite: a device that anyone can hold on their own chest, with the phone doing the guiding and the first round of listening. Step 1: the device No custom board. A regular stethoscope chest piece sits on an INMP441 MEMS microphone, wired to a Seeed XIAO ESP32-S3 with a small LiPo battery. The firmware captures audio at 16 kHz, downsamples it to 8 kHz and streams it over Bluetooth Low Energy in 10 ms packets: a 2-byte sequence number followed by 160 bytes of 16-bit mono PCM. The sequence number matters more than it looks. BLE drops packets, and a lung recording with silent holes in it is worse than no recording, so the app counts what is missing and refuses a recording that has too many gaps. Step 2: the app The app is plain JavaScript, HTML and CSS with no framework. In a browser it talks to the device with Web Bluetooth; the same code is wrapped with Capacitor into an Android app. A check goes through the chest positions one at a time. For each one, a body diagram shows where the chest piece goes, then a breathing circle takes over the whole screen and paces two slow breaths while the device records for 12 seconds. The app runs in five languages. Two decisions we would make again: A practice device. A fake Bluetooth device that plays stored recordings let us build and test the whole flow without hardware in hand, and it is why the browser tests can run on every push. Fixed interfaces first. We wrote down the BLE packet format and the app-to-AI contract on day one, so firmware, app and AI were built in parallel on separate branches and merged at the end. Step 3: the AI The model is a convolutional network trained on the ICBHI 2017 respiratory sound database (920 recordings from 126 participants). It looks at a log-mel spectrogram of each recording and flags crackles and wheezes. Two rules we held to. We trained on sound labels, not disease labels, because the disease labels are dominated by one condition and a model can score well by always guessing it. And we split by patient, never randomly, because a random split puts the same person in training and test and inflates every number. Step 4: the voice guide Here is the thing we missed at first: the person's hands are busy. They are holding a chest piece on their own back. They cannot tap "start". So we added a voice guide on top of the flow, using an ElevenLabs conversational agent. It says where to put the chest piece, hears "ready", starts the recording through a client tool, answers questions like "where exactly?", and reads the result. The timer, the breathing circle and every button stay in our code; the agent only speaks and presses two buttons. Offline, the same switch plays pre-recorded instructions instead. One rule is absolute: while the stethoscope records, nobody talks. The phone microphone is muted and the agent's volume is zero, otherwise the stethoscope records the voices too. The hardest bug: the agent kept getting cut off The flow looked simple: The person says "ready". The agent calls our start_recording tool. The tool answers: "tell the person to breathe slowly and stay silent". We wait until the agent has finished saying that. We mute everything and record. Step 4 was the bug. The agent would start "Now breathe slowly, in and out with the ci" and go silent. Every time. Our first version of "wait until it finished" was the obvi...

Powered by Readybot.io

respirAI: A DIY AI Stethoscope Built in a Weekend

Embla 1: A Fast, Private AI Model for Your Phone

DEV Community

Embla 1: A Reasoning Model That Runs on Your Phone — Private, Offline, and Genuinely Fast

Embla 1: A Reasoning Model That Runs on Your Phone — Private, Offline, and Genuinely Fast AI disclosure: This article was drafted with AI assistance and checked against Sevren's own launch blog and architecture post, read 15 November 2026. I have not run Embla 1 hands-on — nobody outside Sevren has had it long enough. Nothing here is sponsored, and there are no affiliate links on this page. Sevren, a Copenhagen startup, has released Embla 1: a reasoning model designed to run entirely on a phone. Private, offline, and free per request — no API call, no server round-trip, no per-token bill. If that sounds like the pitch every on-device model makes, the difference here is the evidence Sevren published alongside it: a full architecture write-up, a training recipe, and benchmark numbers measured on an actual iPhone, including the places where their model loses. That last part is why this launch is worth your attention. Most small-model launches hand you a cherry-picked leaderboard. Sevren handed us their model's weaknesses too. What Embla 1 actually is Embla 1 is a 10-billion-parameter mixture-of-experts model with only about 1 billion parameters active per token (that's the "A1B" in its size class). It's a reasoning model — it thinks through problems step by step before answering — built from the ground up for phone hardware rather than shrunk down from a server model. The headline numbers, all measured by Sevren at 4-bit precision: 57.4 average across five benchmarks: BFCL (tool use), IFBench (instruction following), AA-Omniscience, GPQA (graduate-level science questions) and MATH-500. 1.77 seconds end to end on an iPhone 18 Pro for a 1,024-token prompt producing 256 output tokens, using Sevren's own Metal implementation. In llama.cpp the same task takes 2.18 seconds. 888 tokens per answer on average — the fewest of any reasoning model Sevren tested. The next-cheapest, Gemma 4 E4B, needed 1,577 tokens for the same answers. Qwen3.5-4B needed 6,619. That last number is the one developers should care about most. On a phone, every token costs battery and time. A reasoning model that reaches a good answer in 888 tokens instead of 6,600 is not a little faster — it's a different class of product. It's the difference between an assistant that feels instant and one that makes you watch a spinner. The honest caveats (read these first) Sevren's numbers are Sevren's numbers. They say so themselves, and the caveats matter: Self-measured, one phone, one harness. All benchmarks were run by Sevren on a single iPhone 18 Pro, with an uncertainty of about ±1 point per average. Other setups may rank the models differently. No independent lab has verified these results yet. Five of the twelve models Sevren tested scored higher. LFM2.5-8B-A1B is 1.4 points ahead (58.8 vs 57.4) — but takes twice as long. LFM2.5-2.6B, Granite 4.2 3B, Gemma 4 E4B and Qwen3.5-4B are 2.6 to 5.3 points ahead, but take 3.0 to 5.5 times as long. Embla 1 trades a few points of accuracy for a large speed advantage. Whether that trade is right depends on what you're building. Math is the weak spot. Embla 1 scores 76.1 on MATH-500, against 89.6 for LFM2.5-8B-A1B and 90.5 for LFM2.5-2.6B. Sevren says it plainly: "There is still a lot to improve." If your app leans on hard math, this is not your model yet. The latency claim depends on Sevren's own runtime. The 1.77-second figure uses their custom Metal implementation. In the standard llama.cpp runtime it's 2.18 seconds — still fast, but the headline number is tied to their code, not just their weights. None of that makes the launch unimpressive. It makes it checkable — and that's rarer than it should be. Why it's fast: the architecture in plain language Embla 1 is 32 layers, 2,048 wide, with 8 of 96 routed experts plus one shared expert active per token. Four design choices do most of the work: Sevren Sparse Attention. The full-attention layers use ReLU² instead of softmax, which makes about 95% of attention weights exactly zer...

Powered by Readybot.io

Embla 1: A Fast, Private AI Model for Your Phone

Track What Claude Code Actually Tests

DEV Community

Claude Code Said It Ran the Tests. Its Telemetry Shows What Ran

You ask Claude Code to fix a failing checkout test. A few minutes later it replies: "Fixed. The tests pass now." You merge. Then CI goes red, and when you scroll back through the session you can't find the moment a test actually ran. It's a common enough experience that a recent DEV post title sums it up: I Got Tired of Claude Code Saying 'It's Fixed' When Nothing Had Run. The summary at the end of a session is the model's account of what happened. It isn't a record. Claude Code can give you that record. It has built-in OpenTelemetry support, and with it turned on, every tool call becomes an event: which tool, whether it succeeded, how long it took and, if you opt in, the exact shell command. In an earlier article I covered what to log for an AI agent you run in production. This one points the same idea at the agent that writes your code: send its events to a file on your machine, then check what actually ran after the last edit. Everything about Claude Code's telemetry below comes from its monitoring documentation. What Claude Code can record Telemetry is off until you set CLAUDE_CODE_ENABLE_TELEMETRY=1. Claude Code then exports metrics (token and cost counters, sessions, commits) if you configure a metrics exporter, and events if you configure a logs exporter. The events are what matter here: claude_code.user_prompt is logged when you submit a prompt. The prompt text is redacted unless you set OTEL_LOG_USER_PROMPTS=1. claude_code.tool_result is logged when a tool finishes. It carries tool_name, success ("true" or "false"), duration_ms, and an error_type such as ShellError when the tool failed. claude_code.tool_decision is logged when a permission decision is made. A call you reject produces this event with decision: "reject" and no tool_result, because the tool never ran. claude_code.api_error and claude_code.api_retries_exhausted tell you when requests to the model failed after retries, which explains some sessions that simply stall. Two attributes tie it together. Every event produced while Claude Code works on one prompt shares a prompt.id, so you can pull up everything that happened for "fix the checkout test" in one filter. event.sequence is a counter that orders events within a Claude Code process. By default, the tool_result event tells you that Bash ran, not what it ran. Commands are part of the detail you have to opt into with OTEL_LOG_TOOL_DETAILS=1. With it set, a Bash event gets a tool_parameters JSON string containing full_command, and every tool's arguments are added as tool_input. Step 1: Run a collector that writes to a file You don't need a dashboard to start. The OpenTelemetry Collector can receive Claude Code's events over OTLP and write them to a local file with its file exporter. This config is all it takes (I used otelcol-contrib 0.165.0): receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
http:
endpoint: localhost:4318

exporters:
file:
path: ./claude-events.jsonl

service:
pipelines:
logs:
receivers: [otlp]
exporters: [file]
Start it with otelcol-contrib --config collector.yaml. With the default format: json, the exporter writes newline-delimited OTLP JSON, one line per batch. Binding to localhost keeps the receiver off your network. Note that the file exporter is marked alpha for logs, and its README says exact field names aren't guaranteed to stay stable. Step 2: Point Claude Code at it In the shell where you start Claude Code: export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_LOG_TOOL_DETAILS=1
claude
This is the docs' logs-only configuration plus the tool-details flag. To check it works, submit a prompt and look for a user_prompt event in the file. If nothing arrives, the docs suggest starting Claude Code with claude --debug-file and looking for [3P telemetry] errors in that log. A word on what...

Powered by Readybot.io

Track What Claude Code Actually Tests

Fix GitHub Actions Artifact Not Found Errors

DEV Community

GitHub Actions Artifact not found for name on download

A GitHub Actions Artifact not found for name error is a search that came back empty: actions/download-artifact asked for artifacts matching one name and got none. The scope of that search is the whole story, because unless you pass a token it covers exactly one run in one repository. The default search covers one run in one repository. Every input that widens it has to be set, and two of them only work together. What this error means A job that has nothing to do fails immediately, usually the first job downstream of a build. The step log is short: a line saying it is downloading a single artifact, the with: block echoed back, and then the failure. The text arrives on three lines and only the first names your artifact. The other two are a standing hint printed on every occurrence of this error, so they are not evidence about your run. The producing job is usually green, which is the confusing part, because a green upload step is not the same thing as an upload that happened. ```Actions log, quoted from opentelemetry-js-contrib#3297 Error: Unable to download artifact(s): Artifact not found for name: compile-cache-1928 Please ensure that your artifact is not expired and the artifact was uploaded using a compatible version of toolkit/upload-artifact. For more information, visit the GitHub Artifacts FAQ: https://github.com/actions/toolkit/blob/main/packages/artifact/docs/faq.md

Common causes

The producing job never uploaded anything

A skipped job, a failed job, or an upload whose glob matched nothing all leave the run with no artifact. The last is the quiet one: the default behavior of an empty match is a warning, so the producing job goes green and the first red step is this one, in a different job, minutes later.

The names differ, usually by a matrix suffix

In our experience this is the single most common cause since version 4, because version 4 forced matrix legs to stop sharing one artifact name and the consuming job was often not updated to match. The download takes an exact name, not a prefix, so build will not match build-ubuntu-latest. The fix is either the full name or the pattern input, and the two behave differently on the destination directory.

The artifact belongs to a different run

Anything triggered by workflow_run, anything re-run on its own, and anything reaching across repositories is searching a run that does not hold the artifact. The default scope has no way to express that, so it quietly searches the wrong place and reports the name as missing.

The artifact expired, or was written by version 3

Both are named in the message and both are real. Retention is 90 days by default and can be shortened per upload or per repository, so re-running an old workflow can look for something deleted. Version 3 closed down on 30 January 2025, and artifacts it wrote are not readable by version 4 and later.

How to fix it

Read the run, not the message

  1. Open the run and look at its artifacts panel: it says at once whether the name is wrong or nothing was uploaded.
  2. If it is empty, the fault is in the producing job and this step is only the messenger.
  3. If it holds similar names, it is a mismatch, and the panel shows you the real ones.
  4. If the names are right, check whether the download is pointed at that run at all.

Match the name, or ask for the pattern

The corrected half of the illustrative pair above. Downloading by pattern with merge-multiple puts every matching artifact into one directory, which is what most consumers of a matrix build want. Without it, each artifact lands in its own subdirectory named after it.

```.github/workflows/ci.yml, corrected (illustrative)
publish:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v8
with:
path: dist
pattern: build-
merge-multiple: true
- run: ls -R dist
Make an empty upload fail where it happens The default for an upload that...

Powered by Readybot.io*

Fix GitHub Actions Artifact Not Found Errors

Why SQL Formatting Makes Code Reviews Safer

DEV Community

The one-line SQL query that broke code review

I once reviewed a pull request where the entire database migration was one line. Four hundred and twelve characters of SQL, no line breaks, no indentation, a JOIN buried somewhere in the middle like a landmine. The query was correct. It also took me twenty minutes to be sure it was correct, because I could not read it. That is the whole case for a SQL formatter. It does not make your query faster. It does not fix your logic. It makes the query readable enough that a human can spot the bug before it ships. Formatting is not cosmetic A formatter does two honest things. First, it puts one clause per line: SELECT, FROM, WHERE, GROUP BY, ORDER BY. Second, it indents the parts that belong together, so a JOIN condition sits under its JOIN and a subquery is visibly nested inside its parent. That is it. No magic, no rewriting. The formatted query does exactly what the original did, because only whitespace and casing changed. The bug I was hunting in that PR turned out to be a missing condition in the WHERE clause. On one line, the WHERE clause looked like a wall of text and my eyes slid right past it. Formatted, the missing condition was obvious in about four seconds, because the list of conditions was vertical and one item was simply absent. The dialect trap nobody warns you about Here is where most people pick the wrong formatter: SQL is not one language. MySQL uses backticks for identifiers. SQL Server uses square brackets. PostgreSQL uses double quotes. BigQuery has its own ideas about everything. A formatter that does not know your dialect will happily "fix" syntax that was never broken, or choke on syntax that is perfectly valid in your database. So the first question a good formatter asks is not "how many spaces" but "which database". Standard SQL, MySQL, PostgreSQL, SQLite, SQL Server, Oracle, BigQuery, Snowflake, Redshift: each one parses differently. If your formatter treats them all the same, it is guessing, and guessing with production queries is a bad habit. Minify is the opposite direction, and it has a use Formatting spreads a query out. Minifying crushes it into one line. That sounds like going backwards, until you need to paste a query into a URL parameter, a log line, or a config value where newlines are not welcome. Minify is a transport format, not a reading format. The rule is simple: format for humans, minify for machines, and never confuse the two. One warning about minifying: a careless minifier will strip a comment that your query actually needs, or join two tokens that were only separated by whitespace. A good one leaves string literals and comments alone. If yours does not, find another one. Your queries should never leave your browser This matters more than people admit. The queries you format are often production queries. They contain real table names, real column names, sometimes real customer IDs baked into a WHERE clause. A formatter that uploads your SQL to a server to format it is a data leak wearing a tool costume. The safe version runs entirely in your browser. Paste, format, copy, done. Nothing is uploaded, nothing is stored, nothing is logged. If a tool cannot promise that, do not paste production SQL into it. I built a free one that works exactly this way, with dialect selection, keyword casing, indentation options and a minify mode: it formats MySQL, PostgreSQL, SQLite, SQL Server, Oracle, BigQuery and more, all in your browser. You can try it here: https://www.theutilityhub.online/tools/sql-formatter A small habit that pays off Before you paste a query into a pull request, a migration file, or a chat message to a colleague, run it through a formatter. It takes three seconds. The person reading it, which is often future you, will be able to see the structure instead of decoding a wall of text. And the next time a WHERE condition goes missing, you will spot it in four seconds instead of twenty minutes.

Powered by Readybot.io

Why SQL Formatting Makes Code Reviews Safer

Claude Frontend Design Skills: Save Your Style Rules

DEV Community

Claude skills for frontend design: stop re-typing your design rules

If you build sites with Claude Code, you have probably written the same paragraph a dozen times: "use one accent color, left-aligned hero, no gradient blobs, real spacing scale, subtle motion only." It works for that one prompt. Next session, it's gone, and the agent drifts back to the average-looking page. Claude skills for frontend design fix exactly this. Instead of pasting your taste into every prompt, you package it once and let the agent load it when the task calls for it. What a skill actually is A skill is a folder with a SKILL.md file. The top of the file holds a name and a one-line description. That description is the sentence the agent uses to decide when to reach for the skill. Below it, you write your steps in plain text. The agent doesn't load every skill into every conversation. It reads the descriptions, and only pulls in the full instructions when your request matches. That means you can keep a dozen narrow skills around (frontend design, icon sets, GSAP animation, video rendering) without bloating every session. Because it's just a folder of text, the same skill works in Claude Code, Codex and Cursor. Where to put it Claude Code reads skills from two places: ~/.claude/skills/ for every project .claude/skills/ inside a single project Create the folder if it isn't there, drop the skill folder in, and restart the agent. There's no command to memorize; the next time you ask for something that matches the description, the skill kicks in. On Claude.ai you add skills under Settings → Customize → Skills instead. Writing a tiny frontend design skill yourself You don't need anyone else's skill to start. Here's a minimal one you can adapt: ---
name: house-style-frontend
description: "Use when building or restyling any web page, landing page or UI component in this project."

  1. Layout: left-aligned hero, max content width 1200px, 8px spacing scale.
  2. Type: one display font for headings, one body font. Headline max 8 words.
  3. Color: near-black background, one accent color (#FF5A1F), no gradients behind text.
  4. Components: no emoji icons, no three-identical-cards row unless asked.
  5. Motion: fade/slide on scroll only, under 400ms, respect prefers-reduced-motion.
  6. Before finishing, list any rule you broke and why.
    The last line is the useful trick: asking the agent to report its own rule-breaks turns a vague "make it look good" into something you can review. Keep the description specific. "Use for frontend" is too broad and will fire on everything; "Use when building or restyling a web page in this project" is easier for the agent to match correctly. Read before you install A skill runs with your agent's permissions. Before you drop someone else's folder into ~/.claude/skills/, open the SKILL.md and read the whole thing. Check the license and the author, and be wary of skills that ship scripts you don't understand. Good skill pages show the full SKILL.md before you download. Skills vs. prompts They solve different problems: A prompt describes one page: this hero, this pricing table, this product. A skill describes how you build every page: the rules that should hold no matter what you ask for. The combination is where AI-built sites stop looking AI-built. The skill keeps the baseline consistent; the prompt carries the specific design for the page in front of you. Where to find more At MotionSites we collect open-source Claude and Codex skills for frontend design, motion graphics and video, grouped by what you want to build, with the install command and license for each and a demo on most. Most are free to download: motionsites.org/skills. Start with one small house-style skill like the one above. Once you notice the agent following your rules without being reminded, you'll want a few more.

    Powered by Readybot.io
Claude Frontend Design Skills: Save Your Style Rules

Fixing Sharp libvips Errors on Vercel

DEV Community

sharp on Vercel: "libvips-cpp.so: cannot open shared object file" when the install was clean

Our first production deploy of Brifora (an AI design studio built with Next.js and Supabase) looked perfect — until every route that used sharp started returning 500. The symptom. The function crashed while loading the module, before the first line of the handler ran. The Vercel runtime log said: Error: Could not load the "sharp" module using the linux-x64 runtime
ERR_DLOPEN_FAILED: libvips-cpp.so.8.18.3: cannot open shared object file:
No such file or directory
The build log was clean: all packages installed, no optional dependency skipped, and the lock file had both Linux entries with the right os and cpu. Read which file is missing. Not sharp, not its native binding — libvips-cpp.so. That detail is the whole story. The cause. Since sharp 0.34, libvips ships in a separate package, @img/sharp-libvips-. The binding loads it through an rpath at dlopen time. Nothing ever requires it, so Next's output file tracing doesn't see it and doesn't copy it into the serverless function. (serverExternalPackages is not the problem — sharp is already external, as the error itself shows.) The fix. Tell the tracer explicitly, in next.config.ts: outputFileTracingIncludes: {
'/api/generate': ['node_modules/@img/'],
'/api/uploads': ['node_modules/@img/
'],
'/api/vectorize': ['node_modules/@img/'],
'/api/edit': ['node_modules/@img/
'],
'/api/maintenance/sweep-uploads': ['node_modules/@img/'],
},
We listed routes by name instead of '/
': libvips weighs tens of megabytes, and the login page or the gallery has no use for it. Act two, two days later. The same error came back — this time on two pages, not API routes. They don't process images at all. But they imported a couple of constants (UPLOAD_MAX_BYTES, UPLOAD_TYPES) from our uploads module — and that module imports sharp. A constant pulled the whole native dependency in with it. We had a comment in the config saying "don't forget to add new routes here". It didn't help: the person who wrote the comment was the person who forgot. So we replaced the comment with a check — a command whose output must have as many lines as there are @img entries in the config: grep -rln "generation/uploads'|generation/preview'|generation/svg'|generation/sources'" src/app/
Takeaways: A clean install log doesn't mean a native library reaches your serverless function. The tracer follows require, not rpath or dlopen. Read exactly which file is missing: libvips-cpp.so and sharp.node point to different problems. A hand-maintained list of exceptions will go stale. Replace "remember to update this" comments with a command that checks it. Importing a constant from a module imports its heavy dependencies too. Keep constants in a light file. Brifora: https://brifora.app — built by Weblevo (weblevo.com)

Powered by Readybot.io*

Fixing Sharp libvips Errors on Vercel

Use AI as a Teammate: A Better Developer Workflow

DEV Community

Use AI Like a Teammate, Not a Search Engine

Most people use AI like a search engine: ask a question, get an answer, close the tab. That works for quick lookups, but it leaves most of the value on the table. The developers getting the most out of AI treat it like a teammate. Here is the approach I use after completing Anthropic's courses on AI Fluency, Claude Code and Agent Skills. 1. Give it a goal, not a prompt "Write a function that validates emails" is a prompt. "Our signup form accepts invalid emails and support is getting complaints; find where validation happens and fix it" is a goal. The second gives the AI context, a problem and a definition of done. 2. Let it plan the steps Ask for a plan before any code is written. Reviewing a five-line plan is far cheaper than reviewing a wrong 500-line change, and it surfaces misunderstandings early. 3. Give it the right tools and skills An assistant that can read your project, run tests and follow your team's conventions beats one working from a pasted snippet. Agent skills are a good way to package repeatable instructions, such as your code style or deployment checklist, so you do not re-explain them every session. 4. Review the output, do not just accept it AI can be confidently wrong. Read the diff, run the tests and check edge cases. You stay responsible for what ships. The takeaway AI does not replace your judgment, it multiplies it. The better you define the problem, the better the result. How are you using AI in your workflow: search engine or teammate? Let me know in the comments.

Powered by Readybot.io

Use AI as a Teammate: A Better Developer Workflow

React Native WhatsApp UI Clone with Expo

DEV Community

WhatsApp UI Clone in React Native with Expo – Complete Mobile App UI Project

WhatsApp UI Clone in React Native with Expo – Complete Mobile App UI Project Building a messaging application is a great way to improve your React Native development skills. One of the best ways to understand mobile app development is to study how popular messaging applications organize their screens, navigation, and user interactions. In this article, we'll explore a WhatsApp UI Clone built with React Native and Expo. This project recreates the familiar messaging experience with multiple screens, interactive conversations, status updates, contacts, communities, and call history. Whether you're learning React Native, preparing a mobile development portfolio, or looking for a ready-made messaging app UI project, this project can help you get started faster. 🚀 Project Overview This WhatsApp-inspired mobile application is built using React Native and Expo. It focuses on recreating the frontend interface and navigation experience of a modern messaging application. Instead of building every screen from scratch, developers can explore an existing UI implementation and customize it according to their requirements. Project highlights: WhatsApp-inspired user interface Interactive chat list and conversation screens Status and updates interface Contacts management UI Communities interface Calls and call history screen Bottom tab navigation Dummy users and conversations Android and iOS development support through Expo Explore the complete project: https://skillhost.in/projects/whatsapp-app-ui-design-in-react-native/ 📱 Main Features and Screens Let's explore the major screens included in this React Native WhatsApp UI project. 1. Chats Screen The Chats screen is the main interface where users can view their conversations. It includes: User profile pictures Contact names Latest message previews Message timestamps Unread message counters Search functionality Chat filters Archived conversations New chat action The layout follows a familiar messaging application design, making it easier for developers to understand how to organize conversation lists in React Native. 2. Individual Chat Screen The individual chat screen provides the core messaging interface. It includes: Incoming and outgoing message bubbles Message timestamps Read indicators User profile information Online and last-seen status Message input field Send message interaction Emoji and attachment buttons Camera and microphone interface Voice and video call actions Developers can use this screen as a starting point when building their own messaging application. 3. Status / Updates Screen The Updates screen recreates the status-sharing experience. Features include: My Status section Recent status updates User profile avatars Status indicators Status viewer Progress indicators Reply interface This screen is useful for understanding how to organize status updates and their navigation flow in React Native. 4. Contacts Screen The Contacts screen provides a simple interface for browsing users. It includes: Contact list Search by name or number Profile avatars Online indicators Recently online users Favorite contacts Add contact action You can later connect this interface to your own contacts API or backend. 5. Communities Screen The Communities screen provides a starting point for building group-based communication features. It includes: Community introduction Community icons Existing communities Community descriptions Member avatars Create community action Example community categories include friends and family, technology groups, and workplace communities. 6. Calls Screen The Calls screen displays a messaging application's call history interface. It includes: Incoming calls Outgoing calls Missed call indicators Voice call icons Video call icons Call timestamps Create call link interface This is a frontend representation. Actual voice and video calling require additional communication services. 🛠️ Technologies Used The project uses the following technologies: Technology Purpose Reac...

Powered by Readybot.io

React Native WhatsApp UI Clone with Expo

Stop Meeting No-Shows with Free Booking Tools

DEV Community

How to Stop No-Shows Without Paying for Scheduling Software

You know the shape of it. A call is booked for 10:00. At 10:05 you are staring at an empty meeting room, or an empty video link, wondering whether to wait or move on. At 10:15 you give up. The client emails at noon: sorry, forgot. No reminder, no confirmation, no calendar invite — just a time agreed in an email thread three days ago and then forgotten. No-shows are rarely rudeness. They are usually a system failure: nothing reminded the person, nothing put the meeting on their calendar, and nothing made it easy to cancel or move. Why people actually no-show Most no-shows come down to four small failures. First, there was no confirmation email, so the booking never felt real. Second, there was no calendar invitation, so the meeting never appeared alongside everything else in the person's day. Third, there was no reminder close to the time — a meeting agreed on Monday is easy to forget by Thursday. Fourth, there was no easy way to reschedule, so a clash became a silence instead of a moved meeting. None of those is a character flaw. All of them are fixable with a booking page, and none of them needs paid software. What a free booking page already does The team at ExactReads tested Calendly and Cal.com on their free plans with real bookings, and both did the basics that prevent no-shows. Both sent a confirmation email within minutes of the booking — Calendly at 08:34 IST and Cal.com at 09:20 IST on the test day — and both bookings appeared in the dashboard. Both connected to a real calendar, so the meeting existed somewhere the client could see it. Cal.com went one step further in the test. When the Cal.com page was opened for Monday 16 November, it offered 9:00, 9:30, 10:30 and 11:00 — but no 10:00 slot. The Calendly test booking occupies 10:00–10:30 on the same shared Google Calendar, so Cal.com was reading the calendar and blocking the busy slot. That is conflict checking doing its job: it stops the double-booking that creates the second kind of no-show, the one where two people turn up for the same hour. Calendly's free setup has its own guardrails: the event was set for weekdays 9:00 am to 5:00 pm IST with a 60-day date range and four hours' minimum notice, so nobody can book you with no warning. A no-show routine that costs nothing You do not need a paid plan to run this. Sign up with Google — neither tool asked for a card or a business email in the test. Create one 30-minute event type called "Intro call". Connect your real calendar. Set a minimum notice period of four hours so a booking always leaves you time to prepare. Then book a test slot yourself through the public link and check the confirmation email arrives. If it does not, fix it before a client ever sees the link. Then change one habit: stop offering times in email. Send the link instead. The client picks a slot that is genuinely free, the calendar updates, and the confirmation email does the reminding. Your job is to turn up. One honest warning about "free" There is one trap to know about. Cal.com put the test account straight on its free plan, with no trial. Calendly put the new account on a free Teams Plus trial that ends on 30 November 2026, after which it drops to the free limits — one event type, one calendar. If you judge Calendly during the trial, you are judging the paid product. Set a reminder for the trial end date and check what disappears. The full test, with the exact free-plan limits as published on 15 November 2026, is on ExactReads — read it before you choose. A no-show costs you the hour you set aside plus the hour you spend rebooking it. A booking page with a confirmation email and a connected calendar removes most of them for free. More practical guides for small teams are on the ExactReads homepage.

Powered by Readybot.io

Stop Meeting No-Shows with Free Booking Tools

5 WordPress Speed Fixes for Better Core Web Vitals

DEV Community

5 WordPress Speed Fixes That Actually Move Core Web Vitals

A slow WordPress site hurts user experience, conversions and search visibility. After years of building and tuning WordPress and WooCommerce sites, these are the five fixes I reach for first, in order of impact. 1. Fix the Largest Contentful Paint (LCP) element On most pages the LCP element is a hero image. Serve it in a modern format (WebP or AVIF), size it correctly for the viewport, and never lazy-load it. Add fetchpriority="high" so the browser fetches it early.
2. Audit plugins before adding caching Caching masks a heavy site, it does not fix it. Deactivate plugins one by one and measure. Replace multi-purpose plugins that load scripts on every page with lighter alternatives, or load their assets only where needed. add_action( 'wp_enqueue_scripts', function () {
if ( ! is_page( 'contact' ) ) {
wp_dequeue_script( 'contact-form-7' );
wp_dequeue_style( 'contact-form-7' );
}
}, 100 );
3. Reduce layout shift (CLS) Always set width and height on images and embeds, and reserve space for ads, banners and cookie notices. Preload key web fonts and use font-display: swap to avoid text jumping. 4. Defer non-critical JavaScript Third-party scripts such as chat widgets, analytics and trackers often block rendering. Load them with defer or after user interaction, and remove any you no longer use. 5. Use proper caching and a CDN Page caching, object caching (Redis or Memcached) and a CDN cut server response time (TTFB) dramatically, especially for WooCommerce stores where uncached pages are expensive. Exclude cart, checkout and account pages from page caching. Measure, then fix Test with PageSpeed Insights and the Chrome DevTools Performance panel, and check field data in Search Console. Fix the biggest bottleneck first, re-measure, and repeat. What is the biggest performance problem you have run into on a WordPress site? Share it in the comments.

Powered by Readybot.io

5 WordPress Speed Fixes for Better Core Web Vitals

AIA Certificate Links: Security Risks and Safe Handling

DEV Community

Certificate AIA links are path-building hints from untrusted input

Certificate AIA links are path-building hints from untrusted input An X.509 certificate can carry an Authority Information Access, or AIA, extension that tells a relying party where to find issuer information. RFC 5280 defines the extension and the id-ad-caIssuers access method. The URI is useful when a client needs an intermediate certificate that was not delivered in the TLS handshake. It is not a trust anchor, and it is not a statement that the remote server is safe to contact. Path building and path validation are different steps. RFC 4158 describes path building as the process of assembling candidate chains from certificates and potentially untrusted network locations. Validation then checks signatures, policies, name constraints, validity, and other conditions against an explicit trust store. A server that returns a certificate from an AIA URL has supplied an input to the first step, not proof for the second. Treat AIA retrieval as an outbound network request An application that fetches AIA or CRL distribution URLs on demand creates a path from attacker-influenced certificate data to the application's network. The URL may point at an internal address, a slow host, an oversized response, or a redirect chain. The client still has to verify the returned certificate's signature and issuer relationship, but the request itself can expose topology or consume resources. Apply an allowlist or proxy policy for certificate retrieval. Set connect, read, and total timeouts. Limit redirects, response size, and certificate count. Reject unsupported schemes and credentials embedded in URLs. Do not send cookies, authorization headers, or application credentials with the request. Cache successful issuer certificates by subject and key identifier, with a bounded lifetime. When a chain validates from a local trust store, a missing or failing AIA URL should not cause a fallback to an unauthenticated chain. If the product deliberately supports AIA retrieval, make that behavior visible and test it against a hostile URL. A certificate verifier that accepts an issuer because the URL returned it has confused availability with trust. Record the chain decision Log the leaf subject, issuer, authority key identifier, certificate fingerprint, trust store, and the path-building source. Do not log private keys or full certificate bundles. Record whether an intermediate came from the handshake, a local cache, or a network fetch. That distinction matters during an incident review. OpenSSL exposes trust anchors and untrusted certificate inputs separately. openssl verify can be given a trust store, an untrusted chain, and verification options that control path building. The exact flags depend on the application, but the design principle is stable: trust anchors are chosen by policy, not discovered from the certificate being evaluated. Test a certificate with an AIA URI to an unreachable host, a URI to a host that returns the wrong issuer, and a URI to a local service that should not be contacted. Confirm that the verifier returns a bounded failure. Then confirm that a valid local chain still works when the network is unavailable. Keep the boundary explicit The AIA extension is a useful hint for PKI interoperability. It becomes dangerous when certificate data controls a privileged network client. Keep the network fetch narrow, validate every returned object, and preserve the local trust decision as a separate step. References RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile RFC 4158, Internet X.509 Public Key Infrastructure: Certification Path Building OpenSSL verification options OpenSSL verify command

Powered by Readybot.io

AIA Certificate Links: Security Risks and Safe Handling