Pixel

Pixel Updates & Events

Server Updates & Events

Announcements

DEV Community

How to calculate print PPI after a Canvas crop

A 6,000 × 4,000 px landscape photo has 600 source pixels per inch at 10 inches wide. But if you want it to fill a 10 × 8-inch print, the photo's 3:2 rectangle is wider than the 5:4 print. A full-bleed export needs a crop. What matters for sharpness is how many source pixels survive that crop. Calculate the crop before creating the canvas For a full-bleed print, let the shorter supply of pixels set the scale. Divide each decoded image dimension by the corresponding print dimension, then take the smaller result. That gives the source pixels per inch for the crop. Multiplying the print dimensions back by that value gives the width and height of the source rectangle. function printCrop(sw, sh, widthIn, heightIn) {
for (const n of [sw, sh, widthIn, heightIn]) {
if (!Number.isFinite(n) || n <= 0) {
throw new RangeError("Image and print dimensions must be positive");
}
}

const sourcePpi = Math.min(sw / widthIn, sh / heightIn);
const cropWidth = Math.min(sw, widthIn * sourcePpi);
const cropHeight = Math.min(sh, heightIn * sourcePpi);

return {
sourcePpi,
cropWidth,
cropHeight,
x: (sw - cropWidth) / 2,
y: (sh - cropHeight) / 2,
};
}

const crop = printCrop(6000, 4000, 10, 8);
// 500 PPI, with a 5000 × 4000 crop beginning at (500, 0).
At 10 × 8 inches, exactly 1,000 pixels of source width are outside the crop. If the subject is near one side, change x within 0 to sw - cropWidth to keep it in frame. Moving the crop changes what is visible. The resolution stays the same until the crop dimensions change. Draw it at the delivery resolution Keep the source crop in image pixels. Size the output canvas separately based on what the lab requests. Here a 10 × 8-inch print at 300 PPI becomes a 3,000 × 2,400 px image. The nine-argument form of Canvas drawImage takes both rectangles explicitly. // bitmap is a decoded image, such as an ImageBitmap.
const widthIn = 10;
const heightIn = 8;
const requestedPpi = 300;
const source = printCrop(bitmap.width, bitmap.height, widthIn, heightIn);

const canvas = document.createElement("canvas");
canvas.width = Math.round(widthIn * requestedPpi);
canvas.height = Math.round(heightIn * requestedPpi);

canvas.getContext("2d").drawImage(
bitmap,
source.x, source.y, source.cropWidth, source.cropHeight,
0, 0, canvas.width, canvas.height,
);
Here the canvas downsamples a 500 PPI source crop. With a 2,400 × 1,600 px original, the same print would have 200 source PPI. Drawing that smaller image into a 3,000 × 2,400 output can satisfy a file-dimension requirement, but the added pixels do not recover source detail. If you display a quality warning, base it on sourcePpi. These calculations apply to a crop that fills the print. A fit-with-borders preview is a different layout. When exporting, check the lab's required pixel dimensions and selected print size. A browser export's density metadata may differ from the PPI used to size the canvas. AI assistance was used to draft and edit this article. The calculations and code examples were checked before publication.

Powered by Readybot.io

**DEV Community** ## How to calculate print PPI after a …

DEV Community

An Advisory-to-Evidence Triage Playbook for CVE-2026-112687

An Advisory-to-Evidence Triage Playbook for CVE-2026-112687 An advisory creates work before it creates certainty. For CVE-2026-112687, the confirmed facts are concise: a MediaRemote issue, a local-network attacker condition, possible system termination or process memory corruption, and fixes in iOS 27.2, iPadOS 27.2, and tvOS 27.2. The playbook should turn those facts into decisions without pretending to know the unpublished trigger. Security operations teams can use five gates: scope, exposure, patch evidence, observation, and closure. Each gate produces a record that another owner can review. Gate 1: define the supported inventory Start with Apple's affected model list. The iOS and iPadOS advisory names iPhone 11 and later and multiple iPad Pro, iPad Air, iPad, and iPad mini generations. The tvOS advisory names Apple TV 4K second generation and later. Merge endpoint-management data, procurement records, network observations, and owner interviews. Deduplicate by device identity rather than user name. Mark devices with unknown ownership or stale check-ins as unresolved, not compliant. The gate closes when the team has a defined population and a named owner for every management class: supervised endpoints, personal devices, and media appliances. Gate 2: model local reachability The advisory says an attacker on the local network may cause the documented impact. It does not identify a packet signature, so the team should map possible local paths rather than search for one known exploit string. Collect wireless segments, routing boundaries, guest isolation, peer-to-peer policy, and management subnet rules for the device population. Identify systems that can initiate communication with the Apple devices and whether the business needs those paths. A reachability review can support two decisions: which devices have a broader local peer population, and which network changes can reduce exposure while patching. No network map alone proves that an attack occurred. Gate 3: obtain current build evidence The fixed release family is 27.2. A valid record includes the reported OS version, device model, last check-in time, and source. Sample devices where management coverage is ambiguous or the record changed recently. For personal devices, collect only the minimum status allowed by policy. For Apple TV, confirm the physical device and location, because a management entry may outlive the hardware. A build below 27.2 creates a remediation task. It does not create a compromise finding. Keep those statuses separate so that a patch exception is not mislabeled as an incident. Gate 4: review observable effects The documented outcomes are unexpected system termination and process-memory corruption. Review crash or diagnostic records involving media services, especially repeated failures after a local-network change or near a suspicious host. Enrich each candidate with the device build, network peers, applications in use, and source logs. Preserve evidence before rebooting or replacing a device when a credible incident lead exists. Use the same review on fixed devices as a control. A repeated failure in both fixed and vulnerable populations may indicate a different cause. The public record does not provide a safe reproduction method, so do not attempt to generate a crash from a speculative trigger. Gate 5: assign an outcome and a next step Each device should end in one of four states: patched with current evidence, remediation pending with an owner, an approved business exception with containment, or an incident candidate under investigation. These states answer different questions and should not collapse into a single "risk" label. A business exception requires more than a recorded reason. It needs a network restriction or compensating control, an accountable owner, and a review date. An incident candidate needs evidence preservation, scope analysis, and a decision about whether the case is malicious, benign, or still unknown. Use exposure data wi...

Powered by Readybot.io

**DEV Community** ## An Advisory-to-Evidence Triage Playbook for CVE-2026-112687 An …

IGN India Pc

Dragon Ball FighterZ - Official Balance Update Trailer

A new balance update is coming soon to DRAGON BALL FighterZ! Check out this new trailer for DRAGON BALL FighterZ, the 3v3 tag fighting game developed by Arc System Works! DRAGON BALL FighterZ is available on PlayStation 4 (PS4), PlayStation 5 (PS5), PC (Steam), Nintendo Switch, Xbox One, and Xbox Series X|S!

Powered by Readybot.io

**IGN India Pc** ## Dragon Ball FighterZ - Official Balance …

DEV Community

Build an LLM From Scratch in 5 Minutes on a Free GPU: I Trained a 5.9-Million-Parameter Storyteller, and Here Is What It Wrote

Part 1 of ten. Each post is a short, plain-words tour of one lesson from e=mc², a free build-an-LLM-from-scratch course; the full lesson, notebook and numbers are on the site. Most people think building a language model takes a lab, a budget and a team. Last month I built one from nothing, on a free Google Colab GPU, in about five minutes end to end. It has 5.9 million parameters, it learned to write bedtime stories, and it is sitting on the Hugging Face Hub right now where you can run it. I want to show you what it wrote, what the numbers mean, and why doing this once makes every headline about trillion-parameter models stop sounding like magic. Meet Momo and Ella The lesson is told through two characters, because the ideas are simpler than the vocabulary. Momo is a young monkey learning to tell stories. Inside his head are millions of tiny dials, all pointing somewhere random, so his first stories are nonsense. Ella is an elephant, and elephants never forget. Every night she reads Momo a story one word at a time, stops before each word, lets him guess, and tells him how wrong he was. Then she nudges his dials a little. Thousands of nights later, Momo tells stories. That is the whole of machine learning in one paragraph. Momo is the model. His dials are the weights (5.9 million of them here). Ella's stories are the training data. "How wrong were you" is the loss. Nudging the dials is gradient descent. Everything else is detail, and the lesson decodes about forty of those details one at a time. What a language model does, in one sentence Given the words so far, guess the next one. A story is that guess repeated. A chat answer is the same thing with your question as the words so far. When Momo continues "Once upon a time, a little", four things happen. The sentence is bitten into tokens, pieces of text with a number on each (our vocabulary has 4,096). Each token becomes a spot on a meaning map, a list of 256 numbers where similar words sit close together. Then every token looks back at the tokens before it and decides how much to listen to each: "capital" finds "France" and borrows some of its meaning. That is attention, from the 2017 paper that started all this, and it runs six times in a row, four heads each. Finally the last token's sharpened meaning is scored against every word in the vocabulary, and one is picked. That is it. That is also, with more stories, more blocks and more GPUs, what the big ones do. The numbers, honestly 5.9 million parameters: 6 blocks, 4 attention heads, 256-wide, a vocabulary of 4,096 pieces learned from the stories themselves. 1,500 training steps, each a batch of 32 windows of 256 tokens. 1.2 minutes of training on Colab's free T4 GPU; about five minutes for the whole notebook; about two minutes on an Apple Silicon Mac. Perplexity 9 on 200 stories the model never saw. Perplexity is "between how many words is Momo still choosing". Random guessing would be 4,096. Watching that number fall from 4,096 to 9 in front of you is the moment the field stops being mysterious. The 200 quiz stories were held out before training, so nothing the model memorised can flatter the score. An earlier draft got that wrong, and fixing it is why I trust the 9. What it wrote Given "Lily had a red balloon.", one run produced this: She ran to her mom and gave her a big bite. They both ate the balloon and had the balloon. It was shiny and yellow. They ran to the park to play with. Grammatical, kid-flavoured, slightly unhinged. That is exactly what 5.9 million parameters and two minutes buy, and I think it is wonderful. Then I gave it "Once upon a time, a little monkey", and it wrote this: Momo was sad because he could not swim like Bo the bear cub. He sat in the tall grass with his feet in the water. Ella said, "Try again, little one. Every time you try, you learn a little more." She held him up with her trunk. Momo kicked and kicked. Soon he could swim all by himself. The end. Lovely, right? It is also, character for...

