今日已更新 168 条资讯 | 累计 21034 条内容
关于我们

标签:#EV

找到 3062 篇相关文章

AI 资讯

One-Time vs Subscription Licensing: Which to Use?

Originally published on the Keylight blog . "Should I charge once or charge monthly?" is one of the first real decisions an indie app faces, and it is usually answered by copying whoever the founder admires rather than by what fits the product. Both models are legitimate. This post lays out when each one actually makes sense, the honest tradeoffs, and how Keylight models perpetual keys and renewing subscriptions so the licensing follows your pricing instead of constraining it. The two models, defined A one-time (perpetual) license is a single payment for a license that does not expire. The customer owns that version — and usually some agreed window of updates — forever. Think of the classic "buy version 3, use it as long as you like" desktop app. A subscription license is a recurring payment for continued access. The license is valid while the customer keeps paying; stop paying and access ends or degrades. The recurring revenue funds ongoing development and any server-side costs the app carries. The distinction is not about the dollar amount — it is about what the customer is buying: ownership of a thing, or ongoing access to a service. Get that framing right and the model usually picks itself. When a one-time license is the right call A perpetual license fits when your app is a tool the customer owns and runs locally , with low ongoing cost to you per user. A focused Mac utility, an audio plugin, a developer tool that does its job on the user's machine — these have little marginal server cost, so charging rent for access is hard to justify and customers feel it. One-time pricing also builds trust. There is no metering, no "what happens if I stop paying," no fear of being locked out of work they already did. For tools people depend on, that ownership feeling is a genuine selling point, and it is exactly the kind of no-value-extraction stance that earns goodwill with developers and power users. The tradeoff is honest: revenue is lumpy and front-loaded. You get paid o

2026-06-27 原文 →
AI 资讯

The System Design Framework I Used to Solve 100+ Problems

Hello Devs, for months, I felt confident about system design interviews. I'd watched endless YouTube videos. I'd studied architecture diagrams. I could explain how Netflix builds recommendation systems. I understood Kafka, Redis, load balancers, and microservices. I'd memorized the designs of Twitter, Uber, YouTube, and TinyURL. Then I sat down for my first real system design interview and froze. The interviewer asked: "How would you design a notification system?" I had memorized notification systems. I knew about push notifications, email queues, delivery workers, and retry logic. I could recite architectural patterns. But suddenly, none of that helped. I didn't know which questions to ask first. I started designing before understanding the actual requirements. I built architecture for problems that didn't exist. I missed obvious bottlenecks. I couldn't articulate why I made specific trade-offs. When the interviewer pushed back, I had no framework to adjust. I failed that interview. But that failure taught me something crucial: System design interviews aren't about knowing technologies. They're about knowing how to think. After that, I went back and systematically practiced 20 system design problems. Not passively watching solutions. Actually designing. Making mistakes and refining my approach. And somewhere around problem 12, a pattern emerged. The best candidates didn't know more technologies than anyone else. They had a framework . They asked the same questions in the same order. They structured their thinking consistently. They could handle curveballs because their framework was flexible. They reasoned through trade-offs explicitly. Here's the framework that finally made it click for me. The Problem with Memorization Before I share the framework, let me explain why memorizing designs fails. When you memorize " How to Design Twitter," you learn: Use relational databases for users and tweets Use NoSQL for timelines Cache with Redis Use message queues for fanout S

2026-06-27 原文 →
AI 资讯

How to ship and sell a paid desktop app outside the app stores (2026)

