今日精选
HOT最新资讯
共 28482 篇Running a software jam in a world of slop
submitted by /u/arrrowfox [link] [留言]
AI เขียนโค้ดแทนเราได้แล้ว — แล้วเราจะเหลืออะไรให้ทำ?
AI เขียนโค้ดแทนเราได้แล้ว — แล้วเราจะเหลืออะไรให้ทำ? มีประโยคที่ได้ยินบ่อยขึ้นทุกวัน: "เดี๋ยวนี้ใครยังไม่ใช้ AI ช่วยเขียนโค้ดบ้าง?" คำตอบคือ — แทบไม่มีแล้วครับ ตั้งแต่ GitHub Copilot, Cursor, Claude, ChatGPT ไปจนถึง agent ที่เขียนโค้ดเองได้ทั้ง project — เราใช้ AI ใน level ที่ต่างกัน: Level หน้าตา ตัวอย่าง 🎵 Vibe Coding พิมพ์สิ่งที่อยากได้ กด accept อย่างเดียว "เขียนหน้า login ให้หน่อย" → กด tab tab tab 🧩 Prompt-Guided คิดก่อน ถามทีละส่วน ตรวจทุกอย่าง "สร้าง UserService ที่ใช้ bcrypt hash password" 🛠️ Skill/Lint-Guided ใช้ AI เป็น editor ชั้นสูง — lint, refactor, test "refactor function นี้ให้เป็น table-driven test" 🏗️ Agent-Based ให้ AI run ทั้ง project — spawn subagent, PR, deploy "พอร์ต microservice นี้จาก Express ไป Fastify" แล้วคำถามคือ — ถ้า AI ทำทั้งหมดนี้ได้ แล้วมนุษย์อย่างเราเหลืออะไร? Unit Test — ตัวอย่างที่เห็นชัดที่สุด ลองดู unit test ที่ AI เขียนให้: // 🤖 AI-generated test func TestCalculateDiscount ( t * testing . T ) { tests := [] struct { name string input float64 expected float64 }{ { "zero" , 0 , 0 }, { "normal" , 100 , 90 }, // 10% discount { "max" , 1000 , 800 }, // 20% discount } for _ , tt := range tests { t . Run ( tt . name , func ( t * testing . T ) { result := CalculateDiscount ( tt . input ) if result != tt . expected { t . Errorf ( "got %v, want %v" , result , tt . expected ) } }) } } ดูเผิน ๆ — สวย, table-driven, ถูกต้องตาม Go convention 1 แต่ถามหน่อย — test นี้บอกอะไรเกี่ยวกับ business? "ส่วนลด 10% สำหรับยอด 100 บาท" — ทำไมต้อง 100? เป็นกฎจากที่ไหน? "ส่วนลด 20% เมื่อยอดถึง 1000" — แล้วถ้าลูกค้าเป็น member ได้เพิ่มอีก 5% ล่ะ? input: 0, expected: 0 — test นี้ cover edge case หรือแค่ cover บรรทัด? AI test ได้ถูกต้องตาม function — แต่มัน ไม่รู้ว่า business จริง ๆ คืออะไร AI ไม่รู้ Business Context — และจะไม่มีวันรู้ นึกภาพระบบ e-commerce: ลูกค้าซื้อสินค้า → ระบบตัดสต็อก → คำนวณส่วนลด → คิดค่าส่ง → ออกใบเสร็จ AI แยก test ทีละ function ได้: ✅ TestDeductStock — "ตัดสต็อก 1 ชิ้น" ✅ TestCalculateDiscount — "ส่วนลด 10%" ✅ TestCalculateShipping —
Show HN: AMA2, messenger built for AI agent
I'm a solo founder building AMA2, a messaging runtime made for AI agents. This is my first Show HN, so I'd really appreciate your feedback. What brought me this idea: At first, I was building an AI agent for solo creators that knows everything about you and can do business chore on your behalf. When I tried to plug it into normal chat tools like Telegram, Discord, Slack... , they all felt wrong for agents: 1. They don't care about an agent's context. To follow a thread, the agent has to pull the
🚀 Build Your First Space Shooter Game with Limn Engine
🚀 Build Your First Space Shooter Game with Limn Engine A Complete Step-by-Step Tutorial for JavaScript Beginners Welcome! In this tutorial, you'll build a complete space shooter game using Limn Engine — a zero‑configuration 2D game engine that runs in your browser. What you'll build: A spaceship that moves, shoots bullets, fights waves of enemies, and keeps score. All in about 100 lines of code . By the end, you'll understand: How to create a game loop How to handle keyboard input How to detect collisions How to use particles for visual effects How to manage game state (lives, score, game over) 🎮 Want to play the finished game? Click here to play Space Shooter Live! Before We Start What You Need A text editor (VS Code, Notepad, or any code editor) A web browser (Chrome, Firefox, Edge) Limn Engine — download epic.js from limn-engine-doc.vercel.app What You Should Know Basic JavaScript (variables, functions, arrays, if-statements) How to open an HTML file in a browser No game development experience required! Step 1: The HTML Structure Every Limn Engine game starts with a simple HTML file. <!doctype html> <html> <head> <script src= "asset/epic.js" ></script> </head> <body> <script> // All your game code goes here </script> </body> </html> What's happening: <script src="asset/epic.js"> — loads the Limn Engine library Everything inside the second <script> tag is your game code Save this as game.html and open it in your browser. You should see a blank canvas with a blue gradient background. Step 2: Setting Up the Game The first thing we need is a Display — this is the engine that creates the canvas, runs the game loop, and handles input. const display = new Display (); display . perform (); // Activates performance mode (dual-canvas rendering) display . start ( 800 , 600 ); // Creates an 800×600 canvas What's happening: new Display() — creates the engine display.perform() — turns on high-performance mode display.start(800, 600) — creates a canvas 800 pixels wide and 600 p
Zero-Knowledge Architecture: What It Means for Your Files
Most of us share files constantly: config files, API specs, design assets, build artifacts. And most of us don't think too hard about where they end up. That's exactly what Zero-Knowledge Architecture (ZKA) is designed to address. But the term gets thrown around loosely, so let's break down what it actually means — and what to look for. The Core Idea: The Server Shouldn't Have to Trust You Traditional cloud storage works roughly like this: You upload a file The server encrypts it (or doesn't) The server holds the key You trust them not to look Zero-knowledge flips this entirely. In a true ZKA system: Encryption happens on your device , before data leaves your control The keys never leave your side — the server never sees them The server handles only encrypted blobs — it's a pipe, not a vault The phrase you'll hear is: "We can't read your data even if we wanted to." That's the point. Why This Actually Matters Here's a concrete scenario: you're sharing a .env file with a contractor. You use a cloud service. The service gets breached a week later. With standard encryption (server holds the key): the attacker potentially has your secrets. With ZKA: the attacker has an encrypted blob that's useless without the key they never had. Beyond breach scenarios, ZKA also helps with: Regulatory compliance — GDPR, HIPAA, and similar frameworks become easier to demonstrate when the service provider has zero access to the data Reduced trust surface — you're not trusting the company, their employees, or anyone who might compel them legally What Real ZKA Looks Like in Practice There's a big difference between claiming zero-knowledge and actually implementing it. Here's what to look for: ✅ Client-side encryption Files should be encrypted in the browser or app before upload. Not on the server. If encryption happens server-side, it's not zero-knowledge — it's just encrypted storage. ✅ Key management stays with you Where do the keys come from? How are they shared with recipients? In a rea
Htmx fragment caching with Accept-Version
IF YOU'VE been developing htmx apps for a while, you might have tried to cache the HTML fragments generated by your server as htmx responses. Caching htmx fragments is the equivalent of caching JSON responses in a SPA. Eg, you might have a fragment response from GET /users/:id that renders a user detail view. You might want to cache this view to avoid expensive queries in the backend if you know the user details haven't changed. But when you start caching htmx fragments, a problem pops up: the style doesn't match the rest of your app. You might be rapidly iterating on the app and making adjustments (small or big) to its CSS. You quickly start to notice that annoyingly frequently, your user fragments are not updating to the latest style. Sure, you can do a hard reload and force the fragment to have the latest style. But surely there must be an easier way? Content negotiation Enter the version headers: Accept-Version : a request header set by your frontend to instruct the backend what version of a resource it wants Version : a response header set by your backend to inform the frontend what version of the resource it is serving. Basically, the backend and frontend have to agree on the version, otherwise they automatically do a hard reload. You can think of this as a lightweight form of content negotiation. Here's a pseudo-code for a backend middleware that shows the rules: if Accept-Version header not in request then continue with request pipeline else if Accept-Version header value = the expected version then continue with request pipeline else if request method is GET then respond with 200 OK empty body and a response header HX-Redirect: request target else continue with request pipeline finally add response header Version: expected version end The meat of this middleware is the redirect if the expected and actual versions don't match. This ensures that the response htmx fragment style can't drift out of sync with the rest of the app. Now, let's look at some of the d
Stop Slouching! Build an AI-Powered Posture Monitor with MediaPipe and Electron
Let’s be honest: as developers, our relationship with our office chairs is... complicated. We start the day sitting upright like productivity gurus, but four hours into a debugging session, we’ve morphed into a human pretzel. This "gamer lean" isn't just a meme; it leads to chronic back pain and decreased focus. In this tutorial, we are going to build a real-time posture tracking system using MediaPipe Pose and Computer Vision to save your spine. By leveraging AI productivity tools and the power of cross-platform Electron desktop apps , we will create a silent guardian that watches your form and pings you the moment you start slouching. If you've been looking for a practical way to dive into MediaPipe and Node.js integration, you're in the right place. For those looking for more production-ready patterns and advanced AI implementations, I highly recommend checking out the deep dives at WellAlly Blog . 🏗 The Architecture The system works by capturing frames from your webcam, processing them through a pre-trained neural network to identify body landmarks, and then applying some basic trigonometry to determine if your posture is healthy. graph TD A[Webcam Stream] --> B[MediaPipe Pose Engine] B --> C[Extract 33 Keypoints] C --> D{Geometry Engine} D -->|Angle > Threshold| E[Slouch Detected] D -->|Angle < Threshold| F[Good Posture] E --> G[Electron Main Process] G --> H[System Notification 🔔] F --> I[Wait 5s] I --> A 🛠 Prerequisites To follow along, you'll need: Node.js (v16+) MediaPipe (The pose solution) OpenCV.js (For frame manipulation) Electron (For the desktop shell) 🚀 Step 1: Setting Up the Pose Engine MediaPipe provides a "Pose" model that gives us 33 landmarks in 3D space. For posture correction, we specifically care about the Ears (7, 8) , Shoulders (11, 12) , and Hips (23, 24) . The Math: Calculating the "Slouch" We measure the angle between the Ear, the Shoulder, and a vertical axis. If your ear moves too far forward relative to your shoulder, that's "Forward
Stop Guessing, Start Modeling: Relationships, Schemas & Joins in Power BI
A database without relationships is just a spreadsheet with delusions of grandeur. If you've ever stared at a Power BI report showing wrong numbers...totals that don't add up, filters that filter nothing, there's a good chance your data model was broken. Not a bug. Just two tables that should've been talking to each other… and weren't. This is your practical guide to data modeling, schemas, relationships, and joins in Power BI, what they are, how they connect, and how to stop getting burned by them. What Is Data Modeling and How Does It Work? Data modeling is the process of defining how your tables connect to each other inside Power BI's engine (called VertiPaq). Think of it like drawing a map between your tables, telling Power BI this column in Table A is the same thing as this column in Table B. When you load multiple tables into Power BI, it doesn't automatically know they're related. A Sales table and a Products table, sitting separately, can't filter each other. Data modeling builds the bridges. Power BI's model view lets you: Define relationships between tables Set cardinality and cross-filter direction Build star or snowflake schemas Create calculated columns and measures using DAX Under the hood, Power BI compresses and stores each column separately ( columnar storage ). Relationships are resolved in-memory at query time, which is why a well-structured model is blazing fast, and a messy one will bring your report to its knees. Key Concepts | Concept | What It Means | |--------------------------|-----------------------------------------------------| | Fact Table | Stores measurable events (sales, transactions, logs)| | Dimension Table | Stores descriptive context (products, customers) | | Primary Key (PK) | Unique identifier column in a dimension table | | Foreign Key (FK) | Column in a fact table referencing a PK in a dim | | Relationship | The defined link between a PK and FK across tables | | Cardinality | Describes how many rows on each side match | | Cro
When paramiko's defaults silently get your IP banned — the look_for_keys and allow_agent trap
One day a multi-site administrator reported a strange bug: "After running the app's SSH connection test 2-3 times, my IP can't reach SSH on that server for a long while ." The errors came back as Connection refused or Connection closed by ... . The server wasn't down, and SSH from a different IP worked fine. The source IP was being temporarily banned at the server. Two external investigation reports gave the cause: server-side protection mechanisms ( fail2ban or PerSourcePenalties in OpenSSH 25+) detect short-windowed authentication failure spikes and temporarily ban the source IP. But the user had only clicked the test button 2-3 times — why were failures "spiking"? The answer turned out to be paramiko's default behavior . paramiko's default — trying many keys per connection paramiko.SSHClient.connect() defaults two options to True : client . connect ( ' host ' , pkey = my_key , # The following are True by default: # look_for_keys=True, # also try ~/.ssh/id_* files # allow_agent=True, # also try ssh-agent registered keys ) When the explicitly passed pkey fails, paramiko falls back through ssh-agent registered keys → ~/.ssh/id_* files → password auth in order. Convenient for developers with a single key. Disastrous for a multi-site administrator: The SSH agent has multiple per-site keys registered ~/.ssh/ holds several id_rsa / id_ed25519 files A single connect call ends up trying 5-10 keys in sequence That blows past the server's MaxAuthTries (default 6) on a single connection So what looked to the user like "one connection test" was being seen by the server as " a suspicious IP racking up 5-10 auth failures in a row ." Repeat that 2-3 times and the protection mechanism declares the IP "exceeded threshold" and bans it. The fix — look_for_keys=False and allow_agent=False paramiko exposes options to scope key trial. We set them explicitly in connect_kwargs : connect_kwargs = { ' pkey ' : my_key , ' look_for_keys ' : False , # don't try ~/.ssh/id_* ' allow_agent ' : F
Top 8 API CLI Tools Every Developer Should Know in 2026
If you've spent any time building or working with APIs, you've probably realized that the terminal is...
Resolve the tenant from the user, not the request
TL;DR A multi-tenant app was resolving the active tenant from the request (subdomain/header) instead of the authenticated user . That makes the client the source of truth for "which tenant am I" — the wrong place for it. Fix: derive the tenant from the user's organization membership, enforce it in middleware, and fail closed. One test locks the behaviour. The bug, in one sentence The request was telling the app which tenant to load, and the app believed it. In a multi-tenant SaaS, every query is implicitly scoped: "give me this tenant's dashboards." If the tenant ID comes from something the client controls — a subdomain, a header, a route param — then the scoping is only as trustworthy as the client. That's a leak waiting to happen. Where the trust should live Think of it like a building pass. The request is someone saying "I'm here for floor 9." The membership record is the pass that says which floors you're actually allowed on. You check the pass, not the claim. Before After Source of truth request (subdomain / header) user's organization membership Who decides the tenant the client the server Failure mode user can land in a tenant they don't belong to resolution fails closed Testable? hard — depends on request shape yes — depends on the user The shape of the fix Resolve the tenant from the authenticated user's organization, in one middleware, before anything tenant-scoped runs: final class SetTenantContext { public function handle ( Request $request , Closure $next ): Response { $org = $request -> user () ?-> currentOrganization (); // No org, no tenant context. Fail closed, never guess. abort_if ( $org === null , 403 , 'No organization context.' ); Tenancy :: setCurrent ( $org -> tenant ); // server-derived, not request-derived return $next ( $request ); } } The key line isn't the setCurrent() — it's that the value comes from $request->user() , not from $request . The user is authenticated; the subdomain is not. request ──> [auth] ──> [SetTenantContext] ──> tena
frontier models are becoming cloud procurement
The interesting part of OpenAI and Codex on AWS is not that another cloud menu got more model names. That part is useful. Enterprises want strong models. Developers want Codex closer to their infrastructure, data, and deployment machinery. The interesting part is that frontier AI is being pulled into the same boring machinery that already governs everything else companies run: procurement, IAM, billing commitments, region policy, audit logs, support contracts, data boundaries, and security review. That sounds like paperwork. It is also how enterprise software becomes real. model access was the easy problem For a while, AI adoption was framed as an access problem. Can we call the model? Can we get enough rate limit? Can we wire the SDK into our product? Can the coding assistant see enough of the repo to be useful? Those are real questions. They are not the end of the story. The next set is much more familiar to anyone who has operated software inside a company: which account owns this usage, which data can cross the boundary, who can create agents, which region runs inference, how the bill is allocated, and what evidence exists when an incident involves model output. That is the part where the demo becomes a platform. OpenAI on AWS matters because many companies already have that platform muscle in AWS. They have IAM, billing, private networking, audit trails, procurement paths, compliance evidence, cost allocation tags, and teams whose job is to make all of this survivable. Putting a frontier model behind that machinery does not make the hard parts disappear. It makes them legible. bedrock is a procurement surface Amazon Bedrock is usually described as a managed model service, which is true and also undersells the point. For enterprises, Bedrock is a procurement and control surface. If OpenAI models and Codex are available through Bedrock, a company can route adoption through an existing cloud relationship instead of creating a new vendor path for every team that wa
When a KPI reads 163 billion instead of 819
TL;DR A metrics engine had two query paths — a SQL push-down for big datasets, an in-memory aggregator for small ones. They drifted. The push-down path bound a metric parameter but never added it to the WHERE . With several metric series in one dataset, every query summed across all of them. A KPI that should read 819 read 163,667,603,769 . Fix: put the metric_key predicate in the shared base WHERE so every compile path inherits it, and regression-test both paths assert it. The setup: two paths, one contract A lot of analytics layers compute the same number two ways. For a big dataset you push the aggregation down to the database. For a small one — a preview, a draft dashboard — you pull the rows and aggregate in memory. Faster path, correct path. Both are supposed to return the same value. That's the contract. The dataset stores rows keyed by a metric_key , because one dataset can hold several series at once — say a plain row count and a count-distinct. Each series lives in the same table, told apart only by its key. The bug: a bound param is not a filter The in-memory aggregator filtered by metric_key correctly. The SQL compiler bound a metric parameter into the query... and never referenced it in the WHERE . With a single series in the dataset, it worked by accident — there was nothing else to sum. Add a second series and the math quietly breaks: the query sums across every series. In this case the second series stored hashed values around 1.9 billion each, so the KPI ballooned from 819 to 163 billion. Before After metric value bound, unused bound WHERE predicate (none on metric) metric_key = {metric:String} 1 series in dataset correct (by luck) correct N series in dataset sums across all isolated The lesson is small and easy to miss: binding a parameter only makes the value available — it does nothing until a predicate references it. When one path already returns sane-looking numbers, nobody goes looking. The real fix is parity, not a patch You could bolt the pr