Powered by Readybot.io

**DEV Community** ## Build an LLM From Scratch in 5 …

DEV Community

7 tips I’d give to beginner developers

7 tips I’d give to beginner developers I’m a full stack developer working with Flutter, React.js, Node.js, MongoDB, and PostgreSQL. Here’s what I wish I’d known when I started: Build projects, don’t just watch tutorials. Tutorials feel productive, but you only learn when you get stuck and fix things yourself. Pick a small idea and build it. Learn the fundamentals first. Frameworks change fast. JavaScript, Dart, HTTP, databases, and Git stay useful for years. Read error messages. Most of the answer is usually in the error. Read it slowly before you search or ask for help. Learn Git early. Commit often, write clear messages, and push your work to GitHub. It becomes your portfolio too. Don’t chase every new tool. Pick one stack, get good at it, and then expand. Depth beats a long list of half-learned technologies. Use AI as a helper, not a replacement. AI tools are great for explaining code and speeding up work, but make sure you understand what they write. If you can’t explain it, you don’t own it. Be patient with yourself. Everyone feels lost sometimes. Getting stuck is not a sign you’re bad at this. It’s how the learning happens. Keep building, keep shipping, and keep learning a little every day. What’s the best tip you would give to someone just starting out? BeginnerDevelopers #WebDevelopment #Programming #CodingTips

Powered by Readybot.io

**DEV Community** ## 7 tips I’d give to beginner developers …

DEV Community

Migrating an existing Next.js app to Cache Components before Next.js 17

With Next.js 16.4 (October 2026), the Next.js team started recommending Cache Components for every app. New projects from create-next-app have it switched on, and the release notes say it will become the default in Next.js 17. If you have an existing App Router app, that gives you a choice: migrate now at your own pace, or do it under pressure during a major upgrade. This post walks through the migration by hand, in the order that keeps your app building the whole time. Short version: enable cacheComponents, run the codemod that opts every route out of validation, fix the few things that can't be deferred, then convert one route at a time. Nothing is cached any more unless you write use cache. Patch to 16.4.5 first. Last checked: 15 November 2026, against the Next.js 16.4 documentation. What actually changes In the older App Router model, caching was mostly implicit and set per route: export const dynamic, export const revalidate, fetchCache, and cache options on fetch. With Cache Components the rule flips: Nothing is cached unless you mark it with the 'use cache' directive. You mark the function or component that should be cached, instead of setting a route-wide config. Anything that needs the request (cookies, headers, search params) goes inside a boundary, so the rest of the page can be prerendered as a static shell and the request-specific part streams in. The Next.js team describes use cache as a component-level version of the Cache-Control header. Before you start Be on Next.js 16. Cache Components needs it. Coming from 15 or older, do the version upgrade first. Install 16.4.5 or later. The November 2026 security release fixed several cache-disclosure bugs in Cache Components. Details in my write-up of that release. Decide who drives. There's an official agent skill that does this migration feature by feature (npx skills add vercel/next.js --skill next-cache-components-adoption), and next upgrade --agent gives a coding agent version-specific guidance. Even if you use them, read on: you're the one reviewing the pull requests. The migration, step by step Step 1: turn it on // next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
cacheComponents: true,
partialPrefetching: true,
};

export default nextConfig;
The 16.4 release notes treat Partial Prefetching as part of the model, so enable both. If you previously used experimental.dynamicIO or experimental.useCache, cacheComponents replaces them. Your build will now fail on any route segment that still exports dynamic, revalidate or fetchCache. That's expected. The table in the next section tells you what to do with each. Step 2: opt every route out of validation In development, Next.js now checks whether each route can render instantly and reports what blocks it. On an existing app that's a lot of reports at once. One codemod defers them all: npx @next/codemod@canary cache-components-instant-false ./app
It adds export const instant = false to every page, layout and default file. Use ./src/app if your project has a src folder. A wrong path reports "0 ok" rather than failing, so check the file count it prints. instant = false means "this segment is allowed to block". It doesn't force the route to be dynamic. Step 3: fix what can't be deferred Synchronous, non-deterministic calls during prerender fail the build whether a route is opted out or not: new Date() and Date.now() Math.random() crypto.randomUUID() Move each one so it runs at request time: put the component that needs it inside and call connection() before it, or move it into a Client Component. Step 4: convert one route at a time Remove instant = false from a route, open it in development and read the dev overlay. Each insight names the component and offers one of two fixes: Cache it: add 'use cache' to the component or data function. Stream it: wrap it in . Repeat until no route opts out. One thing that's easy to miss: insights don't appear i...

Powered by Readybot.io

**DEV Community** ## Migrating an existing Next.js app to Cache …

DEV Community

Installing cPanel & WHM on a VPS: requirements, the install command and what breaks

Most cPanel installs that fail do so before the installer has really started. The command itself is one line; the work is in giving it a server it is willing to run on. This is the checklist we use, written for developers who are comfortable with SSH but have not set up cPanel & WHM from scratch before. Everything about requirements comes from cPanel's own documentation as it stood in November 2026, so check it again if you are reading this much later. First, decide whether you need it at all cPanel on your own VPS makes sense when you are hosting several sites, for yourself or for clients, and you want the WHM side: creating accounts, setting limits, handing each client their own login. It does not make much sense for one website. The arithmetic is simple. You pay for the VPS, and on top of that you pay cPanel for a licence every month, priced by the number of accounts. Even the single-account tier costs more per month than most shared cPanel hosting plans, which already include the licence and someone else patching the server. If you have one WordPress site and no wish to be root, shared cPanel hosting is cheaper and less work. Install cPanel on a VPS when you have outgrown that, not before. Pick a supported operating system cPanel is narrow about distributions. As of November 2026 the documentation lists: OS Versions Notes AlmaLinux OS 8 (cPanel 110+), 9 (114+), 10 (132+) The default choice for most people Ubuntu 24.04 LTS only PowerDNS is the only supported nameserver; AppArmor can stay on CloudLinux 7, 8, 9, 10 10 needs cPanel 134+; 7 cannot take cPanel 112 or later and is not recommended Rocky Linux none for new installs cPanel now says you can no longer install on Rocky Linux Debian is not on the list, and neither is any Ubuntu release other than 24.04. The Rocky Linux change catches people out because older tutorials still recommend it. If you have no reason to prefer otherwise, take AlmaLinux 9 or 10. One quirk: if the server's IP address already has an active CloudLinux licence, the installer converts AlmaLinux to CloudLinux. Add --skip-cloudlinux to the install command to prevent that. Hardware: minimum and what to actually buy From the AlmaLinux and Ubuntu requirement pages: CPU: 64-bit, 1.1 GHz minimum (Ubuntu page recommends 2 GHz). ARM is not supported. RAM: 2 GB minimum, 4 GB recommended. If you plan to run ClamAV, cPanel strongly recommends at least 3 GB. Below the minimum, the installer refuses to continue. Disk: 20 GB minimum, 40 GB recommended, plus at least 5 GB free in /usr/local/cpanel for installs and upgrades. File system: XFS or ext4. On a single partition, at least 1,000,000 inodes, plus 50,000 per cPanel account. Network: a static, public IPv4 address. IPv6-only servers are not supported, DHCP-assigned addresses are not allowed, and cPanel only licenses publicly visible static IPs with working DNS. Behind NAT, you need 1:1 NAT with NAT loopback. In practice, 2 GB is enough to finish the install and not much more. Start at 4 GB and 40 GB if real sites and mail will live on the box. Start from a fresh OS This is the rule people most want to skip, and it is not optional. cPanel's installation guide says to install only on a freshly installed operating system, and warns that services installed before or during the install cause compatibility problems. That means no Apache, Nginx, MySQL, Postfix or Docker stack you set up "just to test". The installer brings its own web, mail, DNS and database services. There is also no uninstaller. cPanel's documentation says removing it means reformatting the server. So if the VPS has history, back up what you need and reinstall the image. Set a proper hostname The hostname must be a fully qualified domain name on a domain you have registered, must not be the same as any domain you will host on the server, can be at most 60 characters, and must resolve to the server's IP. Use a subdomain, not the bare domain. Create the A record (and AAAA if you use IPv6) first, th...