You built a desktop app — macOS, Windows, Linux, native or Tauri/Electron — and you want to sell it directly instead of handing 15–30% to Apple or Microsoft. Selling outside the stores means you keep the margin and own the customer relationship. It also means the plumbing the stores quietly handled is now yours: distribution, payments, licensing, updates, support. Here's the whole path, in roughly the order you'll hit it — with the licensing part (the one most people underestimate) covered properly. Why sell outside the app stores Margin. You keep 85–100% instead of giving up the store's cut. Control. Your own pricing, trials, upgrades, and refund policy — no review gatekeeping, no waiting on approval to ship a fix. The relationship. You get the customer's email and can actually support and re-sell to them. The tradeoff is that the things the store did invisibly — vouching for your binary, taking payment, enforcing the purchase — are now your job. This isn't a Mac thing. Windows devs sell direct constantly, Linux too, and a Tauri or Electron app ships to all three from one codebase. The work below applies across the board. 1. Distribution and updates Before anyone pays, they have to trust and install the thing. macOS: sign with a Developer ID certificate and notarize with Apple, or Gatekeeper will scare users off. Windows: an Authenticode code-signing certificate, ideally EV to build SmartScreen reputation faster. Linux: package as AppImage, .deb / .rpm , or Flatpak depending on your audience. Then updates, because the store won't push them for you: Sparkle (macOS), Squirrel/electron-updater (Electron), the Tauri updater , or your own endpoint. Decide this early — retrofitting auto-update onto a shipped app is miserable. 2. Getting paid Two real models: Stripe (you're the merchant). Lower fees, full control, your brand on the receipt. The catch: sales tax and EU VAT are your responsibility (handle it yourself or bolt on a tax service). Merchant of Record (Lemon Sque

2026-06-27 原文 →
AI 资讯

How to add license keys to a SwiftUI macOS app (in under an hour)

You built a Mac app, you want to sell it outside the App Store, and now you need licensing: a key the customer enters, an activation that sticks, and feature gates that hold up offline. Here's how to do it in an afternoon without standing up a backend. Note: this is cross-posted from the Keylight blog . I build Keylight, so this uses it as the worked example — the shape of the solution applies whatever SDK you choose. The three things licensing actually has to do Strip away the marketing and every licensing system does exactly three jobs: Activate — turn a key the user pastes in into proof-of-purchase bound to this device. Verify — on every launch, confirm that proof is still valid, including offline . Gate — unlock features based on the tier/entitlements the license carries. If you build this by hand you're writing a server, a crypto layer, and a state machine. The point of an SDK is to skip all three. 1. Add the SDK Add the Swift package in Xcode (File ▸ Add Package Dependencies) pointing at the Keylight Swift SDK, then configure it once with your tenant key at app launch: import Keylight let keylight = Keylight ( tenant : "your_tenant_key" ) 2. Activate a key Give the user a text field and call activate . This is the one online step — it exchanges the key for a signed, device-bound lease that's stored locally: do { try await keylight . activate ( key : enteredKey ) // lease stored — the app is now licensed on this device } catch { // show the user why: invalid key, device limit reached, etc. } 3. Verify on launch (offline-safe) On every subsequent launch you don't hit the network. The SDK verifies the stored lease's Ed25519 signature locally and hands you a state: switch keylight . checkOnLaunch () { case . licensed ( let lease ): unlockApp ( entitlements : lease . entitlements ) case . trial ( let daysLeft ): runTrial ( daysLeft : daysLeft ) case . expired , . invalid : showActivationScreen () } No server call, so the app opens instantly and works on a plane. Th

2026-06-27 原文 →
AI 资讯

I compared the licensing tools for my indie Mac app — the honest breakdown

I needed to license a macOS app I sell outside the App Store. I went down the rabbit hole so you don't have to. Here's the honest breakdown — what each tool is genuinely good at, and where it stops. No tool is "best"; they're good at different things. The two questions that decide everything Before the tools, answer these: Do you need real offline verification? (Desktop apps usually do — see firewalls, planes, air-gapped machines.) This eliminates the "license key is just a string you check over HTTP" options for serious use. Do you want payments handled too, or do you already have Stripe? Some of these are licensing-only; some are merchant-of-record that also do keys. The licensing-first tools Keygen — the one most people name first. Language-agnostic API, deep policy engine, open-source, self-hostable. Genuinely powerful. The cost is that it's primitives : you bring your own payments, wire the webhooks, and write the client code. Pick it when you want maximum control and don't mind assembling the flow. Cryptolens — classic license-key system with offline verification via signed responses. Strong .NET heritage. Solid if you're on Windows/.NET and want the traditional key + activation-count model. LicenseSpring — enterprise-leaning. Floating licenses, air-gapped activation, node-locking. Overkill for a solo indie app, right at home if you're selling into companies with offline/dark-site requirements. The payments-first tools (keys as a feature) Lemon Squeezy / Polar — merchant of record, so they handle sales tax for you, with a license-key API bolted on (activate / validate / deactivate). Great for getting paid fast across borders. The licensing side is basic — keys are essentially strings with an activation limit; offline verification isn't really their thing. Gumroad — the simplest possible "sell a thing, get a license key, verify over one endpoint." Fine for a cheap utility where piracy isn't worth fighting. Not infrastructure. StoreKit — only relevant if you shi

2026-06-27 原文 →
AI 资讯

How offline license activation actually works

If you ship a desktop app outside an app store, you eventually hit the same wall: how do you check a license when the user is on a plane, behind a corporate firewall, or just offline? Calling your server on every launch isn't an option. Here's how offline activation actually works, without the hand-waving. The naive version, and why it breaks The first thing everyone reaches for is "call home on launch, get back yes/no." It works in the demo and fails in the wild: No network = no app. Fail-closed locks out paying customers. Fail-open means anyone who blocks your domain runs free. Both are bad. A boolean is forgeable. If your app trusts a {"valid": true} response, a proxy or a patched DNS entry returns that for free. The fix isn't a better endpoint. It's moving the trust off the network and onto cryptography. The model that works: signed leases The durable pattern is a cryptographically signed lease (Keygen calls these license files, Keylight calls them leases — same idea): On first activation, the device talks to the server once . The server returns a small signed document: the license state, an expiry, the device binding, and any entitlements (which features/tiers are unlocked). The document is signed with the server's private key (Ed25519 is the modern choice — small, fast, boring in the good way). Your app ships the matching public key and verifies the signature locally on every launch. No network needed. Because the app only ever verifies with a public key, there's nothing secret in the binary to steal, and a forged lease fails the signature check. That's the whole trick: the server vouches once, math vouches forever after. first launch ──► server signs lease (Ed25519, private key) ──► stored on device every launch ──► app verifies signature (public key) ──► no network Device binding (so one key isn't infinite installs) A lease is bound to a device so a single license can't be pasted onto a thousand machines. The lease embeds a device fingerprint, and the SDK ch