Powered by Readybot.io

**DEV Community** ## Installing cPanel & WHM on a VPS: …

DEV Community

🐾 DEV Pet Corner #6: Show Us Your Pets!

TL;DR DEV Pet Corner is back for another Sunday! It's a weekly series where we take a little break from tech and share our love for animals. Share pictures, stories, and memories of your pets, animals you've met, or adorable animals you follow online. Share as many pictures and links as you'd like! You don't need to own a pet to join in. If animals make you smile, you're welcome here ❤️ Table of Contents ❤️ Thank you for the love 🐶 Show us your animal friends! 🐾 See you next Sunday! ❤️ Thank you for the love! Hey everyone 👋 It's Sunday again, and DEV Pet Corner is back for its 6th edition! First of all, thank you so much to everyone who joined the previous edition ❤️ I loved seeing all your pictures, reading your stories, and getting to know your animal friends. It's always so lovely to see everyone come together and share something they love. I'm really happy this little corner of DEV is bringing us together! Thank you for taking the time to share your pictures and a little piece of your lives with us. It really means a lot to me! If you missed the previous edition, you can still meet all the cuties here 👉 DEV Pet Corner #5 Now, let's do this again 😄 🐶 Show us your animal friends! I'd love to see your pets, whether they're the ones waiting for you at home, the ones you grew up with, or the ones who have a special place in your heart. And you don't need to have a pet of your own to join in! Maybe you've met a friendly dog on a walk, spotted a cat in your neighborhood, or come across an animal on campus that made you stop for a moment. Perhaps you follow an adorable animal account on Instagram or have a favorite animal video you keep going back to. If it involves an animal you love or something that makes you smile, I'd love to see it 😃 Share pictures, funny moments, sweet memories, little stories, or links to your favorite animal posts. Share as many pictures as you'd like. There's no limit! If you're sharing someone else's content, please link to the original post and respect the creator's wishes about sharing their work. A little note for returning readers: You might notice this section looks familiar 😄 I'll keep it in future editions, too, so new readers can easily see what they can share without going back to previous posts. As always, feel free to join in with anything you'd like or simply enjoy all the cuteness in the comments! 🐾 See you next Sunday! I'm so happy this little series is bringing people together over something we love. Thank you for being part of it and making each edition special ❤️ As always, let's keep the comments friendly and welcoming to everyone. I'm looking forward to seeing your animal friends and enjoying all the cuteness with you! Thank you for being here. See you next Sunday for DEV Pet Corner #7!

Powered by Readybot.io

**DEV Community** ## 🐾 DEV Pet Corner #6: Show Us …

DEV Community

I classified 63 item categories for shipping personal luggage to China - here is the open dataset (CC BY)

Most "can I ship X to China" guides answer one item at a time. I wanted to know what the whole set of answers looks like. So I took the 63 paired English / Chinese item Q&A pages we publish for our used-personal-luggage line, classified each direct answer into one of four mutually exclusive verdicts, reviewed all 63 rows a second time, and published the result as an open dataset. The split Verdict Count Share Accepted as personal luggage 33 52.4% Personal-use only; new or resale stock out of scope 6 9.5% Send the item list for confirmation first 15 23.8% Outside our luggage-only scope 9 14.3% Three things fell out of the data that I did not expect: The boundary is the condition of the item, not the object. The same cosmetic travels as personal luggage if it is opened and in use; new or resale stock is out of scope. 54 of 63 categories have some personal-use path. The 15 "check first" cases are not random. Eight involve lithium cells (cameras, drones, headphones, laptops, consoles, phones, power banks, tablets) and need a model or Wh rating. The rest cluster around oversize dimensions, declared value and quantity. The nine exclusions form two clean groups: eight resale / daigou categories (auto parts, formula, coffee, electronics, pet food, snacks, supplements, tea) and one regulated equipment category. Not a scattered blacklist. Method, in short Corpus: 63 English + 63 Chinese first-party item pages, snapshot 15 November 2026, after a service-scope convergence on 13 November. Each direct answer was assigned one verdict by explicit rules, then all 63 rows were reviewed individually; eight boundary cases were corrected (for example, "personal-use only" was initially misread as "out of scope"). Categories are an editorial grouping, not a customs commodity code. No third-party data, no estimates, no search-volume numbers. Important caveat: this index describes OUR service scope. It is not a customs ruling, not a list of import regulations and not legal or declaration advice. Verdicts can change; check the linked item page for current wording. What's in the download JSON: 63 bilingual rows with verdict, category, confirmation fields and both source URLs CSV: the same 63 rows flat, ready for a spreadsheet The report page also has the category x verdict cross-tab and a ready-made citation CC BY 4.0. Credit "Subao Luggage" and link to the report: https://subaog.com/en/report/luggage-item-admissibility-index-2026 Direct downloads: https://subaog.com/assets/downloads/luggage-item-admissibility-2026.json https://subaog.com/assets/downloads/luggage-item-admissibility-2026.csv Chinese edition: https://subaog.com/zh-cn/report/luggage-item-admissibility-index-2026 I run a China-bound consolidated line for used personal luggage and personal effects, so I am not a neutral observer - that is exactly why the methodology and the limits are written down. If you find a row that disagrees with its linked item page, tell me in the comments and I will fix the dataset.

Powered by Readybot.io

**DEV Community** ## I classified 63 item categories for shipping …

DEV Community

内容系统应保存真实标题:工程角度的思考

从工程角度看,内容系统保存真实标题而非从 URL slug 反推,是更稳健的设计选择。 首先,URL slug 往往经过简化处理——移除非 ASCII 字符、转小写、替换空格为连字符。这种有损转换是不可逆的,反推必然丢失原始信息。例如标题 "C++ 内存管理技巧" 变成 "c-memory-management-tips",反推只能得到无法还原的残损字符串。 其次,slug 生成规则多变。不同系统可能采用 kebab-case、snake_case 或添加日期前缀。若后期调整规则,依赖反推的下游系统将集体失效。 再者,国际化场景下,slug 可能被转译为 ASCII 或保留 Unicode,行为不一致。保存真实标题则提供单一可信数据源。 最后,SEO 和分享需求常要求标题与 slug 解耦。保存原标题让系统支持 A/B 测试、多语言版本和动态元数据,而无需重构存储层。 综上,显式存储标题以数据冗余换取系统可靠性和扩展性,是面向未来的工程实践。

Powered by Readybot.io

**DEV Community** ## 内容系统应保存真实标题:工程角度的思考 从工程角度看,内容系统保存真实标题而非从 URL slug 反推,是更稳健的设计选择。 首先,URL slug …

DEV Community

The clever retrieval trick lost. A boring if statement won.

I built a multi-agent freelance copilot, measured it properly, and the results embarrassed my favourite idea. GigBid reads freelance job posts, decides whether to bid, and writes a proposal where every claim must link to evidence from the freelancer's own portfolio. A person approves everything before it is sent. I built it as a coursework project (LangGraph, three MCP servers, a React front end), and I measured it against a simulator I also wrote. This is not a tutorial. It is about the one result that changed how I think about where the effort should go. The idea I was proud of A job post asks for four things: PyTorch, Hugging Face, NLP, and some Python. Searching a portfolio with the whole post feels sloppy; surely it is better to decompose the post into requirements, retrieve evidence for each one separately, and merge the results. It is the standard advice in the advanced-RAG literature, it is satisfying to build, and I built it first. I wrote my hypothesis down before running anything (it is committed in docs/adr/0002-rag-hypotheses.md): decomposition would beat the naive baseline on jobs with four requirements by at least five points of Recall@5. What actually happened Evaluated on 60 stratified jobs per persona, three personas, evidence-level metrics against gold projects: variant Recall@5 MRR naive dense retrieval 0.91 0.63 hybrid BM25 + dense 1.00 0.74 hybrid + cross-encoder rerank 1.00 0.92 requirement decomposition, first version (merged per chunk) 0.84 0.42 requirement decomposition, fixed (merged per project) 0.92 0.45 Decomposition did not just fail to help. It made retrieval worse than the baseline, by a wide margin. My first implementation merged per-requirement rankings at the chunk level, which scatters a project's chunks across lists; merging at project level raised recall back up, but ranking quality stayed far below simple hybrid-plus-rerank. An ablation made the cause unmistakable. I took the full composed pipeline (decompose + BM25 + rerank + outcome boost), MRR 0.47, and removed one component at a time. Removing BM25, the reranker, or the outcome boost changed almost nothing. Removing decomposition alone restored MRR to 0.92. Why? Because on this kind of corpus every skill appears in several projects. A query for "Hugging Face" alone retrieves every project that mentions it; merging four such lists rewards projects that match one requirement strongly over projects that match all four. The whole-post query already contains the conjunction, and the cross-encoder is exactly the tool that reads it. Splitting the question threw that information away. I kept the failed variant in the results, and the chunk-level version's file as well. A negative result that is measured beats a win that is not. The thing that moved the needle more While I was tuning retrieval, a different number was quietly bad. My bid-or-skip decision had precision of about 0.85: it was bidding on jobs it should skip. I assumed the cause was something subtle, like weak evidence matching. It was not subtle. Twenty-four of the failures on the dev set were low-ball jobs: budgets of five to twenty dollars that my system happily bid on, because the decision rule never compared the budget to the freelancer's own rate floor. Fit was fine. Risk was fine. The job was just not worth the paid Connects. The fix was a dozen lines of deterministic code: if the posted budget cannot reach the freelancer's minimum, skip. Bid-or-skip F1 on that sample went from 0.89 to 0.98, and failures from 30 to 6. No model changed. No prompt changed. Set that next to the retrieval work: a day of retrieval variants improved a ranking metric (MRR 0.63 to 0.92), while the largest real error in the decision sat somewhere none of those variants touched, and a boring comparison fixed it. I did not measure how much retrieval quality moves the final decision, so I will not claim it does not. Retrieval quality is easy to measure, so it gets optimised; a missing business rule ...