2026-06-27 原文 →
AI 资讯

The Day I Confused Task Queues with Message Brokers And Built the Wrong Thing

In my journey as a backend developer, I had already spent time working with APIs, databases, authentication flows, and background processing. I understood the basic idea that not everything should occur within a request-response cycle, especially when dealing with expensive operations such as sending emails, processing files, or generating reports. Offloading work to the background felt like a solved problem to me. That confidence was exactly what led me into confusion. When I first encountered message brokers and task queues, they looked like different names for the same idea. Both involved queues, both involved workers, and both involved asynchronous processing. In my head, the distinction didn’t seem important, so I treated them interchangeably and assumed that choosing one over the other was just a matter of preference or framework availability. The real issue was that I had not yet understood the difference in intent between communication and execution. What I thought was a simple design choice actually turned into an architectural mistake that affected how I structured an entire system. How I Misunderstood the Problem At the time, I was building systems where the backend had to handle multiple heavy operations. A user could upload files, request reports, or trigger processes that should not block the main API response. Naturally, I reached for a queue-based solution because it is the standard answer for background work. However, instead of asking what role the system needed to play, I focused on what tool could make things asynchronous. That small shift in thinking created the confusion. I assumed that anything that gets delayed or processed later should automatically go into a queue, without distinguishing whether I was dealing with a job that must be executed or an event that other services should react to. This is where I started building the wrong abstraction. Where Task Queues Actually Fit A task queue exists primarily to assign work that must be complete

2026-06-27 原文 →
AI 资讯

I built a free AI README Generator (with markdown preview)

Every developer hates writing READMEs. It's boring, repetitive, and always gets skipped. So I built ReadmeAI — describe your project, AI writes the README instantly. What it does Fill in project name, description, tech stack, features AI generates a complete professional README.md Switch between Raw and Preview tabs to see rendered markdown One click copy Tech Stack Next.js + Tailwind CSS Groq API (openai/gpt-oss-120b) Deployed on Vercel Why I built it (Write 2-3 sentences personally — mention the challenge, that you're a student builder, makes it relatable) Live link https://readmeai-three.vercel.app/ Built this in a day as part of my 30-day AI tools challenge. Would love feedback from the dev community!

2026-06-27 原文 →
AI 资讯

🚀 I Built DevBrand AI with Google AI Studio

This post is my submission for DEV Education Track: Build Apps with Google AI Studio . What I Built For this project, I built DevBrand AI, an AI-powered web application that helps developers create a complete personal branding kit in just a few clicks. Instead of manually writing bios, portfolio headlines, README introductions, or designing graphics, users simply provide their GitHub username, role, tech stack, experience, and preferred design theme. The application then generates everything automatically. Prompt Used I used Google AI Studio's Build apps with Gemini feature with a prompt similar to this: Build a modern React + TypeScript application called DevBrand AI that generates a complete developer branding kit. Use Gemini to generate professional bios, portfolio headlines, GitHub README introductions, project ideas, mission statements, social media introductions, CTAs, and branding recommendations. Use Imagen to generate a modern 3D developer mascot, hero illustration, and portfolio banner. Create a responsive UI using Tailwind CSS with reusable React components, loading animations, copy buttons, and download functionality. Features 🤖 AI-generated developer bio 🎯 Personal tagline 💻 Portfolio headline 📄 GitHub README introduction 💡 Project ideas 🌈 Suggested branding colors 📢 Social media introduction 🚀 Portfolio call-to-action 🎨 AI-generated developer mascot 🖼️ Hero illustration 🌐 Portfolio banner 📋 Copy buttons 📥 Download generated content 📱 Responsive modern interface Demo Screenshots Live Demo App: https://devbrand-ai-706459620449.asia-southeast1.run.app My Experience This project was my first time using the new Build apps with Gemini experience in Google AI Studio, and it was surprisingly fast to go from an idea to a working application. What impressed me most was how the AI generated a well-structured React + TypeScript project instead of just producing a single file. The generated components, services, and overall architecture made the project easy to und

2026-06-27 原文 →
AI 资讯

What Is an Agent Registry? (And What We Broke Before We Had One)

TL;DR An AI agent registry is a centralized catalog of every agent in your organization — what each agent does, what tools it can access, what version is running, who owns it, and how to call it It's to agents what a container registry is to Docker images or what a service mesh is to microservices — the layer that makes distributed components governable We hit the "which agents do we have?" wall at 14 agents across 3 teams. That's when the registry stopped being a nice-to-have About four months into our agentic AI buildout, our head of security asked a question I couldn't answer: "Can you give me a list of every AI agent running in production, what systems they have access to, and what version of each is currently deployed?" I had a rough mental model. I knew about the agents my team had built. I had a vague idea of what the data engineering team had shipped. The product team had recently added two agents I'd heard about secondhand. I spent the better part of a day pulling together a spreadsheet. By the time I finished, one of the agents I'd listed had already been replaced by a newer version. Two of them had been granted access to an internal API I hadn't known about. The spreadsheet was outdated before I sent it. That was our forcing function for building a proper agent registry. This post is what I wish I'd read before that conversation happened. What an agent registry is An agent registry is a centralized catalog of AI agents — a single source of truth that tracks every agent deployed in your organization, its capabilities, its integrations, its ownership, and its current state. The analogy that landed for me: it's to agents what a container registry (Docker Hub, ECR, GCR) is to container images. When you have three containers running, you don't need a registry — you know what you have. When you have 40 containers across six teams, you need a registry to know what's running, who owns it, what version is deployed, and what depends on what. Agents are the same. At

2026-06-27 原文 →
开发者

I built a free whale tracker for Polymarket — here's what I learned