Powered by Readybot.io

**DEV Community** ## The clever retrieval trick lost. A boring …

DEV Community

Is your Lovable or Supabase app readable without a login? A 15-minute check

In November 2026, the Hamburg security firm Crissy Field published a study of apps built with Lovable, the AI app builder. Working with the German newspaper Handelsblatt, they looked at 159,041 Lovable projects and found personal and confidential data that anyone could read without logging in: passport numbers, payment details, private chat messages, contracts and invoices. If you built an app with Lovable, Bolt, v0, Cursor or any other AI tool and it stores data in Supabase, this is worth 15 minutes today. The same mistake shows up in hand-written apps too. Short version: your Supabase key is visible in the browser on purpose. The only thing protecting your data is Row Level Security (RLS) and grants inside the database. Open the SQL Editor, list the tables that have RLS switched off, then request one of your own tables with nothing but the public key. If rows come back, strangers can read them too. Last checked: 15 November 2026. What the researchers found The numbers, as the report states them: Step Count Lovable projects examined (from the Common Crawl web archive, December 2025 to September 2026) 159,041 Of those, projects using Supabase 34,545 Sites that sent database records as soon as the page loaded, no login 24,664 Of those, sites where further read-only requests returned tables containing email addresses 7,403 (30%) The researchers are careful about that last figure. An email address can be a public contact address or test data, so 30% is not a confirmed leak rate, and their sample doesn't represent every Lovable app. Some news coverage quotes 24,664 or 7,403 as "the number of leaking apps". Neither is quite what the report says. What they did confirm is serious enough: A lifestyle forum exposed more than 80,000 profiles with names, emails and dates of birth, plus more than 200,000 chat messages. A service provider exposed more than 1,000 records with passport numbers, expiry dates and nationalities. Event organisers and restaurants exposed tens of thousands of ticket and food orders, including phone numbers, addresses and payment information. A property manager exposed AI-written summaries of internal emails about tenants and owners. The report could not establish whether any of this data had been misused. Why this happens A Supabase app talks to its database straight from the browser. To do that, the browser needs a key, called the publishable key (older projects call it the anon key). That key is meant to be public. Anyone can open your site, press F12 and copy it. So the key is not what protects your data. Two settings inside the database do: Grants decide whether a role may read or write a table at all. RLS policies decide which rows that role may touch. Supabase's own documentation puts it plainly: a table in an exposed schema without RLS is readable and writable by any role that has a grant on it. On many existing projects, new tables in the public schema are granted to every role by default, including anon, the role used for visitors who aren't signed in. Put together: if a table has RLS off, or has a policy that says "everyone may read everything", then your login screen is decoration. The data is one request away. AI builders produce an app that works. Whether signed-out strangers can read the table behind it is not something you see while clicking through your own app, logged in as yourself. The 15-minute check Do this only on your own project. 1. List tables with RLS switched off In the Supabase Dashboard, open SQL Editor and run: select tablename, rowsecurity
from pg_tables
where schemaname = 'public'
order by rowsecurity, tablename;
Every row showing false is a table with no row protection at all. 2. Look for policies that allow everything select tablename, policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
order by tablename;
Read the qual column. A value of true on a policy whose roles include anon or public means every visitor can read every row. That's right...

Powered by Readybot.io

**DEV Community** ## Is your Lovable or Supabase app readable …

DEV Community

Next.js November 2026 security release: are you affected, and how to patch (16.4.5 and 15.5.29)

On 3 November 2026, the Next.js team released 16.4.5 and 15.5.29 to fix seven security issues. The most serious is a cache bug: in apps that use use cache, data cached for one tenant or locale can be served to another. Four of the seven involve Cache Components and only affect Next.js 16. That used to be a small group. Since Next.js 16.4, every new project made with create-next-app has Cache Components on by default, so it's now worth checking rather than assuming. The other three also affect Next.js 15. Short version: run npm ls next. If you're on 16.x below 16.4.5, or 15.x below 15.5.29, upgrade and redeploy. If your app uses use cache together with root parameters, also clear your caches after the upgrade, because wrong entries can outlive the fix. Last checked: 15 November 2026, against the Next.js blog post and the seven GitHub advisories. The seven issues at a glance Issue Advisory and CVE Affected versions You're exposed if Cache disclosure across root parameters when unstable_cache and use cache are combined GHSA-mfr8-8qww-v76h, CVE-2026-119790 16.3.0 to 16.4.4 The same use cache function is called both directly and from inside unstable_cache, and it reads a root parameter Cache leak across root parameters in nested use cache functions GHSA-vc7v-qv4w-wrv8, CVE-2026-119351 16.2.0 to 16.4.4 Cache Components is on, and one cached function calls another that reads a root parameter Cache disclosure and poisoning through binary use cache arguments GHSA-rhh4-g77r-r9qj, CVE-2026-119349 16.0.0 to 16.4.4 You pass binary values such as Uint8Array or Blob to a use cache function Shared shell cache poisoning GHSA-vvgp-ww4w-46vf, CVE-2026-119350 16.4.0 to 16.4.4 Self-hosted with next start, cacheComponents: true, Partial Prefetching off or unset Response mix-up when forwarding fetched responses GHSA-pc58-hwjq-p385, CVE-2026-119348 16.0.0 to 16.4.4, and 15.x up to 15.5.28 Self-hosted behind an HTTP/1.1 reverse proxy that pipelines requests, and your app returns a fetched Response unchanged HttpOnly cookie values exposed on Edge routes GHSA-f3mh-rxg3-f5g2, CVE-2026-119346 16.0.0 to 16.4.4, and 15.0.0 to 15.5.28 An Edge Route Handler or Edge API route sets a cookie through NextResponse SVG rejection bypass in Image Optimization GHSA-7qx7-33qx-rqx2, CVE-2026-119347 16.0.0 to 16.4.4, and 15.0.0 to 15.5.28 Self-hosted, and the image optimizer can be given an attacker-supplied image A note on severity. The Next.js blog post labels the first issue "High Severity" and the other six medium. On GitHub, all seven advisories are rated Moderate, with CVSS scores between 6.0 and 6.9. Either way, none is a remote code execution bug like the two in the October release. What each one means in plain words Cached data served to the wrong tenant or locale A root parameter is a dynamic segment that sits before the root layout, for example the [tenant] in app/[tenant]/layout.tsx or the [lang] in app/[lang]/layout.tsx. Code reads it with next/root-params. Apps use it to decide whose data, or which language, a page shows. Three of the cache bugs break that separation: unstable_cache plus use cache. Just after a server process starts, an unstable_cache call can pick up the result of another request's use cache call that is still in flight. It then stores that result under a key that ignores the root parameter. From then on, requests for other tenants or locales get the same entry until it's revalidated or evicted. Nested use cache functions. An outer cached function can be stored under a key that leaves out the root parameter its inner function read. The advisory adds that entries written this way can ignore tag invalidation and cache lifetimes. Binary arguments. Two different Uint8Array or Blob arguments can produce the same cache key, so one user can get another's cached result. In all three, an attacker can't choose what leaks. Which data gets served depends on which request filled the cache first. Shared shell poisoning (self-hosted) On a self-hosted...

Powered by Readybot.io

**DEV Community** ## Next.js November 2026 security release: are you …

DEV Community

MongoDB vs PostgreSQL: how I choose between them

I use both in my projects, so people often ask me which one is better. My answer is that it depends on the shape of your data. I reach for PostgreSQL when: Data is highly relational (users, orders, payments, invoices) I need strict consistency and transactions I want complex queries with joins and aggregations The schema is fairly stable and I want the database to enforce it I reach for MongoDB when: Data is flexible or changes shape often (content, logs, product catalogs) I’m prototyping and want to move fast without migrations Documents are naturally nested and read together I’m working with Node.js and want JSON-like data end to end Common mistakes I see: Choosing MongoDB because it feels easier, then fighting relationships later Choosing PostgreSQL for everything without thinking about whether the data really needs that structure Picking based on hype instead of how the data will be queried Neither one is “better.” The right choice comes from your data and your queries, not from trends. And sometimes using both in one project is perfectly fine. Which one do you use most, and why? MongoDB #PostgreSQL #Database #BackendDevelopment #FullStack

Powered by Readybot.io

**DEV Community** ## MongoDB vs PostgreSQL: how I choose between …