The problem: I kept missing big moves on Polymarket because I had no way to see what the biggest traders were betting on in real time. So I built WhaleTrack — a free, no-signup tool that shows you exactly what top Polymarket whales are buying and selling. What it does Live whale activity feed — see the last 40 trades from top wallets, updated on refresh Whale leaderboard — P&L, win rate, trade count for the biggest accounts No login, no ads, no fluff — just the data How it works The whole thing is vanilla HTML/CSS/JS deployed on Vercel with two serverless functions: /api/whales.js — hits the Polymarket leaderboard API, fetches position stats for each whale, calculates win rates from closed positions /api/activity.js — pulls recent trades for each whale wallet in parallel, filters out internal combo transactions (no title / zero price), and returns the 40 most recent trades The serverless layer solves CORS — Polymarket's data API doesn't allow browser requests, so everything goes server-side. Tech stack Frontend: Vanilla HTML/CSS/JS (zero dependencies) Backend: Vercel serverless functions Data: Polymarket public data API Deploy: Vercel (free tier) Biggest lesson Filtering bad data is half the work. The raw API returns combo trades and internal transactions that show up as "Unknown Market @ 0¢" — useless noise. Had to figure out which fields to check (title, price > 0) to strip them. Also: win rate calculation is tricky when most whales have unrealized profits. Showing "—" instead of 0% is more honest. Try it WhaleTrack → Also launched on Product Hunt today if you want to show some love: Product Hunt Built this in a weekend. Happy to answer questions about the Polymarket API or Vercel serverless setup.

2026-06-27 原文 →
AI 资讯

"It’s just HTML and CSS. It’s too simple to post."

For a long time, I hesitated to share my work. I kept telling myself: "If I post a simple hero section, a basic Bootstrap grid, or a landing page clone, people will judge me. They’ll think I’m not a 'real' developer yet." But today, I saw a video of a developer who built a complete Netflix clone using only HTML & CSS in just 4 hours https://x.com/Aditwariii/status/1681403710457643009?s=20 . It made me stop and think. It’s easy to get so obsessed with complex frameworks, cloud architectures, and database optimizations that we begin to look down on the fundamentals. But here is the psychology of software engineering that we often ignore: Every master was once a beginner: The engineers managing complex distributed systems today started exactly where we are—struggling to center a div and fighting with CSS media queries. Shipping beats hiding: Building a clean, responsive interface in 4 hours shows speed, focus, and attention to detail. Those are core professional hygiene habits. Code is for humans, not just machines: Before we write APIs or database queries, we must master how a human being actually interacts with our interface. I’m letting go of the fear of being judged for "simple" things. From now on, I am building in public. Whether it’s a massive full-stack application or just a beautifully aligned hero section, it is proof of active practice and continuous momentum. Massive respect to [ https://x.com/Aditwariii?s=20 Check out Aditya Tiwari on X. POLYMATH 🧑‍💻 sde @IEX_INDIA_ ] for the inspiration and the reminder to keep shipping! 👇 What is a "small" project or layout you built recently that taught you a major lesson? Let's connect in the comments.

2026-06-27 原文 →
AI 资讯

Parsing and Rebuilding EPUB Files in Python: Lessons Learned

How we handle complex EPUB structures for AI translation without breaking navigation and metadata At LectuLibre , we built an AI‑powered book translation service. Users upload an EPUB, and our pipeline translates the text using LLMs like Claude and DeepSeek. That sounds straightforward until you have to parse and rebuild a valid EPUB without mangling the table of contents, internal links, or styles. I’m sharing the real‑world challenge we faced, how we chose our tooling, and the ugly corners we discovered when dealing with real‑world EPUB files. The Problem: EPUB is a Messy Zip File An EPUB is essentially a ZIP archive containing XHTML, CSS, images, and an OPF manifest. It’s a well‑defined standard (EPUB 3.2), but in practice publishers produce files that bend the rules: missing container.xml , inline styles that break after translation, and structural quirks that make parsing fragile. Our translation process needed to: Accept any EPUB the user throws at us. Extract all text content while preserving the exact structure. Send each paragraph to an LLM for translation. Re‑insert the translated text into the original XHTML files. Repackage everything into a new, valid EPUB. Step 4 is the tricky part: the translated text can be longer or shorter, it may contain characters that need escaping, and the surrounding markup must remain intact. Our Approach: Use ebooklib with a Dose of Defensive Coding We evaluated several Python libraries: epub (pypub) – too simple, no editing support. lxml + manual zip – too much boilerplate. ebooklib – full read/write with a clean API. We went with ebooklib . It provides an object‑oriented model of the EPUB structure, allows us to iterate over documents, and can write a new EPUB from the modified objects. The downside: its documentation is sparse and it can choke on malformed files. We had to layer on a lot of validation. Step 1: Loading and Validating the EPUB import ebooklib from ebooklib import epub def load_epub ( epub_path : str ) -> ep

2026-06-27 原文 →
AI 资讯

Three Months with Java 26: My Thoughts After Using the Latest Release

Java 26 was officially released in March 2026, and after spending the past three months exploring its new features, experimenting with preview APIs, and using it in personal projects, I think it's a good time to share my impressions. Unlike launch-day articles that simply list every new feature, this is a practical look at what actually stood out to me after having some time to work with Java 26. Some improvements are immediately useful, while others feel like building blocks for the future of the language. Java continues its predictable six-month release cycle, and Java 26 is another example of gradual, thoughtful evolution rather than dramatic change. In this article, I'll cover the features I found most interesting, what I like, what I probably won't use right away, and whether I think Java 26 is worth upgrading to. Why Upgrade to Java 26? Every Java release makes the platform: Faster More secure Easier to write Better for cloud applications Even if you don't immediately use every new feature, upgrading allows you to benefit from JVM optimizations and improved tooling. 1. Better Performance Java 26 continues improving the JVM with optimizations for: Faster startup Better garbage collection Reduced memory usage Improved JIT compilation Most applications will benefit automatically without changing a single line of code. 2. Improved Pattern Matching Pattern matching keeps becoming more powerful. Instead of writing: if ( obj instanceof String ) { String text = ( String ) obj ; System . out . println ( text . length ()); } You can simply write: if ( obj instanceof String text ) { System . out . println ( text . length ()); } Cleaner code with less casting. 3. Record Improvements Records remain one of Java's best additions for immutable data. public record User ( Long id , String name , String email ) {} Instead of writing dozens of lines containing: constructor getters equals() hashCode() toString() Java generates them automatically. 4. Better String Templates (Previe

2026-06-27 原文 →
AI 资讯

Why I Built a Tiny Repeated-Game Poker Analysis Tool

Most poker solvers answer one question very well: given a single hand and a single decision tree, what is the equilibrium strategy? (Yes, there is subgame solving, node locking, and plenty more — but the default frame is still one hand, one equilibrium.) I kept getting stuck on a different one. What if the same kind of spot shows up over and over, and a player can commit to a fixed strategy across those repetitions? In a few toy games I had a hunch, worked out by hand, that committing to a fixed strategy could change its value relative to the one-shot picture. I wanted a tool that could make that commitment value precise — to actually analyze it rather than just believe it. (Whether any of this rises to a repeated-game equilibrium is a much stronger claim, and one I am deliberately not making here.) I'm still learning software engineering, so until recently I couldn't implement this — I was stuck reasoning about toy games on paper. AI tooling made the analysis feasible, so I finally started building it: repeated-poker-analysis . It's a small research project: write one narrow model down, run small examples, and record what the model does and doesn't justify. What repeated-poker-analysis is It is an experimental Python toolkit for small abstract poker games. The current MVP covers: fixed Hero commitment candidates, exact Villain best-response diagnostics in small finite trees, candidate generation and filtering, T_deadline , an economic adaptation deadline, local T_detect , an observable-distribution sensitivity estimate, analysis reports and Markdown summaries. It is small on purpose. It is not a full solver and it is not wired to real solver ranges. It starts from one toy game — a river spot — that is tiny enough to inspect and test by hand. That toy spot is one where showdown always chops but rake still bites. In a single-hand view, putting more money into a raked pot can be locally unattractive. Across repeated occurrences the same spot raises a commitment questi

2026-06-27 原文 →
AI 资讯

Tests Pass, Design Breaks: Why TDD Can't Hold the Line on Design Intent