DEV Community

Character Swap 1.5: Motion Transfer Plus SAM 3.1 Masking, Eight Steps

Swapping a character in a video splits into two problems that people usually conflate: deciding what gets replaced, and making the replacement move the way the original did. Character Swap 1.5 handles both in one graph, with SAM 3.1 for the first and motion transfer for the second. One workflow, eight steps. What each half contributes SAM 3.1 runs the masking. Prompt-segment the subject you want to replace and it returns a per-frame mask. This is the part that used to be manual rotoscoping: a fighter turning through 180 degrees means the mask has to track limbs, hair and any held props across every frame. Motion transfer runs the replacement. The source clip's motion drives the new character. Body shape, limb timing and the general read of the movement come from the original performance. Why the mask quality decides everything The motion transfer half is actually well-behaved. The failures almost always trace back to the mask: Occlusion. A hand passing in front of the torso needs two mask regions, not one. Single-region masks ghost at the crossing. Fast motion. Between two frames with large displacement, the mask can lose the limb entirely for a frame or two. That reads as a flicker. Soft edges. Hair and loose fabric need a feathered mask. A hard-edged mask produces a visible halo. SAM 3.1 is considerably better than the previous generation at the first two. The third is still on you — feather the mask. The eight-step claim The VDN8 variant uses a distilled sampler, eight steps per frame. In practice that is the difference between a swap that renders overnight and one that renders during a coffee break. The quality cost lands where you would expect: fine fabric texture and small facial details are slightly softer than a 20-step pass. Where this is used Replacing a performer in an existing shot without a reshoot. Casting a specific character into existing motion reference. Localisation: same performance, different character per market. The last one is the commercially interesting case — one shot, several faces, no second shoot. Files HF: https://huggingface.co/AI-KSK/h3-character-swap-sam-vdn8 ModelScope: https://modelscope.cn/models/Sunjian520/h3-character-swap-sam-vdn8 Video walkthrough (Chinese): https://youtu.be/iuEmeHgHGIg Bilibili: https://www.bilibili.com/video/BV1GLnH6NEPC/ Notes Single ComfyUI workflow export; SAM 3.1 and the H3 weights must exist locally. Tutorial material, not a product. Independent AI-KSK release; not affiliated with the model authors.

Powered by Readybot.io

**DEV Community** ## Character Swap 1.5: Motion Transfer Plus SAM …

DEV Community

My agent could fetch a URL but could not search for one

In my September 1 setup of DeepSeek Harness v0.1.1-rc.2, web_fetch worked while web_search could not complete a search. The difference was the service behind each tool, rather than whether the agent could reach the web. This is a record of that setup, not a claim about the current release or every account. Two tools, two dependencies The default profile selected searchProvider: deepseek-official and looked for its key in DEEPSEEK_API_KEY. My fresh DeepSeek API account returned 402 Insufficient Balance. Having a key was therefore insufficient. The request reached a service that required a funded account. In the version I inspected, the three bundled search backends were DeepSeek, Exa, and Perplexity; none supplied a free search path for my setup. web_fetch still worked. Fetching an already-known public URL used anonymous HTTP, without that search-provider balance requirement. That made the failure easy to describe too broadly: “the agent cannot use the web” would have hidden the useful capability that remained. What I would check before changing the model For a similar failure, I would separate these checks: Which provider does the active profile select? A tool named web_search does not tell you which external service will receive the request. Is the credential present, and is the account usable? These are separate conditions. In this setup, the balance response was the evidence that mattered. Can the agent fetch a known URL? A successful fetch does not prove search works, but it narrows the failure to a different dependency. What capability can the task still use? Supplying a known source URL may allow a fetch-only task to proceed. It does not replace discovery when finding sources is the task. Those are diagnostic steps, not a guarantee that every 402 has the same cause. The concrete observation here was the Insufficient Balance response from my account. A backend implementation is not a working fallback I wrote a Tavily provider and plugin, and checked the interface against the installed type declarations. I had not tested it with a Tavily key. That means I had an implementation to try, not a verified alternative, and I cannot report that it fixed search. The useful result from this investigation was a smaller, more accurate description of the system: fetching worked; the configured search service required funding; the proposed replacement remained untested. For agent tooling, I would like a setup check to expose those dependencies before the first task needs them. “Tool enabled” is a much weaker statement than “the selected provider can complete a request with this account.”

Powered by Readybot.io

**DEV Community** ## My agent could fetch a URL but …

DEV Community

Validate Cached Cloudflare Workflow Step Output on Replay

Cloudflare Workflows persist successful step results and resume execution after the last completed step, but a later deployment that tightens an input contract can cause the system to accept stale data without re-running the callback. Quick solution: const result = await step.do("fetch-candidate", async () => {
return await fetchExternalCandidate();
});

if (!isValidCandidate(result)) {
throw new Error("Persisted workflow step result failed validation under current contract");
}
When you deploy a new version of a serverless workflow, understanding how durable persistence interacts with updated code is essential for maintaining application integrity. Developers often assume that changing a validation check inside a step callback ensures that all future runs respect the new rule. However, because Cloudflare Workflows serialize and store successful step results, a resumed workflow instance may bypass the callback entirely and return the older, unvalidated object directly from storage. This creates a hidden window where stale or malformed data slips past your newly introduced checks. The Replay Validation Problem in Serverless Workflows Cloudflare Workflows handle long-running operations by breaking execution into discrete, durable steps. According to the official Build your first Workflow guide, successful step results are persisted automatically, and execution resumes from the boundary of completed steps during subsequent events. While this architecture provides excellent fault tolerance and cost efficiency, it introduces a subtle lifecycle challenge when your validation logic evolves. Imagine you deploy a workflow that selects a candidate from an external provider. In version 1 of your script, the step returns a candidate object containing only an identifier. In version 2, you update your application code to require a strict schema including a security hash and a valid version number. If an active workflow instance completed the step under version 1 and pauses before the next action, deploying version 2 means the workflow will resume by loading the old, minimal object from durable storage. Because the step callback does not re-run, your new validation check inside the callback is never evaluated against that cached result. To prevent your system from accepting legacy payloads under a tightened contract, you must separate the durable data retrieval from the runtime validation guard. If you are looking for ways to ensure your CI/CD pipeline maintains high standards, you can Fixing SonarCloud Quality Gate Rating E to A in Production to ensure your deployments remain clean and compliant. Designing Post-Step Validation Guards To ensure that every workflow execution obeys your latest invariants, place your validation logic immediately after the step.do call returns, rather than exclusively inside the anonymous function passed to the step. This guarantees that whether the step executes fresh or replays from storage, the returned payload must pass the current runtime checks before any downstream side effects occur. Consider the following implementation pattern that evaluates the returned structure against a strict type guard: import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from "cloudflare:workers";

interface CandidatePayload {
id: string;
version: number;
checksum: string;
}

export class CandidateWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
const rawData = await step.do("fetch-candidate", async () => {
return {
id: "cand_123",
version: 1,
checksum: "legacy-hash"
};
});

const candidate = rawData as CandidatePayload;

if (candidate.version < 2 || !candidate.checksum) {
  throw new Error("Stale candidate payload detected during workflow replay validation");
}

await step.do("process-candidate", async () => {
  return await persistCandidate(candidate);
});

}
}
As described in the Rules of...

Powered by Readybot.io

**DEV Community** ## Validate Cached Cloudflare Workflow Step Output on …

DEV Community

MiniMax H3 Video Control: Eight ControlNet 2.0 Modes, Motion Guidance and 1080P Two-Pass

ControlNet on video is a different problem than on images, because the control signal has to stay coherent frame to frame. This episode maps eight ControlNet Union 2.0 modes across four generation tasks and documents where each one holds. The four workflows # Workflow Task 01 CN Union 2.0 video control + local inpaint, VDN 12-step Guided generation 02 Audio-driven digital human, VDN 12-step Talking head 03 General video generation, VDN 12-step Baseline 04 CN Union local inpaint only Pure repaint The eight modes, ranked by usefulness on video Strong on video: Depth — the workhorse. Preserves scene geometry across a cut and survives camera movement. Canny — works for hard-edged subjects (architecture, props) and falls apart on hair and foliage. Pose — good for single-subject motion, degrades when limbs occlude each other. Conditional: Lineart — clean results but sensitive to input line quality; a wobbly line becomes a wobbly render. Normal — useful for lighting-consistent repaints, rarely used alone. Weak on video: Tile — designed for upscaling stills; on video it produces frame-to-frame texture flicker. Seg — segmentation maps jitter between frames, and the jitter transfers directly into the output. The eighth mode — same problem as seg: per-frame instability is amplified by the model. That ranking is the practical content of the episode. The modes that work on stills are not the modes that work on video, because stills have no temporal coherence requirement. The two-pass 1080P finish VDN 12-step at native resolution gives a clean base; the second pass upscales to 1080P and re-renders at low denoise. The reason to split it: a single pass at 1080P produces softer motion because the sampler spends its budget on resolution instead of on movement. Audio-driven digital human Workflow 02 is the one with the most obvious commercial use — one portrait plus one audio track, 12 steps per frame. The limitation is the same as any audio-driven approach: change the audio and you re-render, because the mouth timing is derived from it. Files HF: https://huggingface.co/AI-KSK/minimax-h3-cn2-video-control ModelScope: https://modelscope.cn/models/Sunjian520/minimax-h3-cn2-video-control Video walkthrough (Chinese): https://youtu.be/WdAaPq2Xa0I Bilibili: https://www.bilibili.com/video/BV1SEJm6PE22/ Notes ComfyUI workflow exports; the H3 weights and CN Union 2.0 adapter must exist locally. Tutorial material, not a product. Independent AI-KSK release; not affiliated with the model authors.