There is a popular misconception that if you do TDD, your design also stays correct. That if the tests pass, quality is guaranteed. In AI-assisted development, this misconception is the kind that quietly accumulates — the more tests you have, the more invisible damage builds up underneath. All tests passed. The design was still broken. Here is what happened today. A function called safe_post.py had its signature changed. Two arguments — notify_sh and doctor_sh — were removed. The test suite passed in full. But the callers were still using the old signature. They were silently broken. Why did the tests pass? Because the test code itself was using the old signature. The tests had been written (by AI) at a time when the design intent was already misunderstood. The misunderstanding was baked into the tests from the start. Tests passing and the design being correct are two different things. "All tests pass" tells you only one thing: the implementation matches what the tests expect. Whether the tests express the right design intent is a separate question. TDD verifies "implementation against tests" — nothing more Let me restate the TDD definition. Red → Green → Refactor. Write a test. Write the implementation that passes the test. Refactor. In this loop, what the test verifies is whether the implementation meets the test's expectation. That is one verification — and only one. What TDD does not verify is whether the test itself correctly expresses the design intent. The structure looks like this: Design intent → Tests (← this link is not verified) ↓ Implementation (← this link is verified by tests) If the person writing the tests misunderstands the design intent, the tests will pass and the design will still be wrong. Machine learning engineer Hamel Husain calls this the "Gulf of Specification" — the gap between what you intended to measure and what your metric actually measures. Optimize hard against a flawed metric and you optimize hard in the wrong direction. The same d

2026-06-27 原文 →
AI 资讯

Post-Mortem Best Practices That Actually Drive Change

The Post-Mortem Nobody Learns From I've sat through hundreds of post-mortems. Most follow the same pattern: something breaks, someone writes a Google Doc, we have a meeting, we list action items, nobody follows up, the same thing happens again in 3 months. Here's how to break the cycle. The Blameless Culture Trap "Blameless" doesn't mean "actionless." The biggest failure mode I see is teams that use blameless culture as an excuse to avoid accountability. Blameless means: we don't punish the person who pushed the bad deploy. Blameless does NOT mean: nobody is responsible for fixing the systemic issue. My Post-Mortem Template # Incident: [SERVICE] [SYMPTOM] on [DATE] ## Impact - Duration: X minutes - Users affected: N - Revenue impact: $X - SLO budget consumed: X% ## Timeline (UTC) - HH:MM - First alert fired - HH:MM - On-call acknowledged - HH:MM - Root cause identified - HH:MM - Fix deployed - HH:MM - Service recovered - HH:MM - All-clear declared ## Root Cause [2-3 sentences. Technical but readable.] ## Contributing Factors 1. [Factor that made the incident possible] 2. [Factor that made detection slow] 3. [Factor that made resolution slow] ## What Went Well - [Something that worked] - [Something that helped] ## What Went Wrong - [Process failure] - [Technical gap] ## Action Items | Action | Owner | Priority | Due Date | Status | |--------|-------|----------|----------|--------| | ... | ... | P1/P2/P3 | ... | Open | ## Lessons Learned [1-2 paragraphs of genuine insight] The Action Item Problem Action items from post-mortems have a 30% completion rate industry-wide. That's terrible. Here's why: Too many items (I've seen post-mortems with 15 action items) No clear ownership No deadline No follow-up mechanism Competing with feature work The Fix: Three Rules Rule 1: Maximum 3 action items per post-mortem. If you can't narrow it to 3, you haven't identified the real problems. Rule 2: Every action item gets a JIRA ticket linked to the next sprint. Not "someday." Not "bac

2026-06-27 原文 →
AI 资讯

OTP Verification in Playwright Without Regex

Most guides to OTP testing in Playwright include a function that looks something like this: function extractOtp ( emailBody : string ): string { const patterns = [ / \b(\d{6})\b / , /code [ : \s] + (\d{4,8}) /i , /verification [ : \s] + (\d{4,8}) /i , /OTP [ : \s] + (\d{4,8}) /i , ]; for ( const pattern of patterns ) { const match = emailBody . match ( pattern ); if ( match ) return match [ 1 ]; } throw new Error ( ' OTP not found in email body ' ); } This function is fragile. It breaks when the email template changes. It returns false positives when the email body contains order IDs or timestamps. It requires you to maintain regex patterns for every email provider your app might use. There is a better way. The Problem with Regex OTP Extraction When your app sends a verification email, the OTP is buried somewhere in the HTML body. To extract it you need to: Fetch the raw email body Parse HTML or plain text Apply regex patterns that match your specific email format Handle edge cases — 4-digit vs 6-digit codes, codes in tables, codes in buttons Every time your email provider changes their template, your regex breaks. Every time you add a new auth provider, you write new patterns. It is maintenance overhead that compounds forever. The right place to extract the OTP is at the infrastructure layer — before the email even reaches your test suite. How ZeroDrop Extracts OTPs at the Edge ZeroDrop catches emails at Cloudflare's edge before storing them. When an email arrives, the worker runs OTP detection on the body and stores the result as a structured field alongside the raw email. By the time your test calls waitForLatest() , the OTP is already extracted and sitting in email.otp . No regex. No HTML parsing. No maintenance. const email = await mail . waitForLatest ( inbox ); email . otp // "847291" — already extracted Setup npm install zerodrop-client No API key. No signup. No environment variables. Basic OTP Test import { test , expect } from ' @playwright/test ' ; import