Powered by Readybot.io

**DEV Community** ## MiniMax H3 Video Control: Eight ControlNet 2.0 …

DEV Community

Overcoming Partisan Bias and Trust Barriers in Real-Time AI Political Fact-Checking

System Architecture and Verification Mechanics The LogicLens and Receipts platform operates through an automated real-time processing pipeline designed to ingest streaming audio or document Object Model (DOM) data, extract verifiable claims, and synthesize grounded verdicts via Retrieval-Augmented Generation (RAG). By coupling deterministic parsing with stochastic language modeling, the system attempts to operationalize real-time epistemic accountability during live media consumption. Data Ingestion: Browser extension content scripts and mobile app wrappers extract live speech transcripts from streaming video elements or raw text claims from active web pages, establishing the foundational data pipeline without altering native media rendering. Claim Segmentation: A filtering module isolates verifiable factual assertions from subjective rhetoric, filler speech, and opinions prior to downstream execution, ensuring that compute resources are reserved strictly for falsifiable statements. Evidence Retrieval: The pipeline executes live web search queries to fetch primary and secondary source documents, anchoring the verification context before passing inputs to the language model (Claude) to mitigate hallucination risks and enforce rigorous grounding. Overlay Injection: Asynchronous UI scripts inject confidence scores, truth verdicts, and clickable citations directly into the active viewport without blocking media playback or scrolling threads, minimizing user friction during high-frequency data streams. The Demonstration Artifact and Temporal Decoupling Public distribution of the tool relies on recorded video artifacts as primary product proofs. When an uncalibrated or truncated screen recording is deployed without full execution context, systemic verification logic breaks down at the observational interface, illustrating how human-AI trust dynamics can be fractured by poor communicative framing. Impact: Pressured by a two-year development cycle and active competitor traction, the developer published an unedited screen capture, trading methodological transparency for speed-to-market visibility. Internal Process: The recording window initiated mid-stream, capturing a factual verification instance directed at one political figure while omitting the preceding counter-example segment where an opposing figure's claim was evaluated. Observable Effect: Viewers observed an asymmetric distribution of negative verdicts, triggering immediate user rejection driven by perceived partisan manipulation and a collapse of perceived epistemic neutrality—proving that advanced architectural safeguards can be instantly neutralized by a single compromised demonstration artifact. Structural Instabilities and Friction Vectors Beyond the immediate optics of its public demonstration, the platform exhibits high vulnerability across several operational, economic, and architectural dimensions that threaten its long-term viability as a mainstream civic utility: Vector Mechanistic Failure Mode Epistemic Recursion Users reject LLM-synthesized verdicts due to opaque source-weighting heuristics and inherent model hallucination risks, raising the unsolved verification problem: Who fact-checks the fact-checker? This dynamic generates a recursive loop of systemic skepticism. Unit Economics Continuous real-time LLM inference and live search API calls scale linearly with user watch-time, directly conflicting with a free consumer distribution model and creating structural unsustainability that can only be resolved through monetization shifts or cost-prohibitive subsidies. Permission Boundaries Browsers require broad host permissions (read/modify all site data) to parse arbitrary DOM structures, triggering immediate user threat-modeling friction regarding telemetry, data privacy, and potential surveillance overreach. Temporal Desynchronization Continuous real-time pop-up alerts compete for user attention during fast-paced video consumption, inducing split-attention fati...

Powered by Readybot.io

**DEV Community** ## Overcoming Partisan Bias and Trust Barriers in …

DEV Community

.NET 11 Unpacked: Why I'm Recommending STS This Time

Table of Contents What to Expect From This Article A Short History of LTS and STS Why There Are Two Tracks at All? Why Microsoft Extended STS to 24 Months? The Catch: The Same End Date Why .NET 11 Might Be the Better Migration Target Right Now "But It's Not Battle Tested Yet" When .NET 10 Is Still the Right Call What I'd Recommend, by Situation A Pre-Upgrade Checklist Wrapping Up What to Expect From This Article For years, my advice on .NET upgrades was simple: plan around LTS releases. Skip the STS ones unless you have a very good reason. This November, that advice is not as strong as before. .NET 10 (LTS) and .NET 11 (STS) both reach end of support on November 14, 2028. Same day. One of them is a year newer. In this first article of the .NET 11 Unpacked series, I'll walk through where LTS and STS came from, why the two tracks exist, and why, for a lot of teams right now, .NET 11 may be the better upgrade target. I'll also cover when it isn't. A Short History of LTS and STS The two-track model is almost as old as .NET Core itself, which has been around since 2016. But the rules have changed several times. When What changed Nov 2026 .NET 11 ships as STS with 2 years of support, ending on the same day as .NET 10 LTS Sep 2025 STS support is extended from 18 to 24 months, starting with .NET 9 2020 to 2022 .NET 5 drops "Core" from the name, the non-LTS track gets 18 months, and it's renamed from "Current" to "Standard Term Support" 2019 Microsoft commits to a new major version every November: even numbers are LTS, odd numbers are not 2016 .NET Core 1.0 defines two release types: LTS and "Current" A few things stand out. STS never meant "Short." The official name is Standard Term Support, and Microsoft's policy page still notes that STS releases were previously known as Current releases. Most of us (me included) read the "S" as "Short" for years. That small misreading did a lot of damage to how people see these releases. STS support has only ever grown. It went from "a few months after the next release" to 18 months, and now to 24. So I guess "standard" is even more suitable wording here. By the way, LTS has stayed at three years the whole time. It hasn't changed. The 2025 change is the one that matters here. Under the old rule, an STS release was supported for 6 months after its successor shipped. Under the new rule, it's 12 months. That one change lines up the end date of every STS release with the LTS release before it. Why There Are Two Tracks at All? The two tracks serve two kinds of teams. LTS is for teams that want to upgrade as rarely as possible. STS is for teams that want new features and performance gains every single year. What the tracks don't differ in is quality standards. The .NET release policies say LTS and STS releases differ only by support duration, and that the team uses the same engineering and release processes for both, including for security, compatibility and reliability. The support policy page puts it even more plainly: the quality of all releases is the same. So an STS release isn't a beta, a preview or a "test" version of the next LTS. STS is a completely different concept. It's a full production release with a shorter warranty. Why Microsoft Extended STS to 24 Months? The 2025 extension wasn't really about STS users. It fixed a problem for LTS users (me included). More and more of .NET now ships out of band, outside the yearly release: .NET Aspire, Microsoft.Extensions.AI and the C# Dev Kit, for example. Those components sometimes need package versions from the newest yearly release. So a team that thought it was fully on LTS could pull in a few STS packages without noticing. Under the 18-month rule, those packages lost support six months before the LTS runtime they ran on. Moving STS to 24 months closed that gap: the STS packages now stay supported exactly as long as the LTS release before them. The side effect is the one this article is about. Every STS release now retires on the same day as th...

Powered by Readybot.io

**DEV Community** ## .NET 11 Unpacked: Why I'm Recommending STS …

DEV Community

Show your unread Mail count in your Mac menu bar

This guide first appeared on multimeterapp.com. Multimeter is a Mac menu bar app that turns any number into a live meter. Mail’s Dock badge is easy to miss when the Dock is hidden, and Mail’s window is usually behind everything else. A Script meter asks Mail with AppleScript how many messages in the Inbox are unread and puts the number next to the clock. What you need Multimeter for macOS 13 or later, $19.99 once. The direct download version of Multimeter from this site (the Script source isn’t in the Mac App Store version). Multimeter 1.1.1 or later. Earlier versions can’t ask macOS for permission to talk to other apps. Choose Check for Updates… from any meter’s menu. Apple Mail with at least one account set up. Set it up Here’s the command. It asks Mail for the unread count of the Inbox, the one at the top of Mail’s sidebar that combines your accounts, and prints a placeholder when Mail isn’t running: osascript -e 'if application "Mail" is running then' -e 'tell application "Mail" to return unread count of inbox' -e 'else' -e 'return "{\"value\": 0, \"formatted\": \"closed\"}"' -e 'end if'
In Multimeter, choose Add Meter… from any meter’s menu, pick Script and paste the command. Set Refresh every to 1 minute. Mail answers in well under a second, but there’s no reason to ask it more often, and 5 minutes is fine for a quieter inbox. Set the label to MAIL, the range to 0 to 50, and alerts to High values with a warning at 10 and critical at 25 if you want the number to change color as mail piles up. With Mail open, wait for the first refresh. macOS asks once: “Multimeter” wants access to control “Mail”. Allowing control will provide access to documents and data in “Mail”, and to perform actions within that app. Below it is Multimeter’s reason: “Multimeter runs your script meters, and scripts that read other apps (like Things, Reminders, Mail or Music) need your permission to control them.” Click Allow. Until you do, the meter shows a dash; the number appears at the next refresh, or right away with Refresh Now in the meter’s menu. Multimeter settings In Customize This Meter… (from the meter’s menu): Settings for this meter Setting Value Source Script Command the osascript line above Refresh every 1 minute or slower Range 0 to 50 Alerts High values: warning 10, critical 25 (optional) Label MAIL Face Label & Value or LCD Readout Width 120 pt for Label & Value Tested: Set up on October 31, 2026 in Multimeter 1.1.1 on macOS 27, with one test mail account holding 7 unread messages. macOS showed the Automation prompt with Multimeter’s reason at the first refresh; after Allow the menu bar showed MAIL 7 in Label & Value and LCD Readout. After 2 messages were marked read it showed MAIL 5 at the next refresh. With Mail quit, both meters showed closed and Mail stayed closed for the next two refreshes; reopening Mail brought back MAIL 5. The command took about half a second when run in Terminal. Script meters need the direct download version of Multimeter from this site, which is the one on sale now. How commands run, the PATH they see and the 10 second limit are in the Script meters guide. Limits Mail must be open. That’s on purpose: asking a closed Mail would launch it. The count is the Inbox only. Unread mail that rules moved to other mailboxes isn’t included; see the variation below for one mailbox. If Mail is set to show Categories, its Dock badge can count Primary only. This meter counts every unread message in the Inbox. Variations One account’s inbox Replace inbox with the account’s mailbox. The account name is the one in Mail’s sidebar: Command osascript -e 'if application "Mail" is running then' -e 'tell application "Mail" to return unread count of mailbox "INBOX" of account "Work"' -e 'end if'
Notify me when mail arrives Set alerts to High values with a critical level of 1 and turn on Notify me when it goes critical. Multimeter waits 15 minutes between notifications for the same meter, so a busy inbox won’t keep pinging y...

Powered by Readybot.io

**DEV Community** ## Show your unread Mail count in your …

DEV Community

Marketplace Ingestion: Chunk Boundaries for Low-Latency, Traceable Tutor Retrieval

Short answer: use a staged retrieval design with explicit collections, bounded queries, and source context that survives every handoff from marketplace document ingestion to the online course tutor's answer. Alert on contract failures before users report vague or uncited answers. The page says the tutor returned an answer without usable source context. On-call can see the affected collection, tenant, access decision, query duration, and the identifiers of the retrieved chunks. The ingestion job itself completed, so restarting it would be guesswork and could produce duplicate work. Don't retry blind. The signal that should have fired earlier is a stage-level contract violation: an indexed item without tenant or access-control metadata, a bounded query with no traceable source context, or a representative failure case whose expected source no longer appears. I've been paged by missed jobs and duplicate deliveries; both teach the same lesson here. A green worker process is not proof that the user-visible job succeeded. What should alert before a tutor answer loses its source? Work backward from the answer. Each answer needs enough source context to trace it to retrieved chunks; each query needs an explicit collection and a bound; each indexed item needs tenant and access-control metadata; each ingestion run needs to be observable separately from querying. Those are four different checks, not one generic rag_ok bit. For a marketplace that ingests course descriptions, lesson transcripts, and instructor updates, record stage outcomes using internal document and chunk identifiers. Avoid putting document text, credentials, or learner data in metric labels. A practical event can state that ingestion accepted 148 source records and produced a set of chunk identifiers without claiming that 148 is universally correct. The expected count belongs to that run's input contract, and the alert compares the two. The first alert should name the failed boundary and the affected tenant. Consider a hypothetical page for tenant market-7: ingestion accepted 148 records, but one output chunk from lesson-42 has no access decision. The runbook should lead on-call to that ingestion unit, the rejected item, and the input metadata rather than inviting a replay of all 148 records. If ingestion metadata is complete but a bounded tutor query cannot identify the expected lesson source, the page should instead carry the collection, query bound, returned chunk identifiers, and expected source from the evaluation case. The distinction changes the action. ingestion_metadata_rejected stops the affected ingestion unit before the corpus becomes queryable; retrieval_source_missing sends the case back to boundary and query evaluation. Query latency remains separate because a slow but correct result and a fast irrelevant result require different responses. None of those example identifiers or counts defines a universal threshold. They make the handoff inspectable. This is where Infrai can fit by the first handoff: teams that want to call vector retrieval from a Go worker without installing and maintaining another client library should try its plain REST API for the collection and query boundary. Anything that sends HTTP can use the same surface. Infrai provides a single API key and one consolidated bill across its backend capabilities, so a worker that later needs another supported handoff does not add a separate credential and invoice reconciliation path. The catch is that a team needing a specialist vector database's native operational controls should keep that specialist in the design. How should an online course tutor set retrieval chunk boundaries? Start with a retrieval contract, not a fashionable token count. A chunk should preserve the smallest source unit that can support a cited tutor answer while retaining the tenant and access decision of its parent document. In a course marketplace, a lesson heading plus its explanatory paragraphs is often a better candi...

Powered by Readybot.io

**DEV Community** ## Marketplace Ingestion: Chunk Boundaries for Low-Latency, Traceable …

DEV Community

Building Reliable Audio Datasets for AI/ML Training: An Open-Source Quality Assurance Framework

A WAV or FLAC file that decodes without throwing an exception can still be a catastrophic training example. The defects that degrade deep learning models the most are precisely the ones a human ear misses during a quick spot-listen: brickwall spectral cutoffs from fake upsampling, destructive phase cancellation during mono downmixing, label drift in timed transcripts, and sub-segment train/validation leakage. This article introduces an open-source, reproducible pre-training quality-assurance framework developed at ComposerMind Labs. By evaluating audio corpora across signal forensics, partition isolation, and annotation alignment before compute cycles are spent, this framework provides automated, deterministic quality gates for machine learning workflows. +-------------------------------------------------------------------------+ | COMPOSERMIND AUDIOINTEGRITY WORKFLOW | | | | Raw Audio Corpus (Web Crawls, Multi-Track Stems, Transcripts) | | | | | v | | [ STAGE 1: SIGNAL FORENSICS ] ---------------------------------------+ | | * WaveWash (v0.2.0) --> Clipping, Saturation, DC-Offset Bias | | | * BandCheck (v0.1.1) --> Fake 48kHz Upsampling, Spectral Cutoffs | | | * PhaseCheck (v0.1.0) --> Inter-Channel Mono Cancellation Loss | | | * DriftCheck (v0.1.0) --> Timed Label vs. Audio Offset, Drift (ppm) | | | | | | | v | | | [ STAGE 2: PARTITION SECURITY ] -------------------------------------+ | | * SplitSafe (v0.1.1) --> Acoustic Fingerprint Leakage Firewall | | | | | | | v | | | [ STAGE 3: ANNOTATION INTEGRITY ] -----------------------------------+ | | * TonicFind (v0.1.0) --> 12D Chromagram vs. Musical Key Profiles | | | * TempoCheck (v0.1.0) --> Onset Envelope vs. BPM Octave Ambiguity | | | | | | | v | | | Verified Audit Manifest --> Triage & Review --> PyTorch / HF Loader | +-------------------------------------------------------------------------+ ————————————————————————————————————————————— Why Audio Datasets Require Pre-Training Audits In natural language processing and computer vision, automated deduplication, normalization, and syntax validation are standard pre-requisites. In audio machine learning, however, ingestion pipelines often verify only that soundfile.read() or torchaudio.load() successfully loads an array. This surface-level validation permits silent, high-impact failure modes to contaminate training corpora: Failure Mode A: Sub-Segment Validation Leakage Consider a recording placed in the training partition, while a slightly trimmed (e.g., 50 ms offset), gain-adjusted, or re-encoded copy sits in the validation partition. Standard hash-based deduplication (MD5/SHA-256) fails completely because compression framing and trimming alter bit-level signatures. The model memorizes the underlying acoustic features, validation loss can plummet deceptively, and the model subsequently underperforms on genuine out-of-distribution audio. Original Audio (Train Set): =================================== Trimmed Copy (Validation Set): ============================= Result: File-level hashing misses the duplicate -> Silent cross-split contamination occurs. Failure Mode B: Destructive Mono Downmixing Many speech and audio pipelines downmix stereo inputs to mono (M = (L + R) / 2) prior to computing mel-spectrograms or feeding audio into acoustic backbones. When a stereo stem or recording contains inverted channel polarity (R ≈ -L) due to microphone miswiring or stereo widening effects: M = (L + (-L)) / (2) ≈ 0 The waveform collapses toward digital silence. Even with partial phase cancellation, destructive interference selectively notches out specific frequency bands, training neural models on acoustically corrupted spectra. Left Channel (L): /\ /\ /\ /\ (Active audio signal) Right Channel (-L): \/ \/ \/ \/ (Inverted polarity) ------------------- Mono Sum (L + R): ------------------- (CANCELLATION: near-total signal null) Failure Mode C: Codec Cutoffs in High-Sample-Rate Containers Web-crawled audio is frequently transcoded from l...

Powered by Readybot.io

**DEV Community** ## Building Reliable Audio Datasets for AI/ML Training: …

DEV Community