2026-06-27 原文 →
AI 资讯

When Old Things Take On New Meaning in the Age of AI (Bite-size Article)

Introduction — On What I've Been Writing for Years This is a follow-up to my previous post on Claude and MCP . Just sharing some recent thoughts. Personally, I've always enjoyed keeping records and analyzing my own work. So for years, I've been logging my daily tasks, jotting down thoughts, hesitations, and impressions in notes. I've drawn on these records for reviews, analysis, and decisions on various projects. The tools have shifted over time — Evernote, Notion, Logseq, Taskuma, and so on — but the habit itself, of writing notes into some app or tool, has stayed with me for years. What Happened with MCP I recently wrote about connecting Notion and Google Docs through MCP, and the results have surprised even me. I won't repeat the details here since they're in that post, but ever since I introduced MCP, the flow of information has accelerated dramatically. In particular, I'd been accumulating reviews, task management notes, and brainstorms in Notion for years, and letting Claude read all of this has shifted the meaning of what I'd previously written. When I first started recording in Notion, it never occurred to me that it might be useful to AI. Of course — I had no way to imagine a time when AI would become this close to everyday life, used in this way. I was just writing for plain, analog reasons — "so I could look back later," "so I could organize my own thinking." But the moment MCP made it all readable, the feeling shifted. It's as if my past self comes forward to help my current self. Claude answers my current questions while drawing on the reasoning behind old project decisions, or on impressions I'd noted at the time. I've had moments like that more than once now. Thinking about it: the human brain's memory has limits — even the person who wrote something forgets it quickly. That's why I kept taking notes, leaving behind my thoughts and conclusions at each point in time as a record. And now, in the flow of conversation, AI reads from those records, distill

2026-06-27 原文 →
AI 资讯

Your cloud keys should not exist

Most cloud platforms that need access to your infrastructure start with the same onboarding step: paste in a service account key. Or an access key and secret. Or a JSON blob you downloaded from the console and definitely should not be emailing to yourself. You paste it in. The platform stores it. You hope they encrypted it. You hope they rotate it. You hope nobody on their team can read it. You move on with your day and try not to think about it. We built Zero — b0gy's platform for engineering truth — around a different premise. For cloud infrastructure access — GCP and AWS — we don't store credentials at all. The platform connects to your projects and accounts using short-lived, federated identity tokens that are minted on demand and expire in minutes. There is nothing to leak because there is nothing stored. Not every integration can work this way. GitHub, Slack, and Jira use OAuth, which means we do hold tokens for those services. But for the highest-risk connections — the ones with read access to your entire cloud infrastructure — keyless was a hard requirement. This is the first post in a three-part series about building Zero. We're starting here because the connector model shaped everything else. Why stored secrets are the wrong default The argument for storing a service account key is convenience. You paste it once, the platform can access your cloud whenever it needs to. Simple. The argument against it is longer. A stored secret is a liability that compounds over time. The moment you paste a GCP service account key into a third-party platform, you've created a credential that is valid indefinitely, scoped to whatever permissions you granted, and stored in a system you don't control. If that platform gets breached — or if an employee with database access gets curious — that key works until someone revokes it. And nobody revokes it, because nobody remembers it exists. This isn't theoretical. The GitGuardian 2026 report found 28.65 million hardcoded secrets pus

2026-06-27 原文 →