Python 3 Standard Library Socket Programming Cookbook: TCP, UDP, select.select(), struct Packing, and Checksums

A zero-dependency cookbook for beginners. Everything below uses only the Python 3 standard library (socket, select, struct, hashlib, zlib, json, sys), flat procedural code, no asyncio, threads, or classes. Every script prints connections, messages and state changes so you can watch the protocol work. Run servers and clients in separate terminal tabs with python3 script.py . Part 1: Core Concepts & Standard Library Rules What a Socket Is: An Operating System endpoint that sends and receives raw bytes over a network. IP vs. Port: The IP address ('localhost' or '127.0.0.1') identifies the machine; the Port (an integer like 10000) identifies the specific Python process. Networks Only Speak Bytes (b"..."): Convert str to bytes before sending with .encode(), and convert received bytes back to str with .decode(). TCP (SOCK_STREAM) vs. UDP (SOCK_DGRAM): TCP is connection-oriented (bind -> listen -> accept on server; connect -> sendall -> recv on client). UDP is connectionless (sendto and recvfrom). A UDP server uses a single socket for all clients and never uses select.select(). Socket Port Reuse (SO_REUSEADDR): Always add server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) before bind() on TCP servers and proxies to avoid Address already in use errors when restarting. Binary Struct Packing (struct.Struct): Format codes: i (4-byte int), I (4-byte unsigned int), f (4-byte float), ? (1-byte bool), c or 1s (1-byte char as bytes), Xs like 7s (X-byte string as bytes). C Alignment Padding Rule: Never count bytes manually ('c i' is 8 bytes due to 3 padding bytes; 'i c' is 5 bytes; 'i i c' is 9 bytes; 'I I 1s' is 12 bytes; '7s6s' is 13 bytes). Always pass packer.size to recv(packer.size). Null-Byte Padding Rule: Packing a shorter string like b"FAIL" into a 7s field pads the trailing bytes with null bytes (b"FAIL\x00\x00\x00"). Always strip null bytes after unpacking: status = status_bytes.decode().strip('\x00'). Part 2: Essential Building Blocks import sys, struct, json, hashlib, zlib

1. Command-Line Arguments (python3 script.py localhost 10000 input.txt)

ip = sys.argv[1]
port = int(sys.argv[2])
filename = sys.argv[3]

2. Struct Packing & Unpacking

packer = struct.Struct('i i 1s')
packed_bytes = packer.pack(10, 25, b'+')
a, b, raw_op = packer.unpack(packed_bytes)
op = raw_op.decode().strip('\x00')

3. Delimiter-Separated Payloads (':', ';', '|')

numbers = [3, 7, 12, 18, 20]
bet = 500
msg_bytes = (":".join(str(x) for x in numbers) + f":{bet}").encode()
parts = [int(x) for x in msg_bytes.decode().split(":")]
recv_nums, recv_bet = parts[:-1], parts[-1]

4. Reading Text, JSON, and Binary Files

with open("input.json", "r") as f:
data = json.load(f)

5. MD5 and CRC32 Checksums

md5_hex = hashlib.md5(b"1:5:12:19:20").hexdigest()
crc_int = zlib.crc32(b"1:5:12:19:20")
Part 3: Master Network Templates (TCP, Select, UDP, TCP-UDP Proxy) Template 1: Single-Client TCP Server & Client # --- tcp_server.py ---
import socket, sys

ip, port = sys.argv[1], int(sys.argv[2])
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((ip, port))
server.listen(5)
print(f"TCP Server listening on {ip}:{port}")
while True:
conn, addr = server.accept()
with conn:
print(f"Connected by {addr}")
data = conn.recv(1024)
if data:
print("Received:", data.decode())
conn.sendall(b"Hello client")
# --- tcp_client.py ---
import socket, sys

ip, port = sys.argv[1], int(sys.argv[2])
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client:
client.connect((ip, port))
client.sendall(b"Hello server")
print("Server replied:", client.recv(1024).decode())
Template 2: Multi-Client TCP Server with select.select() # --- select_tcp_server.py ---
import socket, select, sys

ip, port = sys.argv[1], int(sys.argv[2])
server = socket.socket(socket.AF_INET, socke...

Powered by Readybot.io

**DEV Community** ## Python 3 Standard Library Socket Programming Cookbook: …

DEV Community

Unsubscribe'ı doğru kurmak: Tek tık çıkış, suppression listesi, kanal bazlı izin ve gönderim öncesi kontrol

Bir pazarlama otomasyonu projesinde en az konuşulan ama en çok sorun çıkaran parça, "abonelikten çık" bağlantısıdır. Kampanya akışları, segmentler, şablonlar ve raporlar uzun uzun tartışılır; çıkış ise e-posta altbilgisine konan küçük bir link olarak görülür. Sonra bir gün müşteri, aylar önce çıktığı listeden hâlâ mesaj aldığını söyleyerek şikâyet eder. İncelendiğinde çıkışın bir araçta kaydedildiği, ama CRM'den gelen bir yeniden senkronun kişiyi listeye geri eklediği ortaya çıkar. Ben Koray Yalçın; lead yönetimi, CRM ve pazarlama otomasyonu altyapıları kuruyorum, ağırlıklı olarak gayrimenkul ve PropTech tarafında. Bu yazıda unsubscribe konusunu hukuk metni olarak değil, bir yazılım tasarımı problemi olarak ele alacağım: çıkış olayı nasıl modellenir, tek tık çıkış nasıl uygulanır, suppression listesi neden ayrı bir tablo olmalıdır, kanal bazlı izinler nasıl tutulur ve her gönderimden önce hangi kontrol mutlaka çalışmalıdır. Not: Bu yazı teknik bir tasarım rehberidir, hukuki görüş değildir. KVKK, ticari ileti mevzuatı ve İYS yükümlülükleri için hukuk danışmanınızla çalışın. Unsubscribe bir alan değil, bir olaydır En yaygın hata, kişi tablosuna is_subscribed boolean gibi tek bir alan eklemektir. Bu alan üç soruyu cevaplayamaz: Kişi ne zaman çıktı? Hangi kanaldan ve hangi listeden çıktı? Bu bilgiyi hangi sistem yazdı? Daha kötüsü, tek bir boolean her senkronda üzerine yazılabilir. Dış sistemden true gelirse, kişinin kendi iradesiyle yaptığı çıkış sessizce silinir. Bu yüzden çıkışı bir olay olarak, yalnızca eklenen (append-only) bir tabloda tutuyorum. Güncel durum bu olaylardan türetilir. CREATE TABLE consent_event (
id bigserial PRIMARY KEY,
contact_id bigint NOT NULL REFERENCES contact(id),
channel text NOT NULL CHECK (channel IN ('email','sms','whatsapp','call')),
topic text NOT NULL DEFAULT 'all', -- 'newsletter', 'launch', 'all' ...
action text NOT NULL CHECK (action IN ('opt_in','opt_out')),
source text NOT NULL, -- 'one_click', 'preference_center', 'reply_stop', 'agent', 'import'
evidence jsonb NOT NULL DEFAULT '{}', -- ip, user_agent, message_id, kayıt formu sürümü
occurred_at timestamptz NOT NULL DEFAULT now(),
recorded_by text NOT NULL -- servis veya kullanıcı kimliği
);

CREATE INDEX ON consent_event (contact_id, channel, topic, occurred_at DESC);
Burada iki ayrıntı önemli. Birincisi topic: kişi lansman duyurularından çıkıp aylık bültende kalmak isteyebilir. Tek bir "çık" butonu her şeyi kapatıyorsa insanlar ya hepsinden çıkar ya da spam olarak işaretler; ikisi de sizin için kötüdür. İkincisi evidence: bir gün "bu kişi izin vermiş miydi, ne zaman çıktı?" diye sorulduğunda cevabın kanıtıyla birlikte veritabanında olması gerekir. Güncel durumu türetmek Olay tablosundan güncel izni okumak için her kanal ve konu için son olayı almak yeterlidir. Kanal genelindeki all çıkışı, konu bazlı her izni ezmelidir. CREATE VIEW consent_state AS
SELECT DISTINCT ON (contact_id, channel, topic)
contact_id, channel, topic, action, occurred_at, source
FROM consent_event
ORDER BY contact_id, channel, topic, occurred_at DESC, id DESC;

    • Belirli bir konuda gönderim izni var mı?
      CREATE FUNCTION can_send(p_contact bigint, p_channel text, p_topic text)
      RETURNS boolean LANGUAGE sql STABLE AS $$
      SELECT
      NOT EXISTS ( -- kanal genelinde çıkış var mı?
      SELECT 1 FROM consent_state
      WHERE contact_id = p_contact AND channel = p_channel
      AND topic = 'all' AND action = 'opt_out')
      AND EXISTS ( -- bu konu için açık izin var mı?
      SELECT 1 FROM consent_state
      WHERE contact_id = p_contact AND channel = p_channel
      AND topic IN (p_topic, 'all') AND action = 'opt_in')
      AND NOT EXISTS ( -- bu konu için çıkış var mı?
      SELECT 1 FROM consent_state
      WHERE contact_id = p_contact AND chann...

      Powered by Readybot.io
**DEV Community** ## Unsubscribe'ı doğru kurmak: Tek tık çıkış, suppression …